Duet Client, again

Modified Duet Client to new structure, smaller fixes here and there
pull/125/head
Matthias Grimm 2020-12-14 16:41:58 -06:00
parent 627979416e
commit d736cd31c0
4 changed files with 148 additions and 185 deletions

View File

@ -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
}
} */
}

View File

@ -4,19 +4,14 @@
#include <base64.h>
#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);

View File

@ -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;
}

View File

@ -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);