diff --git a/printermonitor.ino.d1_mini_SH1106-2.5.bin b/printermonitor.ino.d1_mini_SH1106-2.5.bin deleted file mode 100644 index d03871c..0000000 Binary files a/printermonitor.ino.d1_mini_SH1106-2.5.bin and /dev/null differ diff --git a/printermonitor.ino.d1_mini_SSD1306-2.5.bin b/printermonitor.ino.d1_mini_SSD1306-2.5.bin deleted file mode 100644 index a3ba1e5..0000000 Binary files a/printermonitor.ino.d1_mini_SSD1306-2.5.bin and /dev/null differ diff --git a/printermonitor/OctoPrintClient.cpp b/printermonitor/OctoPrintClient.cpp index 7d19d2c..f67df70 100644 --- a/printermonitor/OctoPrintClient.cpp +++ b/printermonitor/OctoPrintClient.cpp @@ -27,10 +27,10 @@ SOFTWARE. #include "OctoPrintClient.h" OctoPrintClient::OctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu) { - updateOctoPrintClient(ApiKey, server, port, user, pass, psu); + updatePrintClient(ApiKey, server, port, user, pass, psu); } -void OctoPrintClient::updateOctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu) { +void OctoPrintClient::updatePrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu) { server.toCharArray(myServer, 100); myApiKey = ApiKey; myPort = port; @@ -82,7 +82,7 @@ WiFiClient OctoPrintClient::getSubmitRequest(String apiGetData) { printerData.error = "Connection to " + String(myServer) + ":" + String(myPort) + " failed."; return printClient; } - } + } else { Serial.println("Connection to OctoPrint failed: " + String(myServer) + ":" + String(myPort)); //error message if no client connect Serial.println(); @@ -142,7 +142,7 @@ WiFiClient OctoPrintClient::getPostRequest(String apiPostData, String apiPostBod printerData.error = "Connection to " + String(myServer) + ":" + String(myPort) + " failed."; return printClient; } - } + } else { Serial.println("Connection to OctoPrint failed: " + String(myServer) + ":" + String(myPort)); //error message if no client connect Serial.println(); @@ -194,7 +194,7 @@ void OctoPrintClient::getPrinterJobResults() { printerData.state = ""; return; } - + printerData.averagePrintTime = (const char*)root["job"]["averagePrintTime"]; printerData.estimatedPrintTime = (const char*)root["job"]["estimatedPrintTime"]; printerData.fileName = (const char*)root["job"]["file"]["name"]; @@ -236,6 +236,8 @@ void OctoPrintClient::getPrinterJobResults() { String printing = (const char*)root2["state"]["flags"]["printing"]; if (printing == "true") { printerData.isPrinting = true; + } else { + printerData.isPrinting = false; } printerData.toolTemp = (const char*)root2["temperature"]["tool0"]["actual"]; printerData.toolTargetTemp = (const char*)root2["temperature"]["tool0"]["target"]; @@ -263,14 +265,14 @@ void OctoPrintClient::getPrinterPsuState() { } const size_t bufferSize3 = JSON_OBJECT_SIZE(2) + 300; DynamicJsonBuffer jsonBuffer3(bufferSize3); - + // Parse JSON object JsonObject& root3 = jsonBuffer3.parseObject(printClient); if (!root3.success()) { printerData.isPSUoff = false; // we do not know PSU state, so assume on return; } - + String psu = (const char*)root3["isPSUOn"]; if (psu == "true") { printerData.isPSUoff = false; // PSU checked and is on @@ -330,7 +332,7 @@ String OctoPrintClient::getProgressCompletion() { } String OctoPrintClient::getProgressFilepos() { - return printerData.progressFilepos; + return printerData.progressFilepos; } String OctoPrintClient::getProgressPrintTime() { @@ -394,3 +396,19 @@ String OctoPrintClient::getValueRounded(String value) { int rounded = (int)(f+0.5f); return String(rounded); } + +String OctoPrintClient::getPrinterType() { + return printerType; +} + +int OctoPrintClient::getPrinterPort() { + return myPort; +} + +String OctoPrintClient::getPrinterName() { + return printerData.printerName; +} + +void OctoPrintClient::setPrinterName(String printer) { + printerData.printerName = printer; +} diff --git a/printermonitor/OctoPrintClient.h b/printermonitor/OctoPrintClient.h index d8d7b8d..76b4722 100644 --- a/printermonitor/OctoPrintClient.h +++ b/printermonitor/OctoPrintClient.h @@ -37,12 +37,13 @@ class OctoPrintClient { String myApiKey = ""; String encodedAuth = ""; boolean pollPsu; + const String printerType = "OctoPrint"; void resetPrintData(); boolean validate(); WiFiClient getSubmitRequest(String apiGetData); WiFiClient getPostRequest(String apiPostData, String apiPostBody); - + String result; typedef struct { @@ -64,16 +65,17 @@ class OctoPrintClient { boolean isPrinting; boolean isPSUoff; String error; + String printerName; } PrinterStruct; PrinterStruct printerData; - + public: OctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu); void getPrinterJobResults(); void getPrinterPsuState(); - void updateOctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu); + void updatePrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu); String getAveragePrintTime(); String getEstimatedPrintTime(); @@ -95,4 +97,8 @@ class OctoPrintClient { String getFilamentLength(); String getValueRounded(String value); String getError(); + String getPrinterType(); + int getPrinterPort(); + String getPrinterName(); + void setPrinterName(String printer); }; diff --git a/printermonitor/OpenWeatherMapClient.cpp b/printermonitor/OpenWeatherMapClient.cpp index e3c7874..48a8af5 100644 --- a/printermonitor/OpenWeatherMapClient.cpp +++ b/printermonitor/OpenWeatherMapClient.cpp @@ -54,7 +54,7 @@ void OpenWeatherMapClient::updateWeather() { weatherClient.println("User-Agent: ArduinoWiFi/1.1"); weatherClient.println("Connection: close"); weatherClient.println(); - } + } else { Serial.println("connection for weather data failed"); //error message if no client connect Serial.println(); @@ -62,7 +62,7 @@ void OpenWeatherMapClient::updateWeather() { } while(weatherClient.connected() && !weatherClient.available()) delay(1); //waits for data - + Serial.println("Waiting for data"); // Check HTTP status @@ -133,7 +133,7 @@ void OpenWeatherMapClient::updateWeather() { Serial.println("description: " + weathers[inx].description); Serial.println("icon: " + weathers[inx].icon); Serial.println(); - + } } @@ -150,7 +150,7 @@ void OpenWeatherMapClient::updateCityIdList(int CityIDs[], int cityCount) { if (myCityIDs != "") { myCityIDs = myCityIDs + ","; } - myCityIDs = myCityIDs + String(CityIDs[inx]); + myCityIDs = myCityIDs + String(CityIDs[inx]); } } } @@ -250,7 +250,7 @@ String OpenWeatherMapClient::getWeatherIcon(int index) case 802: W = "H"; break; case 803: W = "H"; break; case 804: W = "Y"; break; - + case 200: W = "0"; break; case 201: W = "0"; break; case 202: W = "0"; break; @@ -261,7 +261,7 @@ String OpenWeatherMapClient::getWeatherIcon(int index) case 230: W = "0"; break; case 231: W = "0"; break; case 232: W = "0"; break; - + case 300: W = "R"; break; case 301: W = "R"; break; case 302: W = "R"; break; @@ -271,7 +271,7 @@ String OpenWeatherMapClient::getWeatherIcon(int index) case 313: W = "R"; break; case 314: W = "R"; break; case 321: W = "R"; break; - + case 500: W = "R"; break; case 501: W = "R"; break; case 502: W = "R"; break; @@ -282,7 +282,7 @@ String OpenWeatherMapClient::getWeatherIcon(int index) case 521: W = "R"; break; case 522: W = "R"; break; case 531: W = "R"; break; - + case 600: W = "W"; break; case 601: W = "W"; break; case 602: W = "W"; break; @@ -293,7 +293,7 @@ String OpenWeatherMapClient::getWeatherIcon(int index) case 620: W = "W"; break; case 621: W = "W"; break; case 622: W = "W"; break; - + case 701: W = "M"; break; case 711: W = "M"; break; case 721: W = "M"; break; @@ -304,8 +304,8 @@ String OpenWeatherMapClient::getWeatherIcon(int index) case 762: W = "M"; break; case 771: W = "M"; break; case 781: W = "M"; break; - - default:break; + + default:break; } return W; -} +} diff --git a/printermonitor/OpenWeatherMapClient.h b/printermonitor/OpenWeatherMapClient.h index 9a8a44b..8ee90c7 100644 --- a/printermonitor/OpenWeatherMapClient.h +++ b/printermonitor/OpenWeatherMapClient.h @@ -32,7 +32,7 @@ class OpenWeatherMapClient { String myApiKey = ""; String units = ""; String lang = ""; - + const char* servername = "api.openweathermap.org"; // remote server we will connect to String result; @@ -56,7 +56,7 @@ class OpenWeatherMapClient { weather weathers[5]; String roundValue(String value); - + public: OpenWeatherMapClient(String ApiKey, int CityIDs[], int cityCount, boolean isMetric, String language); void updateWeather(); diff --git a/printermonitor/RepetierClient.cpp b/printermonitor/RepetierClient.cpp new file mode 100755 index 0000000..e547916 --- /dev/null +++ b/printermonitor/RepetierClient.cpp @@ -0,0 +1,367 @@ +/** 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. +*/ + +// Additional Contributions: +/* 15 Jan 2019 : Owen Carter : Add psucontrol query via POST api call */ +/* 07 April 2019 : Jon Smith : Redesigned this class for Repetier Server */ + +#include "RepetierClient.h" + +RepetierClient::RepetierClient(String ApiKey, String server, int port, String user, String pass, boolean psu) { + updatePrintClient(ApiKey, server, port, user, pass, psu); +} + +void RepetierClient::updatePrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu) { + server.toCharArray(myServer, 100); + myApiKey = ApiKey; + myPort = port; + encodedAuth = ""; + if (user != "") { + String userpass = user + ":" + pass; + base64 b64; + encodedAuth = b64.encode(userpass, true); + } + pollPsu = psu; +} + +boolean RepetierClient::validate() { + boolean rtnValue = false; + printerData.error = ""; + if (String(myServer) == "") { + printerData.error += "Server address is required; "; + } + if (myApiKey == "") { + printerData.error += "ApiKey is required; "; + } + if (printerData.error == "") { + rtnValue = true; + } + return rtnValue; +} + +WiFiClient RepetierClient::getSubmitRequest(String apiGetData) { + WiFiClient printClient; + printClient.setTimeout(5000); + + Serial.println("Getting Repetier Data via GET"); + Serial.println(apiGetData); + result = ""; + if (printClient.connect(myServer, myPort)) { //starts client connection, checks for connection + printClient.println(apiGetData); + printClient.println("Host: " + String(myServer) + ":" + String(myPort)); + printClient.println("X-Api-Key: " + myApiKey); + if (encodedAuth != "") { + printClient.print("Authorization: "); + printClient.println("Basic " + encodedAuth); + } + printClient.println("User-Agent: ArduinoWiFi/1.1"); + printClient.println("Connection: close"); + if (printClient.println() == 0) { + Serial.println("Connection to " + String(myServer) + ":" + String(myPort) + " failed."); + Serial.println(); + resetPrintData(); + printerData.error = "Connection to " + String(myServer) + ":" + String(myPort) + " failed."; + return printClient; + } + } + else { + Serial.println("Connection to Repetier failed: " + String(myServer) + ":" + String(myPort)); //error message if no client connect + Serial.println(); + resetPrintData(); + printerData.error = "Connection to Repetier failed: " + String(myServer) + ":" + String(myPort); + return printClient; + } +/* + // Check HTTP status + char status[32] = {0}; + printClient.readBytesUntil('\r', status, sizeof(status)); + if (strcmp(status, "HTTP/1.1 200 OK") != 0) { + Serial.print(F("Unexpected response: ")); + Serial.println(status); + printerData.state = ""; + printerData.error = "Response: " + String(status); + return printClient; + } + + // Skip HTTP headers + char endOfHeaders[] = "\r\n\r\n"; + if (!printClient.find(endOfHeaders)) { + Serial.println(F("Invalid response")); + printerData.error = "Invalid response from " + String(myServer) + ":" + String(myPort); + printerData.state = ""; + } +*/ + return printClient; +} + + +void RepetierClient::getPrinterJobResults() { + if (!validate()) { + return; + } + //**** get the Printer Job status + String apiGetData = "GET /printer/api/?a=listPrinter&apikey=" + myApiKey; + WiFiClient printClient = getSubmitRequest(apiGetData); + if (printerData.error != "") { + return; + } + const size_t bufferSize = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 2*JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + 710; + DynamicJsonBuffer jsonBuffer(bufferSize); + + // Parse JSON object + JsonArray& root = jsonBuffer.parseArray(printClient); + + if (!root.success()) { + printerData.error = "Repetier Data Parsing failed: " + String(myServer) + ":" + String(myPort); + Serial.println(printerData.error); + printerData.state = ""; + return; + } + + int inx = 0; + int count = root.size(); + Serial.println("Size of root: " + String(count)); + for (int i = 0; i < count; i++) { + Serial.println("Printer: " + String((const char*)root[i]["slug"])); + if (String((const char*)root[i]["slug"]) == printerData.printerName) { + inx = i; + break; + } + } + + JsonObject& pr = root[inx]; + + //printerData.averagePrintTime = (const char*)pr[""]; + printerData.estimatedPrintTime = (const char*)pr["printTime"]; + printerData.fileName = (const char*) pr["job"]; + printerData.fileSize = (const char*) pr["totalLines"]; + //printerData.filamentLength = (const char*) pr[""]; + printerData.state = (const char*) pr["online"]; + //printerData.lastPrintTime = (const char*) pr[""]; + printerData.progressCompletion = (const char*) pr["done"]; + printerData.progressFilepos = (const char*) pr["linesSend"]; + printerData.progressPrintTime = (const char*) pr["printedTimeComp"]; + +//Figure out Time Left + long timeTot=0; + long timeElap=0; + long timeLeft=0; + if (printerData.estimatedPrintTime != "" ) { + timeTot = atol(pr["printTime"]); + } + if (printerData.progressPrintTime != "") { + timeElap= atol(pr["printedTimeComp"]); + } + timeLeft = timeTot-timeElap; + printerData.progressPrintTimeLeft = String(timeLeft); + + if (printerData.fileName != "none") { + printerData.isPrinting = true; + } else { + printerData.isPrinting = false; + } + + if (printerData.isPrinting) { + Serial.println("Printing: " + printerData.fileName); + } + + if (isOperational()) { + Serial.println("Status: " + printerData.state); + } else { + Serial.println("Printer Not Operational"); + } + + //**** get the Printer Temps and Stat + apiGetData = "GET /printer/api/?a=stateList&apikey=" + myApiKey; + printClient = getSubmitRequest(apiGetData); + if (printerData.error != "") { + return; + } + const size_t bufferSize2 = 3*JSON_OBJECT_SIZE(2) + 2*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(9) + 300; + DynamicJsonBuffer jsonBuffer2(bufferSize2); + + //Parse JSON object + JsonObject& root2 = jsonBuffer2.parseObject(printClient); + + //Select printer + JsonObject& pr2 = root2[printerData.printerName]; + + if (!root2.success()) { + printerData.isPrinting = false; + printerData.toolTemp = ""; + printerData.toolTargetTemp = ""; + printerData.bedTemp = ""; + printerData.bedTargetTemp = ""; + return; + } + + printerData.toolTemp = (const char*) pr2["extruder"][0]["tempRead"]; + printerData.toolTargetTemp = (const char*) pr2["extruder"][0]["tempSet"]; + printerData.bedTemp = (const char*) pr2["heatedBeds"][0]["tempRead"]; + printerData.bedTargetTemp = (const char*) pr2["heatedBeds"][0]["tempSet"]; + + if (printerData.isPrinting) { + Serial.println("Status: " + printerData.state + " " + printerData.fileName + "(" + printerData.progressCompletion + "%)"); + } +} + +void RepetierClient::getPrinterPsuState() { + //**** get the PSU state (if enabled and printer operational) + //Not implemented in Repetier Server AFAIK +} + +// Reset all PrinterData +void RepetierClient::resetPrintData() { + printerData.averagePrintTime = ""; + printerData.estimatedPrintTime = ""; + printerData.fileName = ""; + printerData.fileSize = ""; + printerData.lastPrintTime = ""; + printerData.progressCompletion = ""; + printerData.progressFilepos = ""; + printerData.progressPrintTime = ""; + printerData.progressPrintTimeLeft = ""; + printerData.state = ""; + printerData.toolTemp = ""; + printerData.toolTargetTemp = ""; + printerData.filamentLength = ""; + printerData.bedTemp = ""; + printerData.bedTargetTemp = ""; + printerData.isPrinting = false; + printerData.isPSUoff = false; + printerData.error = ""; +} + +String RepetierClient::getAveragePrintTime(){ + return printerData.averagePrintTime; +} + +String RepetierClient::getEstimatedPrintTime() { + return printerData.estimatedPrintTime; +} + +String RepetierClient::getFileName() { + return printerData.fileName; +} + +String RepetierClient::getFileSize() { + return printerData.fileSize; +} + +String RepetierClient::getLastPrintTime(){ + return printerData.lastPrintTime; +} + +String RepetierClient::getProgressCompletion() { + return String(printerData.progressCompletion.toInt()); +} + +String RepetierClient::getProgressFilepos() { + return printerData.progressFilepos; +} + +String RepetierClient::getProgressPrintTime() { + return printerData.progressPrintTime; +} + +String RepetierClient::getProgressPrintTimeLeft() { + String rtnValue = printerData.progressPrintTimeLeft; + if (getProgressCompletion() == "100") { + rtnValue = "0"; // Print is done so this should be 0 this is a fix for OctoPrint + } + return rtnValue; +} + +String RepetierClient::getState() { + String rtnValue = "Offline"; + if (printerData.state == "1") { + rtnValue = "Operational"; + } + return rtnValue; +} + +boolean RepetierClient::isPrinting() { + return printerData.isPrinting; +} + +boolean RepetierClient::isPSUoff() { + return printerData.isPSUoff; +} + +boolean RepetierClient::isOperational() { + boolean operational = false; + if (printerData.state == "1" || isPrinting()) { + operational = true; + } + return operational; +} + +String RepetierClient::getTempBedActual() { + String temp = printerData.bedTemp; + temp.remove(temp.indexOf(".") + 3); + return temp; +} + +String RepetierClient::getTempBedTarget() { + return printerData.bedTargetTemp; +} + +String RepetierClient::getTempToolActual() { + String temp = printerData.toolTemp; + temp.remove(temp.indexOf(".") + 3); + return temp; +} + +String RepetierClient::getTempToolTarget() { + return printerData.toolTargetTemp; +} + +String RepetierClient::getFilamentLength() { + return printerData.filamentLength; +} + +String RepetierClient::getError() { + return printerData.error; +} + +String RepetierClient::getValueRounded(String value) { + float f = value.toFloat(); + int rounded = (int)(f+0.5f); + return String(rounded); +} + +String RepetierClient::getPrinterType() { + return printerType; +} + +int RepetierClient::getPrinterPort() { + return myPort; +} + +String RepetierClient::getPrinterName() { + return printerData.printerName; +} + +void RepetierClient::setPrinterName(String printer) { + printerData.printerName = printer; +} diff --git a/printermonitor/RepetierClient.h b/printermonitor/RepetierClient.h new file mode 100755 index 0000000..7c92105 --- /dev/null +++ b/printermonitor/RepetierClient.h @@ -0,0 +1,104 @@ +/** 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. +*/ + +/* 07 April 2019 : Jon Smith : added class for Repetier Server (kg4iae@github)*/ + + +#pragma once +#include +#include "libs/ArduinoJson/ArduinoJson.h" +#include + +class RepetierClient { + +private: + char myServer[100]; + int myPort = 3344; + String myApiKey = ""; + String encodedAuth = ""; + boolean pollPsu; + const String printerType = "Repetier"; + + void resetPrintData(); + boolean validate(); + WiFiClient getSubmitRequest(String apiGetData); + WiFiClient getPostRequest(String apiPostData, String apiPostBody); + + String result; + + typedef struct { + String averagePrintTime; + String estimatedPrintTime; + String fileName; + String fileSize; + String lastPrintTime; + String progressCompletion; + String progressFilepos; + String progressPrintTime; + String progressPrintTimeLeft; + String state; + String toolTemp; + String toolTargetTemp; + String filamentLength; + String bedTemp; + String bedTargetTemp; + boolean isPrinting; + boolean isPSUoff; + String error; + String printerName; + } PrinterStruct; + + PrinterStruct printerData; + + +public: + RepetierClient(String ApiKey, String server, int port, String user, String pass, boolean psu); + void getPrinterJobResults(); + void getPrinterPsuState(); + void updatePrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu); + + String getAveragePrintTime(); + String getEstimatedPrintTime(); + String getFileName(); + String getFileSize(); + String getLastPrintTime(); + String getProgressCompletion(); + String getProgressFilepos(); + String getProgressPrintTime(); + String getProgressPrintTimeLeft(); + String getState(); + boolean isPrinting(); + boolean isOperational(); + boolean isPSUoff(); + String getTempBedActual(); + String getTempBedTarget(); + String getTempToolActual(); + String getTempToolTarget(); + String getFilamentLength(); + String getValueRounded(String value); + String getError(); + String getPrinterType(); + int getPrinterPort(); + String getPrinterName(); + void setPrinterName(String printer); +}; diff --git a/printermonitor/Settings.h b/printermonitor/Settings.h index d478fec..7821569 100644 --- a/printermonitor/Settings.h +++ b/printermonitor/Settings.h @@ -31,10 +31,10 @@ SOFTWARE. * 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 + * 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. ******************************************************************************/ @@ -45,6 +45,7 @@ SOFTWARE. #include #include #include "TimeClient.h" +#include "RepetierClient.h" #include "OctoPrintClient.h" #include "OpenWeatherMapClient.h" #include "WeatherStationFonts.h" @@ -57,13 +58,14 @@ SOFTWARE. // 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) +// OctoPrint / Repetier Monitoring -- Monitor your 3D OctoPrint or Repetier Server +//#define USE_REPETIER_CLIENT // Uncomment this line to use the Repetier Printer Server -- OctoPrint is used by default and is most common +String PrinterApiKey = ""; // ApiKey from your User Account on OctoPrint / Repetier +String PrinterHostName = "octopi";// Default 'octopi' -- or hostname if different (optional if your IP changes) +String PrinterServer = ""; // IP or Address of your OctoPrint / Repetier Server (DO NOT include http://) +int PrinterPort = 80; // the port you are running your OctoPrint / Repetier server on (usually 80); +String PrinterAuthUser = ""; // only used if you have haproxy or basic athentintication turned on (not default) +String PrinterAuthPass = ""; // 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 @@ -87,6 +89,9 @@ 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 +// Nightmode +boolean USE_NIGHT = false; // Dim the Screen if enabled + // Display Settings const int I2C_DISPLAY_ADDRESS = 0x3c; // I2C Address of your Display (usually 0x3c or 0x3d) const int SDA_PIN = D2; @@ -95,7 +100,8 @@ boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bott //#define DISPLAY_SH1106 // Uncomment this line to use the SH1106 display -- SSD1306 is used by default and is most common // LED Settings -const int externalLight = LED_BUILTIN; // Set to unused pin, like D1, to disable use of built-in LED (LED_BUILTIN) +const int externalLight = LED_BUILTIN; // LED will always flash on bootup or Wifi Errors +boolean USE_FLASH = true; // true = System LED will Flash on Service Calls; false = disabled LED flashing // PSU Control boolean HAS_PSU = false; // Set to true if https://github.com/kantlivelong/OctoPrint-PSUControl/ in use diff --git a/printermonitor/TimeClient.cpp b/printermonitor/TimeClient.cpp index b0753e0..a298ad2 100644 --- a/printermonitor/TimeClient.cpp +++ b/printermonitor/TimeClient.cpp @@ -33,7 +33,7 @@ TimeClient::TimeClient(float utcOffset) { void TimeClient::updateTime() { WiFiClient client; - + if (!client.connect(ntpServerName, httpPort)) { Serial.println("connection failed"); return; @@ -149,4 +149,4 @@ long TimeClient::getCurrentEpoch() { long TimeClient::getCurrentEpochWithUtcOffset() { return (long)round(getCurrentEpoch() + 3600 * myUtcOffset + 86400L) % 86400L; -} +} diff --git a/printermonitor/TimeClient.h b/printermonitor/TimeClient.h index dee7601..6be71bb 100644 --- a/printermonitor/TimeClient.h +++ b/printermonitor/TimeClient.h @@ -40,13 +40,13 @@ class TimeClient { long localEpoc = 0; long localMillisAtUpdate; const char* ntpServerName = "www.google.com"; - const int httpPort = 80; + const int httpPort = 80; byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets public: TimeClient(float utcOffset); void updateTime(); - + void setUtcOffset(float utcOffset); String getHours(); String getAmPmHours(); @@ -59,4 +59,3 @@ class TimeClient { long getCurrentEpochWithUtcOffset(); }; - diff --git a/printermonitor/WeatherStationFonts.h b/printermonitor/WeatherStationFonts.h index 054fccc..d8d3033 100644 --- a/printermonitor/WeatherStationFonts.h +++ b/printermonitor/WeatherStationFonts.h @@ -1298,4 +1298,3 @@ const char Meteocons_Plain_10[] PROGMEM = { 0xFC,0x0F,0x20,0x02,0x10,0x02,0x10,0x02,0xE0,0x01, // 254 0x30,0x08,0xC4,0x04,0x00,0x03,0xC4,0x00,0x30 // 255 }; - diff --git a/printermonitor/printermonitor.ino b/printermonitor/printermonitor.ino index 5fea51d..0855c0f 100644 --- a/printermonitor/printermonitor.ino +++ b/printermonitor/printermonitor.ino @@ -30,9 +30,9 @@ SOFTWARE. #include "Settings.h" -#define VERSION "2.5" +#define VERSION "3.1" -#define HOSTNAME "OctMon-" +#define HOSTNAME "PrintMon-" #define CONFIG "/conf.txt" /* Useful Constants */ @@ -40,8 +40,8 @@ SOFTWARE. #define SECS_PER_HOUR (3600UL) /* Useful Macros for getting elapsed time */ -#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) -#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) +#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) +#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) #define numberOfHours(_time_) (_time_ / SECS_PER_HOUR) // Initialize the oled display for I2C_DISPLAY_ADDRESS @@ -74,7 +74,7 @@ OverlayCallback overlays[] = { drawHeaderOverlay }; OverlayCallback clockOverlay[] = { drawClockHeaderOverlay }; int numberOfOverlays = 1; -// Time +// Time TimeClient timeClient(UtcOffset); long lastEpoch = 0; long firstEpoch = 0; @@ -84,8 +84,12 @@ String lastSecond = "xx"; String lastReportStatus = ""; boolean displayOn = true; -// OctoPrint Client -OctoPrintClient printerClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass, HAS_PSU); +// Printer Client +#if defined(USE_REPETIER_CLIENT) + RepetierClient printerClient(PrinterApiKey, PrinterServer, PrinterPort, PrinterAuthUser, PrinterAuthPass, HAS_PSU); +#else + OctoPrintClient printerClient(PrinterApiKey, PrinterServer, PrinterPort, PrinterAuthUser, PrinterAuthPass, HAS_PSU); +#endif int printerCount = 0; // Weather Client @@ -98,47 +102,43 @@ int8_t getWifiQuality(); ESP8266WebServer server(WEBSERVER_PORT); ESP8266HTTPUpdateServer serverUpdater; -String WEB_ACTIONS = " Home" - " Configure" +static const char WEB_ACTIONS[] PROGMEM = " Home" + " Settings" " Weather" " Reset Settings" " Forget WiFi" " Firmware Update" " About"; - -String CHANGE_FORM = "

