diff --git a/src/Clients/DuetClient.cpp b/src/Clients/DuetClient.cpp index aca5994..6f7099f 100644 --- a/src/Clients/DuetClient.cpp +++ b/src/Clients/DuetClient.cpp @@ -1,4 +1,4 @@ -// Duet 'API': https://github.com/Arksine/moonraker/blob/master/docs/web_api.md +// Moonraker API: https://github.com/Arksine/moonraker/blob/master/docs/web_api.md // ArduinoJSON Assistant: https://arduinojson.org/v6/assistant/ #include "DuetClient.h" @@ -9,7 +9,6 @@ DuetClient::DuetClient(GlobalDataController *globalDataController, DebugControll } void DuetClient::updatePrintClient() { - myApiKey = this->globalDataController->getPrinterApiKey(); encodedAuth = ""; if (this->globalDataController->getPrinterAuthUser() != "") { String userpass = this->globalDataController->getPrinterAuthUser() + ":" + this->globalDataController->getPrinterAuthPass(); @@ -22,11 +21,8 @@ void DuetClient::updatePrintClient() { boolean DuetClient::validate() { boolean rtnValue = false; printerData.error = ""; - if (this->globalDataController->getPrinterServer() == "") { - printerData.error += "Server address is required; "; - } - if (myApiKey == "") { - printerData.error += "ApiKey is required; "; + if ((this->globalDataController->getPrinterServer() == "") && (this->globalDataController->getPrinterHostName() == "")) { + printerData.error += "Server address or host name is required; "; } if (printerData.error == "") { rtnValue = true; @@ -34,160 +30,147 @@ boolean DuetClient::validate() { return rtnValue; } -WiFiClient DuetClient::getSubmitRequest(String apiGetData) { - WiFiClient printClient; - printClient.setTimeout(5000); - this->debugController->printLn("Getting Duet Data via GET"); - this->debugController->printLn(apiGetData); - result = ""; - if (printClient.connect(this->globalDataController->getPrinterServer(), this->globalDataController->getPrinterPort())) { //starts client connection, checks for connection - printClient.println(apiGetData); - printClient.println("Host: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort())); - 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) { - this->debugController->printLn("Connection to " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()) + " failed."); - this->debugController->printLn(""); - resetPrintData(); - printerData.error = "Connection to " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()) + " failed."; - return printClient; - } - } - else { - this->debugController->printLn("Connection to Duet failed: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort())); //error message if no client connect - this->debugController->printLn(""); - resetPrintData(); - printerData.error = "Connection to Duet failed: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()); - 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) { - this->debugController->printLn("Unexpected response: "); - this->debugController->printLn(status); - printerData.state = ""; - printerData.error = "Response: " + String(status); - return printClient; - } - - // Skip HTTP headers - char endOfHeaders[] = "\r\n\r\n"; - if (!printClient.find(endOfHeaders)) { - this->debugController->printLn("Invalid response"); - printerData.error = "Invalid response from " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()); - printerData.state = ""; - } - - return printClient; -} - -WiFiClient DuetClient::getPostRequest(String apiPostData, String apiPostBody) { - WiFiClient printClient; - printClient.setTimeout(5000); - - this->debugController->printLn("Getting Duet Data via POST"); - this->debugController->printLn(apiPostData + " | " + apiPostBody); - result = ""; - if (printClient.connect(this->globalDataController->getPrinterServer(), this->globalDataController->getPrinterPort())) { //starts client connection, checks for connection - printClient.println(apiPostData); - printClient.println("Host: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort())); - 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) { - this->debugController->printLn("Connection to " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()) + " failed."); - this->debugController->printLn(""); - resetPrintData(); - printerData.error = "Connection to " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()) + " failed."; - return printClient; - } - } - else { - this->debugController->printLn("Connection to Duet failed: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort())); //error message if no client connect - this->debugController->printLn(""); - resetPrintData(); - printerData.error = "Connection to Duet failed: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()); - 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) { - this->debugController->print("Unexpected response: "); - this->debugController->printLn(status); - printerData.state = ""; - printerData.error = "Response: " + String(status); - return printClient; - } - - // Skip HTTP headers - char endOfHeaders[] = "\r\n\r\n"; - if (!printClient.find(endOfHeaders)) { - this->debugController->printLn("Invalid response"); - printerData.error = "Invalid response from " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()); - printerData.state = ""; - } - - return printClient; -} void DuetClient::getPrinterJobResults() { + // const size_t bufferSize = JSON_ARRAY_SIZE(4) + JSON_OBJECT_SIZE(1) + 4*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(7) + JSON_OBJECT_SIZE(9) + 426; + const size_t bufferSize = 2048; // according to ArduinoJson assistant + DynamicJsonDocument *jsonDoc; if (!validate()) { return; } - //**** get the Printer Job status - String apiGetData = "GET /rr_status?type=3"; - WiFiClient printClient = getSubmitRequest(apiGetData); - if (printerData.error != "") { - return; - } - const size_t bufferSize = 6*JSON_ARRAY_SIZE(1) + 3*JSON_ARRAY_SIZE(2) + 5*JSON_ARRAY_SIZE(3) + 5*JSON_OBJECT_SIZE(2) + 4*JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(9) + 257; - DynamicJsonDocument jsonBuffer(bufferSize); - // Parse JSON object - DeserializationError error = deserializeJson(jsonBuffer, printClient); - if (error) { - this->debugController->printLn("Duet Data Parsing failed: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort())); - printerData.error = "Duet Data Parsing failed: " + this->globalDataController->getPrinterServer() + ":" + String(this->globalDataController->getPrinterPort()); + // Req 1 + this->debugController->printLn("Get Duet Data: " + this->getInstanceServerTarget() + ":" + String(this->getInstanceServerPort())); + jsonDoc = this->jsonRequestClient->requestJson( + PRINTER_REQUEST_GET, + this->getInstanceServerTarget(), + this->getInstanceServerPort(), + this->encodedAuth, + "/rr_status?type=1", + "", + bufferSize, + true + ); + if (this->jsonRequestClient->getLastError() != "") { + this->debugController->printLn(this->jsonRequestClient->getLastError()); + printerData.error = this->jsonRequestClient->getLastError(); printerData.state = ""; printerData.isPrinting = false; printerData.toolTemp = ""; printerData.toolTargetTemp = ""; printerData.bedTemp = ""; - printerData.bedTargetTemp = (const char*)jsonBuffer["result"]["status"]["heater_bed"]["target"]; - return; + printerData.bedTargetTemp = ""; return; } + + printerData.state = (const char*)(*jsonDoc)["status"]; + + if (printerData.state == "P") { + printerData.isPrinting = true; + } else { + printerData.isPrinting = false; + } + if (BasePrinterClientImpl::isOperational()) { + this->debugController->printLn("Status: " + printerData.state); + } else { + this->debugController->printLn("Printer Not Operational"); + } + + // Req 2 + if (printerData.state == "P") { + jsonDoc = this->jsonRequestClient->requestJson( + PRINTER_REQUEST_GET, + this->getInstanceServerTarget(), + this->getInstanceServerPort(), + this->encodedAuth, + "/rr_status?type=3", + "", + bufferSize, + true + ); + if (this->jsonRequestClient->getLastError() != "") { + this->debugController->printLn(this->jsonRequestClient->getLastError()); + printerData.error = this->jsonRequestClient->getLastError(); + printerData.state = ""; + printerData.isPrinting = false; + printerData.toolTemp = ""; + printerData.toolTargetTemp = ""; + printerData.bedTemp = ""; + printerData.bedTargetTemp = ""; + return; + } + + printerData.filamentLength = (const char*)(*jsonDoc)["result"]["status"]["job"]["print_stats"]["filament_used"]; + printerData.progressPrintTime = (const char*)(*jsonDoc)["printDuration"]; + printerData.fileName = (const char*)(*jsonDoc)["result"]["status"]["print_stats"]["filename"]; + printerData.progressCompletion = (int)(*jsonDoc)["fractionPrinted"]; + printerData.toolTemp = (int)(*jsonDoc)["temps"]["current"][1]; + printerData.toolTargetTemp = (int)(*jsonDoc)["temps"]["tools"]["active"][0][0]; + printerData.bedTemp = (int)(*jsonDoc)["temps"]["bed"]["current"]; + printerData.bedTargetTemp = (int)(*jsonDoc)["temps"]["bed"]["active"]; + float fileProgress = (float)(*jsonDoc)["fractionPrinted"]; + printerData.progressFilepos = (const char*)(*jsonDoc)["filePosition"]; + printerData.estimatedPrintTime = (float)(*jsonDoc)["file"]; + + /* + printerData.progressPrintTimeLeft : No metadata is available, print duration and progress can be used to calculate the ETA: + */ + float totalPrintTime = printerData.progressPrintTime.toFloat() / fileProgress; + printerData.progressPrintTimeLeft = String(totalPrintTime - printerData.progressPrintTime.toFloat()); + + } + + // // Req 3 + // jsonDoc = this->jsonRequestClient->requestJson( + // PRINTER_REQUEST_GET, + // this->getInstanceServerTarget(), + // this->getInstanceServerPort(), + // this->encodedAuth, + // "/printer/objects/query?toolhead&virtual_sdcard", + // "", + // bufferSize, + // true + // ); + // if (this->jsonRequestClient->getLastError() != "") { + // this->debugController->printLn(this->jsonRequestClient->getLastError()); + // printerData.error = this->jsonRequestClient->getLastError(); + // printerData.state = ""; + // printerData.isPrinting = false; + // printerData.toolTemp = ""; + // printerData.toolTargetTemp = ""; + // printerData.bedTemp = ""; + // printerData.bedTargetTemp = ""; + // return; + // } + + // float fileProgress = (float)(*jsonDoc)["result"]["status"]["virtual_sdcard"]["progress"]; + // printerData.progressFilepos = (const char*)(*jsonDoc)["result"]["status"]["virtual_sdcard"]["file_position"]; + // printerData.estimatedPrintTime = (float)(*jsonDoc)["result"]["status"]["toolhead"]["estimated_print_time"]; + + // /* + // printerData.progressPrintTimeLeft : No metadata is available, print duration and progress can be used to calculate the ETA: + // */ + // float totalPrintTime = printerData.progressPrintTime.toFloat() / fileProgress; + // printerData.progressPrintTimeLeft = String(totalPrintTime - printerData.progressPrintTime.toFloat()); + + + + + +// // &webhooks&virtual_sdcard&print_stats + + + /* printerData.averagePrintTime = (int)jsonBuffer["result"]["status"]["toolhead"]["averagePrintTime"]; - printerData.estimatedPrintTime = (float)jsonBuffer["result"]["status"]["toolhead"]["estimated_print_time"]; - printerData.fileName = (const char*)jsonBuffer["result"]["status"]["print_stats"]["filename"]; // printerData.fileSize = (const char*)jsonBuffer["job"]["file"]["size"]; printerData.lastPrintTime = (const char*)jsonBuffer["job"]["lastPrintTime"]; - printerData.progressCompletion = (int)jsonBuffer["result"]["status"]["display_status"]["progress"]; - printerData.progressFilepos = (const char*)jsonBuffer["result"]["status"]["virtual_sdcard"]["file_position"]; - printerData.progressPrintTime = (const char*)jsonBuffer["result"]["status"]["print_stats"]["print_duration"]; - printerData.progressPrintTimeLeft = (const char*)jsonBuffer["progress"]["printTimeLeft"]; - printerData.filamentLength = (const char*)jsonBuffer["result"]["status"]["job"]["print_stats"]["filament_used"]; - printerData.state = (const char*)jsonBuffer["status"]; + ; + + + */ /** printerData.progressPrintTimeLeft : If no metadata is available, print duration and progress can be used to calculate the ETA: @@ -199,51 +182,42 @@ let total_time = pstats.print_duration / vsd.progress; let eta = total_time - pstats.print_duration; */ - if (BasePrinterClientImpl::isOperational()) { - this->debugController->printLn("Status: " + printerData.state); - } else { - this->debugController->printLn("Printer Not Operational"); - } + /* - // //**** get the fileseize - // apiGetData = "GET /server/files/metadata?filename=" + printerData.fileName; - // printClient = getSubmitRequest(apiGetData); - // if (printerData.error != "") { - // return; - // } - // const size_t bufferSize2 = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(8) + 128; - // DynamicJsonDocument jsonBuffer2(bufferSize2); + // get the fileseize + apiGetData = "GET /server/files/metadata?filename=" + printerData.fileName; + printClient = getSubmitRequest(apiGetData); + if (printerData.error != "") { + return; + } + const size_t bufferSize2 = JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(8) + 128; + DynamicJsonDocument jsonBuffer2(bufferSize2); // Parse JSON object - DeserializationError error2 = deserializeJson(jsonBuffer, printClient); + DeserializationError error2 = deserializeJson(jsonBuffer2, printClient); if (error2) { printerData.isPrinting = false; printerData.toolTemp = ""; printerData.toolTargetTemp = ""; printerData.bedTemp = ""; - printerData.bedTargetTemp = (int)jsonBuffer["temps"]["bed"]["active"]; + printerData.bedTargetTemp = (int)jsonBuffer["result"]["status"]["heater_bed"]["target"]; return; } - String printing = (const char*)jsonBuffer["status"]; - if (printing == "P") { - printerData.isPrinting = true; - } else { - printerData.isPrinting = false; - } - printerData.toolTemp = (int)jsonBuffer["result"]["status"]["extruder"]["temperature"]; - printerData.toolTargetTemp = (int)jsonBuffer["result"]["status"]["extruder"]["target"]; - printerData.bedTemp = (int)jsonBuffer["result"]["status"]["heater_bed"]["temperature"]; - printerData.bedTargetTemp = (int)jsonBuffer["result"]["status"]["heater_bed"]["target"]; - printerData.fileSize = (long)jsonBuffer["result"]["size"]; + String printing = (const char*)jsonBuffer["result"]["status"]["print_stats"]["state"]; + + + printerData.fileSize = (long)jsonBuffer2["result"]["size"]; - if (BasePrinterClientImpl::isPrinting()) { + */ + + if (BasePrinterClientImpl::isOperational()) { this->debugController->printLn("Status: " + printerData.state + " " + printerData.fileName + "(" + printerData.progressCompletion + "%)"); } } void DuetClient::getPrinterPsuState() { - //**** get the PSU state (if enabled and printer operational) + /*// get the PSU state (if enabled and printer operational) if (pollPsu && BasePrinterClientImpl::isOperational()) { if (!validate()) { printerData.isPSUoff = false; // we do not know PSU state, so assume on. @@ -275,5 +249,5 @@ void DuetClient::getPrinterPsuState() { printClient.stop(); //stop client } else { printerData.isPSUoff = false; // we are not checking PSU state, so assume on - } + } */ } diff --git a/src/Clients/DuetClient.h b/src/Clients/DuetClient.h index bf76586..4095a81 100644 --- a/src/Clients/DuetClient.h +++ b/src/Clients/DuetClient.h @@ -4,19 +4,14 @@ #include #include "Debug.h" #include "BasePrinterClientImpl.h" +#include "../Global/GlobalDataController.h" class DuetClient : public BasePrinterClientImpl { private: - String myApiKey = ""; - String encodedAuth = ""; boolean pollPsu; boolean validate(); - WiFiClient getSubmitRequest(String apiGetData); - WiFiClient getPostRequest(String apiPostData, String apiPostBody); - - String result; - + public: DuetClient(GlobalDataController *globalDataController, DebugController *debugController, JsonRequestClient *jsonRequestClient); diff --git a/src/Clients/KlipperClient.cpp b/src/Clients/KlipperClient.cpp index 0a87c7f..c8816b7 100644 --- a/src/Clients/KlipperClient.cpp +++ b/src/Clients/KlipperClient.cpp @@ -102,12 +102,6 @@ void KlipperClient::getPrinterJobResults() { printerData.toolTargetTemp = ""; printerData.bedTemp = ""; printerData.bedTargetTemp = ""; - printerData.state = ""; - printerData.isPrinting = false; - printerData.toolTemp = ""; - printerData.toolTargetTemp = ""; - printerData.bedTemp = ""; - printerData.bedTargetTemp = ""; return; } diff --git a/src/Network/JsonRequestClient.cpp b/src/Network/JsonRequestClient.cpp index 3d7c16d..1b65cd8 100644 --- a/src/Network/JsonRequestClient.cpp +++ b/src/Network/JsonRequestClient.cpp @@ -72,7 +72,7 @@ WiFiClient JsonRequestClient::requestWifiClient( // Check HTTP status char status[32] = {0}; requestClient.readBytesUntil('\r', status, sizeof(status)); - if (strcmp(status, "HTTP/1.1 200 OK") != 0 && strcmp(status, "HTTP/1.1 409 CONFLICT") != 0) { + if (strcmp(status, "HTTP/1.1 200 OK") != 0 && strcmp(status, "HTTP/1.1 409 CONFLICT") != 0 && strcmp(status, "HTTP/1.1 503 Service Unavailable") != 0) { this->debugController->print("Unexpected response: "); this->debugController->printLn(status); this->lastError = "Response: " + String(status);