diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index ece2454..6d0918f 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -2,8 +2,8 @@ * AutoConnect class implementation. * @file AutoConnect.cpp * @author hieromon@gmail.com - * @version 0.9.9 - * @date 2019-05-25 + * @version 0.9.11 + * @date 2019-07-09 * @copyright MIT license. */ @@ -59,6 +59,7 @@ void AutoConnect::_initialize(void) { #endif _aux.release(); _auxUri = String(""); + _ticker.reset(); } /** @@ -103,6 +104,13 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long if (_apConfig.hostName.length()) SET_HOSTNAME(_apConfig.hostName.c_str()); + // Start Ticker according to the WiFi condition with Ticker is available. + if (_apConfig.ticker) { + _ticker.reset(new AutoConnectTicker(_apConfig.tickerPort, _apConfig.tickerOn)); + if (WiFi.status() != WL_CONNECTED) + _ticker->start(AUTOCONNECT_FLICKER_PERIOD, (uint8_t)AUTOCONNECT_FLICKER_WIDTHDC); + } + // Advance configuration for STA mode. #ifdef AC_DEBUG String staip_s = _apConfig.staip.toString(); @@ -195,6 +203,10 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long _currentHostIP = WiFi.softAPIP(); AC_DBG("SoftAP %s/%s Ch(%d) IP:%s %s\n", _apConfig.apid.c_str(), _apConfig.psk.c_str(), _apConfig.channel, _currentHostIP.toString().c_str(), _apConfig.hidden ? "hidden" : ""); + // Start ticker with AP_STA + if (_ticker) + _ticker->start(AUTOCONNECT_FLICKER_PERIOD, (uint8_t)AUTOCONNECT_FLICKER_WIDTHAP); + // Fork to the exit routine that starts captive portal. cs = _onDetectExit ? _onDetectExit(_currentHostIP) : true; @@ -250,6 +262,11 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long if (!_responsePage) _startWebServer(); + // Stop ticker + if (cs) + if (_ticker) + _ticker->stop(); + return cs; } @@ -323,6 +340,8 @@ void AutoConnect::end(void) { break; } } + + _ticker.reset(); } /** diff --git a/src/AutoConnect.h b/src/AutoConnect.h index 78e94c3..e7ee717 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -2,8 +2,8 @@ * Declaration of AutoConnect class and accompanying AutoConnectConfig class. * @file AutoConnect.h * @author hieromon@gmail.com - * @version 0.9.9 - * @date 2019-05-25 + * @version 0.9.11 + * @date 2019-07-08 * @copyright MIT license. */ @@ -32,6 +32,7 @@ using WebServerClass = WebServer; #include "AutoConnectPage.h" #include "AutoConnectCredential.h" #include "AutoConnectAux.h" +#include "AutoConnectTicker.h" /**< A type to save established credential at WiFi.begin automatically. */ typedef enum AC_SAVECREDENTIAL { @@ -69,6 +70,9 @@ class AutoConnectConfig { immediateStart(false), retainPortal(false), portalTimeout(AUTOCONNECT_CAPTIVEPORTAL_TIMEOUT), + ticker(false), + tickerPort(AUTOCONNECT_TICKER_PORT), + tickerOn(LOW), hostName(String("")), homeUri(AUTOCONNECT_HOMEURI), title(AUTOCONNECT_MENU_TITLE), @@ -98,6 +102,9 @@ class AutoConnectConfig { immediateStart(false), retainPortal(false), portalTimeout(portalTimeout), + ticker(false), + tickerPort(AUTOCONNECT_TICKER_PORT), + tickerOn(LOW), hostName(String("")), homeUri(AUTOCONNECT_HOMEURI), title(AUTOCONNECT_MENU_TITLE), @@ -127,6 +134,9 @@ class AutoConnectConfig { immediateStart = o.immediateStart; retainPortal = o.retainPortal; portalTimeout = o.portalTimeout; + ticker = o.ticker; + tickerPort = o.tickerPort; + tickerOn = o.tickerOn; hostName = o.hostName; homeUri = o.homeUri; title = o.title; @@ -155,6 +165,9 @@ class AutoConnectConfig { bool immediateStart; /**< Skips WiFi.begin(), start portal immediately */ bool retainPortal; /**< Even if the captive portal times out, it maintains the portal state. */ unsigned long portalTimeout; /**< Timeout value for stay in the captive portal */ + bool ticker; /**< Drives LED flicker according to WiFi connection status. */ + uint8_t tickerPort; /**< GPIO for flicker */ + uint8_t tickerOn; /**< A signal for flicker turn on */ String hostName; /**< host name */ String homeUri; /**< A URI of user site */ String title; /**< Menu title */ @@ -285,6 +298,7 @@ class AutoConnect { #ifdef ARDUINO_ARCH_ESP32 WiFiEventId_t _disconnectEventId; /**< STA disconnection event handler registered id */ #endif + std::unique_ptr _ticker; /**< */ /** HTTP header information of the currently requested page. */ IPAddress _currentHostIP; /**< host IP address */ diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index bde08d6..7b39870 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -2,8 +2,8 @@ * Predefined AutoConnect configuration parameters. * @file AutoConnectDefs.h * @author hieromon@gmail.com - * @version 0.9.9 - * @date 2019-05-25 + * @version 0.9.11 + * @date 2019-07-08 * @copyright MIT license. */ @@ -137,6 +137,24 @@ #define AUTOCONNECT_SD_SPEED 4000000 #endif // !AUTOCONNECT_SD_SPEED +// Factors related to a flickering signal indicating WiFi connection status +#ifndef AUTOCONNECT_FLICKER_PERIOD // Flicker cycle [ms] +#define AUTOCONNECT_FLICKER_PERIOD 2000 +#endif // !AUTOCONNECT_FLICKER_PERIOD +#ifndef AUTOCONNECT_FLICKER_WIDTHAP // Flicking pulse width in APSTA +#define AUTOCONNECT_FLICKER_WIDTHAP 128 +#endif // !AUTOCONNECT_FLICKER_WIDTHAPSTA +#ifndef AUTOCONNECT_FLICKER_WIDTHDC // Flicking pulse width in disconnected +#define AUTOCONNECT_FLICKER_WIDTHDC 25 +#endif // !AUTOCONNECT_FLICKER_WIDTHDISCON +#ifndef AUTOCONNECT_TICKER_PORT +#if defined(BUILDIN_LED) || defined(LED_BUILTIN) +#define AUTOCONNECT_TICKER_PORT LED_BUILTIN +#else // Native pin number +#define AUTOCONNECT_TICKER_PORT 2 +#endif +#endif + // ArduinoJson buffer size #ifndef AUTOCONNECT_JSONBUFFER_SIZE #define AUTOCONNECT_JSONBUFFER_SIZE 256 diff --git a/src/AutoConnectTicker.cpp b/src/AutoConnectTicker.cpp new file mode 100644 index 0000000..d417038 --- /dev/null +++ b/src/AutoConnectTicker.cpp @@ -0,0 +1,56 @@ +/** + * AutoConnectTicker class implementation. + * Provides a service that shows the flicker signal according to WiFi + * connection status. + * @file AutoConnect.cpp + * @author hieromon@gmail.com + * @version 0.9.11 + * @date 2019-07-09 + * @copyright MIT license. + */ + +#include "AutoConnectTicker.h" + +/** + * Start ticker cycle + * @param cycle Cycle time in [ms] + * @param duty Duty cycle in [ms] + */ +void AutoConnectTicker::start(const uint32_t cycle, const uint32_t duty) { + _cycle = cycle; + if (duty <= _cycle) + _duty = duty; + start(); +} + +/** + * Start ticker cycle + */ +void AutoConnectTicker::start(void) { + pinMode(_port, OUTPUT); + _pulse.detach(); + _period.attach_ms(_cycle, AutoConnectTicker::_onPeriod, this); +} + +/** + * Turn on the flicker signal and reserves a ticker to turn off the + * signal. This behavior will perform every cycle to generate the + * pseudo-PWM signal. + * If the function is registered, call the callback function at the + * end of one cycle. + * @param t Its own address + */ +void AutoConnectTicker::_onPeriod(AutoConnectTicker* t) { + digitalWrite(t->_port, t->_turnOn); + t->_pulse.once_ms(t->_duty, AutoConnectTicker::_onPulse, t); + if (t->_callback) + t->_callback(); +} + +/** + * Turn off the flicker signal + * @param t Its own address + */ +void AutoConnectTicker::_onPulse(AutoConnectTicker* t) { + digitalWrite(t->_port, !(t->_turnOn)); +} diff --git a/src/AutoConnectTicker.h b/src/AutoConnectTicker.h new file mode 100644 index 0000000..9319306 --- /dev/null +++ b/src/AutoConnectTicker.h @@ -0,0 +1,53 @@ +/** + * Declaration of AutoConnectTicker class. + * @file AutoConnectTicker.h + * @author hieromon@gmail.com + * @version 0.9.11 + * @date 2019-07-09 + * @copyright MIT license. + */ + +#ifndef _AUTOCONNECTTICKER_H_ +#define _AUTOCONNECTTICKER_H_ + +#include +#if defined(ARDUINO_ARCH_ESP8266) +#include +#elif defined(ARDUINO_ARCH_ESP32) +#include +#endif +#include +#include "AutoConnectDefs.h" + +class AutoConnectTicker { + public: + explicit AutoConnectTicker(const uint8_t port = AUTOCONNECT_TICKER_PORT, const uint8_t active = LOW, const uint32_t cycle = 0, uint32_t duty = 0) : _cycle(cycle), _duty(duty), _port(port), _turnOn(active), _callback(nullptr) { + if (_duty > _cycle) + _duty = _cycle; + } + ~AutoConnectTicker() { stop(); } + + typedef std::function Callback_ft; + void setCycle(const uint32_t cycle) { _cycle = cycle; } + void setDuty(const uint32_t duty) { _duty = duty <= _cycle ? duty : _duty; } + void start(const uint32_t cycle, const uint32_t duty); + void start(const uint32_t cycle, const uint8_t width) { start(cycle, (uint32_t)((cycle * width) >> 8)); } + void start(void); + void stop(void) { _period.detach(); _pulse.detach(); digitalWrite(_port, !_turnOn); } + void onPeriod(Callback_ft cb) { _callback = cb ;} + + protected: + Ticker _period; /**< Ticker for flicking cycle */ + Ticker _pulse; /**< Ticker for pulse width generating */ + uint32_t _cycle; /**< Cycle time in [ms] */ + uint32_t _duty; /**< Pulse width in [ms] */ + + private: + static void _onPeriod(AutoConnectTicker* t); + static void _onPulse(AutoConnectTicker* t); + uint8_t _port; /**< Port to output signal */ + uint8_t _turnOn; /**< Signal to turn on */ + Callback_ft _callback; /**< An exit by every cycle */ +}; + +#endif // !_AUTOCONNECTTICKER_H_