From 417e5f2964a0a7e82dd886be130f34e7c846edd8 Mon Sep 17 00:00:00 2001 From: Chrome Legion Date: Thu, 21 Jun 2018 21:42:09 -0700 Subject: [PATCH 1/7] Qrome - added option to turn off web interface authentication --- printermonitor/Settings.h | 1 + printermonitor/printermonitor.ino | 33 ++++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/printermonitor/Settings.h b/printermonitor/Settings.h index 5cd795c..170b1da 100644 --- a/printermonitor/Settings.h +++ b/printermonitor/Settings.h @@ -70,6 +70,7 @@ boolean IS_METRIC = false; // false = Imperial and true = Metric const int WEBSERVER_PORT = 80; // The port you can access this device on over HTTP const boolean WEBSERVER_ENABLED = true; // Device will provide a web interface via http://[ip]:[port]/ +boolean IS_BASIC_AUTH = true; // true = require athentication to change configuration settings / false = no auth char* www_username = "admin"; // User account for the Web Interface char* www_password = "password"; // Password for the Web Interface float UtcOffset = -7; // Hour offset from GMT for your timezone diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index 9914324..f786205 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -27,7 +27,7 @@ SOFTWARE. #include "Settings.h" -#define VERSION "2.1" +#define VERSION "2.2" #define HOSTNAME "OctMon-" #define CONFIG "/conf.txt" @@ -115,6 +115,7 @@ String CHANGE_FORM = "
Theme Color

" "


" + " Use Security Credentials for Configuration Changes" "

" "

" "
"; @@ -373,8 +374,15 @@ void getUpdateTime() { digitalWrite(externalLight, HIGH); // turn off the LED } +boolean authentication() { + if (IS_BASIC_AUTH && (strlen(www_username) >= 1 && strlen(www_password) >= 1)) { + return server.authenticate(www_username, www_password); + } + return true; // Authentication not required +} + void handleSystemReset() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } Serial.println("Reset System Configuration"); @@ -385,7 +393,7 @@ void handleSystemReset() { } void handleUpdateWeather() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } DISPLAYWEATHER = server.hasArg("isWeatherEnabled"); @@ -400,7 +408,7 @@ void handleUpdateWeather() { } void handleUpdateConfig() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } OctoPrintApiKey = server.arg("octoPrintApiKey"); @@ -414,6 +422,7 @@ void handleUpdateConfig() { minutesBetweenDataRefresh = server.arg("refresh").toInt(); themeColor = server.arg("theme"); UtcOffset = server.arg("utcoffset").toFloat(); + IS_BASIC_AUTH = server.hasArg("isBasicAuth"); String temp = server.arg("userid"); temp.toCharArray(www_username, sizeof(temp)); temp = server.arg("stationpassword"); @@ -427,7 +436,7 @@ void handleUpdateConfig() { } void handleWifiReset() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } //WiFiManager @@ -439,7 +448,7 @@ void handleWifiReset() { } void handleWeatherConfigure() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } digitalWrite(externalLight, LOW); @@ -479,7 +488,7 @@ void handleWeatherConfigure() { } void handleConfigure() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } digitalWrite(externalLight, LOW); @@ -519,6 +528,11 @@ void handleConfigure() { themeOptions.replace(">"+String(themeColor)+"<", " selected>"+String(themeColor)+"<"); form.replace("%THEME_OPTIONS%", themeOptions); form.replace("%UTCOFFSET%", String(UtcOffset)); + String isUseSecurityChecked = ""; + if (IS_BASIC_AUTH) { + isUseSecurityChecked = "checked='checked'"; + } + form.replace("%IS_BASICAUTH_CHECKED%", isUseSecurityChecked); form.replace("%USERID%", String(www_username)); form.replace("%STATIONPASSWORD%", String(www_password)); @@ -933,6 +947,7 @@ void writeSettings() { f.println("octoPass=" + OctoAuthPass); f.println("refreshRate=" + String(minutesBetweenDataRefresh)); f.println("themeColor=" + themeColor); + f.println("IS_BASIC_AUTH=" + String(IS_BASIC_AUTH)); f.println("www_username=" + String(www_username)); f.println("www_password=" + String(www_password)); f.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); @@ -1000,6 +1015,10 @@ void readSettings() { themeColor.trim(); Serial.println("themeColor=" + themeColor); } + if (line.indexOf("IS_BASIC_AUTH=") >= 0) { + IS_BASIC_AUTH = line.substring(line.lastIndexOf("IS_BASIC_AUTH=") + 14).toInt(); + Serial.println("IS_BASIC_AUTH=" + String(IS_BASIC_AUTH)); + } if (line.indexOf("www_username=") >= 0) { String temp = line.substring(line.lastIndexOf("www_username=") + 13); temp.trim(); From 5f461adc21781f0eefe26b85ea8cd0259b427287 Mon Sep 17 00:00:00 2001 From: derpicknicker1 <10minutemail@web.de> Date: Wed, 19 Sep 2018 16:08:38 +0200 Subject: [PATCH 2/7] ignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dff1ca8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +printermonitor/my_Settings.h From 602bf84f4c9639abbb7b44699aed7d3d2d4c69bc Mon Sep 17 00:00:00 2001 From: derpicknicker1 <10minutemail@web.de> Date: Thu, 20 Sep 2018 09:35:17 +0200 Subject: [PATCH 3/7] Added option to invert display Added the option to invert the display to the config menu. So noone has to care about this beforre flashing the firmware. --- printermonitor/Settings.h | 3 ++- printermonitor/printermonitor.ino | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/printermonitor/Settings.h b/printermonitor/Settings.h index 5cd795c..5a0ccbe 100644 --- a/printermonitor/Settings.h +++ b/printermonitor/Settings.h @@ -1,6 +1,7 @@ /** The MIT License (MIT) Copyright (c) 2018 David Payne +Copyright (c) 2018 Florian Schütte Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -81,7 +82,7 @@ boolean DISPLAYCLOCK = true; // true = Show Clock when not printing / false = const int I2C_DISPLAY_ADDRESS = 0x3c; // I2C Address of your Display (usually 0x3c or 0x3d) const int SDA_PIN = D2; const int SCL_PIN = D5; -const boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bottom +boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bottom //#define DISPLAY_SH1106 // Uncomment this line to use the SH1106 display -- SSD1306 is used by default and is most common boolean ENABLE_OTA = true; // this will allow you to load firmware to the device over WiFi (see OTA for ESP8266) diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index 9914324..6b65082 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -1,6 +1,7 @@ /** The MIT License (MIT) Copyright (c) 2018 David Payne +Copyright (c) 2018 Florian Schütte Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -112,6 +113,7 @@ String CHANGE_FORM = "
Display Clock when printer is off

" "

Use 24 Hour Clock (military time)

" + "

Flip display?

" "

