From 59c2023b2709db0c174785c53d28a691cb46a720 Mon Sep 17 00:00:00 2001 From: Chrome Legion Date: Wed, 9 May 2018 21:47:54 -0700 Subject: [PATCH] Qrome - fixed bug that didn't load the printer data on boot --- printermonitor/printermonitor.ino | 1698 ++++++++++++++--------------- 1 file changed, 849 insertions(+), 849 deletions(-) diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index bed3409..79d64fa 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -1,850 +1,850 @@ - /** The MIT License (MIT) - -Copyright (c) 2018 David Payne - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - - /********************************************** - * Edit Settings.h for personalization - ***********************************************/ - -#include "Settings.h" - -#define VERSION "1.2" - -#define HOSTNAME "ESP8266-" -#define CONFIG "/conf.txt" - -/* Useful Constants */ -#define SECS_PER_MIN (60UL) -#define SECS_PER_HOUR (3600UL) -#define SECS_PER_DAY (SECS_PER_HOUR * 24L) - -/* Useful Macros for getting elapsed time */ -#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) -#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) -#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) -#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) - -// Initialize the oled display for I2C_DISPLAY_ADDRESS -// SDA_PIN and SCL_PIN -SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SCL_PIN); -OLEDDisplayUi ui( &display ); - -void drawProgress(OLEDDisplay *display, int percentage, String label); -void drawOtaProgress(unsigned int, unsigned int); -void drawScreen1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); -void drawScreen2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); -void drawScreen3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); -void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state); -void drawClock(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); -void drawClockHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state); - -// Set the number of Frames supported -const int numberOfFrames = 3; -FrameCallback frames[numberOfFrames]; -FrameCallback clockFrame[1]; -boolean isClockOn = false; - -OverlayCallback overlays[] = { drawHeaderOverlay }; -OverlayCallback clockOverlay[] = { drawClockHeaderOverlay }; -int numberOfOverlays = 1; - -// Time -TimeClient timeClient(UtcOffset); -long lastEpoch = 0; -long firstEpoch = 0; -long displayOffEpoch = 0; -String lastMinute = "xx"; -String lastSecond = "xx"; -String lastReportStatus = ""; -boolean displayOn = true; - -// OctoPrint Client -OctoPrintClient printerClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort); -int printerCount = 0; - -//declairing prototypes -void configModeCallback (WiFiManager *myWiFiManager); -int8_t getWifiQuality(); - -ESP8266WebServer server(WEBSERVER_PORT); - -const String WEB_ACTIONS = " Home" - " Configure" - " Reset Settings" - " Forget WiFi" - " About"; - -const String CHANGE_FORM = "

Station Config:

" - "" - "" - "" - " Display Clock when printer is off

" - "Time Refresh (minutes)

" - "Theme Color

