#include #include //this needs to be first, or it all crashes and burns... #include #include //https://github.com/esp8266/Arduino #include //needed for library #include #include #include #include #include #include "SevenSegmentClock.h" // NTP WiFiUDP ntpUDP; // You can specify the time server pool and the offset (in seconds, can be // changed later with setTimeOffset() ). Additionaly you can specify the // update interval (in milliseconds, can be changed using setUpdateInterval() ). NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 3600, 60000); #define MODE_DEMO 1 #define MODE_REALCLOCK 2 #define MODE_FASTCLOCK 3 static int appMode = MODE_REAL; static const char *appName = "FastclockClient7Seg"; #define MAX_CLOCK_NAME_LEN 16 #define MAX_CLOCK_CHANNEL_STRING_LEN 3 #define MAX_CLOCK_COLOR_LEN 16 #define DEFAULT_CLOCK_NAME "fastclk" #define DEFAULT_CLOCK_CHANNEL_STRING "1" #define DEFAULT_CLOCK_CHANNEL 1 #define DEFAULT_CLOCK_COLOR "blue" SevenSegmentClock sevenSegmentClock; ESP8266WebServer *server; char static_ip[16] = "10.0.1.56"; char static_gw[16] = "10.0.1.1"; char static_sn[16] = "255.255.255.0"; static struct ColorSelection { uint8_t id; SevenSegmentClock::Color colorHandle; String colorName; } colorSelection[] = { { 1, SevenSegmentClock::Black, "black" }, { 2, SevenSegmentClock::Blue, "blue" }, { 3, SevenSegmentClock::Red, "red" }, { 4, SevenSegmentClock::Green, "green" }, { 5, SevenSegmentClock::White, "white" }, { 6, SevenSegmentClock::Yellow, "yellow" } }; static const String getColorName(uint8_t color) { for (unsigned int i=0; i{v}"; const char _STYLE[] PROGMEM = ""; const char _SCRIPT[] PROGMEM = ""; const char _HEAD_END[] PROGMEM = "
"; const char _PORTAL_OPTIONS[] PROGMEM = "



"; const char _ITEM[] PROGMEM = "
{v} {r}%
"; const char _FORM_START[] PROGMEM = "
"; const char _FORM_CLOCKNAME[] PROGMEM = "
"; const char _FORM_CLOCKMODE_HEADLINE[] PROGMEM = "
Clock mode:
"; const char _FORM_CLOCKMODE_DEMO[] PROGMEM = "
"; const char _FORM_CLOCKMODE_REAL[] PROGMEM = "
"; const char _FORM_CLOCKMODE_FAST[] PROGMEM = "
"; const char _FORM_PARAM[] PROGMEM = "
"; const char _FORM_COLOR_HEADLINE[] PROGMEM = "
Display color:
"; const char _FORM_COLOR_BLUE[] PROGMEM = "
"; const char _FORM_COLOR_RED[] PROGMEM = "
"; const char _FORM_COLOR_GREEN[] PROGMEM = "
"; const char _FORM_COLOR_WHITE[] PROGMEM = "
"; const char _FORM_COLOR_YELLOW[] PROGMEM = "
"; const char _FORM_BRIGHTNESS[] PROGMEM = "

"; const char _FORM_END[] PROGMEM = "
"; const char _SCAN_LINK[] PROGMEM = "
"; const char _SAVED[] PROGMEM = "
Credentials Saved
Trying to connect ESP to network.
If it fails reconnect to AP to try again
"; const char _END[] PROGMEM = "
"; void appConfig() { String page = FPSTR(_HEAD); String input; String value; page.replace("{v}", "7Seg Config"); page += FPSTR(_SCRIPT); page += FPSTR(_STYLE); //page += _customHeadElement; page += FPSTR(_HEAD_END); page += String(F("

")); page += appName; page += String(F("

")); page += String(F("

Clock Options