Station Config:

" - "

" - "

" - "

" - "

" - "

" - "


" - "

Display Clock when printer is off

" + +String CHANGE_FORM = ""; // moved to config to make it dynamic + +static const char CLOCK_FORM[] PROGMEM = "

Display Clock when printer is operational or off

" "

Use 24 Hour Clock (military time)

" + "

Night Mode (Dim the Screen)

" "

Flip display orientation

" + "

Flash System LED on Service Calls

" "

Use OctoPrint PSU control plugin for clock/blank

" "

Clock Sync / Weather Refresh (minutes)

"; - -String THEME_FORM = "

Theme Color

" + +static const char THEME_FORM[] PROGMEM = "

Theme Color

" "


" "

Use Security Credentials for Configuration Changes

" "

" "

" "
"; -String WEATHER_FORM = "

Weather Config:

" +static const char WEATHER_FORM[] PROGMEM = "

Weather Config:

" "

Display Weather when printer is off

" "" "" - "

" + "

" "

Use Metric (Celsius)

" - "

Weather Language

" + "

Weather Language (for the Weather Descriptions, mostly)

" "
" ""; -String LANG_OPTIONS = "" +static const char LANG_OPTIONS[] PROGMEM = "" "" "" "" @@ -172,7 +172,7 @@ String LANG_OPTIONS = "" "" ""; -String COLOR_THEMES = "" +static const char COLOR_THEMES[] PROGMEM = "" "" "" "" @@ -195,19 +195,22 @@ String COLOR_THEMES = "" "" "" ""; - + 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); + //Some Defaults before loading from Config.txt + PrinterPort = printerClient.getPrinterPort(); + readSettings(); // initialize display @@ -222,17 +225,17 @@ void setup() { 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.drawString(64, 5, "Printer Monitor\nfor " + printerClient.getPrinterType() + "\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 @@ -241,7 +244,7 @@ void setup() { ESP.reset(); delay(5000); } - + // You can change the transition that is used // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN ui.setFrameAnimation(SLIDE_LEFT); @@ -254,13 +257,13 @@ void setup() { 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()); @@ -284,7 +287,7 @@ void setup() { 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()); + ArduinoOTA.setHostname((const char *)hostname.c_str()); if (OTA_Password != "") { ArduinoOTA.setPassword(((const char *)OTA_Password.c_str())); } @@ -311,7 +314,7 @@ void setup() { 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.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)); @@ -323,45 +326,45 @@ void setup() { display.setFont(ArialMT_Plain_10); display.drawString(64, 10, "Web Interface is Off"); display.drawString(64, 20, "Enable in Settings.h"); - display.display(); + display.display(); } - flashLED(5, 500); - findMDNS(); //go find Octoprint Server by the hostname + flashLED(5, 100); + findMDNS(); //go find Printer Server by the hostname Serial.println("*** Leaving setup()"); } void findMDNS() { - if (OctoPrintHostName == "" || ENABLE_OTA == false) { + if (PrinterHostName == "" || ENABLE_OTA == false) { 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"); + Serial.println("no services found - make sure Printer server is turned on"); return; } - Serial.println("*** Looking for " + OctoPrintHostName + " over mDNS"); + Serial.println("*** Looking for " + PrinterHostName + " 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) { + if (MDNS.hostname(i) == PrinterHostName) { IPAddress serverIp = MDNS.IP(i); - OctoPrintServer = serverIp.toString(); - OctoPrintPort = MDNS.port(i); // save the port - Serial.println("*** Found OctoPrint Server " + OctoPrintHostName + " http://" + OctoPrintServer + ":" + OctoPrintPort); + PrinterServer = serverIp.toString(); + PrinterPort = MDNS.port(i); // save the port + Serial.println("*** Found Printer Server " + PrinterHostName + " http://" + PrinterServer + ":" + PrinterPort); writeSettings(); // update the settings } } } //************************************************************ -// Main Looop +// Main Loop //************************************************************ void loop() { - + //Get Time Update if((getMinutesFromLastRefresh() >= minutesBetweenDataRefresh) || lastEpoch == 0) { getUpdateTime(); @@ -369,19 +372,19 @@ void loop() { if (lastMinute != timeClient.getMinutes() && !printerClient.isPrinting()) { // Check status every 60 seconds - digitalWrite(externalLight, LOW); + ledOnOff(true); lastMinute = timeClient.getMinutes(); // reset the check value printerClient.getPrinterJobResults(); printerClient.getPrinterPsuState(); - digitalWrite(externalLight, HIGH); + ledOnOff(false); } 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); + ledOnOff(true); printerClient.getPrinterJobResults(); printerClient.getPrinterPsuState(); - digitalWrite(externalLight, HIGH); + ledOnOff(false); } } @@ -398,7 +401,7 @@ void loop() { } void getUpdateTime() { - digitalWrite(externalLight, LOW); // turn on the LED + ledOnOff(true); // turn on the LED Serial.println(); if (displayOn && DISPLAYWEATHER) { @@ -412,13 +415,13 @@ void getUpdateTime() { lastEpoch = timeClient.getCurrentEpoch(); Serial.println("Local time: " + timeClient.getAmPmFormattedTime()); - digitalWrite(externalLight, HIGH); // turn off the LED + ledOnOff(false); // 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 } @@ -454,15 +457,20 @@ void handleUpdateConfig() { if (!authentication()) { 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"); + if (server.hasArg("printer")) { + printerClient.setPrinterName(server.arg("printer")); + } + PrinterApiKey = server.arg("PrinterApiKey"); + PrinterHostName = server.arg("PrinterHostName"); + PrinterServer = server.arg("PrinterAddress"); + PrinterPort = server.arg("PrinterPort").toInt(); + PrinterAuthUser = server.arg("octoUser"); + PrinterAuthPass = server.arg("octoPass"); DISPLAYCLOCK = server.hasArg("isClockEnabled"); IS_24HOUR = server.hasArg("is24hour"); + USE_NIGHT = server.hasArg("useNight"); INVERT_DISPLAY = server.hasArg("invDisp"); + USE_FLASH = server.hasArg("useFlash"); HAS_PSU = server.hasArg("hasPSU"); minutesBetweenDataRefresh = server.arg("refresh").toInt(); themeColor = server.arg("theme"); @@ -477,7 +485,7 @@ void handleUpdateConfig() { printerClient.getPrinterPsuState(); if (INVERT_DISPLAY != flipOld) { ui.init(); - if(INVERT_DISPLAY) + if(INVERT_DISPLAY) display.flipScreenVertically(); ui.update(); } @@ -502,7 +510,7 @@ void handleWeatherConfigure() { if (!authentication()) { return server.requestAuthentication(); } - digitalWrite(externalLight, LOW); + ledOnOff(true); String html = ""; server.sendHeader("Cache-Control", "no-cache, no-store"); @@ -513,8 +521,8 @@ void handleWeatherConfigure() { html = getHeader(); server.sendContent(html); - - String form = WEATHER_FORM; + + String form = FPSTR(WEATHER_FORM); String isWeatherChecked = ""; if (DISPLAYWEATHER) { isWeatherChecked = "checked='checked'"; @@ -528,23 +536,23 @@ void handleWeatherConfigure() { checked = "checked='checked'"; } form.replace("%METRIC%", checked); - String options = LANG_OPTIONS; + String options = FPSTR(LANG_OPTIONS); options.replace(">"+String(WeatherLanguage)+"<", " selected>"+String(WeatherLanguage)+"<"); form.replace("%LANGUAGEOPTIONS%", options); server.sendContent(form); - + html = getFooter(); server.sendContent(html); server.sendContent(""); server.client().stop(); - digitalWrite(externalLight, HIGH); + ledOnOff(false); } void handleConfigure() { if (!authentication()) { return server.requestAuthentication(); } - digitalWrite(externalLight, LOW); + ledOnOff(true); String html = ""; server.sendHeader("Cache-Control", "no-cache, no-store"); @@ -555,20 +563,74 @@ void handleConfigure() { html = getHeader(); server.sendContent(html); - + + CHANGE_FORM = "