Clock Sync / Weather Refresh (minutes)

" "

Theme Color

" "


" @@ -400,6 +402,7 @@ void handleUpdateWeather() { } void handleUpdateConfig() { + boolean flipOld = INVERT_DISPLAY; if (!server.authenticate(www_username, www_password)) { return server.requestAuthentication(); } @@ -411,6 +414,7 @@ void handleUpdateConfig() { OctoAuthPass = server.arg("octoPass"); DISPLAYCLOCK = server.hasArg("isClockEnabled"); IS_24HOUR = server.hasArg("is24hour"); + INVERT_DISPLAY = server.hasArg("invDisp"); minutesBetweenDataRefresh = server.arg("refresh").toInt(); themeColor = server.arg("theme"); UtcOffset = server.arg("utcoffset").toFloat(); @@ -421,6 +425,12 @@ void handleUpdateConfig() { writeSettings(); findMDNS(); printerClient.getPrinterJobResults(); + if (INVERT_DISPLAY != flipOld) { + ui.init(); + if(INVERT_DISPLAY) + display.flipScreenVertically(); + ui.update(); + } checkDisplay(); lastEpoch = 0; redirectHome(); @@ -512,6 +522,11 @@ void handleConfigure() { is24hourChecked = "checked='checked'"; } form.replace("%IS_24HOUR_CHECKED%", is24hourChecked); + String isInvDisp = ""; + if (INVERT_DISPLAY) { + isInvDisp = "checked='checked'"; + } + form.replace("%IS_INVDISP_CHECKED%", isInvDisp); String options = ""; options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<"); form.replace("%OPTIONS%", options); @@ -937,6 +952,7 @@ void writeSettings() { f.println("www_password=" + String(www_password)); f.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); f.println("is24hour=" + String(IS_24HOUR)); + f.println("invertDisp=" + String(INVERT_DISPLAY)); f.println("isWeather=" + String(DISPLAYWEATHER)); f.println("weatherKey=" + WeatherApiKey); f.println("CityID=" + String(CityIDs[0])); @@ -1020,6 +1036,10 @@ void readSettings() { IS_24HOUR = line.substring(line.lastIndexOf("is24hour=") + 9).toInt(); Serial.println("IS_24HOUR=" + String(IS_24HOUR)); } + if(line.indexOf("invertDisp=") >= 0) { + INVERT_DISPLAY = line.substring(line.lastIndexOf("invertDisp=") + 11).toInt(); + Serial.println("INVERT_DISPLAY=" + String(INVERT_DISPLAY)); + } if (line.indexOf("isWeather=") >= 0) { DISPLAYWEATHER = line.substring(line.lastIndexOf("isWeather=") + 10).toInt(); Serial.println("DISPLAYWEATHER=" + String(DISPLAYWEATHER)); From ef9fb455c4804c33d4425f4f5745ad9132ff98c9 Mon Sep 17 00:00:00 2001 From: derpicknicker1 <10minutemail@web.de> Date: Thu, 27 Sep 2018 09:35:19 +0200 Subject: [PATCH 4/7] changed (c) --- printermonitor/Settings.h | 185 +++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 93 deletions(-) diff --git a/printermonitor/Settings.h b/printermonitor/Settings.h index 5a0ccbe..0c66f2d 100644 --- a/printermonitor/Settings.h +++ b/printermonitor/Settings.h @@ -1,94 +1,93 @@ -/** The MIT License (MIT) - -Copyright (c) 2018 David Payne -Copyright (c) 2018 Florian Schütte - -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. -*/ - -/****************************************************************************** - * Printer Monitor is designed for the Wemos D1 ESP8266 - * Wemos D1 Mini: https://amzn.to/2qLyKJd - * 0.96" OLED I2C 128x64 Display (12864) SSD1306 - * OLED Display: https://amzn.to/2JDEAUF - ******************************************************************************/ -/****************************************************************************** - * NOTE: The settings here are the default settings for the first loading. - * After loading you will manage changes to the settings via the Web Interface. - * If you want to change settings again in the settings.h, you will need to - * erase the file system on the Wemos or use the “Reset Settings” option in - * the Web Interface. - ******************************************************************************/ - -#include -#include -#include -#include -#include -#include "TimeClient.h" -#include "OctoPrintClient.h" -#include "OpenWeatherMapClient.h" -#include "WeatherStationFonts.h" -#include "FS.h" -#include "SH1106Wire.h" -#include "SSD1306Wire.h" -#include "OLEDDisplayUi.h" - -//****************************** -// Start Settings -//****************************** - -// OctoPrint Monitoring -- Monitor your 3D printer OctoPrint Server -String OctoPrintApiKey = ""; // ApiKey from your User Account on OctoPrint -String OctoPrintHostName = "octopi";// Default 'octopi' -- or hostname if different (optional if your IP changes) -String OctoPrintServer = ""; // IP or Address of your OctoPrint Server (DO NOT include http://) -int OctoPrintPort = 80; // the port you are running your OctoPrint server on (usually 80); -String OctoAuthUser = ""; // only used if you have haproxy or basic athentintication turned on (not default) -String OctoAuthPass = ""; // only used with haproxy or basic auth (only needed if you must authenticate) - -// Weather Configuration -boolean DISPLAYWEATHER = true; // true = show weather when not printing / false = no weather -String WeatherApiKey = ""; // Your API Key from http://openweathermap.org/ -// Default City Location (use http://openweathermap.org/find to find city ID) -int CityIDs[] = { 5304391 }; //Only USE ONE for weather marquee -boolean IS_METRIC = false; // false = Imperial and true = Metric - -const int WEBSERVER_PORT = 80; // The port you can access this device on over HTTP -const boolean WEBSERVER_ENABLED = true; // Device will provide a web interface via http://[ip]:[port]/ -char* www_username = "admin"; // User account for the Web Interface -char* www_password = "password"; // Password for the Web Interface -float UtcOffset = -7; // Hour offset from GMT for your timezone -boolean IS_24HOUR = false; // 23:00 millitary 24 hour clock -int minutesBetweenDataRefresh = 15; -boolean DISPLAYCLOCK = true; // true = Show Clock when not printing / false = turn off display when not printing - -// Display Settings -const int I2C_DISPLAY_ADDRESS = 0x3c; // I2C Address of your Display (usually 0x3c or 0x3d) -const int SDA_PIN = D2; -const int SCL_PIN = D5; -boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bottom -//#define DISPLAY_SH1106 // Uncomment this line to use the SH1106 display -- SSD1306 is used by default and is most common - -boolean ENABLE_OTA = true; // this will allow you to load firmware to the device over WiFi (see OTA for ESP8266) -String OTA_Password = ""; // Set an OTA password here -- leave blank if you don't want to be prompted for password -//****************************** -// End Settings -//****************************** - +/** 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. +*/ + +/****************************************************************************** + * Printer Monitor is designed for the Wemos D1 ESP8266 + * Wemos D1 Mini: https://amzn.to/2qLyKJd + * 0.96" OLED I2C 128x64 Display (12864) SSD1306 + * OLED Display: https://amzn.to/2JDEAUF + ******************************************************************************/ +/****************************************************************************** + * NOTE: The settings here are the default settings for the first loading. + * After loading you will manage changes to the settings via the Web Interface. + * If you want to change settings again in the settings.h, you will need to + * erase the file system on the Wemos or use the “Reset Settings” option in + * the Web Interface. + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include "TimeClient.h" +#include "OctoPrintClient.h" +#include "OpenWeatherMapClient.h" +#include "WeatherStationFonts.h" +#include "FS.h" +#include "SH1106Wire.h" +#include "SSD1306Wire.h" +#include "OLEDDisplayUi.h" + +//****************************** +// Start Settings +//****************************** + +// OctoPrint Monitoring -- Monitor your 3D printer OctoPrint Server +String OctoPrintApiKey = ""; // ApiKey from your User Account on OctoPrint +String OctoPrintHostName = "octopi";// Default 'octopi' -- or hostname if different (optional if your IP changes) +String OctoPrintServer = ""; // IP or Address of your OctoPrint Server (DO NOT include http://) +int OctoPrintPort = 80; // the port you are running your OctoPrint server on (usually 80); +String OctoAuthUser = ""; // only used if you have haproxy or basic athentintication turned on (not default) +String OctoAuthPass = ""; // only used with haproxy or basic auth (only needed if you must authenticate) + +// Weather Configuration +boolean DISPLAYWEATHER = true; // true = show weather when not printing / false = no weather +String WeatherApiKey = ""; // Your API Key from http://openweathermap.org/ +// Default City Location (use http://openweathermap.org/find to find city ID) +int CityIDs[] = { 5304391 }; //Only USE ONE for weather marquee +boolean IS_METRIC = false; // false = Imperial and true = Metric + +const int WEBSERVER_PORT = 80; // The port you can access this device on over HTTP +const boolean WEBSERVER_ENABLED = true; // Device will provide a web interface via http://[ip]:[port]/ +char* www_username = "admin"; // User account for the Web Interface +char* www_password = "password"; // Password for the Web Interface +float UtcOffset = -7; // Hour offset from GMT for your timezone +boolean IS_24HOUR = false; // 23:00 millitary 24 hour clock +int minutesBetweenDataRefresh = 15; +boolean DISPLAYCLOCK = true; // true = Show Clock when not printing / false = turn off display when not printing + +// Display Settings +const int I2C_DISPLAY_ADDRESS = 0x3c; // I2C Address of your Display (usually 0x3c or 0x3d) +const int SDA_PIN = D2; +const int SCL_PIN = D5; +boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bottom +//#define DISPLAY_SH1106 // Uncomment this line to use the SH1106 display -- SSD1306 is used by default and is most common + +boolean ENABLE_OTA = true; // this will allow you to load firmware to the device over WiFi (see OTA for ESP8266) +String OTA_Password = ""; // Set an OTA password here -- leave blank if you don't want to be prompted for password +//****************************** +// End Settings +//****************************** + String themeColor = "light-green"; // this can be changed later in the web interface. From a91da219eec71ee94f758337e4fabbb6896d986a Mon Sep 17 00:00:00 2001 From: derpicknicker1 <10minutemail@web.de> Date: Thu, 27 Sep 2018 09:35:42 +0200 Subject: [PATCH 5/7] changed (c) --- printermonitor/printermonitor.ino | 2301 ++++++++++++++--------------- 1 file changed, 1150 insertions(+), 1151 deletions(-) diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index 6b65082..52c22eb 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -1,1152 +1,1151 @@ - /** The MIT License (MIT) - -Copyright (c) 2018 David Payne -Copyright (c) 2018 Florian Schütte - -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 "2.1" - -#define HOSTNAME "OctMon-" -#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 -#if defined(DISPLAY_SH1106) - SH1106Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SCL_PIN); -#else - SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SCL_PIN); // this is the default -#endif - -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 drawWeather(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[2]; -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, OctoAuthUser, OctoAuthPass); -int printerCount = 0; - -// Weather Client -OpenWeatherMapClient weatherClient(WeatherApiKey, CityIDs, 1, IS_METRIC); - -//declairing prototypes -void configModeCallback (WiFiManager *myWiFiManager); -int8_t getWifiQuality(); - -ESP8266WebServer server(WEBSERVER_PORT); - -String WEB_ACTIONS = " Home" - " Configure" - " Weather" - " Reset Settings" - " Forget WiFi" - " About"; - -String CHANGE_FORM = "

Station Config:

" - "

" - "

" - "

" - "

" - "

" - "


" - "

Display Clock when printer is off

" - "

Use 24 Hour Clock (military time)

" - "

Flip display?

" - "

Clock Sync / Weather Refresh (minutes)

" - "

Theme Color

" - "


" - "

" - "

" - ""; - -String WEATHER_FORM = "

Weather Config:

" - "

Display Weather when printer is off

" - "" - "" - "

" - "

" - "

Use Metric (Celsius)

" - "
" - ""; - -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(); - if (INVERT_DISPLAY) { - display.flipScreenVertically(); // connections at top of OLED display - } - 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); - - String hostname(HOSTNAME); - hostname += String(ESP.getChipId(), HEX); - if (!wifiManager.autoConnect((const char *)hostname.c_str())) {// new addition - delay(3000); - WiFi.disconnect(true); - ESP.reset(); - delay(5000); - } - - // 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; - clockFrame[1] = drawWeather; - ui.setOverlays(overlays, numberOfOverlays); - - // Inital UI takes care of initalising the display too. - ui.init(); - if (INVERT_DISPLAY) { - display.flipScreenVertically(); //connections at top of OLED display - } - - // 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.setHostname((const char *)hostname.c_str()); - if (OTA_Password != "") { - ArduinoOTA.setPassword(((const char *)OTA_Password.c_str())); - } - ArduinoOTA.begin(); - } - - if (WEBSERVER_ENABLED) { - server.on("/", displayPrinterStatus); - server.on("/systemreset", handleSystemReset); - server.on("/forgetwifi", handleWifiReset); - server.on("/updateconfig", handleUpdateConfig); - server.on("/updateweatherconfig", handleUpdateWeather); - server.on("/configure", handleConfigure); - server.on("/configureweather", handleWeatherConfigure); - 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); - findMDNS(); //go find Octoprint Server by the hostname -} - -void findMDNS() { - if (OctoPrintHostName == "") { - return; // nothing to do here - } - // We now query our network for 'web servers' service - // over tcp, and get the number of available devices - int n = MDNS.queryService("http", "tcp"); - if (n == 0) { - Serial.println("no services found - make sure OctoPrint server is turned on"); - return; - } - Serial.println("*** Looking for " + OctoPrintHostName + " over mDNS"); - for (int i = 0; i < n; ++i) { - // Going through every available service, - // we're searching for the one whose hostname - // matches what we want, and then get its IP - Serial.println("Found: " + MDNS.hostname(i)); - if (MDNS.hostname(i) == OctoPrintHostName) { - IPAddress serverIp = MDNS.IP(i); - OctoPrintServer = serverIp.toString(); - OctoPrintPort = MDNS.port(i); // save the port - Serial.println("*** Found OctoPrint Server " + OctoPrintHostName + " http://" + OctoPrintServer + ":" + OctoPrintPort); - writeSettings(); // update the settings - } - } -} - -//************************************************************ -// 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(); - - if (displayOn && DISPLAYWEATHER) { - Serial.println("Getting Weather Data..."); - weatherClient.updateWeather(); - } - - 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 handleUpdateWeather() { - if (!server.authenticate(www_username, www_password)) { - return server.requestAuthentication(); - } - DISPLAYWEATHER = server.hasArg("isWeatherEnabled"); - WeatherApiKey = server.arg("openWeatherMapApiKey"); - CityIDs[0] = server.arg("city1").toInt(); - IS_METRIC = server.hasArg("metric"); - writeSettings(); - isClockOn = false; // this will force a check for the display - checkDisplay(); - lastEpoch = 0; - redirectHome(); -} - -void handleUpdateConfig() { - boolean flipOld = INVERT_DISPLAY; - if (!server.authenticate(www_username, www_password)) { - return server.requestAuthentication(); - } - OctoPrintApiKey = server.arg("octoPrintApiKey"); - OctoPrintHostName = server.arg("octoPrintHostName"); - OctoPrintServer = server.arg("octoPrintAddress"); - OctoPrintPort = server.arg("octoPrintPort").toInt(); - OctoAuthUser = server.arg("octoUser"); - OctoAuthPass = server.arg("octoPass"); - DISPLAYCLOCK = server.hasArg("isClockEnabled"); - IS_24HOUR = server.hasArg("is24hour"); - INVERT_DISPLAY = server.hasArg("invDisp"); - 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(); - findMDNS(); - printerClient.getPrinterJobResults(); - if (INVERT_DISPLAY != flipOld) { - ui.init(); - if(INVERT_DISPLAY) - display.flipScreenVertically(); - ui.update(); - } - 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 handleWeatherConfigure() { - 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 = WEATHER_FORM; - String isWeatherChecked = ""; - if (DISPLAYWEATHER) { - isWeatherChecked = "checked='checked'"; - } - form.replace("%IS_WEATHER_CHECKED%", isWeatherChecked); - form.replace("%WEATHERKEY%", WeatherApiKey); - form.replace("%CITYNAME1%", weatherClient.getCity(0)); - form.replace("%CITY1%", String(CityIDs[0])); - String checked = ""; - if (IS_METRIC) { - checked = "checked='checked'"; - } - form.replace("%METRIC%", checked); - - server.sendContent(form); - - html = getFooter(); - server.sendContent(html); - server.sendContent(""); - server.client().stop(); - digitalWrite(externalLight, HIGH); -} - -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 = CHANGE_FORM; - - form.replace("%OCTOKEY%", OctoPrintApiKey); - form.replace("%OCTOHOST%", OctoPrintHostName); - form.replace("%OCTOADDRESS%", OctoPrintServer); - form.replace("%OCTOPORT%", String(OctoPrintPort)); - form.replace("%OCTOUSER%", OctoAuthUser); - form.replace("%OCTOPASS%", OctoAuthPass); - String isClockChecked = ""; - if (DISPLAYCLOCK) { - isClockChecked = "checked='checked'"; - } - form.replace("%IS_CLOCK_CHECKED%", isClockChecked); - String is24hourChecked = ""; - if (IS_24HOUR) { - is24hourChecked = "checked='checked'"; - } - form.replace("%IS_24HOUR_CHECKED%", is24hourChecked); - String isInvDisp = ""; - if (INVERT_DISPLAY) { - isInvDisp = "checked='checked'"; - } - form.replace("%IS_INVDISP_CHECKED%", isInvDisp); - String options = ""; - options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<"); - form.replace("%OPTIONS%", options); - String themeOptions = 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(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 = 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 += "
"; - if (lastReportStatus != "") { - html += " Report Status: " + lastReportStatus + "
"; - } - html += " Version: " + String(VERSION) + "
"; - html += " Signal Strength: "; - html += String(rssi) + "%"; - 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))); - - String displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds() + " " + timeClient.getAmPm(); - if (IS_24HOUR) { - displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); - } - - html += "

Time: " + displayTime + "

"; - html += "

"; - html += "Host Name: " + OctoPrintHostName + "
"; - if (printerClient.getError() != "") { - html += "Error: " + printerClient.getError() + "
"; - } - html += "Status: " + printerClient.getState() + "
"; - - if (printerClient.isPrinting()) { - 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() + "%
"; - } else { - html += "
"; - } - - html += "

"; - - server.sendContent(html); // spit out what we got - html = ""; - - if (DISPLAYWEATHER) { - if (weatherClient.getCity(0) == "") { - html += "

Please Configure Weather API

"; - if (weatherClient.getError() != "") { - html += "

Weather Error: " + weatherClient.getError() + "

"; - } - } else { - html += "

" + weatherClient.getCity(0) + ", " + weatherClient.getCountry(0) + "

"; - html += "
"; - html += "" + weatherClient.getDescription(0) + "
"; - html += weatherClient.getHumidity(0) + "% Humidity
"; - html += weatherClient.getWind(0) + " " + getSpeedSymbol() + " Wind
"; - html += "
"; - html += "

"; - html += weatherClient.getCondition(0) + " (" + weatherClient.getDescription(0) + ")
"; - html += weatherClient.getTempRounded(0) + getTempSymbol(true) + "
"; - html += " Map It!
"; - html += "

"; - } - - server.sendContent(html); // spit out what we got - html = ""; // fresh start - } - - 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()); - - display.clear(); - display.setTextAlignment(TEXT_ALIGN_CENTER); - display.setFont(ArialMT_Plain_10); - display.drawString(64, 0, "Wifi Manager"); - display.drawString(64, 10, "Please connect to AP"); - display.setFont(ArialMT_Plain_16); - display.drawString(64, 23, myWiFiManager->getConfigPortalSSID()); - display.setFont(ArialMT_Plain_10); - display.drawString(64, 42, "To setup Wifi connection"); - display.display(); - - 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); - String bed = printerClient.getValueRounded(printerClient.getTempBedActual()); - String tool = printerClient.getValueRounded(printerClient.getTempToolActual()); - display->drawString(2 + x, 14 + y, bed + "°"); - display->drawString(64 + x, 14 + y, tool + "°"); -} - -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); - - String displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); - if (IS_24HOUR) { - displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); - } - display->setFont(ArialMT_Plain_16); - display->drawString(64 + x, 0 + y, OctoPrintHostName); - display->setFont(ArialMT_Plain_24); - display->drawString(64 + x, 17 + y, displayTime); -} - -void drawWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->setFont(ArialMT_Plain_24); - display->drawString(0 + x, 0 + y, weatherClient.getTempRounded(0) + getTempSymbol()); - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->setFont(ArialMT_Plain_24); - - display->setFont(ArialMT_Plain_16); - display->drawString(0 + x, 24 + y, weatherClient.getCondition(0)); - display->setFont((const uint8_t*)Meteocons_Plain_42); - display->drawString(86 + x, 0 + y, weatherClient.getWeatherIcon(0)); -} - -String getTempSymbol() { - return getTempSymbol(false); -} - -String getTempSymbol(boolean forHTML) { - String rtnValue = "F"; - if (IS_METRIC) { - rtnValue = "C"; - } - if (forHTML) { - rtnValue = "°" + rtnValue; - } else { - rtnValue = "°" + rtnValue; - } - return rtnValue; -} - -String getSpeedSymbol() { - String rtnValue = "mph"; - if (IS_METRIC) { - rtnValue = "kph"; - } - return rtnValue; -} - -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 displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes(); - if (IS_24HOUR) { - displayTime = timeClient.getHours() + ":" + timeClient.getMinutes(); - } - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawString(0, 48, displayTime); - - if (!IS_24HOUR) { - 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); - display->setTextAlignment(TEXT_ALIGN_LEFT); - if (!IS_24HOUR) { - display->drawString(0, 48, timeClient.getAmPm()); - display->setTextAlignment(TEXT_ALIGN_CENTER); - display->drawString(64, 48, "offline"); - } else { - display->drawString(0,48, "offline"); - } - display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawRect(0, 43, 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("octoHost=" + OctoPrintHostName); - f.println("octoServer=" + OctoPrintServer); - f.println("octoPort=" + String(OctoPrintPort)); - f.println("octoUser=" + OctoAuthUser); - f.println("octoPass=" + OctoAuthPass); - 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.println("is24hour=" + String(IS_24HOUR)); - f.println("invertDisp=" + String(INVERT_DISPLAY)); - f.println("isWeather=" + String(DISPLAYWEATHER)); - f.println("weatherKey=" + WeatherApiKey); - f.println("CityID=" + String(CityIDs[0])); - f.println("isMetric=" + String(IS_METRIC)); - } - 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("octoHost=") >= 0) { - OctoPrintHostName = line.substring(line.lastIndexOf("octoHost=") + 9); - OctoPrintHostName.trim(); - Serial.println("OctoPrintHostName=" + OctoPrintHostName); - } - 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("octoUser=") >= 0) { - OctoAuthUser = line.substring(line.lastIndexOf("octoUser=") + 9); - OctoAuthUser.trim(); - Serial.println("OctoAuthUser=" + OctoAuthUser); - } - if (line.indexOf("octoPass=") >= 0) { - OctoAuthPass = line.substring(line.lastIndexOf("octoPass=") + 9); - OctoAuthPass.trim(); - Serial.println("OctoAuthPass=" + OctoAuthPass); - } - 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)); - } - if (line.indexOf("is24hour=") >= 0) { - IS_24HOUR = line.substring(line.lastIndexOf("is24hour=") + 9).toInt(); - Serial.println("IS_24HOUR=" + String(IS_24HOUR)); - } - if(line.indexOf("invertDisp=") >= 0) { - INVERT_DISPLAY = line.substring(line.lastIndexOf("invertDisp=") + 11).toInt(); - Serial.println("INVERT_DISPLAY=" + String(INVERT_DISPLAY)); - } - if (line.indexOf("isWeather=") >= 0) { - DISPLAYWEATHER = line.substring(line.lastIndexOf("isWeather=") + 10).toInt(); - Serial.println("DISPLAYWEATHER=" + String(DISPLAYWEATHER)); - } - if (line.indexOf("weatherKey=") >= 0) { - WeatherApiKey = line.substring(line.lastIndexOf("weatherKey=") + 11); - WeatherApiKey.trim(); - Serial.println("WeatherApiKey=" + WeatherApiKey); - } - if (line.indexOf("CityID=") >= 0) { - CityIDs[0] = line.substring(line.lastIndexOf("CityID=") + 7).toInt(); - Serial.println("CityID: " + String(CityIDs[0])); - } - if (line.indexOf("isMetric=") >= 0) { - IS_METRIC = line.substring(line.lastIndexOf("isMetric=") + 9).toInt(); - Serial.println("IS_METRIC=" + String(IS_METRIC)); - } - } - fr.close(); - printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass); - weatherClient.updateWeatherApiKey(WeatherApiKey); - weatherClient.setMetric(IS_METRIC); - weatherClient.updateCityIdList(CityIDs, 1); - 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."); - if (!DISPLAYWEATHER) { - ui.disableAutoTransition(); - ui.setFrames(clockFrame, 1); - clockFrame[0] = drawClock; - } else { - ui.enableAutoTransition(); - ui.setFrames(clockFrame, 2); - clockFrame[0] = drawClock; - clockFrame[1] = drawWeather; - } - 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 "2.1" + +#define HOSTNAME "OctMon-" +#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 +#if defined(DISPLAY_SH1106) + SH1106Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SCL_PIN); +#else + SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SCL_PIN); // this is the default +#endif + +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 drawWeather(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[2]; +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, OctoAuthUser, OctoAuthPass); +int printerCount = 0; + +// Weather Client +OpenWeatherMapClient weatherClient(WeatherApiKey, CityIDs, 1, IS_METRIC); + +//declairing prototypes +void configModeCallback (WiFiManager *myWiFiManager); +int8_t getWifiQuality(); + +ESP8266WebServer server(WEBSERVER_PORT); + +String WEB_ACTIONS = " Home" + " Configure" + " Weather" + " Reset Settings" + " Forget WiFi" + " About"; + +String CHANGE_FORM = "