")); //page += FPSTR(_PORTAL_OPTIONS); page += FPSTR(_FORM_START); page += FPSTR(_FORM_CLOCKMODE_HEADLINE); input = FPSTR(_FORM_CLOCKMODE_DEMO); input.replace("{check}", (appMode == MODE_DEMO) ? "checked" : ""); page += input; input = FPSTR(_FORM_CLOCKMODE_REAL); input.replace("{check}", (appMode == MODE_REALCLOCK) ? "checked" : ""); page += input; input = FPSTR(_FORM_CLOCKMODE_FAST); input.replace("{check}", (appMode == MODE_FASTCLOCK) ? "checked" : ""); page += input; page += FPSTR(_FORM_CLOCKNAME); page += FPSTR(_FORM_COLOR_HEADLINE); input = FPSTR(_FORM_COLOR_BLUE); input.replace("{check}", (clockColor == SevenSegmentClock::Blue) ? "checked" : ""); page += input; input = FPSTR(_FORM_COLOR_RED); input.replace("{check}", (clockColor == SevenSegmentClock::Red) ? "checked" : ""); page += input; input = FPSTR(_FORM_COLOR_GREEN); input.replace("{check}", (clockColor == SevenSegmentClock::Green) ? "checked" : ""); page += input; input = FPSTR(_FORM_COLOR_YELLOW); input.replace("{check}", (clockColor == SevenSegmentClock::Yellow) ? "checked" : ""); page += input; input = FPSTR(_FORM_COLOR_WHITE); input.replace("{check}", (clockColor == SevenSegmentClock::White) ? "checked" : ""); page += input; input = FPSTR(_FORM_BRIGHTNESS); value = String(sevenSegmentClock.getBrightness()); input.replace("{bright}", value); page += input; page += FPSTR(_FORM_END); page += FPSTR(_END); server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); } void appConfigSave() { String page = FPSTR(_HEAD); Serial.print("appConfigSave "); Serial.print(server->args()); Serial.println(" arguments"); for (int i=0; iargs(); ++i) { Serial.print(server->argName(i)); Serial.print(": "); Serial.println(server->arg(i)); } if (server->hasArg("b")) { sevenSegmentClock.setBrightness(server->arg("b").toInt()); } if (server->hasArg("c")) { String colorName = server->arg("c"); SevenSegmentClock::Color colorHandle = getColorHandleByName(server->arg("c")); sevenSegmentClock.setColor(colorHandle); } if (server->hasArg("m")) { Serial.print("setting clock mode to "); Serial.println(server->arg("m")); if (server->arg("m").equals("real")) appMode = MODE_REALCLOCK; else if (server->arg("m").equals("fast")) appMode = MODE_FASTCLOCK; else if (server->arg("m").equals("demo")) appMode = MODE_DEMO; else { Serial.println("ERROR: Unknown application mode, going into demo mode"); appMode = MODE_DEMO; } } page.replace("{v}", "7Seg Config"); page += FPSTR(_SCRIPT); page += FPSTR(_STYLE); //page += _customHeadElement; page += FPSTR(_HEAD_END); page += String(F("

")); page += appName; page += String(F("

