Merge pull request #69 from easytarget/master

Add ability to respect PSU status if psucontrol plugin is used.
pull/70/head
Qrome 2019-01-16 19:54:26 -07:00 committed by GitHub
commit 336ea9abd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 175 additions and 25 deletions

View File

@ -41,6 +41,7 @@ SOFTWARE.
* Supports OTA (loading firmware over WiFi connection on same LAN)
* Basic Authentication to protect your settings
* Version 2.2 added the ability to update firmware through web interface from a compiled binary
* Can query the Octoprint [PSU Control plugin](https://plugins.octoprint.org/plugins/psucontrol/) to enter clock or blank mode when PSU is off
* Video: https://youtu.be/niRv9SCgAPk
* Detailed build video by Chris Riley: https://youtu.be/Rm-l1FSuJpI

View File

@ -21,13 +21,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/* 15 Jan 2019 : Owen Carter : Add psucontrol query via POST api call */
#include "OctoPrintClient.h"
OctoPrintClient::OctoPrintClient(String ApiKey, String server, int port, String user, String pass) {
updateOctoPrintClient(ApiKey, server, port, user, pass);
OctoPrintClient::OctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu) {
updateOctoPrintClient(ApiKey, server, port, user, pass, psu);
}
void OctoPrintClient::updateOctoPrintClient(String ApiKey, String server, int port, String user, String pass) {
void OctoPrintClient::updateOctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu) {
server.toCharArray(myServer, 100);
myApiKey = ApiKey;
myPort = port;
@ -37,6 +39,7 @@ void OctoPrintClient::updateOctoPrintClient(String ApiKey, String server, int po
base64 b64;
encodedAuth = b64.encode(userpass, true);
}
pollPsu = psu;
}
boolean OctoPrintClient::validate() {
@ -58,7 +61,7 @@ WiFiClient OctoPrintClient::getSubmitRequest(String apiGetData) {
WiFiClient printClient;
printClient.setTimeout(5000);
Serial.println("Getting Octoprint Data");
Serial.println("Getting Octoprint Data via GET");
Serial.println(apiGetData);
result = "";
if (printClient.connect(myServer, myPort)) { //starts client connection, checks for connection
@ -109,18 +112,76 @@ WiFiClient OctoPrintClient::getSubmitRequest(String apiGetData) {
return printClient;
}
WiFiClient OctoPrintClient::getPostRequest(String apiPostData, String apiPostBody) {
WiFiClient printClient;
printClient.setTimeout(5000);
Serial.println("Getting Octoprint Data via POST");
Serial.println(apiPostData + " | " + apiPostBody);
result = "";
if (printClient.connect(myServer, myPort)) { //starts client connection, checks for connection
printClient.println(apiPostData);
printClient.println("Host: " + String(myServer) + ":" + String(myPort));
printClient.println("Connection: close");
printClient.println("X-Api-Key: " + myApiKey);
if (encodedAuth != "") {
printClient.print("Authorization: ");
printClient.println("Basic " + encodedAuth);
}
printClient.println("User-Agent: ArduinoWiFi/1.1");
printClient.println("Content-Type: application/json");
printClient.print("Content-Length: ");
printClient.println(apiPostBody.length());
printClient.println();
printClient.println(apiPostBody);
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 OctoPrint failed: " + String(myServer) + ":" + String(myPort)); //error message if no client connect
Serial.println();
resetPrintData();
printerData.error = "Connection to OctoPrint 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 && strcmp(status, "HTTP/1.1 409 CONFLICT") != 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 OctoPrintClient::getPrinterJobResults() {
if (!validate()) {
return;
}
//**** get the Printer Job status
String apiGetData = "GET /api/job HTTP/1.1";
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);
@ -148,7 +209,7 @@ void OctoPrintClient::getPrinterJobResults() {
if (isOperational()) {
Serial.println("Status: " + printerData.state);
} else {
Serial.println("Printer Not Opperational");
Serial.println("Printer Not Operational");
}
//**** get the Printer Temps and Stat
@ -183,8 +244,42 @@ void OctoPrintClient::getPrinterJobResults() {
if (isPrinting()) {
Serial.println("Status: " + printerData.state + " " + printerData.fileName + "(" + printerData.progressCompletion + "%)");
}
}
printClient.stop(); //stop client
void OctoPrintClient::getPrinterPsuState() {
//**** get the PSU state (if enabled and printer operational)
if (pollPsu && isOperational()) {
if (!validate()) {
printerData.isPSUoff = false; // we do not know PSU state, so assume on.
return;
}
String apiPostData = "POST /api/plugin/psucontrol HTTP/1.1";
String apiPostBody = "{\"command\":\"getPSUState\"}";
WiFiClient printClient = getPostRequest(apiPostData,apiPostBody);
if (printerData.error != "") {
printerData.isPSUoff = false; // we do not know PSU state, so assume on.
return;
}
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
} else {
printerData.isPSUoff = true; // PSU checked and is off, set flag
}
printClient.stop(); //stop client
} else {
printerData.isPSUoff = false; // we are not checking PSU state, so assume on
}
}
// Reset all PrinterData
@ -205,6 +300,7 @@ void OctoPrintClient::resetPrintData() {
printerData.bedTemp = "";
printerData.bedTargetTemp = "";
printerData.isPrinting = false;
printerData.isPSUoff = false;
printerData.error = "";
}
@ -256,6 +352,10 @@ boolean OctoPrintClient::isPrinting() {
return printerData.isPrinting;
}
boolean OctoPrintClient::isPSUoff() {
return printerData.isPSUoff;
}
boolean OctoPrintClient::isOperational() {
boolean operational = false;
if (printerData.state == "Operational" || isPrinting()) {

View File

@ -21,6 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/* 15 Jan 2019 : Owen Carter : Add psucontrol query via POST api call */
#pragma once
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
@ -33,10 +35,12 @@ private:
int myPort = 80;
String myApiKey = "";
String encodedAuth = "";
boolean pollPsu;
void resetPrintData();
boolean validate();
WiFiClient getSubmitRequest(String apiGetData);
WiFiClient getPostRequest(String apiPostData, String apiPostBody);
String result;
@ -57,6 +61,7 @@ private:
String bedTemp;
String bedTargetTemp;
boolean isPrinting;
boolean isPSUoff;
String error;
} PrinterStruct;
@ -64,9 +69,10 @@ private:
public:
OctoPrintClient(String ApiKey, String server, int port, String user, String pass);
OctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu);
void getPrinterJobResults();
void updateOctoPrintClient(String ApiKey, String server, int port, String user, String pass);
void getPrinterPsuState();
void updateOctoPrintClient(String ApiKey, String server, int port, String user, String pass, boolean psu);
String getAveragePrintTime();
String getEstimatedPrintTime();
@ -80,6 +86,7 @@ public:
String getState();
boolean isPrinting();
boolean isOperational();
boolean isPSUoff();
String getTempBedActual();
String getTempBedTarget();
String getTempToolActual();

View File

@ -21,6 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/* 15 Jan 2019 : Owen Carter : Add psucontrol setting */
/******************************************************************************
* Printer Monitor is designed for the Wemos D1 ESP8266
* Wemos D1 Mini: https://amzn.to/2qLyKJd
@ -71,11 +73,14 @@ boolean IS_METRIC = false; // false = Imperial and true = Metric
// Languages: ar, bg, ca, cz, de, el, en, fa, fi, fr, gl, hr, hu, it, ja, kr, la, lt, mk, nl, pl, pt, ro, ru, se, sk, sl, es, tr, ua, vi, zh_cn, zh_tw
String WeatherLanguage = "en"; //Default (en) English
// Webserver
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
// Date and Time
float UtcOffset = -7; // Hour offset from GMT for your timezone
boolean IS_24HOUR = false; // 23:00 millitary 24 hour clock
int minutesBetweenDataRefresh = 15;
@ -91,8 +96,13 @@ boolean INVERT_DISPLAY = false; // true = pins at top | false = pins at the bott
// LED Settings
const int externalLight = LED_BUILTIN; // Set to unused pin, like D1, to disable use of built-in LED (LED_BUILTIN)
// PSU Control
boolean HAS_PSU = false; // Set to true if https://github.com/kantlivelong/OctoPrint-PSUControl/ in use
// OTA Updates
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
//******************************

View File

@ -21,6 +21,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/* 15 Jan 2019 : Owen Carter : Add psucontrol option and processing */
/**********************************************
* Edit Settings.h for personalization
***********************************************/
@ -82,7 +84,7 @@ String lastReportStatus = "";
boolean displayOn = true;
// OctoPrint Client
OctoPrintClient printerClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass);
OctoPrintClient printerClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass, HAS_PSU);
int printerCount = 0;
// Weather Client
@ -113,6 +115,7 @@ String CHANGE_FORM = "<form class='w3-container' action='/updateconfig' method=
"<p><input name='isClockEnabled' class='w3-check w3-margin-top' type='checkbox' %IS_CLOCK_CHECKED%> Display Clock when printer is off</p>"
"<p><input name='is24hour' class='w3-check w3-margin-top' type='checkbox' %IS_24HOUR_CHECKED%> Use 24 Hour Clock (military time)</p>"
"<p><input name='invDisp' class='w3-check w3-margin-top' type='checkbox' %IS_INVDISP_CHECKED%> Flip display orientation</p>"
"<p><input name='hasPSU' class='w3-check w3-margin-top' type='checkbox' %HAS_PSU_CHECKED%> Use OctoPrint PSU control plugin for clock/blank</p>"
"<p>Clock Sync / Weather Refresh (minutes) <select class='w3-option w3-padding' name='refresh'>%OPTIONS%</select></p>"
"<p>Theme Color <select class='w3-option w3-padding' name='theme'>%THEME_OPTIONS%</select></p>"
"<p><label>UTC Time Offset</label><input class='w3-input w3-border w3-margin-bottom' type='text' name='utcoffset' value='%UTCOFFSET%' maxlength='12'></p><hr>"
@ -205,7 +208,7 @@ void setup() {
readSettings();
// initialize dispaly
// initialize display
display.init();
if (INVERT_DISPLAY) {
display.flipScreenVertically(); // connections at top of OLED display
@ -367,6 +370,7 @@ void loop() {
digitalWrite(externalLight, LOW);
lastMinute = timeClient.getMinutes(); // reset the check value
printerClient.getPrinterJobResults();
printerClient.getPrinterPsuState();
digitalWrite(externalLight, HIGH);
} else if (printerClient.isPrinting()) {
if (lastSecond != timeClient.getSeconds() && timeClient.getSeconds().endsWith("0")) {
@ -374,6 +378,7 @@ void loop() {
// every 10 seconds while printing get an update
digitalWrite(externalLight, LOW);
printerClient.getPrinterJobResults();
printerClient.getPrinterPsuState();
digitalWrite(externalLight, HIGH);
}
}
@ -456,6 +461,7 @@ void handleUpdateConfig() {
DISPLAYCLOCK = server.hasArg("isClockEnabled");
IS_24HOUR = server.hasArg("is24hour");
INVERT_DISPLAY = server.hasArg("invDisp");
HAS_PSU = server.hasArg("hasPSU");
minutesBetweenDataRefresh = server.arg("refresh").toInt();
themeColor = server.arg("theme");
UtcOffset = server.arg("utcoffset").toFloat();
@ -466,6 +472,7 @@ void handleUpdateConfig() {
writeSettings();
findMDNS();
printerClient.getPrinterJobResults();
printerClient.getPrinterPsuState();
if (INVERT_DISPLAY != flipOld) {
ui.init();
if(INVERT_DISPLAY)
@ -570,6 +577,12 @@ void handleConfigure() {
isInvDisp = "checked='checked'";
}
form.replace("%IS_INVDISP_CHECKED%", isInvDisp);
String hasPSUchecked = "";
if (HAS_PSU) {
hasPSUchecked = "checked='checked'";
}
form.replace("%HAS_PSU_CHECKED%", hasPSUchecked);
String options = "<option>10</option><option>15</option><option>20</option><option>30</option><option>60</option>";
options.replace(">"+String(minutesBetweenDataRefresh)+"<", " selected>"+String(minutesBetweenDataRefresh)+"<");
form.replace("%OPTIONS%", options);
@ -695,9 +708,15 @@ void displayPrinterStatus() {
html += "<div class='w3-cell w3-container' style='width:100%'><p>";
html += "Host Name: " + OctoPrintHostName + "<br>";
if (printerClient.getError() != "") {
html += "Error: " + printerClient.getError() + "<br>";
html += "Status: Offline<br>";
html += "Reason: " + printerClient.getError() + "<br>";
} else {
html += "Status: " + printerClient.getState();
if (printerClient.isPSUoff() && HAS_PSU) {
html += ", PSU off";
}
html += "<br>";
}
html += "Status: " + printerClient.getState() + "<br>";
if (printerClient.isPrinting()) {
html += "File: " + printerClient.getFileName() + "<br>";
@ -941,9 +960,17 @@ void drawClockHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
if (!IS_24HOUR) {
display->drawString(0, 48, timeClient.getAmPm());
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64, 48, "offline");
if (printerClient.isPSUoff()) {
display->drawString(64, 47, "psu off");
} else {
display->drawString(64, 47, "offline");
}
} else {
display->drawString(0,48, "offline");
if (printerClient.isPSUoff()) {
display->drawString(0, 47, "psu off");
} else {
display->drawString(0, 47, "offline");
}
}
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawRect(0, 43, 128, 2);
@ -1004,6 +1031,7 @@ void writeSettings() {
f.println("CityID=" + String(CityIDs[0]));
f.println("isMetric=" + String(IS_METRIC));
f.println("language=" + String(WeatherLanguage));
f.println("hasPSU=" + String(HAS_PSU));
}
f.close();
readSettings();
@ -1091,6 +1119,10 @@ void readSettings() {
INVERT_DISPLAY = line.substring(line.lastIndexOf("invertDisp=") + 11).toInt();
Serial.println("INVERT_DISPLAY=" + String(INVERT_DISPLAY));
}
if (line.indexOf("hasPSU=") >= 0) {
HAS_PSU = line.substring(line.lastIndexOf("hasPSU=") + 7).toInt();
Serial.println("HAS_PSU=" + String(HAS_PSU));
}
if (line.indexOf("isWeather=") >= 0) {
DISPLAYWEATHER = line.substring(line.lastIndexOf("isWeather=") + 10).toInt();
Serial.println("DISPLAYWEATHER=" + String(DISPLAYWEATHER));
@ -1115,7 +1147,7 @@ void readSettings() {
}
}
fr.close();
printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass);
printerClient.updateOctoPrintClient(OctoPrintApiKey, OctoPrintServer, OctoPrintPort, OctoAuthUser, OctoAuthPass, HAS_PSU);
weatherClient.updateWeatherApiKey(WeatherApiKey);
weatherClient.updateLanguage(WeatherLanguage);
weatherClient.setMetric(IS_METRIC);
@ -1167,7 +1199,7 @@ void checkDisplay() {
return;
}
} else if (DISPLAYCLOCK) {
if (!printerClient.isOperational() && !isClockOn) {
if ((!printerClient.isOperational() || printerClient.isPSUoff()) && !isClockOn) {
Serial.println("Clock Mode is turned on.");
if (!DISPLAYWEATHER) {
ui.disableAutoTransition();
@ -1181,7 +1213,7 @@ void checkDisplay() {
}
ui.setOverlays(clockOverlay, numberOfOverlays);
isClockOn = true;
} else if (printerClient.isOperational() && isClockOn) {
} else if (printerClient.isOperational() && !printerClient.isPSUoff() && isClockOn) {
Serial.println("Printer Monitor is active.");
ui.setFrames(frames, numberOfFrames);
ui.setOverlays(overlays, numberOfOverlays);