Station Config:

" + "

" + "

" + "

" + "

" + "

" + "


" + "

Display Clock when printer is off

" + "

Use 24 Hour Clock (military time)

" + "

Flip display?

" + "

Clock Sync / Weather Refresh (minutes)

" + "

Theme Color

" + "


" + "

" + "

" + "
"; + +String WEATHER_FORM = "

Weather Config:

" + "

Display Weather when printer is off

" + "" + "" + "

" + "

" + "

Use Metric (Celsius)

" + "
" + ""; + +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(); + if (INVERT_DISPLAY) { + display.flipScreenVertically(); // connections at top of OLED display + } + 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); + + String hostname(HOSTNAME); + hostname += String(ESP.getChipId(), HEX); + if (!wifiManager.autoConnect((const char *)hostname.c_str())) {// new addition + delay(3000); + WiFi.disconnect(true); + ESP.reset(); + delay(5000); + } + + // 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; + clockFrame[1] = drawWeather; + ui.setOverlays(overlays, numberOfOverlays); + + // Inital UI takes care of initalising the display too. + ui.init(); + if (INVERT_DISPLAY) { + display.flipScreenVertically(); //connections at top of OLED display + } + + // 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.setHostname((const char *)hostname.c_str()); + if (OTA_Password != "") { + ArduinoOTA.setPassword(((const char *)OTA_Password.c_str())); + } + ArduinoOTA.begin(); + } + + if (WEBSERVER_ENABLED) { + server.on("/", displayPrinterStatus); + server.on("/systemreset", handleSystemReset); + server.on("/forgetwifi", handleWifiReset); + server.on("/updateconfig", handleUpdateConfig); + server.on("/updateweatherconfig", handleUpdateWeather); + server.on("/configure", handleConfigure); + server.on("/configureweather", handleWeatherConfigure); + 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); + findMDNS(); //go find Octoprint Server by the hostname +} + +void findMDNS() { + if (OctoPrintHostName == "") { + return; // nothing to do here + } + // We now query our network for 'web servers' service + // over tcp, and get the number of available devices + int n = MDNS.queryService("http", "tcp"); + if (n == 0) { + Serial.println("no services found - make sure OctoPrint server is turned on"); + return; + } + Serial.println("*** Looking for " + OctoPrintHostName + " over mDNS"); + for (int i = 0; i < n; ++i) { + // Going through every available service, + // we're searching for the one whose hostname + // matches what we want, and then get its IP + Serial.println("Found: " + MDNS.hostname(i)); + if (MDNS.hostname(i) == OctoPrintHostName) { + IPAddress serverIp = MDNS.IP(i); + OctoPrintServer = serverIp.toString(); + OctoPrintPort = MDNS.port(i); // save the port + Serial.println("*** Found OctoPrint Server " + OctoPrintHostName + " http://" + OctoPrintServer + ":" + OctoPrintPort); + writeSettings(); // update the settings + } + } +} + +//************************************************************ +// 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(); + + if (displayOn && DISPLAYWEATHER) { + Serial.println("Getting Weather Data..."); + weatherClient.updateWeather(); + } + + 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 handleUpdateWeather() { + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + DISPLAYWEATHER = server.hasArg("isWeatherEnabled"); + WeatherApiKey = server.arg("openWeatherMapApiKey"); + CityIDs[0] = server.arg("city1").toInt(); + IS_METRIC = server.hasArg("metric"); + writeSettings(); + isClockOn = false; // this will force a check for the display + checkDisplay(); + lastEpoch = 0; + redirectHome(); +} + +void handleUpdateConfig() { + boolean flipOld = INVERT_DISPLAY; + if (!server.authenticate(www_username, www_password)) { + return server.requestAuthentication(); + } + OctoPrintApiKey = server.arg("octoPrintApiKey"); + OctoPrintHostName = server.arg("octoPrintHostName"); + OctoPrintServer = server.arg("octoPrintAddress"); + OctoPrintPort = server.arg("octoPrintPort").toInt(); + OctoAuthUser = server.arg("octoUser"); + OctoAuthPass = server.arg("octoPass"); + DISPLAYCLOCK = server.hasArg("isClockEnabled"); + IS_24HOUR = server.hasArg("is24hour"); + INVERT_DISPLAY = server.hasArg("invDisp"); + 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(); + findMDNS(); + printerClient.getPrinterJobResults(); + if (INVERT_DISPLAY != flipOld) { + ui.init(); + if(INVERT_DISPLAY) + display.flipScreenVertically(); + ui.update(); + } + 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 handleWeatherConfigure() { + 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 = WEATHER_FORM; + String isWeatherChecked = ""; + if (DISPLAYWEATHER) { + isWeatherChecked = "checked='checked'"; + } + form.replace("%IS_WEATHER_CHECKED%", isWeatherChecked); + form.replace("%WEATHERKEY%", WeatherApiKey); + form.replace("%CITYNAME1%", weatherClient.getCity(0)); + form.replace("%CITY1%", String(CityIDs[0])); + String checked = ""; + if (IS_METRIC) { + checked = "checked='checked'"; + } + form.replace("%METRIC%", checked); + + server.sendContent(form); + + html = getFooter(); + server.sendContent(html); + server.sendContent(""); + server.client().stop(); + digitalWrite(externalLight, HIGH); +} + +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 = CHANGE_FORM; + + form.replace("%OCTOKEY%", OctoPrintApiKey); + form.replace("%OCTOHOST%", OctoPrintHostName); + form.replace("%OCTOADDRESS%", OctoPrintServer); + form.replace("%OCTOPORT%", String(OctoPrintPort)); + form.replace("%OCTOUSER%", OctoAuthUser); + form.replace("%OCTOPASS%", OctoAuthPass); + String isClockChecked = ""; + if (DISPLAYCLOCK) { + isClockChecked = "checked='checked'"; + } + form.replace("%IS_CLOCK_CHECKED%", isClockChecked); + String is24hourChecked = ""; + if (IS_24HOUR) { + is24hourChecked = "checked='checked'"; + } + form.replace("%IS_24HOUR_CHECKED%", is24hourChecked); + String isInvDisp = ""; + if (INVERT_DISPLAY) { + isInvDisp = "checked='checked'"; + } + form.replace("%IS_INVDISP_CHECKED%", isInvDisp); + String options = ""; + options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<"); + form.replace("%OPTIONS%", options); + String themeOptions = 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(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 = 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 += "
"; + if (lastReportStatus != "") { + html += " Report Status: " + lastReportStatus + "
"; + } + html += " Version: " + String(VERSION) + "
"; + html += " Signal Strength: "; + html += String(rssi) + "%"; + 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))); + + String displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds() + " " + timeClient.getAmPm(); + if (IS_24HOUR) { + displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); + } + + html += "