Settings:

" + "

" + "

"; + if (printerClient.getPrinterType() == "OctoPrint") { + CHANGE_FORM += "

"; + } + CHANGE_FORM += "

" + "

" + "

" + "

"; + if (printerClient.getPrinterType() == "Repetier") { + CHANGE_FORM += //"" + "

" + "

" + ""; + } else { + CHANGE_FORM += //"

" + "

"; + } + CHANGE_FORM += "

" + "

"; + + + + if (printerClient.getPrinterType() == "Repetier") { + html = ""; + + server.sendContent(html); + } else { + html = ""; + 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); + + form.replace("%OCTOKEY%", PrinterApiKey); + form.replace("%OCTOHOST%", PrinterHostName); + form.replace("%OCTOADDRESS%", PrinterServer); + form.replace("%OCTOPORT%", String(PrinterPort)); + form.replace("%OCTOUSER%", PrinterAuthUser); + form.replace("%OCTOPASS%", PrinterAuthPass); + + server.sendContent(form); + + form = FPSTR(CLOCK_FORM); + String isClockChecked = ""; if (DISPLAYCLOCK) { isClockChecked = "checked='checked'"; } form.replace("%IS_CLOCK_CHECKED%", isClockChecked); + String isNightchecked = ""; + if (USE_NIGHT) { + isNightchecked = "checked='checked'"; + } + form.replace("%USENIGHT%", isNightchecked); String is24hourChecked = ""; if (IS_24HOUR) { is24hourChecked = "checked='checked'"; @@ -579,21 +641,26 @@ void handleConfigure() { isInvDisp = "checked='checked'"; } form.replace("%IS_INVDISP_CHECKED%", isInvDisp); + String isFlashLED = ""; + if (USE_FLASH) { + isFlashLED = "checked='checked'"; + } + form.replace("%USEFLASH%", isFlashLED); String hasPSUchecked = ""; if (HAS_PSU) { hasPSUchecked = "checked='checked'"; } form.replace("%HAS_PSU_CHECKED%", hasPSUchecked); - + String options = ""; options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<"); form.replace("%OPTIONS%", options); server.sendContent(form); - form = THEME_FORM; - - String themeOptions = COLOR_THEMES; + form = FPSTR(THEME_FORM); + + String themeOptions = FPSTR(COLOR_THEMES); themeOptions.replace(">"+String(themeColor)+"<", " selected>"+String(themeColor)+"<"); form.replace("%THEME_OPTIONS%", themeOptions); form.replace("%UTCOFFSET%", String(UtcOffset)); @@ -606,16 +673,16 @@ void handleConfigure() { form.replace("%STATIONPASSWORD%", String(www_password)); server.sendContent(form); - + html = getFooter(); server.sendContent(html); server.sendContent(""); server.client().stop(); - digitalWrite(externalLight, HIGH); + ledOnOff(false); } void displayMessage(String message) { - digitalWrite(externalLight, LOW); + ledOnOff(true); server.sendHeader("Cache-Control", "no-cache, no-store"); server.sendHeader("Pragma", "no-cache"); @@ -629,8 +696,8 @@ void displayMessage(String message) { server.sendContent(String(html)); server.sendContent(""); server.client().stop(); - - digitalWrite(externalLight, HIGH); + + ledOnOff(false); } void redirectHome() { @@ -648,10 +715,11 @@ String getHeader() { } String getHeader(boolean refresh) { - String menu = WEB_ACTIONS; + String menu = FPSTR(WEB_ACTIONS); String html = ""; html += "Printer Monitor"; + html += ""; html += ""; html += ""; if (refresh) { @@ -696,7 +764,7 @@ String getFooter() { } void displayPrinterStatus() { - digitalWrite(externalLight, LOW); + ledOnOff(true); String html = ""; server.sendHeader("Cache-Control", "no-cache, no-store"); @@ -710,21 +778,32 @@ void displayPrinterStatus() { if (IS_24HOUR) { displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); } - - html += "

Time: " + displayTime + "

"; + + html += "

" + printerClient.getPrinterType() + " Monitor

"; html += "

"; - html += "Host Name: " + OctoPrintHostName + "
"; + if (printerClient.getPrinterType() == "Repetier") { + html += "Drucker Name: " + printerClient.getPrinterName() + "
"; + } else { + html += "Host Name: " + PrinterHostName + "
"; + } + if (printerClient.getError() != "") { html += "Status: Offline
"; html += "Reason: " + printerClient.getError() + "
"; } else { - html += "Status: " + printerClient.getState(); - if (printerClient.isPSUoff() && HAS_PSU) { - html += ", PSU off"; + html += "Status: " ; + if (printerClient.isPSUoff() && HAS_PSU) { + html += printerClient.getState() + ", PSU off"; + } + if (printerClient.isPrinting()) { + html += "Printing"; + } + else { + html += printerClient.getState(); } html += "
"; } - + if (printerClient.isPrinting()) { html += "File: " + printerClient.getFileName() + "
"; float fileSize = printerClient.getFileSize().toFloat(); @@ -737,31 +816,32 @@ void displayPrinterStatus() { float fLength = float(filamentLength) / 1000; html += "Filament: " + String(fLength) + "m
"; } - + html += "Tool Temperature: " + printerClient.getTempToolActual() + "° C
"; if ( printerClient.getTempBedActual() != 0 ) { html += "Bed Temperature: " + printerClient.getTempBedActual() + "° C
"; } - + int val = printerClient.getProgressPrintTimeLeft().toInt(); 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(); hours = numberOfHours(val); minutes = numberOfMinutes(val); seconds = numberOfSeconds(val); html += "Printing Time: " + zeroPad(hours) + ":" + zeroPad(minutes) + ":" + zeroPad(seconds) + "
"; - html += ""; - html += "

" + printerClient.getProgressCompletion() + "%
"; + html += "
" + printerClient.getProgressCompletion() + "%
"; } else { html += "
"; } html += "

"; + html += "

Time: " + displayTime + "

"; + server.sendContent(html); // spit out what we got html = ""; @@ -772,19 +852,17 @@ void displayPrinterStatus() { 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 += "

" + weatherClient.getCity(0) + ", " + weatherClient.getTempRounded(0) + getTempSymbol(true) +"

"; + html += "
"; + html += "" + weatherClient.getDescription(0) + "" +getTranslate() +"
"; + html += weatherClient.getDescription(0) + "
"; + html += "" + weatherClient.getHumidity(0) + "% Humidity
"; + html += "" + weatherClient.getWind(0) + "" + getSpeedSymbol() + " Wind
"; + html += " Map It!
"; + html += "
"; 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 } @@ -792,7 +870,7 @@ void displayPrinterStatus() { server.sendContent(String(getFooter())); server.sendContent(""); server.client().stop(); - digitalWrite(externalLight, HIGH); + ledOnOff(false); } void configModeCallback (WiFiManager *myWiFiManager) { @@ -809,7 +887,7 @@ void configModeCallback (WiFiManager *myWiFiManager) { 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()); @@ -817,12 +895,22 @@ void configModeCallback (WiFiManager *myWiFiManager) { flashLED(20, 50); } +void ledOnOff(boolean value) { + if (USE_FLASH) { + if (value) { + digitalWrite(externalLight, LOW); // LED ON + } else { + digitalWrite(externalLight, HIGH); // LED OFF + } + } +} + void flashLED(int number, int delayTime) { - for (int inx = 0; inx < number; inx++) { + for (int inx = 0; inx <= number; inx++) { delay(delayTime); - digitalWrite(externalLight, LOW); + digitalWrite(externalLight, LOW); // ON delay(delayTime); - digitalWrite(externalLight, HIGH); + digitalWrite(externalLight, HIGH); // OFF delay(delayTime); } } @@ -830,19 +918,36 @@ void flashLED(int number, int delayTime) { void drawScreen1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { String bed = printerClient.getValueRounded(printerClient.getTempBedActual()); String tool = printerClient.getValueRounded(printerClient.getTempToolActual()); + + // Nightmode, dim the Display. 0 is the darkest and 255 the brightest + if (USE_NIGHT) { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(0); // default is 0 + } + } else { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(255); // default is 255 + } + } display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_16); if (bed != "0") { - display->drawString(64 + x, 0 + y, "Bed / Tool Temp"); + display->drawString(25 + x, 0 + y, "Tool"); + display->drawString(91 + x, 0 + y, "Bed"); } else { display->drawString(64 + x, 0 + y, "Tool Temp"); } display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(ArialMT_Plain_24); if (bed != "0") { + display->setTextAlignment(TEXT_ALIGN_RIGHT); + display->drawString(50 + x, 14 + y, tool + "°"); display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawString(2 + x, 14 + y, bed + "°"); - display->drawString(64 + x, 14 + y, tool + "°"); + display->drawString(76 + x, 14 + y, bed + "°"); } else { display->setTextAlignment(TEXT_ALIGN_CENTER); display->drawString(64 + x, 14 + y, tool + "°"); @@ -850,22 +955,65 @@ void drawScreen1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int } void drawScreen2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + + // Nightmode, dim the Display. 0 is the darkest and 255 the brightest + if (USE_NIGHT) { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(0); // default is 255 + } + } else { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(255); // default is 255 + } + } display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_16); display->drawString(64 + x, 0 + y, "Time Remaining"); - //display->setTextAlignment(TEXT_ALIGN_LEFT); + + display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(ArialMT_Plain_24); int val = printerClient.getProgressPrintTimeLeft().toInt(); int hours = numberOfHours(val); + String hour = zeroPad(hours); + display->drawString(22 + x, 14 + y, hour); + + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_10); + display->drawString(50 + x, 26 + y, "hr"); + + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_24); int minutes = numberOfMinutes(val); - int seconds = numberOfSeconds(val); + String minute = zeroPad(minutes); + display->drawString(72 + x, 14 + y, minute); + + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_10); + display->drawString(100 + x, 26 + y, "min."); - 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) { + + // Nightmode, dim the Display. 0 is the darkest and 255 the brightest + if (USE_NIGHT) { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(0); // default is 255 + } + } else { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(255); // default is 255 + } + } display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_16); @@ -882,19 +1030,53 @@ void drawScreen3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int } void drawClock(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + + // Nightmode, dim the Display. 0 is the darkest and 255 the brightest + if (USE_NIGHT) { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(0); // default is 255 + } + } else { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(255); // default is 255 + } + } display->setTextAlignment(TEXT_ALIGN_CENTER); - + String displayTime = timeClient.getAmPmHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); if (IS_24HOUR) { - displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); + displayTime = timeClient.getHours() + ":" + timeClient.getMinutes() + ":" + timeClient.getSeconds(); + } + String displayName = PrinterHostName; + if (printerClient.getPrinterType() == "Repetier") { + displayName = printerClient.getPrinterName(); } display->setFont(ArialMT_Plain_16); - display->drawString(64 + x, 0 + y, OctoPrintHostName); + display->drawString(64 + x, 0 + y, displayName); display->setFont(ArialMT_Plain_24); display->drawString(64 + x, 17 + y, displayTime); } void drawWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + + // Nightmode, dim the Display. 0 is the darkest and 255 the brightest + if (USE_NIGHT) { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(0); // default is 255 + } + } else { + if (!displayOn) { + enableDisplay(false); + } else { + display->setBrightness(255); // default is 255 + } + } display->setTextAlignment(TEXT_ALIGN_LEFT); display->setFont(ArialMT_Plain_24); display->drawString(0 + x, 0 + y, weatherClient.getTempRounded(0) + getTempSymbol()); @@ -902,7 +1084,7 @@ void drawWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int display->setFont(ArialMT_Plain_24); display->setFont(ArialMT_Plain_16); - display->drawString(0 + x, 24 + y, weatherClient.getCondition(0)); + display->drawString(0 + x, 24 + y, getTranslate()); display->setFont((const uint8_t*)Meteocons_Plain_42); display->drawString(86 + x, 0 + y, weatherClient.getWeatherIcon(0)); } @@ -949,7 +1131,7 @@ void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { } display->setTextAlignment(TEXT_ALIGN_LEFT); display->drawString(0, 48, displayTime); - + if (!IS_24HOUR) { String ampm = timeClient.getAmPm(); display->setFont(ArialMT_Plain_10); @@ -960,7 +1142,7 @@ void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { 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); @@ -968,7 +1150,7 @@ void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { display->drawHorizontalLine(0, 43, updatePos); display->drawHorizontalLine(0, 44, updatePos); display->drawHorizontalLine(0, 45, updatePos); - + drawRssi(display); } @@ -981,25 +1163,29 @@ void drawClockHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { display->setTextAlignment(TEXT_ALIGN_CENTER); if (printerClient.isPSUoff()) { display->drawString(64, 47, "psu off"); + } else if (printerClient.getState() == "Operational") { + display->drawString(64, 47, "Operational"); } else { display->drawString(64, 47, "offline"); } } else { if (printerClient.isPSUoff()) { display->drawString(0, 47, "psu off"); + } else if (printerClient.getState() == "Operational") { + display->drawString(0, 47, "Operational"); } else { display->drawString(0, 47, "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++) { @@ -1031,20 +1217,23 @@ void writeSettings() { } 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("printerApiKey=" + PrinterApiKey); + f.println("printerHostName=" + PrinterHostName); + f.println("printerServer=" + PrinterServer); + f.println("printerPort=" + String(PrinterPort)); + f.println("printerName=" + printerClient.getPrinterName()); + f.println("printerAuthUser=" + PrinterAuthUser); + f.println("printerAuthPass=" + PrinterAuthPass); 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)); + f.println("USE_NIGHT=" + String(USE_NIGHT)); f.println("is24hour=" + String(IS_24HOUR)); f.println("invertDisp=" + String(INVERT_DISPLAY)); + f.println("USE_FLASH=" + String(USE_FLASH)); f.println("isWeather=" + String(DISPLAYWEATHER)); f.println("weatherKey=" + WeatherApiKey); f.println("CityID=" + String(CityIDs[0])); @@ -1072,34 +1261,40 @@ void readSettings() { 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("printerApiKey=") >= 0) { + PrinterApiKey = line.substring(line.lastIndexOf("printerApiKey=") + 14); + PrinterApiKey.trim(); + Serial.println("PrinterApiKey=" + PrinterApiKey); } - if (line.indexOf("octoHost=") >= 0) { - OctoPrintHostName = line.substring(line.lastIndexOf("octoHost=") + 9); - OctoPrintHostName.trim(); - Serial.println("OctoPrintHostName=" + OctoPrintHostName); + if (line.indexOf("printerHostName=") >= 0) { + PrinterHostName = line.substring(line.lastIndexOf("printerHostName=") + 16); + PrinterHostName.trim(); + Serial.println("PrinterHostName=" + PrinterHostName); } - if (line.indexOf("octoServer=") >= 0) { - OctoPrintServer = line.substring(line.lastIndexOf("octoServer=") + 11); - OctoPrintServer.trim(); - Serial.println("OctoPrintServer=" + OctoPrintServer); + if (line.indexOf("printerServer=") >= 0) { + PrinterServer = line.substring(line.lastIndexOf("printerServer=") + 14); + PrinterServer.trim(); + Serial.println("PrinterServer=" + PrinterServer); } - if (line.indexOf("octoPort=") >= 0) { - OctoPrintPort = line.substring(line.lastIndexOf("octoPort=") + 9).toInt(); - Serial.println("OctoPrintPort=" + String(OctoPrintPort)); + if (line.indexOf("printerPort=") >= 0) { + PrinterPort = line.substring(line.lastIndexOf("printerPort=") + 12).toInt(); + Serial.println("PrinterPort=" + String(PrinterPort)); } - if (line.indexOf("octoUser=") >= 0) { - OctoAuthUser = line.substring(line.lastIndexOf("octoUser=") + 9); - OctoAuthUser.trim(); - Serial.println("OctoAuthUser=" + OctoAuthUser); + if (line.indexOf("printerName=") >= 0) { + String printer = line.substring(line.lastIndexOf("printerName=") + 12); + printer.trim(); + printerClient.setPrinterName(printer); + Serial.println("PrinterName=" + printerClient.getPrinterName()); } - if (line.indexOf("octoPass=") >= 0) { - OctoAuthPass = line.substring(line.lastIndexOf("octoPass=") + 9); - OctoAuthPass.trim(); - Serial.println("OctoAuthPass=" + OctoAuthPass); + if (line.indexOf("printerAuthUser=") >= 0) { + PrinterAuthUser = line.substring(line.lastIndexOf("printerAuthUser=") + 16); + PrinterAuthUser.trim(); + Serial.println("PrinterAuthUser=" + PrinterAuthUser); + } + if (line.indexOf("printerAuthPass=") >= 0) { + PrinterAuthPass = line.substring(line.lastIndexOf("printerAuthPass=") + 16); + PrinterAuthPass.trim(); + Serial.println("PrinterAuthPass=" + PrinterAuthPass); } if (line.indexOf("refreshRate=") >= 0) { minutesBetweenDataRefresh = line.substring(line.lastIndexOf("refreshRate=") + 12).toInt(); @@ -1130,6 +1325,10 @@ void readSettings() { DISPLAYCLOCK = line.substring(line.lastIndexOf("DISPLAYCLOCK=") + 13).toInt(); Serial.println("DISPLAYCLOCK=" + String(DISPLAYCLOCK)); } + if(line.indexOf("USE_NIGHT=") >= 0) { + USE_NIGHT = line.substring(line.lastIndexOf("USE_NIGHT=") + 10).toInt(); + Serial.println("USE_NIGHT=" + String(USE_NIGHT)); + } if (line.indexOf("is24hour=") >= 0) { IS_24HOUR = line.substring(line.lastIndexOf("is24hour=") + 9).toInt(); Serial.println("IS_24HOUR=" + String(IS_24HOUR)); @@ -1138,6 +1337,10 @@ void readSettings() { INVERT_DISPLAY = line.substring(line.lastIndexOf("invertDisp=") + 11).toInt(); Serial.println("INVERT_DISPLAY=" + String(INVERT_DISPLAY)); } + if(line.indexOf("USE_FLASH=") >= 0) { + USE_FLASH = line.substring(line.lastIndexOf("USE_FLASH=") + 10).toInt(); + Serial.println("USE_FLASH=" + String(USE_FLASH)); + } if (line.indexOf("hasPSU=") >= 0) { HAS_PSU = line.substring(line.lastIndexOf("hasPSU=") + 7).toInt(); Serial.println("HAS_PSU=" + String(HAS_PSU)); @@ -1166,7 +1369,7 @@ void readSettings() { } } fr.close(); - printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass, HAS_PSU); + printerClient.updatePrintClient(PrinterApiKey, PrinterServer, PrinterPort, PrinterAuthUser, PrinterAuthPass, HAS_PSU); weatherClient.updateWeatherApiKey(WeatherApiKey); weatherClient.updateLanguage(WeatherLanguage); weatherClient.setMetric(IS_METRIC); @@ -1201,7 +1404,7 @@ void checkDisplay() { delay(5000); enableDisplay(false); Serial.println("Printer is offline going down to sleep..."); - return; + return; } else if (!displayOn && !DISPLAYCLOCK) { if (printerClient.isOperational()) { // Wake the Screen up @@ -1218,7 +1421,7 @@ void checkDisplay() { return; } } else if (DISPLAYCLOCK) { - if ((!printerClient.isOperational() || printerClient.isPSUoff()) && !isClockOn) { + if ((!printerClient.isPrinting() || printerClient.isPSUoff()) && !isClockOn) { Serial.println("Clock Mode is turned on."); if (!DISPLAYWEATHER) { ui.disableAutoTransition(); @@ -1232,7 +1435,7 @@ void checkDisplay() { } ui.setOverlays(clockOverlay, numberOfOverlays); isClockOn = true; - } else if (printerClient.isOperational() && !printerClient.isPSUoff() && isClockOn) { + } else if (printerClient.isPrinting() && !printerClient.isPSUoff() && isClockOn) { Serial.println("Printer Monitor is active."); ui.setFrames(frames, numberOfFrames); ui.setOverlays(overlays, numberOfOverlays); @@ -1258,3 +1461,44 @@ void enableDisplay(boolean enable) { displayOffEpoch = lastEpoch; } } + +// Weather String Translation +String getTranslate() { + String rtnValue = ""; + if (WeatherLanguage == "de") { //If Language set to German + if (weatherClient.getCondition(0) == "Clear") { + rtnValue = "Klar"; + } else if (weatherClient.getCondition(0) == "Clouds") { + rtnValue = "Wolken"; + } else if (weatherClient.getCondition(0) == "Rain") { + rtnValue = "Regen"; + } else if (weatherClient.getCondition(0) == "Snow") { + rtnValue = "Schnee"; + } else if (weatherClient.getCondition(0) == "Drizzle") { + rtnValue = "Nieseln"; + } else if (weatherClient.getCondition(0) == "Thunderstorm") { + rtnValue = "Gewitter"; + } else if (weatherClient.getCondition(0) == "Mist") { + rtnValue = "Nebel"; + } else if (weatherClient.getCondition(0) == "Smoke") { + rtnValue = "Rauch"; + } else if (weatherClient.getCondition(0) == "Haze") { + rtnValue = "Dunst"; + } else if (weatherClient.getCondition(0) == "Dust") { + rtnValue = "Staub"; + } else if (weatherClient.getCondition(0) == "Fog") { + rtnValue = "Nebel"; + } else if (weatherClient.getCondition(0) == "Sand") { + rtnValue = "Sand"; + } else if (weatherClient.getCondition(0) == "Ash") { + rtnValue = "Asche"; + } else if (weatherClient.getCondition(0) == "Squall") { + rtnValue = "Böen"; + } else if (weatherClient.getCondition(0) == "Tornado") { + rtnValue = "Tornado"; + } + } else { + rtnValue = weatherClient.getCondition(0); //Else choose the set Language + } + return rtnValue; +} diff --git a/printermonitor_d1_mini_SH1106-3.1.bin b/printermonitor_d1_mini_SH1106-3.1.bin new file mode 100644 index 0000000..9942ca3 Binary files /dev/null and b/printermonitor_d1_mini_SH1106-3.1.bin differ diff --git a/printermonitor_d1_mini_SSD1306-3.1.bin b/printermonitor_d1_mini_SSD1306-3.1.bin new file mode 100644 index 0000000..39ca740 Binary files /dev/null and b/printermonitor_d1_mini_SSD1306-3.1.bin differ