/* * ESP8266 JJY Simulator * Original Code by http://tocchan.ddo.jp:84/pukiwiki/index.php?ESP8266TimeCode * Modified by Toshi Nagata */ #include #include #include #include #include #include #include extern "C" { #include "user_interface.h" } WiFiManager wifiManager; WiFiUDP Udp; #define Wait() delayMicroseconds(100) byte timecode[60]; unsigned long lastNTPTime = 0; Ticker ticker; char ntp_host[40]; char start_time[10]; char end_time[10]; // PIN assign #define PIN_LED_R 5 #define PIN_LED_Y 4 #define PIN_LED_G 13 #define PIN_RADIO 14 #define PIN_CLEAR 12 #define LED_ON HIGH #define LED_OFF LOW //char *poolNTP = "jp.pool.ntp.org"; //char *nictNTP = "ntp.jst.mfeed.ad.jp";//mfeed ??????Q??????? #if 0 #pragma mark ====== NTP ====== #endif const unsigned int localPort = 8888; // local UDP port const int NTP_PACKET_SIZE = 48; byte packetBuffer[NTP_PACKET_SIZE]; unsigned long sendNTPpacket(char *address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request 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; //send NTP request packet (port 123) Udp.beginPacket(address, 123); Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); } bool NTPSetTimeInternal(char *address, bool force) { sendNTPpacket(address); int sendedMillis = millis(); Serial.print("Waiting NTP response ... "); Serial.println(address); // Wait till data is there or timeout... byte timeout = 0; int cb = 0; do { delay(1); cb = Udp.parsePacket(); if (timeout > 100) return false; // timeout after 100 ms timeout++; } while (cb == 0); Serial.print("parsePacket size="); Serial.println(cb); Udp.read(packetBuffer, NTP_PACKET_SIZE); long elaps = millis() - sendedMillis; unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); unsigned long secsSince1900 = (highWord << 16) | lowWord; unsigned int fraction_hi = word(packetBuffer[44], packetBuffer[45]); // Unix time starts on Jan 1 1970, v.s. NTP ans is since Jan 1 1900. const unsigned long seventyYears = 2208988800UL; unsigned long epoch = secsSince1900 - seventyYears; epoch += 60 * 2; // 2 minutes forward (for testing) unsigned long wait_sec = 0; if (!force) wait_sec = 60 - (epoch + 2) % 60; //59sに合わせる // wait until next 0 second delay(1000 - elaps / 2 - fraction_hi / (65536 / 1000) + wait_sec * 1000); // Set current time in JST (GMT+0900) setTime(epoch + 1 + 9 * 60 * 60 + wait_sec); Serial.print("localtime = "); Serial.print(epoch); Serial.print(" delay(ms) = "); Serial.println(elaps); return true; } void timePrint() { // print out current time char buf[24]; sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d", year(), month(), day(), hour(), minute(), second()); // String objecttmp = ""; // String msg = objecttmp + year() + "/" + month() + "/" + day() + " " + hour() + ":" + minute() + ":" + second() + "(" + weekday() + ")" + dayOfYear(); Serial.println(""); Serial.println(buf); } bool NTPSetTime(char *address, bool force) { Udp.begin(localPort); bool ret = NTPSetTimeInternal(address, force); Udp.stop(); if (ret) { Serial.print("NTP success from "); Serial.println(address); } else { Serial.print("NTP failure from "); Serial.println(address); } return ret; } void NtpClientSetup() { Serial.println("\nStarting connection to server..."); while (NTPSetTime(ntp_host, true) == 0) { int i; Serial.println("Retrying..."); for (i = 0; i < 10; i++) { digitalWrite(PIN_LED_R, LED_ON); delay(100); digitalWrite(PIN_LED_R, LED_OFF); delay(900); } } } void NtpUpdate() { static unsigned long nextNTPTime = 0; if (minute() > 32) { if (millis() > nextNTPTime) { timePrint(); bool ret = NTPSetTime(ntp_host, false); if (ret) { nextNTPTime = millis() + 50 * 60 * 1000L; timePrint(); } else nextNTPTime = millis() + 5 * 60 * 1000L; } } } #if 0 #pragma mark ====== JJY ====== #endif void Signal_SETUP() { pinMode(PIN_LED_R, OUTPUT); pinMode(PIN_LED_Y, OUTPUT); pinMode(PIN_LED_G, OUTPUT); pinMode(PIN_RADIO, OUTPUT); pinMode(PIN_CLEAR, INPUT); digitalWrite(PIN_LED_R, LED_OFF); digitalWrite(PIN_LED_Y, LED_OFF); digitalWrite(PIN_LED_G, LED_OFF); digitalWrite(PIN_RADIO, LOW); } void Signal_ON(int n) { digitalWrite(PIN_RADIO, HIGH); if (n == 0) digitalWrite(PIN_LED_G, LED_ON); #if 0 /* For debug */ if (n == 1) digitalWrite(PIN_LED_Y, LED_ON); else if (n == 2) digitalWrite(PIN_LED_R, LED_ON); #endif } void Signal_OFF() { digitalWrite(PIN_RADIO, LOW); digitalWrite(PIN_LED_R, LED_OFF); digitalWrite(PIN_LED_Y, LED_OFF); digitalWrite(PIN_LED_G, LED_OFF); } unsigned int calcTimeCodeDuration() { int s = second(); if (s == 0) setupTimeCode(); return timecode[s] * 100; } void setupTimeCode() { int i; memset(timecode, 8, sizeof(timecode)); setupTimeCode100(minute(), 0); timecode[0] = 2; setupTimeCode100(hour(), 10); int d = dayOfYear(); setupTimeCode100(d / 10, 20); setupTimeCode100(d % 10 * 10, 30); int parity1 = 0, parity2 = 0; for (i = 12; i < 20; i++) parity1 ^= timecode[i] == 5; for (i = 1; i < 10; i++) parity2 ^= timecode[i] == 5; timecode[36] = parity1 ? 5 : 8; timecode[37] = parity2 ? 5 : 8; setupTimeCode100(year() % 100, 40); for (i = 44; i > 40; i--) timecode[i] = timecode[i - 1]; timecode[40] = 8; int w = weekday() - 1; timecode[50] = (w & 4) ? 5 : 8; timecode[51] = (w & 2) ? 5 : 8; timecode[52] = (w & 1) ? 5 : 8; timecode[59] = 2; /* dump */ for (i = 0; i < 60; i++) { Serial.print(timecode[i], DEC); Serial.print(i % 10 == 9 ? "\r\n" : " "); } } void setupTimeCode100(int m, int i) { timecode[i + 0] = ((m / 10) & 8) ? 5 : 8; timecode[i + 1] = ((m / 10) & 4) ? 5 : 8; timecode[i + 2] = ((m / 10) & 2) ? 5 : 8; timecode[i + 3] = ((m / 10) & 1) ? 5 : 8; timecode[i + 4] = 8; timecode[i + 5] = ((m % 10) & 8) ? 5 : 8; timecode[i + 6] = ((m % 10) & 4) ? 5 : 8; timecode[i + 7] = ((m % 10) & 2) ? 5 : 8; timecode[i + 8] = ((m % 10) & 1) ? 5 : 8; timecode[i + 9] = 2; } int dayOfYear() { tmElements_t tm = {0, 0, 0, 0, 1, 1, CalendarYrToTm(year())}; time_t t = makeTime(tm); return (now() - t) / SECS_PER_DAY + 1; } #if 0 #pragma mark ====== setup & loop ====== #endif //int count = 0; int old_second = -1; int off_timing = 0; void timeCodeEvent() { //count++; if (old_second != second()) { char n; long nowmills = millis(); old_second = second(); int ms = calcTimeCodeDuration(); off_timing = nowmills + ms; if (ms <= 300) n = 0; else if (ms <= 600) n = 1; else n = 2; Signal_ON(n); if (second() == 0) timePrint(); else Serial.print("-"); return; } if (millis() > off_timing) { Signal_OFF(); off_timing = millis() + 1000; } } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); } bool shouldSaveConfig = false; // Callback for WifiManager: on exiting config mode void saveConfigCallback() { shouldSaveConfig = true; } // Callback for WifiManager: on starting config mode void configModeCallback(WiFiManager *myWiFiManager) { digitalWrite(PIN_LED_Y, LED_ON); // Light config LED } // RTC memory address #define USER_DATA_ADDR 66 #define DATA_CHECK_MASK 0x36C5A7BD int start_time_minutes, end_time_minutes; void setup() { File f; int i; long sleep_sec, remain_sec; bool manualConfig = false; Serial.begin(115200); Signal_SETUP(); Signal_OFF(); SPIFFS.begin(); #if 0 // This should be done ONLY ONCE Serial.println("Please wait 30 secs for SPIFFS to be formatted"); SPIFFS.format(); Serial.println("Spiffs formatted"); exit(0); #endif // Check RTC memory struct { unsigned long n1, n2; } n12; system_rtc_mem_read(USER_DATA_ADDR, &n12, sizeof(n12)); if (n12.n1 == (n12.n2 ^ DATA_CHECK_MASK)) { // RTC memory has a valid data sleep_sec = n12.n1; if (sleep_sec > 0) { // We will go to deep sleep deep_sleep: if (sleep_sec > 3600) remain_sec = sleep_sec - 3600; else remain_sec = 0; sleep_sec -= remain_sec; // Record the remaining seconds to SPIFFS if (remain_sec > 0) { n12.n1 = remain_sec; n12.n2 = (remain_sec ^ DATA_CHECK_MASK); } else { n12.n1 = n12.n2 = 0; } system_rtc_mem_write(USER_DATA_ADDR, &n12, sizeof(n12)); // Blink red LED three times { for (i = 0; i < 3; i++) { digitalWrite(PIN_LED_R, LED_ON); delay(100); digitalWrite(PIN_LED_R, LED_OFF); delay(400); } } Serial.print("\nGoing to sleep for "); Serial.print(sleep_sec); Serial.print(" seconds (remaining "); Serial.print(remain_sec); Serial.println(" seconds)..."); // Do deep sleep ESP.deepSleep(sleep_sec * 1000000UL, (remain_sec == 0 ? RF_DEFAULT : RF_DISABLED)); delay(10000); ESP.restart(); // Should not reach here } } digitalWrite(PIN_LED_G, LED_ON); for (i = 0; i < 10; i++) { delay(500); // Check the CLEAR button: if it is pushed, then clear the wifi settings if (digitalRead(PIN_CLEAR) == 0) { Serial.println("Entering manual configuration mode..."); manualConfig = true; break; } } digitalWrite(PIN_LED_G, LED_OFF); // Is the auxiliary information stored? f = SPIFFS.open("/auxinfo.txt", "r"); if (f) { String s = f.readStringUntil('\n'); s.toCharArray(ntp_host, sizeof(ntp_host)); ntp_host[sizeof(ntp_host) - 1] = 0; s = f.readStringUntil('\n'); s.toCharArray(start_time, sizeof(start_time)); start_time[sizeof(start_time) - 1] = 0; s = f.readStringUntil('\n'); s.toCharArray(end_time, sizeof(end_time)); end_time[sizeof(end_time) - 1] = 0; f.close(); } else { strcpy(ntp_host, "ntp.jst.mfeed.ad.jp"); strcpy(start_time, "0:00"); strcpy(end_time, "0:00"); } // Create custom parameters WiFiManagerParameter ntp_host_param("ntp_host", "ntp_host", ntp_host, 40); WiFiManagerParameter start_time_param("start_time", "start_time", start_time, 10); WiFiManagerParameter end_time_param("end_time", "end_time", end_time, 10); WiFiManagerParameter text1("NTP host"); WiFiManagerParameter text2("Start time"); WiFiManagerParameter text3("End time"); wifiManager.addParameter(&text1); wifiManager.addParameter(&ntp_host_param); wifiManager.addParameter(&text2); wifiManager.addParameter(&start_time_param); wifiManager.addParameter(&text3); wifiManager.addParameter(&end_time_param); wifiManager.setSaveConfigCallback(saveConfigCallback); shouldSaveConfig = false; if (manualConfig) { digitalWrite(PIN_LED_Y, LED_ON); wifiManager.startConfigPortal("ESP_WiFi_Configure"); } else { wifiManager.setAPCallback(configModeCallback); wifiManager.autoConnect("ESP_WiFi_Configure"); } digitalWrite(PIN_LED_Y, LED_OFF); Serial.println("Connected to wifi"); printWifiStatus(); strncpy(ntp_host, ntp_host_param.getValue(), sizeof(ntp_host) - 1); ntp_host[sizeof(ntp_host) - 1] = 0; strncpy(start_time, start_time_param.getValue(), sizeof(start_time) - 1); start_time[sizeof(start_time) - 1] = 0; strncpy(end_time, end_time_param.getValue(), sizeof(end_time) - 1); end_time[sizeof(end_time) - 1] = 0; Serial.print("ntp_host = "); Serial.println(ntp_host); Serial.print("start_time = "); Serial.println(start_time); Serial.print("end_time = "); Serial.println(end_time); if (shouldSaveConfig) { f = SPIFFS.open("/auxinfo.txt", "w"); if (f) { f.print(ntp_host); f.print("\n"); f.print(start_time); f.print("\n"); f.print(end_time); f.print("\n"); f.close(); } } char *p; start_time_minutes = strtol(start_time, &p, 0) * 60; if (p != NULL) start_time_minutes += strtol(p, NULL, 0); start_time_minutes = start_time_minutes % 1440; if (start_time_minutes < 0) start_time_minutes += 1440; end_time_minutes = strtol(end_time, &p, 0) * 60; if (p != NULL) end_time_minutes += strtol(p, NULL, 0); end_time_minutes = end_time_minutes % 1440; if (end_time_minutes < 0) end_time_minutes += 1440; delay(5000); NtpClientSetup(); timePrint(); setupTimeCode(); int h = hour(); int m = minute() + h * 60; Serial.print("start_time_minutes = "); Serial.println(start_time_minutes); Serial.print("end_time_minutes = "); Serial.println(end_time_minutes); Serial.print("m = "); Serial.println(m); if ((start_time_minutes < end_time_minutes && (m < start_time_minutes || m > end_time_minutes)) || (start_time_minutes > end_time_minutes && (m > end_time_minutes && m < start_time_minutes))) { // The time is out of range: we will go to sleep m = start_time_minutes - m; // time to sleep (in minutes) if (m < 0) m += 1440; // Roll over sleep_sec = (long)m * 60L; goto deep_sleep; } ticker.attach_ms(1, timeCodeEvent); } void loop() { if (minute() == 30) { if (millis() - lastNTPTime > 50 * 60 * 1000L) { timePrint(); NtpUpdate(); lastNTPTime = millis(); } } if (second() == 0 && minute() % 10 == 0) timePrint(); delay(10); }