")); page += String(F("
Configuration updated.
")); page += FPSTR(_END); server->sendHeader("Content-Length", String(page.length())); server->send(200, "text/html", page); } void setup() { Serial.begin(115200); Serial.println("---"); Serial.print("Starting *** "); Serial.println(appName); Serial.print("Reset reason: "); Serial.println(ESP.getResetReason()); //clean FS, for testing //SPIFFS.format(); //read configuration from FS json Serial.println("mounting FS..."); if (SPIFFS.begin()) { Serial.println("mounted file system"); if (SPIFFS.exists("/config.json")) { //file exists, reading and loading Serial.println("reading config file"); File configFile = SPIFFS.open("/config.json", "r"); if (configFile) { Serial.println("opened config file"); size_t size = configFile.size(); // Allocate a buffer to store contents of the file. std::unique_ptr buf(new char[size]); configFile.readBytes(buf.get(), size); DynamicJsonDocument config(2048); //JsonObject json = jsonBuffer.createObject(); DeserializationError error = deserializeJson(config, configFile); serializeJson(config, Serial); if (!error) { Serial.println("\nparsed json"); //**strcpy(mqtt_server, json["mqtt_server"]); //**strcpy(mqtt_port, json["mqtt_port"]); //strcpy(blynk_token, json["blynk_token"]); if (config["clock_name"]) { strncpy(clockName, config["clock_name"], MAX_CLOCK_NAME_LEN); } else { Serial.println("no clock name in config"); } if (config["clock_channel"]) { strncpy(clockChannelString, config["clock_channel"], MAX_CLOCK_CHANNEL_STRING_LEN); } else { Serial.println("no clock channel in config"); } if (config["clock_color"]) { //strncpy(clockColor, config["clock_color"], MAX_CLOCK_COLOR_LEN); clockColor = getColorHandle(config["clock_color"]); } else { Serial.println("no clock color in config"); } #if 0 if (json["ip"]) { Serial.print("setting custom ip from config: "); //**strcpy(static_ip, json["ip"]); //**strcpy(static_gw, json["gateway"]); //**strcpy(static_sn, json["subnet"]); Serial.println(static_ip); /* Serial.println("converting ip"); IPAddress ip = ipFromCharArray(static_ip); Serial.println(ip);*/ } else { Serial.println("no custom ip in config"); } #endif } else { Serial.println("failed to load json config, using defaults"); strncpy(clockName, DEFAULT_CLOCK_NAME, MAX_CLOCK_NAME_LEN); strncpy(clockChannelString, DEFAULT_CLOCK_CHANNEL_STRING, MAX_CLOCK_CHANNEL_STRING_LEN); //strncpy(clockColor, DEFAULT_CLOCK_COLOR, MAX_CLOCK_COLOR_LEN); clockColor = SevenSegmentClock::Blue; } } } else { Serial.println("no config file found"); } } else { Serial.println("failed to mount FS"); } //end read Serial.print("static ip: "); Serial.println(static_ip); // setupWifiConnection(); /* radio.setClockChannel(clockChannel); radio.setClockName(clockName); radio.begin(); fastclock.begin(); pinMode(POWER_OFF_PIN, INPUT); */ setupWifiConnection(); Serial.println("Starting NTP Client"); timeClient.begin(); Serial.println("Have following configuration:"); Serial.print(" Clock name: "); Serial.println(clockName); Serial.print(" Clock channel: "); Serial.println(clockChannelString); Serial.print(" Clock color: "); Serial.println(getColorName(clockColor)); Serial.println("Starting 7-segment clock display ..."); sevenSegmentClock.begin(); // setting up web server for clock configuration server = new ESP8266WebServer(80); server->on("/config", HTTP_GET, appConfig); server->on("/configsave", HTTP_GET, appConfigSave); server->begin(); } int hours = 0, minutes = 0; uint32_t nextUpdate_ms = 0; void loop() { timeClient.update(); //Serial.println(timeClient.getFormattedTime()); switch (appMode) { case MODE_DEMO: if (millis() > nextUpdate_ms) { nextUpdate_ms = millis() + 1000; minutes++; if (minutes > 99) { minutes = 0; } if (minutes % 5 == 0) hours++; if (hours > 99) hours = 0; sevenSegmentClock.displayTime(hours, minutes); if (hours % 4 == 0) sevenSegmentClock.setBlinkMode(SevenSegmentClock::SeperatorBlinking); else sevenSegmentClock.setBlinkMode(SevenSegmentClock::NoBlinking); } break; case MODE_REALCLOCK: sevenSegmentClock.displayTime(timeClient.getHours(), timeClient.getMinutes()); break; case MODE_FASTCLOCK: break; } sevenSegmentClock.displayUpdate(); server->handleClient(); }