| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- /**
- This test illustrates the use if yield methods and internal StatusRequest objects
- THIS TEST HAS BEEN TESTED ON NODEMCU V.2 (ESP8266)
- The WiFi initialization and NTP update is executed in parallel to blinking the onboard LED
- and an external LED connected to D2 (GPIO04)
- Try running with and without correct WiFi parameters to observe the difference in behaviour
- */
- #define _TASK_SLEEP_ON_IDLE_RUN
- #define _TASK_STATUS_REQUEST
- #include <TaskScheduler.h>
- #include <ESP8266WiFi.h>
- #include <WiFiUdp.h>
- Scheduler ts;
- // Callback methods prototypes
- void connectInit();
- void ledCallback();
- bool ledOnEnable();
- void ledOnDisable();
- void ledOn();
- void ledOff();
- void ntpUpdateInit();
- // Tasks
- Task tConnect (TASK_SECOND, TASK_FOREVER, &connectInit, &ts, true);
- Task tLED (TASK_IMMEDIATE, TASK_FOREVER, &ledCallback, &ts, false, &ledOnEnable, &ledOnDisable);
- // Tasks running on events
- Task tNtpUpdate (&ntpUpdateInit, &ts);
- // Replace with WiFi parameters of your Access Point/Router:
- const char *ssid = "wifi_network";
- const char *pwd = "wifi_password";
- long ledDelayOn, ledDelayOff;
- #define LEDPIN D0 // Onboard LED pin - linked to WiFi
- #define LEDPIN2 D2 // External LED
- #define CONNECT_TIMEOUT 30 // Seconds
- #define CONNECT_OK 0 // Status of successful connection to WiFi
- #define CONNECT_FAILED (-99) // Status of failed connection to WiFi
- // NTP Related Definitions
- #define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message
- IPAddress timeServerIP; // time.nist.gov NTP server address
- const char* ntpServerName = "time.nist.gov";
- byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
- unsigned long epoch;
- WiFiUDP udp; // A UDP instance to let us send and receive packets over UDP
- #define LOCAL_NTP_PORT 2390 // Local UDP port for NTP update
- void setup() {
- Serial.begin(74880);
- Serial.println(F("TaskScheduler test #14 - Yield and internal StatusRequests"));
- Serial.println(F("=========================================================="));
- Serial.println();
- pinMode (LEDPIN, OUTPUT);
- pinMode (LEDPIN2, OUTPUT);
- tNtpUpdate.waitFor( tConnect.getInternalStatusRequest() ); // NTP Task will start only after connection is made
- }
- void loop() {
- ts.execute(); // Only Scheduler should be executed in the loop
- }
- /**
- Initiate connection to the WiFi network
- */
- void connectInit() {
- Serial.print(millis());
- Serial.println(F(": connectInit."));
- Serial.println(F("WiFi parameters: "));
- Serial.print(F("SSID: ")); Serial.println(ssid);
- Serial.print(F("PWD : ")); Serial.println(pwd);
- WiFi.mode(WIFI_STA);
- WiFi.hostname("esp8266");
- WiFi.begin(ssid, pwd);
- yield();
- ledDelayOn = TASK_SECOND / 2;
- ledDelayOff = TASK_SECOND / 4;
- tLED.enable();
- tConnect.yield(&connectCheck); // This will pass control back to Scheduler and then continue with connection checking
- }
- /**
- Periodically check if connected to WiFi
- Re-request connection every 5 seconds
- Stop trying after a timeout
- */
- void connectCheck() {
- Serial.print(millis());
- Serial.println(F(": connectCheck."));
- if (WiFi.status() == WL_CONNECTED) { // Connection established
- Serial.print(millis());
- Serial.print(F(": Connected to AP. Local ip: "));
- Serial.println(WiFi.localIP());
- tConnect.disable();
- }
- else {
- if (tConnect.getRunCounter() % 5 == 0) { // re-request connection every 5 seconds
- Serial.print(millis());
- Serial.println(F(": Re-requesting connection to AP..."));
- WiFi.disconnect(true);
- yield(); // This is an esp8266 standard yield to allow linux wifi stack run
- WiFi.hostname("esp8266");
- WiFi.mode(WIFI_STA);
- WiFi.begin(ssid, pwd);
- yield(); // This is an esp8266 standard yield to allow linux wifi stack run
- }
- if (tConnect.getRunCounter() == CONNECT_TIMEOUT) { // Connection Timeout
- tConnect.getInternalStatusRequest()->signal(CONNECT_FAILED); // Signal unsuccessful completion
- tConnect.disable();
- Serial.print(millis());
- Serial.println(F(": connectOnDisable."));
- Serial.print(millis());
- Serial.println(F(": Unable to connect to WiFi."));
- ledDelayOn = TASK_SECOND / 16; // Blink LEDs quickly due to error
- ledDelayOff = TASK_SECOND / 16;
- tLED.enable();
- }
- }
- }
- /**
- Initiate NTP update if connection was established
- */
- void ntpUpdateInit() {
- Serial.print(millis());
- Serial.println(F(": ntpUpdateInit."));
- if ( tConnect.getInternalStatusRequest()->getStatus() != CONNECT_OK ) { // Check status of the Connect Task
- Serial.print(millis());
- Serial.println(F(": cannot update NTP - not connected."));
- return;
- }
- udp.begin(LOCAL_NTP_PORT);
- if ( WiFi.hostByName(ntpServerName, timeServerIP) ) { //get a random server from the pool
- Serial.print(millis());
- Serial.print(F(": timeServerIP = "));
- Serial.println(timeServerIP);
- sendNTPpacket(timeServerIP); // send an NTP packet to a time server
- }
- else {
- Serial.print(millis());
- Serial.println(F(": NTP server address lookup failed."));
- tLED.disable();
- udp.stop();
- tNtpUpdate.disable();
- return;
- }
- ledDelayOn = TASK_SECOND / 8;
- ledDelayOff = TASK_SECOND / 8;
- tLED.enable();
- tNtpUpdate.set( TASK_SECOND, CONNECT_TIMEOUT, &ntpCheck );
- tNtpUpdate.enableDelayed();
- }
- /**
- * Check if NTP packet was received
- * Re-request every 5 seconds
- * Stop trying after a timeout
- */
- void ntpCheck() {
- Serial.print(millis());
- Serial.println(F(": ntpCheck."));
- if ( tNtpUpdate.getRunCounter() % 5 == 0) {
- Serial.print(millis());
- Serial.println(F(": Re-requesting NTP update..."));
- udp.stop();
- yield();
- udp.begin(LOCAL_NTP_PORT);
- sendNTPpacket(timeServerIP);
- return;
- }
- if ( doNtpUpdateCheck()) {
- Serial.print(millis());
- Serial.println(F(": NTP Update successful"));
- Serial.print(millis());
- Serial.print(F(": Unix time = "));
- Serial.println(epoch);
- tLED.disable();
- tNtpUpdate.disable();
- udp.stop();
- }
- else {
- if ( tNtpUpdate.isLastIteration() ) {
- Serial.print(millis());
- Serial.println(F(": NTP Update failed"));
- tLED.disable();
- udp.stop();
- }
- }
- }
- /**
- * Send NTP packet to NTP server
- */
- void sendNTPpacket(IPAddress & address)
- {
- Serial.print(millis());
- Serial.println(F(": sendNTPpacket."));
- // set all bytes in the buffer to 0
- memset(packetBuffer, 0, NTP_PACKET_SIZE);
- // Initialize values needed to form NTP request
- // (see URL above for details on the packets)
- packetBuffer[0] = 0b11100011; // LI, Version, Mode
- packetBuffer[1] = 0; // Stratum, or type of clock
- packetBuffer[2] = 6; // Polling Interval
- packetBuffer[3] = 0xEC; // Peer Clock Precision
- // 8 bytes of zero for Root Delay & Root Dispersion
- packetBuffer[12] = 49;
- packetBuffer[13] = 0x4E;
- packetBuffer[14] = 49;
- packetBuffer[15] = 52;
- // all NTP fields have been given values, now
- // you can send a packet requesting a timestamp:
- udp.beginPacket(address, 123); //NTP requests are to port 123
- udp.write(packetBuffer, NTP_PACKET_SIZE);
- udp.endPacket();
- yield();
- }
- /**
- * Check if a packet was recieved.
- * Process NTP information if yes
- */
- bool doNtpUpdateCheck() {
- Serial.print(millis());
- Serial.println(F(": doNtpUpdateCheck."));
- yield();
- int cb = udp.parsePacket();
- if (cb) {
- // We've received a packet, read the data from it
- udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
- //the timestamp starts at byte 40 of the received packet and is four bytes,
- // or two words, long. First, esxtract the two words:
- unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
- unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
- // combine the four bytes (two words) into a long integer
- // this is NTP time (seconds since Jan 1 1900):
- unsigned long secsSince1900 = highWord << 16 | lowWord;
- // now convert NTP time into everyday time:
- // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
- const unsigned long seventyYears = 2208988800UL;
- // subtract seventy years:
- epoch = secsSince1900 - seventyYears;
- return (epoch != 0);
- }
- return false;
- }
- /**
- * Flip the LED state based on the current state
- */
- bool ledState;
- void ledCallback() {
- if ( ledState ) ledOff();
- else ledOn();
- }
- /**
- * Make sure the LED starts lit
- */
- bool ledOnEnable() {
- ledOn();
- return true;
- }
- /**
- * Make sure LED ends dimmed
- */
- void ledOnDisable() {
- ledOff();
- }
- /**
- * Turn LEDs on.
- * Set appropriate delay.
- * PLEASE NOTE: NodeMCU onbaord LED is active-low
- */
- void ledOn() {
- ledState = true;
- digitalWrite(LEDPIN, LOW);
- digitalWrite(LEDPIN2, HIGH);
- tLED.delay( ledDelayOn );
- }
- /**
- * Turn LEDs off.
- * Set appropriate delay.
- * PLEASE NOTE: NodeMCU onbaord LED is active-low
- */
- void ledOff() {
- ledState = false;
- digitalWrite(LEDPIN, HIGH);
- digitalWrite(LEDPIN2, LOW);
- tLED.delay( ledDelayOff );
- }
|