" - "" - "" - "" - "
"; - -const String COLOR_THEMES = "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - ""; - - -// Change the externalLight to the pin you wish to use if other than the Built-in LED -int externalLight = LED_BUILTIN; // LED_BUILTIN is is the built in LED on the Wemos - -void setup() { - Serial.begin(115200); - SPIFFS.begin(); - delay(10); - - //New Line to clear from start garbage - Serial.println(); - - // Initialize digital pin for LED (little blue light on the Wemos D1 Mini) - pinMode(externalLight, OUTPUT); - - readSettings(); - - // initialize dispaly - display.init(); - display.clear(); - display.display(); - - //display.flipScreenVertically(); - display.setFont(ArialMT_Plain_16); - display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setContrast(255); // default is 255 - display.drawString(64, 5, "Printer Monitor\nBy Qrome\nV" + String(VERSION)); - display.display(); - - //WiFiManager - //Local intialization. Once its business is done, there is no need to keep it around - WiFiManager wifiManager; - - // Uncomment for testing wifi manager - //wifiManager.resetSettings(); - wifiManager.setAPCallback(configModeCallback); - - //or use this for auto generated name ESP + ChipID - wifiManager.autoConnect(); - - //Manual Wifi - String hostname(HOSTNAME); - hostname += String(ESP.getChipId(), HEX); - WiFi.hostname(hostname); - - int cnt = 0; - while (WiFi.status() != WL_CONNECTED) { - digitalWrite(externalLight, LOW); - delay(500); - Serial.print("."); - cnt++; - digitalWrite(externalLight, HIGH); - } - - // You can change the transition that is used - // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN - ui.setFrameAnimation(SLIDE_LEFT); - ui.setTargetFPS(30); - ui.disableAllIndicators(); - ui.setFrames(frames, (numberOfFrames)); - frames[0] = drawScreen1; - frames[1] = drawScreen2; - frames[2] = drawScreen3; - clockFrame[0] = drawClock; - ui.setOverlays(overlays, numberOfOverlays); - - // Inital UI takes care of initalising the display too. - ui.init(); - - // print the received signal strength: - Serial.print("Signal Strength (RSSI): "); - Serial.print(getWifiQuality()); - Serial.println("%"); - - if (ENABLE_OTA) { - ArduinoOTA.onStart([]() { - Serial.println("Start"); - }); - ArduinoOTA.onEnd([]() { - Serial.println("\nEnd"); - }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - Serial.printf("Progress: %u%%\r", (progress / (total / 100))); - }); - ArduinoOTA.onError([](ota_error_t error) { - Serial.printf("Error[%u]: ", error); - if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); - else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); - else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); - else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); - else if (error == OTA_END_ERROR) Serial.println("End Failed"); - }); - ArduinoOTA.begin(); - } - - if (WEBSERVER_ENABLED) { - server.on("/", displayPrinterStatus); - server.on("/systemreset", handleSystemReset); - server.on("/forgetwifi", handleWifiReset); - server.on("/updateconfig", handleUpdateConfig); - server.on("/configure", handleConfigure); - server.onNotFound(redirectHome); - // Start the server - server.begin(); - Serial.println("Server started"); - // Print the IP address - String webAddress = "http://" + WiFi.localIP().toString() + ":" + String(WEBSERVER_PORT) + "/"; - Serial.println("Use this URL : " + webAddress); - display.clear(); - display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setFont(ArialMT_Plain_10); - display.drawString(64, 10, "Web Interface On"); - display.drawString(64, 20, "You May Connect to IP"); - display.setFont(ArialMT_Plain_16); - display.drawString(64, 30, WiFi.localIP().toString()); - display.drawString(64, 46, "Port: " + String(WEBSERVER_PORT)); - display.display(); - } else { - Serial.println("Web Interface is Disabled"); - display.clear(); - display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setFont(ArialMT_Plain_10); - display.drawString(64, 10, "Web Interface is Off"); - display.drawString(64, 20, "Enable in Settings.h"); - display.display(); - } - - flashLED(5, 500); -} - -//************************************************************ -// Main Looop -//************************************************************ -void loop() { - - //Get Time Update - if((getMinutesFromLastRefresh() >= minutesBetweenDataRefresh) || lastEpoch == 0) { - getUpdateTime(); - } - - if (lastMinute != timeClient.getMinutes() && !printerClient.isPrinting()) { - // Check status every 60 seconds - digitalWrite(externalLight, LOW); - lastMinute = timeClient.getMinutes(); // reset the check value - printerClient.getPrinterJobResults(); - digitalWrite(externalLight, HIGH); - } else if (printerClient.isPrinting()) { - if (lastSecond != timeClient.getSeconds() && timeClient.getSeconds().endsWith("0")) { - lastSecond = timeClient.getSeconds(); - // every 10 seconds while printing get an update - digitalWrite(externalLight, LOW); - printerClient.getPrinterJobResults(); - digitalWrite(externalLight, HIGH); - } - } - - checkDisplay(); // Check to see if the printer is on or offline and change display. - - ui.update(); - - if (WEBSERVER_ENABLED) { - server.handleClient(); - } - if (ENABLE_OTA) { - ArduinoOTA.handle(); - } -} - -void getUpdateTime() { - digitalWrite(externalLight, LOW); // turn on the LED - Serial.println(); - - Serial.println("Updating Time..."); - //Update the Time - timeClient.updateTime(); - lastEpoch = timeClient.getCurrentEpoch(); - Serial.println("Local time: " + timeClient.getAmPmFormattedTime()); - - digitalWrite(externalLight, HIGH); // turn off the LED -} - -void handleSystemReset() { - if (!server.authenticate(www_username, www_password)) { - return server.requestAuthentication(); - } - Serial.println("Reset System Configuration"); - if (SPIFFS.remove(CONFIG)) { - redirectHome(); - ESP.restart(); - } -} - -void handleUpdateConfig() { - if (!server.authenticate(www_username, www_password)) { - return server.requestAuthentication(); - } - OctoPrintApiKey = server.arg("octoPrintApiKey"); - OctoPrintServer = server.arg("octoPrintAddress"); - OctoPrintPort = server.arg("octoPrintPort").toInt(); - DISPLAYCLOCK = server.hasArg("isClockEnabled"); - minutesBetweenDataRefresh = server.arg("refresh").toInt(); - themeColor = server.arg("theme"); - UtcOffset = server.arg("utcoffset").toFloat(); - String temp = server.arg("userid"); - temp.toCharArray(www_username, sizeof(temp)); - temp = server.arg("stationpassword"); - temp.toCharArray(www_password, sizeof(temp)); - writeSettings(); - printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort); - printerClient.getPrinterJobResults(); - checkDisplay(); - lastEpoch = 0; - redirectHome(); -} - -void handleWifiReset() { - if (!server.authenticate(www_username, www_password)) { - return server.requestAuthentication(); - } - //WiFiManager - //Local intialization. Once its business is done, there is no need to keep it around - redirectHome(); - WiFiManager wifiManager; - wifiManager.resetSettings(); - ESP.restart(); -} - -void handleConfigure() { - if (!server.authenticate(www_username, www_password)) { - return server.requestAuthentication(); - } - digitalWrite(externalLight, LOW); - String html = ""; - - server.sendHeader("Cache-Control", "no-cache, no-store"); - server.sendHeader("Pragma", "no-cache"); - server.sendHeader("Expires", "-1"); - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - server.send(200, "text/html", ""); - - html = getHeader(); - server.sendContent(html); - - String form = String(CHANGE_FORM); - - form.replace("%OCTOKEY%", OctoPrintApiKey); - form.replace("%OCTOADDRESS%", OctoPrintServer); - form.replace("%OCTOPORT%", String(OctoPrintPort)); - String isClockChecked = ""; - if (DISPLAYCLOCK) { - isClockChecked = "checked='checked'"; - } - form.replace("%IS_CLOCK_CHECKED%", isClockChecked); - String options = ""; - options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<"); - form.replace("%OPTIONS%", options); - String themeOptions = String(COLOR_THEMES); - themeOptions.replace(">"+String(themeColor)+"<", " selected>"+String(themeColor)+"<"); - form.replace("%THEME_OPTIONS%", themeOptions); - form.replace("%UTCOFFSET%", String(UtcOffset)); - form.replace("%USERID%", String(www_username)); - form.replace("%STATIONPASSWORD%", String(www_password)); - - server.sendContent(String(form)); - - html = getFooter(); - server.sendContent(html); - server.sendContent(""); - server.client().stop(); - digitalWrite(externalLight, HIGH); -} - -void displayMessage(String message) { - digitalWrite(externalLight, LOW); - - server.sendHeader("Cache-Control", "no-cache, no-store"); - server.sendHeader("Pragma", "no-cache"); - server.sendHeader("Expires", "-1"); - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - server.send(200, "text/html", ""); - String html = getHeader(); - server.sendContent(String(html)); - server.sendContent(String(message)); - html = getFooter(); - server.sendContent(String(html)); - server.sendContent(""); - server.client().stop(); - - digitalWrite(externalLight, HIGH); -} - -void redirectHome() { - // Send them back to the Root Directory - server.sendHeader("Location", String("/"), true); - server.sendHeader("Cache-Control", "no-cache, no-store"); - server.sendHeader("Pragma", "no-cache"); - server.sendHeader("Expires", "-1"); - server.send(302, "text/plain", ""); - server.client().stop(); -} - -String getHeader() { - return getHeader(false); -} - -String getHeader(boolean refresh) { - String menu = String(WEB_ACTIONS); - - String html = ""; - html += "Printer Monitor"; - html += ""; - if (refresh) { - html += ""; - } - html += ""; - html += ""; - html += ""; - html += ""; - html += ""; - html += "