Time: " + displayTime + "

"; + html += "

"; + html += "Host Name: " + OctoPrintHostName + "
"; + if (printerClient.getError() != "") { + html += "Error: " + printerClient.getError() + "
"; + } + html += "Status: " + printerClient.getState() + "
"; + + if (printerClient.isPrinting()) { + 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() + "%
"; + } else { + html += "
"; + } + + html += "

"; + + server.sendContent(html); // spit out what we got + html = ""; + + if (DISPLAYWEATHER) { + if (weatherClient.getCity(0) == "") { + html += "

Please Configure Weather API

"; + if (weatherClient.getError() != "") { + html += "

Weather Error: " + weatherClient.getError() + "

"; + } + } else { + html += "

" + weatherClient.getCity(0) + ", " + weatherClient.getCountry(0) + "

"; + html += "
"; + html += "" + weatherClient.getDescription(0) + "
"; + html += weatherClient.getHumidity(0) + "% Humidity
"; + html += weatherClient.getWind(0) + " " + getSpeedSymbol() + " Wind
"; + html += "
"; + html += "

"; + html += weatherClient.getCondition(0) + " (" + weatherClient.getDescription(0) + ")
"; + html += weatherClient.getTempRounded(0) + getTempSymbol(true) + "
"; + html += " Map It!
"; + html += "

"; + } + + server.sendContent(html); // spit out what we got + html = ""; // fresh start + } + + 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()); + + display.clear(); + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.setFont(ArialMT_Plain_10); + display.drawString(64, 0, "Wifi Manager"); + display.drawString(64, 10, "Please connect to AP"); + display.setFont(ArialMT_Plain_16); + display.drawString(64, 23, myWiFiManager->getConfigPortalSSID()); + display.setFont(ArialMT_Plain_10); + display.drawString(64, 42, "To setup Wifi connection"); + display.display(); + + 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); + String bed = printerClient.getValueRounded(printerClient.getTempBedActual()); + String tool = printerClient.getValueRounded(printerClient.getTempToolActual()); + display->drawString(2 + x, 14 + y, bed + "°"); + display->drawString(64 + x, 14 + y, tool + "°"); +} + +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); + + String displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); + if (IS_24HOUR) { + displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); + } + display->setFont(ArialMT_Plain_16); + display->drawString(64 + x, 0 + y, OctoPrintHostName); + display->setFont(ArialMT_Plain_24); + display->drawString(64 + x, 17 + y, displayTime); +} + +void drawWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_24); + display->drawString(0 + x, 0 + y, weatherClient.getTempRounded(0) + getTempSymbol()); + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_24); + + display->setFont(ArialMT_Plain_16); + display->drawString(0 + x, 24 + y, weatherClient.getCondition(0)); + display->setFont((const uint8_t*)Meteocons_Plain_42); + display->drawString(86 + x, 0 + y, weatherClient.getWeatherIcon(0)); +} + +String getTempSymbol() { + return getTempSymbol(false); +} + +String getTempSymbol(boolean forHTML) { + String rtnValue = "F"; + if (IS_METRIC) { + rtnValue = "C"; + } + if (forHTML) { + rtnValue = "°" + rtnValue; + } else { + rtnValue = "°" + rtnValue; + } + return rtnValue; +} + +String getSpeedSymbol() { + String rtnValue = "mph"; + if (IS_METRIC) { + rtnValue = "kph"; + } + return rtnValue; +} + +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 displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes(); + if (IS_24HOUR) { + displayTime = timeClient.getHours() + ":" + timeClient.getMinutes(); + } + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->drawString(0, 48, displayTime); + + if (!IS_24HOUR) { + 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); + display->setTextAlignment(TEXT_ALIGN_LEFT); + if (!IS_24HOUR) { + display->drawString(0, 48, timeClient.getAmPm()); + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->drawString(64, 48, "offline"); + } else { + display->drawString(0,48, "offline"); + } + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->drawRect(0, 43, 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("octoHost=" + OctoPrintHostName); + f.println("octoServer=" + OctoPrintServer); + f.println("octoPort=" + String(OctoPrintPort)); + f.println("octoUser=" + OctoAuthUser); + f.println("octoPass=" + OctoAuthPass); + 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.println("is24hour=" + String(IS_24HOUR)); + f.println("invertDisp=" + String(INVERT_DISPLAY)); + f.println("isWeather=" + String(DISPLAYWEATHER)); + f.println("weatherKey=" + WeatherApiKey); + f.println("CityID=" + String(CityIDs[0])); + f.println("isMetric=" + String(IS_METRIC)); + } + 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("octoHost=") >= 0) { + OctoPrintHostName = line.substring(line.lastIndexOf("octoHost=") + 9); + OctoPrintHostName.trim(); + Serial.println("OctoPrintHostName=" + OctoPrintHostName); + } + 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("octoUser=") >= 0) { + OctoAuthUser = line.substring(line.lastIndexOf("octoUser=") + 9); + OctoAuthUser.trim(); + Serial.println("OctoAuthUser=" + OctoAuthUser); + } + if (line.indexOf("octoPass=") >= 0) { + OctoAuthPass = line.substring(line.lastIndexOf("octoPass=") + 9); + OctoAuthPass.trim(); + Serial.println("OctoAuthPass=" + OctoAuthPass); + } + 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)); + } + if (line.indexOf("is24hour=") >= 0) { + IS_24HOUR = line.substring(line.lastIndexOf("is24hour=") + 9).toInt(); + Serial.println("IS_24HOUR=" + String(IS_24HOUR)); + } + if(line.indexOf("invertDisp=") >= 0) { + INVERT_DISPLAY = line.substring(line.lastIndexOf("invertDisp=") + 11).toInt(); + Serial.println("INVERT_DISPLAY=" + String(INVERT_DISPLAY)); + } + if (line.indexOf("isWeather=") >= 0) { + DISPLAYWEATHER = line.substring(line.lastIndexOf("isWeather=") + 10).toInt(); + Serial.println("DISPLAYWEATHER=" + String(DISPLAYWEATHER)); + } + if (line.indexOf("weatherKey=") >= 0) { + WeatherApiKey = line.substring(line.lastIndexOf("weatherKey=") + 11); + WeatherApiKey.trim(); + Serial.println("WeatherApiKey=" + WeatherApiKey); + } + if (line.indexOf("CityID=") >= 0) { + CityIDs[0] = line.substring(line.lastIndexOf("CityID=") + 7).toInt(); + Serial.println("CityID: " + String(CityIDs[0])); + } + if (line.indexOf("isMetric=") >= 0) { + IS_METRIC = line.substring(line.lastIndexOf("isMetric=") + 9).toInt(); + Serial.println("IS_METRIC=" + String(IS_METRIC)); + } + } + fr.close(); + printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass); + weatherClient.updateWeatherApiKey(WeatherApiKey); + weatherClient.setMetric(IS_METRIC); + weatherClient.updateCityIdList(CityIDs, 1); + 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."); + if (!DISPLAYWEATHER) { + ui.disableAutoTransition(); + ui.setFrames(clockFrame, 1); + clockFrame[0] = drawClock; + } else { + ui.enableAutoTransition(); + ui.setFrames(clockFrame, 2); + clockFrame[0] = drawClock; + clockFrame[1] = drawWeather; + } + 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; + } } From 04ed5ae77dc0d0fecfd6e71887713f089e0ec9ed Mon Sep 17 00:00:00 2001 From: Chrome Legion Date: Thu, 27 Sep 2018 08:07:53 -0700 Subject: [PATCH 6/7] Qrome - updated with ability to turn on or off Basic Auth for web interface --- README.md | 3 ++- printermonitor/Settings.h | 5 +++-- printermonitor/printermonitor.ino | 34 +++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 803273b..c751ef5 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,8 @@ Please do not feel obligated, but donations and tips are warmly welcomed. I hav ## Contributors David Payne -Daniel Eichhorn -- Author of the TimeClient class and OLEDDisplayUi . +Daniel Eichhorn -- Author of the TimeClient class and OLEDDisplayUi +Florian Schütte -- added flip display to web interface Contributing to this software is warmly welcomed. You can do this basically by forking from master, committing modifications and then making a pulling requests to be reviewed (follow the links above diff --git a/printermonitor/Settings.h b/printermonitor/Settings.h index dfa100e..5bf439c 100644 --- a/printermonitor/Settings.h +++ b/printermonitor/Settings.h @@ -70,6 +70,7 @@ boolean IS_METRIC = false; // false = Imperial and true = Metric const int WEBSERVER_PORT = 80; // The port you can access this device on over HTTP const boolean WEBSERVER_ENABLED = true; // Device will provide a web interface via http://[ip]:[port]/ +boolean IS_BASIC_AUTH = true; // true = require athentication to change configuration settings / false = no auth char* www_username = "admin"; // User account for the Web Interface char* www_password = "password"; // Password for the Web Interface float UtcOffset = -7; // Hour offset from GMT for your timezone @@ -82,7 +83,7 @@ const int I2C_DISPLAY_ADDRESS = 0x3c; // I2C Address of your Display (usually 0x const int SDA_PIN = D2; const int SCL_PIN = D5; boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bottom -//#define DISPLAY_SH1106 // Uncomment this line to use the SH1106 display -- SSD1306 is used by default and is most common +#define DISPLAY_SH1106 // Uncomment this line to use the SH1106 display -- SSD1306 is used by default and is most common boolean ENABLE_OTA = true; // this will allow you to load firmware to the device over WiFi (see OTA for ESP8266) String OTA_Password = ""; // Set an OTA password here -- leave blank if you don't want to be prompted for password @@ -90,4 +91,4 @@ String OTA_Password = ""; // Set an OTA password here -- leave blank if you // End Settings //****************************** -String themeColor = "light-green"; // this can be changed later in the web interface. +String themeColor = "light-green"; // this can be changed later in the web interface. diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index f827286..e3685cb 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -112,10 +112,11 @@ String CHANGE_FORM = "
Display Clock when printer is off