Printer Monitor

"; - html += ""; - html += "
"; - return html; -} - -String getFooter() { - int8_t rssi = getWifiQuality(); - Serial.print("Signal Strength (RSSI): "); - Serial.print(rssi); - Serial.println("%"); - String html = "


"; - html += "
"; - html += ""; - html += ""; - return html; -} - -void displayPrinterStatus() { - digitalWrite(externalLight, LOW); - String html = ""; - - server.sendHeader("Cache-Control", "no-cache, no-store"); - server.sendHeader("Pragma", "no-cache"); - server.sendHeader("Expires", "-1"); - server.setContentLength(CONTENT_LENGTH_UNKNOWN); - server.send(200, "text/html", ""); - server.sendContent(String(getHeader(true))); - - html += "

Time: " + timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds() + " " + timeClient.getAmPm() + "

"; - html += "

"; - if (printerClient.getError() != "") { - html += "Error: " + printerClient.getError() + "
"; - } - html += "Status: " + printerClient.getState() + "
"; - html += "File: " + printerClient.getFileName() + "
"; - float fileSize = printerClient.getFileSize().toFloat(); - if (fileSize > 0) { - fileSize = fileSize / 1024; - html += "File Size: " + String(fileSize) + "KB
"; - } - int filamentLength = printerClient.getFilamentLength().toInt(); - if (filamentLength > 0) { - float fLength = float(filamentLength) / 1000; - html += "Filament: " + String(fLength) + "m
"; - } - - html += "Tool Temperature: " + printerClient.getTempToolActual() + " C
"; - html += "Bed Temperature: " + printerClient.getTempBedActual() + " C
"; - - int val = printerClient.getProgressPrintTimeLeft().toInt(); - int days = elapsedDays(val); - int hours = numberOfHours(val); - int minutes = numberOfMinutes(val); - int seconds = numberOfSeconds(val); - html += "Est. Print Time Left: " + zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds) + "
"; - - val = printerClient.getProgressPrintTime().toInt(); - days = elapsedDays(val); - hours = numberOfHours(val); - minutes = numberOfMinutes(val); - seconds = numberOfSeconds(val); - html += "Printing Time: " + zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds) + "
"; - html += ""; - html += "

" + printerClient.getProgressCompletion() + "%
"; - html += "

"; - - server.sendContent(String(html)); // spit out what we got - - - server.sendContent(String(getFooter())); - server.sendContent(""); - server.client().stop(); - digitalWrite(externalLight, HIGH); -} - -void configModeCallback (WiFiManager *myWiFiManager) { - Serial.println("Entered config mode"); - Serial.println(WiFi.softAPIP()); - Serial.println("Wifi Manager"); - Serial.println("Please connect to AP"); - Serial.println(myWiFiManager->getConfigPortalSSID()); - Serial.println("To setup Wifi Configuration"); - flashLED(20, 50); -} - -void flashLED(int number, int delayTime) { - for (int inx = 0; inx < number; inx++) { - delay(delayTime); - digitalWrite(externalLight, LOW); - delay(delayTime); - digitalWrite(externalLight, HIGH); - delay(delayTime); - } -} - -void drawScreen1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->setFont(ArialMT_Plain_16); - display->drawString(64 + x, 0 + y, "Bed / Tool Temp"); - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->setFont(ArialMT_Plain_24); - int bed = printerClient.getTempBedActual().toInt(); - int tool = printerClient.getTempToolActual().toInt(); - display->drawString(2 + x, 14 + y, String(bed)); - display->drawString(64 + x, 14 + y, String(tool)); - display->setFont(ArialMT_Plain_16); - display->drawString(38 + x, 14 + y, "C"); - display->drawString(115 + x, 14 + y, "C"); -} - -void drawScreen2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->setFont(ArialMT_Plain_16); - - display->drawString(64 + x, 0 + y, "Time Remaining"); - //display->setTextAlignment(TEXT_ALIGN_LEFT); - display->setFont(ArialMT_Plain_24); - int val = printerClient.getProgressPrintTimeLeft().toInt(); - int days = elapsedDays(val); - int hours = numberOfHours(val); - int minutes = numberOfMinutes(val); - int seconds = numberOfSeconds(val); - - String time = zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds); - display->drawString(64 + x, 14 + y, time); -} - -void drawScreen3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->setFont(ArialMT_Plain_16); - - display->drawString(64 + x, 0 + y, "Printing Time"); - //display->setTextAlignment(TEXT_ALIGN_LEFT); - display->setFont(ArialMT_Plain_24); - int val = printerClient.getProgressPrintTime().toInt(); - int days = elapsedDays(val); - int hours = numberOfHours(val); - int minutes = numberOfMinutes(val); - int seconds = numberOfSeconds(val); - - String time = zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds); - display->drawString(64 + x, 14 + y, time); -} - -void drawClock(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->setFont(ArialMT_Plain_24); - String time = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); - display->drawString(64 + x, 10 + y, time); -} - -String zeroPad(int value) { - String rtnValue = String(value); - if (value < 10) { - rtnValue = "0" + rtnValue; - } - return rtnValue; -} - -void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { - display->setColor(WHITE); - display->setFont(ArialMT_Plain_16); - String time = timeClient.getAmPmHours() + ":" + timeClient.getMinutes(); - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawString(0, 48, time); - String ampm = timeClient.getAmPm(); - display->setFont(ArialMT_Plain_10); - display->drawString(39, 54, ampm); - display->setFont(ArialMT_Plain_16); - display->setTextAlignment(TEXT_ALIGN_LEFT); - String percent = String(printerClient.getProgressCompletion()) + "%"; - display->drawString(64, 48, percent); - - // Draw indicator to show next update - int updatePos = (printerClient.getProgressCompletion().toFloat() / float(100)) * 128; - display->drawRect(0, 41, 128, 6); - display->drawHorizontalLine(0, 42, updatePos); - display->drawHorizontalLine(0, 43, updatePos); - display->drawHorizontalLine(0, 44, updatePos); - display->drawHorizontalLine(0, 45, updatePos); - - drawRssi(display); -} - -void drawClockHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { - display->setColor(WHITE); - display->setFont(ArialMT_Plain_16); - String time = timeClient.getAmPm(); - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawString(0, 48, time); - display->setFont(ArialMT_Plain_16); - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->drawString(64, 48, "offline"); - display->setTextAlignment(TEXT_ALIGN_LEFT); - - display->drawRect(0, 41, 128, 2); - - drawRssi(display); -} - -void drawRssi(OLEDDisplay *display) { - - - int8_t quality = getWifiQuality(); - for (int8_t i = 0; i < 4; i++) { - for (int8_t j = 0; j < 3 * (i + 2); j++) { - if (quality > i * 25 || j == 0) { - display->setPixel(114 + 4 * i, 63 - j); - } - } - } -} - -// converts the dBm to a range between 0 and 100% -int8_t getWifiQuality() { - int32_t dbm = WiFi.RSSI(); - if(dbm <= -100) { - return 0; - } else if(dbm >= -50) { - return 100; - } else { - return 2 * (dbm + 100); - } -} - - -void writeSettings() { - // Save decoded message to SPIFFS file for playback on power up. - File f = SPIFFS.open(CONFIG, "w"); - if (!f) { - Serial.println("File open failed!"); - } else { - Serial.println("Saving settings now..."); - f.println("UtcOffset=" + String(UtcOffset)); - f.println("octoKey=" + OctoPrintApiKey); - f.println("octoServer=" + OctoPrintServer); - f.println("octoPort=" + String(OctoPrintPort)); - f.println("refreshRate=" + String(minutesBetweenDataRefresh)); - f.println("themeColor=" + themeColor); - f.println("www_username=" + String(www_username)); - f.println("www_password=" + String(www_password)); - f.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); - } - f.close(); - readSettings(); - timeClient.setUtcOffset(UtcOffset); -} - -void readSettings() { - if (SPIFFS.exists(CONFIG) == false) { - Serial.println("Settings File does not yet exists."); - writeSettings(); - return; - } - File fr = SPIFFS.open(CONFIG, "r"); - String line; - while(fr.available()) { - line = fr.readStringUntil('\n'); - - if (line.indexOf("UtcOffset=") >= 0) { - UtcOffset = line.substring(line.lastIndexOf("UtcOffset=") + 10).toFloat(); - Serial.println("UtcOffset=" + String(UtcOffset)); - } - if (line.indexOf("octoKey=") >= 0) { - OctoPrintApiKey = line.substring(line.lastIndexOf("octoKey=") + 8); - OctoPrintApiKey.trim(); - Serial.println("OctoPrintApiKey=" + OctoPrintApiKey); - } - if (line.indexOf("octoServer=") >= 0) { - OctoPrintServer = line.substring(line.lastIndexOf("octoServer=") + 11); - OctoPrintServer.trim(); - Serial.println("OctoPrintServer=" + OctoPrintServer); - } - if (line.indexOf("octoPort=") >= 0) { - OctoPrintPort = line.substring(line.lastIndexOf("octoPort=") + 9).toInt(); - Serial.println("OctoPrintPort=" + String(OctoPrintPort)); - } - if (line.indexOf("refreshRate=") >= 0) { - minutesBetweenDataRefresh = line.substring(line.lastIndexOf("refreshRate=") + 12).toInt(); - Serial.println("minutesBetweenDataRefresh=" + String(minutesBetweenDataRefresh)); - } - if (line.indexOf("themeColor=") >= 0) { - themeColor = line.substring(line.lastIndexOf("themeColor=") + 11); - themeColor.trim(); - Serial.println("themeColor=" + themeColor); - } - if (line.indexOf("www_username=") >= 0) { - String temp = line.substring(line.lastIndexOf("www_username=") + 13); - temp.trim(); - temp.toCharArray(www_username, sizeof(temp)); - Serial.println("www_username=" + String(www_username)); - } - if (line.indexOf("www_password=") >= 0) { - String temp = line.substring(line.lastIndexOf("www_password=") + 13); - temp.trim(); - temp.toCharArray(www_password, sizeof(temp)); - Serial.println("www_password=" + String(www_password)); - } - if (line.indexOf("DISPLAYCLOCK=") >= 0) { - DISPLAYCLOCK = line.substring(line.lastIndexOf("DISPLAYCLOCK=") + 13).toInt(); - Serial.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); - } - } - fr.close(); - timeClient.setUtcOffset(UtcOffset); -} - -int getMinutesFromLastRefresh() { - int minutes = (timeClient.getCurrentEpoch() - lastEpoch) / 60; - return minutes; -} - -int getMinutesFromLastDisplay() { - int minutes = (timeClient.getCurrentEpoch() - displayOffEpoch) / 60; - return minutes; -} - -// Toggle on and off the display if user defined times -void checkDisplay() { - if (!displayOn && DISPLAYCLOCK) { - enableDisplay(true); - } - if (displayOn && !(printerClient.isOperational() || printerClient.isPrinting()) && !DISPLAYCLOCK) { - // Put Display to sleep - display.clear(); - display.display(); - display.setFont(ArialMT_Plain_16); - display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setContrast(255); // default is 255 - display.drawString(64, 5, "Printer Offline\nSleep Mode..."); - display.display(); - delay(5000); - enableDisplay(false); - Serial.println("Printer is offline going down to sleep..."); - return; - } else if (!displayOn && !DISPLAYCLOCK) { - if (printerClient.isOperational()) { - // Wake the Screen up - enableDisplay(true); - display.clear(); - display.display(); - display.setFont(ArialMT_Plain_16); - display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setContrast(255); // default is 255 - display.drawString(64, 5, "Printer Online\nWake up..."); - display.display(); - Serial.println("Printer is online waking up..."); - delay(5000); - return; - } - } else if (DISPLAYCLOCK) { - if (!printerClient.isOperational() && !isClockOn) { - Serial.println("Clock Mode is turned on."); - ui.disableAutoTransition(); - ui.setFrames(clockFrame, 1); - clockFrame[0] = drawClock; - ui.setOverlays(clockOverlay, numberOfOverlays); - isClockOn = true; - } else if (printerClient.isOperational() && isClockOn) { - Serial.println("Printer Monitor is active."); - ui.setFrames(frames, numberOfFrames); - ui.setOverlays(overlays, numberOfOverlays); - ui.enableAutoTransition(); - isClockOn = false; - } - } -} - -void enableDisplay(boolean enable) { - displayOn = enable; - if (enable) { - if (getMinutesFromLastDisplay() >= minutesBetweenDataRefresh) { - // The display has been off longer than the minutes between refresh -- need to get fresh data - lastEpoch = 0; // this should force a data pull - displayOffEpoch = 0; // reset - } - display.displayOn(); - Serial.println("Display was turned ON: " + timeClient.getFormattedTime()); - } else { - display.displayOff(); - Serial.println("Display was turned OFF: " + timeClient.getFormattedTime()); - displayOffEpoch = lastEpoch; - } + /** The MIT License (MIT) + +Copyright (c) 2018 David Payne + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + + /********************************************** + * Edit Settings.h for personalization + ***********************************************/ + +#include "Settings.h" + +#define VERSION "1.2" + +#define HOSTNAME "ESP8266-" +#define CONFIG "/conf.txt" + +/* Useful Constants */ +#define SECS_PER_MIN (60UL) +#define SECS_PER_HOUR (3600UL) +#define SECS_PER_DAY (SECS_PER_HOUR * 24L) + +/* Useful Macros for getting elapsed time */ +#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) +#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) +#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) +#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) + +// Initialize the oled display for I2C_DISPLAY_ADDRESS +// SDA_PIN and SCL_PIN +SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SCL_PIN); +OLEDDisplayUi ui( &display ); + +void drawProgress(OLEDDisplay *display, int percentage, String label); +void drawOtaProgress(unsigned int, unsigned int); +void drawScreen1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); +void drawScreen2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); +void drawScreen3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); +void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state); +void drawClock(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); +void drawClockHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state); + +// Set the number of Frames supported +const int numberOfFrames = 3; +FrameCallback frames[numberOfFrames]; +FrameCallback clockFrame[1]; +boolean isClockOn = false; + +OverlayCallback overlays[] = { drawHeaderOverlay }; +OverlayCallback clockOverlay[] = { drawClockHeaderOverlay }; +int numberOfOverlays = 1; + +// Time +TimeClient timeClient(UtcOffset); +long lastEpoch = 0; +long firstEpoch = 0; +long displayOffEpoch = 0; +String lastMinute = "xx"; +String lastSecond = "xx"; +String lastReportStatus = ""; +boolean displayOn = true; + +// OctoPrint Client +OctoPrintClient printerClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort); +int printerCount = 0; + +//declairing prototypes +void configModeCallback (WiFiManager *myWiFiManager); +int8_t getWifiQuality(); + +ESP8266WebServer server(WEBSERVER_PORT); + +const String WEB_ACTIONS = " Home" + " Configure" + " Reset Settings" + " Forget WiFi" + " About"; + +const String CHANGE_FORM = "