" "

Use 24 Hour Clock (military time)

" - "

Flip display?

" + "

Flip display orientation

" "

Clock Sync / Weather Refresh (minutes)

" "

Theme Color

" "


" + "

Use Security Credentials for Configuration Changes

" "

" "

" "
"; @@ -374,8 +375,15 @@ void getUpdateTime() { digitalWrite(externalLight, HIGH); // turn off the LED } +boolean authentication() { + if (IS_BASIC_AUTH && (strlen(www_username) >= 1 && strlen(www_password) >= 1)) { + return server.authenticate(www_username, www_password); + } + return true; // Authentication not required +} + void handleSystemReset() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } Serial.println("Reset System Configuration"); @@ -386,7 +394,7 @@ void handleSystemReset() { } void handleUpdateWeather() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } DISPLAYWEATHER = server.hasArg("isWeatherEnabled"); @@ -402,7 +410,7 @@ void handleUpdateWeather() { void handleUpdateConfig() { boolean flipOld = INVERT_DISPLAY; - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } OctoPrintApiKey = server.arg("octoPrintApiKey"); @@ -436,7 +444,7 @@ void handleUpdateConfig() { } void handleWifiReset() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } //WiFiManager @@ -448,7 +456,7 @@ void handleWifiReset() { } void handleWeatherConfigure() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } digitalWrite(externalLight, LOW); @@ -488,7 +496,7 @@ void handleWeatherConfigure() { } void handleConfigure() { - if (!server.authenticate(www_username, www_password)) { + if (!authentication()) { return server.requestAuthentication(); } digitalWrite(externalLight, LOW); @@ -533,6 +541,11 @@ void handleConfigure() { themeOptions.replace(">"+String(themeColor)+"<", " selected>"+String(themeColor)+"<"); form.replace("%THEME_OPTIONS%", themeOptions); form.replace("%UTCOFFSET%", String(UtcOffset)); + String isUseSecurityChecked = ""; + if (IS_BASIC_AUTH) { + isUseSecurityChecked = "checked='checked'"; + } + form.replace("%IS_BASICAUTH_CHECKED%", isUseSecurityChecked); form.replace("%USERID%", String(www_username)); form.replace("%STATIONPASSWORD%", String(www_password)); @@ -947,6 +960,7 @@ void writeSettings() { f.println("octoPass=" + OctoAuthPass); f.println("refreshRate=" + String(minutesBetweenDataRefresh)); f.println("themeColor=" + themeColor); + f.println("IS_BASIC_AUTH=" + String(IS_BASIC_AUTH)); f.println("www_username=" + String(www_username)); f.println("www_password=" + String(www_password)); f.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); @@ -1015,6 +1029,10 @@ void readSettings() { themeColor.trim(); Serial.println("themeColor=" + themeColor); } + if (line.indexOf("IS_BASIC_AUTH=") >= 0) { + IS_BASIC_AUTH = line.substring(line.lastIndexOf("IS_BASIC_AUTH=") + 14).toInt(); + Serial.println("IS_BASIC_AUTH=" + String(IS_BASIC_AUTH)); + } if (line.indexOf("www_username=") >= 0) { String temp = line.substring(line.lastIndexOf("www_username=") + 13); temp.trim(); @@ -1148,4 +1166,4 @@ void enableDisplay(boolean enable) { Serial.println("Display was turned OFF: " + timeClient.getFormattedTime()); displayOffEpoch = lastEpoch; } -} +} From 2277c8805f981f15f80e6c211ea33dd22f0c4c9b Mon Sep 17 00:00:00 2001 From: Chrome Legion Date: Sun, 25 Nov 2018 17:02:37 -0700 Subject: [PATCH 7/7] Qrome - fixed bug where ENABLE_OTA = false and crash on MDNS call --- printermonitor/printermonitor.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index e3685cb..1f662f9 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -287,13 +287,13 @@ void setup() { display.drawString(64, 20, "Enable in Settings.h"); display.display(); } - flashLED(5, 500); findMDNS(); //go find Octoprint Server by the hostname + Serial.println("*** Leaving setup()"); } void findMDNS() { - if (OctoPrintHostName == "") { + if (OctoPrintHostName == "" || ENABLE_OTA == false) { return; // nothing to do here } // We now query our network for 'web servers' service