Station Config:

" + "" + "" + "" + " Display Clock when printer is off

" + "Time Refresh (minutes)

" + "Theme Color

" + "" + "" + "" + "
"; + +const String COLOR_THEMES = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + +// Change the externalLight to the pin you wish to use if other than the Built-in LED +int externalLight = LED_BUILTIN; // LED_BUILTIN is is the built in LED on the Wemos + +void setup() { + Serial.begin(115200); + SPIFFS.begin(); + delay(10); + + //New Line to clear from start garbage + Serial.println(); + + // Initialize digital pin for LED (little blue light on the Wemos D1 Mini) + pinMode(externalLight, OUTPUT); + + readSettings(); + + // initialize dispaly + display.init(); + display.clear(); + display.display(); + + //display.flipScreenVertically(); + display.setFont(ArialMT_Plain_16); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setContrast(255); // default is 255 + display.drawString(64, 5, "Printer Monitor\nBy Qrome\nV" + String(VERSION)); + display.display(); + + //WiFiManager + //Local intialization. Once its business is done, there is no need to keep it around + WiFiManager wifiManager; + + // Uncomment for testing wifi manager + //wifiManager.resetSettings(); + wifiManager.setAPCallback(configModeCallback); + + //or use this for auto generated name ESP + ChipID + wifiManager.autoConnect(); + + //Manual Wifi + String hostname(HOSTNAME); + hostname += String(ESP.getChipId(), HEX); + WiFi.hostname(hostname); + + int cnt = 0; + while (WiFi.status() != WL_CONNECTED) { + digitalWrite(externalLight, LOW); + delay(500); + Serial.print("."); + cnt++; + digitalWrite(externalLight, HIGH); + } + + // You can change the transition that is used + // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN + ui.setFrameAnimation(SLIDE_LEFT); + ui.setTargetFPS(30); + ui.disableAllIndicators(); + ui.setFrames(frames, (numberOfFrames)); + frames[0] = drawScreen1; + frames[1] = drawScreen2; + frames[2] = drawScreen3; + clockFrame[0] = drawClock; + ui.setOverlays(overlays, numberOfOverlays); + + // Inital UI takes care of initalising the display too. + ui.init(); + + // print the received signal strength: + Serial.print("Signal Strength (RSSI): "); + Serial.print(getWifiQuality()); + Serial.println("%"); + + if (ENABLE_OTA) { + ArduinoOTA.onStart([]() { + Serial.println("Start"); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nEnd"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) Serial.println("End Failed"); + }); + ArduinoOTA.begin(); + } + + if (WEBSERVER_ENABLED) { + server.on("/", displayPrinterStatus); + server.on("/systemreset", handleSystemReset); + server.on("/forgetwifi", handleWifiReset); + server.on("/updateconfig", handleUpdateConfig); + server.on("/configure", handleConfigure); + server.onNotFound(redirectHome); + // Start the server + server.begin(); + Serial.println("Server started"); + // Print the IP address + String webAddress = "http://" + WiFi.localIP().toString() + ":" + String(WEBSERVER_PORT) + "/"; + Serial.println("Use this URL : " + webAddress); + display.clear(); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setFont(ArialMT_Plain_10); + display.drawString(64, 10, "Web Interface On"); + display.drawString(64, 20, "You May Connect to IP"); + display.setFont(ArialMT_Plain_16); + display.drawString(64, 30, WiFi.localIP().toString()); + display.drawString(64, 46, "Port: " + String(WEBSERVER_PORT)); + display.display(); + } else { + Serial.println("Web Interface is Disabled"); + display.clear(); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setFont(ArialMT_Plain_10); + display.drawString(64, 10, "Web Interface is Off"); + display.drawString(64, 20, "Enable in Settings.h"); + display.display(); + } + + flashLED(5, 500); +} + +//************************************************************ +// Main Looop +//************************************************************ +void loop() { + + //Get Time Update + if((getMinutesFromLastRefresh() >= minutesBetweenDataRefresh) || lastEpoch == 0) { + getUpdateTime(); + } + + if (lastMinute != timeClient.getMinutes() && !printerClient.isPrinting()) { + // Check status every 60 seconds + digitalWrite(externalLight, LOW); + lastMinute = timeClient.getMinutes(); // reset the check value + printerClient.getPrinterJobResults(); + digitalWrite(externalLight, HIGH); + } else if (printerClient.isPrinting()) { + if (lastSecond != timeClient.getSeconds() && timeClient.getSeconds().endsWith("0")) { + lastSecond = timeClient.getSeconds(); + // every 10 seconds while printing get an update + digitalWrite(externalLight, LOW); + printerClient.getPrinterJobResults(); + digitalWrite(externalLight, HIGH); + } + } + + checkDisplay(); // Check to see if the printer is on or offline and change display. + + ui.update(); + + if (WEBSERVER_ENABLED) { + server.handleClient(); + } + if (ENABLE_OTA) { + ArduinoOTA.handle(); + } +} + +void getUpdateTime() { + digitalWrite(externalLight, LOW); // turn on the LED + Serial.println(); + + Serial.println("Updating Time..."); + //Update the Time + timeClient.updateTime(); + lastEpoch = timeClient.getCurrentEpoch(); + Serial.println("Local time: " + timeClient.getAmPmFormattedTime()); + + digitalWrite(externalLight, HIGH); // turn off the LED +} + +void handleSystemReset() { + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + Serial.println("Reset System Configuration"); + if (SPIFFS.remove(CONFIG)) { + redirectHome(); + ESP.restart(); + } +} + +void handleUpdateConfig() { + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + OctoPrintApiKey = server.arg("octoPrintApiKey"); + OctoPrintServer = server.arg("octoPrintAddress"); + OctoPrintPort = server.arg("octoPrintPort").toInt(); + DISPLAYCLOCK = server.hasArg("isClockEnabled"); + minutesBetweenDataRefresh = server.arg("refresh").toInt(); + themeColor = server.arg("theme"); + UtcOffset = server.arg("utcoffset").toFloat(); + String temp = server.arg("userid"); + temp.toCharArray(www_username, sizeof(temp)); + temp = server.arg("stationpassword"); + temp.toCharArray(www_password, sizeof(temp)); + writeSettings(); + printerClient.getPrinterJobResults(); + checkDisplay(); + lastEpoch = 0; + redirectHome(); +} + +void handleWifiReset() { + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + //WiFiManager + //Local intialization. Once its business is done, there is no need to keep it around + redirectHome(); + WiFiManager wifiManager; + wifiManager.resetSettings(); + ESP.restart(); +} + +void handleConfigure() { + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + digitalWrite(externalLight, LOW); + String html = ""; + + server.sendHeader("Cache-Control", "no-cache, no-store"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.setContentLength(CONTENT_LENGTH_UNKNOWN); + server.send(200, "text/html", ""); + + html = getHeader(); + server.sendContent(html); + + String form = String(CHANGE_FORM); + + form.replace("%OCTOKEY%", OctoPrintApiKey); + form.replace("%OCTOADDRESS%", OctoPrintServer); + form.replace("%OCTOPORT%", String(OctoPrintPort)); + String isClockChecked = ""; + if (DISPLAYCLOCK) { + isClockChecked = "checked='checked'"; + } + form.replace("%IS_CLOCK_CHECKED%", isClockChecked); + String options = ""; + options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<"); + form.replace("%OPTIONS%", options); + String themeOptions = String(COLOR_THEMES); + themeOptions.replace(">"+String(themeColor)+"<", " selected>"+String(themeColor)+"<"); + form.replace("%THEME_OPTIONS%", themeOptions); + form.replace("%UTCOFFSET%", String(UtcOffset)); + form.replace("%USERID%", String(www_username)); + form.replace("%STATIONPASSWORD%", String(www_password)); + + server.sendContent(String(form)); + + html = getFooter(); + server.sendContent(html); + server.sendContent(""); + server.client().stop(); + digitalWrite(externalLight, HIGH); +} + +void displayMessage(String message) { + digitalWrite(externalLight, LOW); + + server.sendHeader("Cache-Control", "no-cache, no-store"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.setContentLength(CONTENT_LENGTH_UNKNOWN); + server.send(200, "text/html", ""); + String html = getHeader(); + server.sendContent(String(html)); + server.sendContent(String(message)); + html = getFooter(); + server.sendContent(String(html)); + server.sendContent(""); + server.client().stop(); + + digitalWrite(externalLight, HIGH); +} + +void redirectHome() { + // Send them back to the Root Directory + server.sendHeader("Location", String("/"), true); + server.sendHeader("Cache-Control", "no-cache, no-store"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.send(302, "text/plain", ""); + server.client().stop(); +} + +String getHeader() { + return getHeader(false); +} + +String getHeader(boolean refresh) { + String menu = String(WEB_ACTIONS); + + String html = ""; + html += "Printer Monitor"; + html += ""; + if (refresh) { + html += ""; + } + html += ""; + html += ""; + html += ""; + html += ""; + html += ""; + html += "

Printer Monitor

"; + html += ""; + html += "
"; + return html; +} + +String getFooter() { + int8_t rssi = getWifiQuality(); + Serial.print("Signal Strength (RSSI): "); + Serial.print(rssi); + Serial.println("%"); + String html = "


"; + html += "
"; + html += ""; + html += ""; + return html; +} + +void displayPrinterStatus() { + digitalWrite(externalLight, LOW); + String html = ""; + + server.sendHeader("Cache-Control", "no-cache, no-store"); + server.sendHeader("Pragma", "no-cache"); + server.sendHeader("Expires", "-1"); + server.setContentLength(CONTENT_LENGTH_UNKNOWN); + server.send(200, "text/html", ""); + server.sendContent(String(getHeader(true))); + + html += "

Time: " + timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds() + " " + timeClient.getAmPm() + "

"; + html += "

"; + if (printerClient.getError() != "") { + html += "Error: " + printerClient.getError() + "
"; + } + html += "Status: " + printerClient.getState() + "
"; + html += "File: " + printerClient.getFileName() + "
"; + float fileSize = printerClient.getFileSize().toFloat(); + if (fileSize > 0) { + fileSize = fileSize / 1024; + html += "File Size: " + String(fileSize) + "KB
"; + } + int filamentLength = printerClient.getFilamentLength().toInt(); + if (filamentLength > 0) { + float fLength = float(filamentLength) / 1000; + html += "Filament: " + String(fLength) + "m
"; + } + + html += "Tool Temperature: " + printerClient.getTempToolActual() + " C
"; + html += "Bed Temperature: " + printerClient.getTempBedActual() + " C
"; + + int val = printerClient.getProgressPrintTimeLeft().toInt(); + int days = elapsedDays(val); + int hours = numberOfHours(val); + int minutes = numberOfMinutes(val); + int seconds = numberOfSeconds(val); + html += "Est. Print Time Left: " + zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds) + "
"; + + val = printerClient.getProgressPrintTime().toInt(); + days = elapsedDays(val); + hours = numberOfHours(val); + minutes = numberOfMinutes(val); + seconds = numberOfSeconds(val); + html += "Printing Time: " + zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds) + "
"; + html += ""; + html += "

" + printerClient.getProgressCompletion() + "%
"; + html += "

"; + + server.sendContent(String(html)); // spit out what we got + + + server.sendContent(String(getFooter())); + server.sendContent(""); + server.client().stop(); + digitalWrite(externalLight, HIGH); +} + +void configModeCallback (WiFiManager *myWiFiManager) { + Serial.println("Entered config mode"); + Serial.println(WiFi.softAPIP()); + Serial.println("Wifi Manager"); + Serial.println("Please connect to AP"); + Serial.println(myWiFiManager->getConfigPortalSSID()); + Serial.println("To setup Wifi Configuration"); + flashLED(20, 50); +} + +void flashLED(int number, int delayTime) { + for (int inx = 0; inx < number; inx++) { + delay(delayTime); + digitalWrite(externalLight, LOW); + delay(delayTime); + digitalWrite(externalLight, HIGH); + delay(delayTime); + } +} + +void drawScreen1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_16); + display->drawString(64 + x, 0 + y, "Bed / Tool Temp"); + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_24); + int bed = printerClient.getTempBedActual().toInt(); + int tool = printerClient.getTempToolActual().toInt(); + display->drawString(2 + x, 14 + y, String(bed)); + display->drawString(64 + x, 14 + y, String(tool)); + display->setFont(ArialMT_Plain_16); + display->drawString(38 + x, 14 + y, "C"); + display->drawString(115 + x, 14 + y, "C"); +} + +void drawScreen2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_16); + + display->drawString(64 + x, 0 + y, "Time Remaining"); + //display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_24); + int val = printerClient.getProgressPrintTimeLeft().toInt(); + int days = elapsedDays(val); + int hours = numberOfHours(val); + int minutes = numberOfMinutes(val); + int seconds = numberOfSeconds(val); + + String time = zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds); + display->drawString(64 + x, 14 + y, time); +} + +void drawScreen3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_16); + + display->drawString(64 + x, 0 + y, "Printing Time"); + //display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_24); + int val = printerClient.getProgressPrintTime().toInt(); + int days = elapsedDays(val); + int hours = numberOfHours(val); + int minutes = numberOfMinutes(val); + int seconds = numberOfSeconds(val); + + String time = zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds); + display->drawString(64 + x, 14 + y, time); +} + +void drawClock(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_24); + String time = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); + display->drawString(64 + x, 10 + y, time); +} + +String zeroPad(int value) { + String rtnValue = String(value); + if (value < 10) { + rtnValue = "0" + rtnValue; + } + return rtnValue; +} + +void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { + display->setColor(WHITE); + display->setFont(ArialMT_Plain_16); + String time = timeClient.getAmPmHours() + ":" + timeClient.getMinutes(); + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->drawString(0, 48, time); + String ampm = timeClient.getAmPm(); + display->setFont(ArialMT_Plain_10); + display->drawString(39, 54, ampm); + display->setFont(ArialMT_Plain_16); + display->setTextAlignment(TEXT_ALIGN_LEFT); + String percent = String(printerClient.getProgressCompletion()) + "%"; + display->drawString(64, 48, percent); + + // Draw indicator to show next update + int updatePos = (printerClient.getProgressCompletion().toFloat() / float(100)) * 128; + display->drawRect(0, 41, 128, 6); + display->drawHorizontalLine(0, 42, updatePos); + display->drawHorizontalLine(0, 43, updatePos); + display->drawHorizontalLine(0, 44, updatePos); + display->drawHorizontalLine(0, 45, updatePos); + + drawRssi(display); +} + +void drawClockHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { + display->setColor(WHITE); + display->setFont(ArialMT_Plain_16); + String time = timeClient.getAmPm(); + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->drawString(0, 48, time); + display->setFont(ArialMT_Plain_16); + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->drawString(64, 48, "offline"); + display->setTextAlignment(TEXT_ALIGN_LEFT); + + display->drawRect(0, 41, 128, 2); + + drawRssi(display); +} + +void drawRssi(OLEDDisplay *display) { + + + int8_t quality = getWifiQuality(); + for (int8_t i = 0; i < 4; i++) { + for (int8_t j = 0; j < 3 * (i + 2); j++) { + if (quality > i * 25 || j == 0) { + display->setPixel(114 + 4 * i, 63 - j); + } + } + } +} + +// converts the dBm to a range between 0 and 100% +int8_t getWifiQuality() { + int32_t dbm = WiFi.RSSI(); + if(dbm <= -100) { + return 0; + } else if(dbm >= -50) { + return 100; + } else { + return 2 * (dbm + 100); + } +} + + +void writeSettings() { + // Save decoded message to SPIFFS file for playback on power up. + File f = SPIFFS.open(CONFIG, "w"); + if (!f) { + Serial.println("File open failed!"); + } else { + Serial.println("Saving settings now..."); + f.println("UtcOffset=" + String(UtcOffset)); + f.println("octoKey=" + OctoPrintApiKey); + f.println("octoServer=" + OctoPrintServer); + f.println("octoPort=" + String(OctoPrintPort)); + f.println("refreshRate=" + String(minutesBetweenDataRefresh)); + f.println("themeColor=" + themeColor); + f.println("www_username=" + String(www_username)); + f.println("www_password=" + String(www_password)); + f.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); + } + f.close(); + readSettings(); + timeClient.setUtcOffset(UtcOffset); +} + +void readSettings() { + if (SPIFFS.exists(CONFIG) == false) { + Serial.println("Settings File does not yet exists."); + writeSettings(); + return; + } + File fr = SPIFFS.open(CONFIG, "r"); + String line; + while(fr.available()) { + line = fr.readStringUntil('\n'); + + if (line.indexOf("UtcOffset=") >= 0) { + UtcOffset = line.substring(line.lastIndexOf("UtcOffset=") + 10).toFloat(); + Serial.println("UtcOffset=" + String(UtcOffset)); + } + if (line.indexOf("octoKey=") >= 0) { + OctoPrintApiKey = line.substring(line.lastIndexOf("octoKey=") + 8); + OctoPrintApiKey.trim(); + Serial.println("OctoPrintApiKey=" + OctoPrintApiKey); + } + if (line.indexOf("octoServer=") >= 0) { + OctoPrintServer = line.substring(line.lastIndexOf("octoServer=") + 11); + OctoPrintServer.trim(); + Serial.println("OctoPrintServer=" + OctoPrintServer); + } + if (line.indexOf("octoPort=") >= 0) { + OctoPrintPort = line.substring(line.lastIndexOf("octoPort=") + 9).toInt(); + Serial.println("OctoPrintPort=" + String(OctoPrintPort)); + } + if (line.indexOf("refreshRate=") >= 0) { + minutesBetweenDataRefresh = line.substring(line.lastIndexOf("refreshRate=") + 12).toInt(); + Serial.println("minutesBetweenDataRefresh=" + String(minutesBetweenDataRefresh)); + } + if (line.indexOf("themeColor=") >= 0) { + themeColor = line.substring(line.lastIndexOf("themeColor=") + 11); + themeColor.trim(); + Serial.println("themeColor=" + themeColor); + } + if (line.indexOf("www_username=") >= 0) { + String temp = line.substring(line.lastIndexOf("www_username=") + 13); + temp.trim(); + temp.toCharArray(www_username, sizeof(temp)); + Serial.println("www_username=" + String(www_username)); + } + if (line.indexOf("www_password=") >= 0) { + String temp = line.substring(line.lastIndexOf("www_password=") + 13); + temp.trim(); + temp.toCharArray(www_password, sizeof(temp)); + Serial.println("www_password=" + String(www_password)); + } + if (line.indexOf("DISPLAYCLOCK=") >= 0) { + DISPLAYCLOCK = line.substring(line.lastIndexOf("DISPLAYCLOCK=") + 13).toInt(); + Serial.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); + } + } + fr.close(); + printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort); + timeClient.setUtcOffset(UtcOffset); +} + +int getMinutesFromLastRefresh() { + int minutes = (timeClient.getCurrentEpoch() - lastEpoch) / 60; + return minutes; +} + +int getMinutesFromLastDisplay() { + int minutes = (timeClient.getCurrentEpoch() - displayOffEpoch) / 60; + return minutes; +} + +// Toggle on and off the display if user defined times +void checkDisplay() { + if (!displayOn && DISPLAYCLOCK) { + enableDisplay(true); + } + if (displayOn && !(printerClient.isOperational() || printerClient.isPrinting()) && !DISPLAYCLOCK) { + // Put Display to sleep + display.clear(); + display.display(); + display.setFont(ArialMT_Plain_16); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setContrast(255); // default is 255 + display.drawString(64, 5, "Printer Offline\nSleep Mode..."); + display.display(); + delay(5000); + enableDisplay(false); + Serial.println("Printer is offline going down to sleep..."); + return; + } else if (!displayOn && !DISPLAYCLOCK) { + if (printerClient.isOperational()) { + // Wake the Screen up + enableDisplay(true); + display.clear(); + display.display(); + display.setFont(ArialMT_Plain_16); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setContrast(255); // default is 255 + display.drawString(64, 5, "Printer Online\nWake up..."); + display.display(); + Serial.println("Printer is online waking up..."); + delay(5000); + return; + } + } else if (DISPLAYCLOCK) { + if (!printerClient.isOperational() && !isClockOn) { + Serial.println("Clock Mode is turned on."); + ui.disableAutoTransition(); + ui.setFrames(clockFrame, 1); + clockFrame[0] = drawClock; + ui.setOverlays(clockOverlay, numberOfOverlays); + isClockOn = true; + } else if (printerClient.isOperational() && isClockOn) { + Serial.println("Printer Monitor is active."); + ui.setFrames(frames, numberOfFrames); + ui.setOverlays(overlays, numberOfOverlays); + ui.enableAutoTransition(); + isClockOn = false; + } + } +} + +void enableDisplay(boolean enable) { + displayOn = enable; + if (enable) { + if (getMinutesFromLastDisplay() >= minutesBetweenDataRefresh) { + // The display has been off longer than the minutes between refresh -- need to get fresh data + lastEpoch = 0; // this should force a data pull + displayOffEpoch = 0; // reset + } + display.displayOn(); + Serial.println("Display was turned ON: " + timeClient.getFormattedTime()); + } else { + display.displayOff(); + Serial.println("Display was turned OFF: " + timeClient.getFormattedTime()); + displayOffEpoch = lastEpoch; + } }