mirror of
https://github.com/suchmememanyskill/CYD-Klipper.git
synced 2026-03-21 05:33:24 +00:00
Split json parsing from printer impl
This commit is contained in:
30
CYD-Klipper/.vscode/settings.json
vendored
30
CYD-Klipper/.vscode/settings.json
vendored
@@ -20,7 +20,35 @@
|
|||||||
"limits": "cpp",
|
"limits": "cpp",
|
||||||
"memory": "cpp",
|
"memory": "cpp",
|
||||||
"new": "cpp",
|
"new": "cpp",
|
||||||
"type_traits": "cpp"
|
"type_traits": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"cinttypes": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
},
|
},
|
||||||
"cmake.configureOnOpen": false
|
"cmake.configureOnOpen": false
|
||||||
}
|
}
|
||||||
@@ -35,9 +35,7 @@ int KlipperPrinter::get_slicer_time_estimate_s()
|
|||||||
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
int time_estimate_s = doc["result"]["estimated_time"];
|
return parse_slicer_time_estimate(doc);
|
||||||
LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s))
|
|
||||||
return time_estimate_s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KlipperPrinter::send_gcode(const char *gcode, bool wait)
|
bool KlipperPrinter::send_gcode(const char *gcode, bool wait)
|
||||||
@@ -89,6 +87,22 @@ bool KlipperPrinter::move_printer(const char* axis, float amount, bool relative)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KlipperPrinter::send_emergency_stop()
|
||||||
|
{
|
||||||
|
HTTPClient client;
|
||||||
|
configure_http_client(client, "/printer/emergency_stop", false, 5000);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return client.GET() == 200;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LOG_LN("Failed to send estop");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool KlipperPrinter::execute_feature(PrinterFeatures feature)
|
bool KlipperPrinter::execute_feature(PrinterFeatures feature)
|
||||||
{
|
{
|
||||||
HTTPClient client;
|
HTTPClient client;
|
||||||
@@ -112,16 +126,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature)
|
|||||||
case PrinterFeatureEmergencyStop:
|
case PrinterFeatureEmergencyStop:
|
||||||
LOG_LN("Sending estop");
|
LOG_LN("Sending estop");
|
||||||
send_gcode("M112", false);
|
send_gcode("M112", false);
|
||||||
configure_http_client(client, "/printer/emergency_stop", false, 5000);
|
send_emergency_stop();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
client.GET();
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
LOG_LN("Failed to send estop");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
case PrinterFeatureExtrude:
|
case PrinterFeatureExtrude:
|
||||||
@@ -182,177 +187,7 @@ bool KlipperPrinter::fetch()
|
|||||||
klipper_request_consecutive_fail_count = 0;
|
klipper_request_consecutive_fail_count = 0;
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto status = doc["result"]["status"];
|
parse_state(doc);
|
||||||
bool emit_state_update = false;
|
|
||||||
|
|
||||||
if (status.containsKey("webhooks"))
|
|
||||||
{
|
|
||||||
const char* state = status["webhooks"]["state"];
|
|
||||||
const char* message = status["webhooks"]["state_message"];
|
|
||||||
|
|
||||||
if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError)
|
|
||||||
{
|
|
||||||
printer_data.state = PrinterStateIdle;
|
|
||||||
}
|
|
||||||
else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError)
|
|
||||||
{
|
|
||||||
printer_data.state = PrinterStateError;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message)))
|
|
||||||
{
|
|
||||||
printer_data.state_message = (char *)malloc(strlen(message) + 1);
|
|
||||||
strcpy(printer_data.state_message, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printer_data.state != PrinterStateError)
|
|
||||||
{
|
|
||||||
if (status.containsKey("extruder"))
|
|
||||||
{
|
|
||||||
printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["temperature"];
|
|
||||||
printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["target"];
|
|
||||||
bool can_extrude = status["extruder"]["can_extrude"];
|
|
||||||
printer_data.pressure_advance = status["extruder"]["pressure_advance"];
|
|
||||||
printer_data.smooth_time = status["extruder"]["smooth_time"];
|
|
||||||
printer_data.can_extrude = can_extrude == true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("heater_bed"))
|
|
||||||
{
|
|
||||||
printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["temperature"];
|
|
||||||
printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["target"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("toolhead"))
|
|
||||||
{
|
|
||||||
const char *homed_axis = status["toolhead"]["homed_axes"];
|
|
||||||
printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("gcode_move"))
|
|
||||||
{
|
|
||||||
printer_data.position[0] = status["gcode_move"]["gcode_position"][0];
|
|
||||||
printer_data.position[1] = status["gcode_move"]["gcode_position"][1];
|
|
||||||
printer_data.position[2] = status["gcode_move"]["gcode_position"][2];
|
|
||||||
gcode_offset[0] = status["gcode_move"]["homing_origin"][0];
|
|
||||||
gcode_offset[1] = status["gcode_move"]["homing_origin"][1];
|
|
||||||
gcode_offset[2] = status["gcode_move"]["homing_origin"][2];
|
|
||||||
bool absolute_coords = status["gcode_move"]["absolute_coordinates"];
|
|
||||||
|
|
||||||
if (lock_absolute_relative_mode_swap > 0)
|
|
||||||
{
|
|
||||||
lock_absolute_relative_mode_swap--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printer_data.absolute_coords = absolute_coords == true;
|
|
||||||
}
|
|
||||||
|
|
||||||
printer_data.speed_mult = status["gcode_move"]["speed_factor"];
|
|
||||||
printer_data.extrude_mult = status["gcode_move"]["extrude_factor"];
|
|
||||||
printer_data.feedrate_mm_per_s = status["gcode_move"]["speed"];
|
|
||||||
printer_data.feedrate_mm_per_s /= 60; // convert mm/m to mm/s
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("fan"))
|
|
||||||
{
|
|
||||||
printer_data.fan_speed = status["fan"]["speed"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("virtual_sdcard"))
|
|
||||||
{
|
|
||||||
printer_data.print_progress = status["virtual_sdcard"]["progress"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("print_stats"))
|
|
||||||
{
|
|
||||||
const char *filename = status["print_stats"]["filename"];
|
|
||||||
|
|
||||||
if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename)))
|
|
||||||
{
|
|
||||||
printer_data.print_filename = (char *)malloc(strlen(filename) + 1);
|
|
||||||
strcpy(printer_data.print_filename, filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
printer_data.elapsed_time_s = status["print_stats"]["total_duration"];
|
|
||||||
printer_data.printed_time_s = status["print_stats"]["print_duration"];
|
|
||||||
printer_data.filament_used_mm = status["print_stats"]["filament_used"];
|
|
||||||
printer_data.total_layers = status["print_stats"]["info"]["total_layer"];
|
|
||||||
printer_data.current_layer = status["print_stats"]["info"]["current_layer"];
|
|
||||||
|
|
||||||
const char *state = status["print_stats"]["state"];
|
|
||||||
|
|
||||||
if (state == nullptr)
|
|
||||||
{
|
|
||||||
// Continue
|
|
||||||
}
|
|
||||||
else if (strcmp(state, "printing") == 0)
|
|
||||||
{
|
|
||||||
printer_data.state = PrinterStatePrinting;
|
|
||||||
}
|
|
||||||
else if (strcmp(state, "paused") == 0)
|
|
||||||
{
|
|
||||||
printer_data.state = PrinterStatePaused;
|
|
||||||
}
|
|
||||||
else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0)
|
|
||||||
{
|
|
||||||
printer_data.state = PrinterStateIdle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("display_status"))
|
|
||||||
{
|
|
||||||
printer_data.print_progress = status["display_status"]["progress"];
|
|
||||||
const char* message = status["display_status"]["message"];
|
|
||||||
|
|
||||||
if (message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message)))
|
|
||||||
{
|
|
||||||
printer_data.popup_message = (char*)malloc(strlen(message) + 1);
|
|
||||||
strcpy(printer_data.popup_message, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printer_data.state == PrinterStatePrinting && printer_data.print_progress > 0)
|
|
||||||
{
|
|
||||||
float remaining_time_s_percentage = (printer_data.printed_time_s / printer_data.print_progress) - printer_data.printed_time_s;
|
|
||||||
float remaining_time_s_slicer = 0;
|
|
||||||
|
|
||||||
if (slicer_estimated_print_time_s > 0)
|
|
||||||
{
|
|
||||||
remaining_time_s_slicer = slicer_estimated_print_time_s - printer_data.printed_time_s;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining_time_s_slicer <= 0 || printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE)
|
|
||||||
{
|
|
||||||
printer_data.remaining_time_s = remaining_time_s_percentage;
|
|
||||||
}
|
|
||||||
else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED)
|
|
||||||
{
|
|
||||||
printer_data.remaining_time_s = remaining_time_s_percentage * printer_data.print_progress + remaining_time_s_slicer * (1 - printer_data.print_progress);
|
|
||||||
}
|
|
||||||
else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER)
|
|
||||||
{
|
|
||||||
printer_data.remaining_time_s = remaining_time_s_slicer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printer_data.remaining_time_s < 0)
|
|
||||||
{
|
|
||||||
printer_data.remaining_time_s = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printer_data.state == PrinterStateIdle)
|
|
||||||
{
|
|
||||||
slicer_estimated_print_time_s = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printer_data.state == PrinterStatePrinting && millis() - last_slicer_time_query > 30000 && slicer_estimated_print_time_s <= 0)
|
|
||||||
{
|
|
||||||
last_slicer_time_query = millis();
|
|
||||||
slicer_estimated_print_time_s = get_slicer_time_estimate_s();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -393,47 +228,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min()
|
|||||||
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto status = doc["result"]["status"];
|
return parse_state_min(doc);
|
||||||
|
|
||||||
if (status.containsKey("webhooks"))
|
|
||||||
{
|
|
||||||
const char *state = status["webhooks"]["state"];
|
|
||||||
|
|
||||||
if (strcmp(state, "shutdown") == 0)
|
|
||||||
{
|
|
||||||
data.state = PrinterState::PrinterStateError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.state != PrinterStateError)
|
|
||||||
{
|
|
||||||
if (status.containsKey("virtual_sdcard"))
|
|
||||||
{
|
|
||||||
data.print_progress = status["virtual_sdcard"]["progress"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.containsKey("print_stats"))
|
|
||||||
{
|
|
||||||
const char *state = status["print_stats"]["state"];
|
|
||||||
|
|
||||||
if (state == nullptr)
|
|
||||||
{
|
|
||||||
data.state = PrinterState::PrinterStateError;
|
|
||||||
}
|
|
||||||
else if (strcmp(state, "printing") == 0)
|
|
||||||
{
|
|
||||||
data.state = PrinterState::PrinterStatePrinting;
|
|
||||||
}
|
|
||||||
else if (strcmp(state, "paused") == 0)
|
|
||||||
{
|
|
||||||
data.state = PrinterState::PrinterStatePaused;
|
|
||||||
}
|
|
||||||
else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0)
|
|
||||||
{
|
|
||||||
data.state = PrinterState::PrinterStateIdle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -461,27 +256,7 @@ Macros KlipperPrinter::get_macros()
|
|||||||
if (http_code == 200){
|
if (http_code == 200){
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto result = doc["result"].as<JsonObject>();
|
return parse_macros(doc);
|
||||||
macros.macros = (char**)malloc(sizeof(char*) * 32);
|
|
||||||
macros.count = 0;
|
|
||||||
macros.success = true;
|
|
||||||
|
|
||||||
for (JsonPair i : result){
|
|
||||||
const char *key = i.key().c_str();
|
|
||||||
const char *value = i.value().as<String>().c_str();
|
|
||||||
if (strcmp(value, "CYD_SCREEN_MACRO") == 0) {
|
|
||||||
char* macro = (char*)malloc(strlen(key) + 1);
|
|
||||||
strcpy(macro, key);
|
|
||||||
macros.macros[macros.count++] = macro;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (global_config.sort_macros)
|
|
||||||
{
|
|
||||||
std::sort(macros.macros, macros.macros + macros.count, [](const char* a, const char* b) {
|
|
||||||
return strcmp(a, b) < 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return macros;
|
return macros;
|
||||||
@@ -497,18 +272,7 @@ int KlipperPrinter::get_macros_count()
|
|||||||
if (http_code == 200){
|
if (http_code == 200){
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto result = doc["result"].as<JsonObject>();
|
return parse_macros_count(doc);
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (JsonPair i : result){
|
|
||||||
const char *value = i.value().as<String>().c_str();
|
|
||||||
if (strcmp(value, "CYD_SCREEN_MACRO") == 0) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -531,20 +295,7 @@ PowerDevices KlipperPrinter::get_power_devices()
|
|||||||
if (http_code == 200){
|
if (http_code == 200){
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto result = doc["result"]["devices"].as<JsonArray>();
|
return parse_power_devices(doc);
|
||||||
power_devices.power_devices = (char**)malloc(sizeof(char*) * 16);
|
|
||||||
power_devices.power_states = (bool*)malloc(sizeof(bool) * 16);
|
|
||||||
power_devices.count = 0;
|
|
||||||
power_devices.success = true;
|
|
||||||
|
|
||||||
for (auto i : result){
|
|
||||||
const char * device_name = i["device"];
|
|
||||||
const char * device_state = i["status"];
|
|
||||||
power_devices.power_devices[power_devices.count] = (char*)malloc(strlen(device_name) + 1);
|
|
||||||
strcpy(power_devices.power_devices[power_devices.count], device_name);
|
|
||||||
power_devices.power_states[power_devices.count] = strcmp(device_state, "on") == 0;
|
|
||||||
power_devices.count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return power_devices;
|
return power_devices;
|
||||||
@@ -560,15 +311,7 @@ int KlipperPrinter::get_power_devices_count()
|
|||||||
if (http_code == 200){
|
if (http_code == 200){
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto result = doc["result"]["devices"].as<JsonArray>();
|
return parse_power_devices_count(doc);
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (auto i : result){
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -582,11 +325,6 @@ bool KlipperPrinter::set_power_device_state(const char* device_name, bool state)
|
|||||||
return client.POST("") == 200;
|
return client.POST("") == 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* name;
|
|
||||||
float modified;
|
|
||||||
} FileSystemFile;
|
|
||||||
|
|
||||||
#define KLIPPER_FILE_FETCH_LIMIT 20
|
#define KLIPPER_FILE_FETCH_LIMIT 20
|
||||||
|
|
||||||
Files KlipperPrinter::get_files()
|
Files KlipperPrinter::get_files()
|
||||||
@@ -606,46 +344,7 @@ Files KlipperPrinter::get_files()
|
|||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
auto parseResult = deserializeJson(doc, client.getStream());
|
auto parseResult = deserializeJson(doc, client.getStream());
|
||||||
LOG_F(("Json parse: %s\n", parseResult.c_str()))
|
LOG_F(("Json parse: %s\n", parseResult.c_str()))
|
||||||
auto result = doc["result"].as<JsonArray>();
|
parse_file_list(doc, files, KLIPPER_FILE_FETCH_LIMIT);
|
||||||
|
|
||||||
for (auto file : result){
|
|
||||||
FileSystemFile f = {0};
|
|
||||||
const char* path = file["path"];
|
|
||||||
float modified = file["modified"];
|
|
||||||
auto file_iter = files.begin();
|
|
||||||
|
|
||||||
while (file_iter != files.end()){
|
|
||||||
if ((*file_iter).modified < modified)
|
|
||||||
break;
|
|
||||||
|
|
||||||
file_iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_iter == files.end() && files.size() >= KLIPPER_FILE_FETCH_LIMIT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
f.name = (char*)malloc(strlen(path) + 1);
|
|
||||||
if (f.name == NULL){
|
|
||||||
LOG_LN("Failed to allocate memory");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
strcpy(f.name, path);
|
|
||||||
f.modified = modified;
|
|
||||||
|
|
||||||
if (file_iter != files.end())
|
|
||||||
files.insert(file_iter, f);
|
|
||||||
else
|
|
||||||
files.push_back(f);
|
|
||||||
|
|
||||||
if (files.size() > KLIPPER_FILE_FETCH_LIMIT){
|
|
||||||
auto last_entry = files.back();
|
|
||||||
|
|
||||||
if (last_entry.name != NULL)
|
|
||||||
free(last_entry.name);
|
|
||||||
|
|
||||||
files.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
files_result.available_files = (char**)malloc(sizeof(char*) * files.size());
|
files_result.available_files = (char**)malloc(sizeof(char*) * files.size());
|
||||||
@@ -724,30 +423,7 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena
|
|||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
deserializeJson(doc, client.getStream());
|
deserializeJson(doc, client.getStream());
|
||||||
auto result = doc["result"].as<JsonArray>();
|
img_filename_path = parse_thumbnails(doc);
|
||||||
const char* chosen_thumb = NULL;
|
|
||||||
for (auto file : result){
|
|
||||||
int width = file["width"];
|
|
||||||
int height = file["height"];
|
|
||||||
int size = file["size"];
|
|
||||||
const char* thumbnail = file["thumbnail_path"];
|
|
||||||
|
|
||||||
if (width != height || width != 32)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
chosen_thumb = thumbnail;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chosen_thumb != NULL){
|
|
||||||
LOG_F(("Found 32x32 PNG gcode img at %s\n", gcode_filename))
|
|
||||||
img_filename_path = (char*)malloc(strlen(chosen_thumb) + 1);
|
|
||||||
strcpy(img_filename_path, chosen_thumb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -759,6 +435,10 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena
|
|||||||
LOG_LN("No compatible thumbnail found");
|
LOG_LN("No compatible thumbnail found");
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_F(("Found 32x32 PNG gcode img at %s\n", gcode_filename));
|
||||||
|
}
|
||||||
|
|
||||||
client.end();
|
client.end();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
#include "../printer_integration.hpp"
|
#include "../printer_integration.hpp"
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* name;
|
||||||
|
float modified;
|
||||||
|
} FileSystemFile;
|
||||||
|
|
||||||
class KlipperPrinter : public BasePrinter
|
class KlipperPrinter : public BasePrinter
|
||||||
{
|
{
|
||||||
@@ -10,6 +17,22 @@ class KlipperPrinter : public BasePrinter
|
|||||||
unsigned char klipper_request_consecutive_fail_count{};
|
unsigned char klipper_request_consecutive_fail_count{};
|
||||||
unsigned int slicer_estimated_print_time_s{};
|
unsigned int slicer_estimated_print_time_s{};
|
||||||
unsigned int last_slicer_time_query{};
|
unsigned int last_slicer_time_query{};
|
||||||
|
void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool send_emergency_stop();
|
||||||
|
int get_slicer_time_estimate_s();
|
||||||
|
void init_ui_panels();
|
||||||
|
|
||||||
|
int parse_slicer_time_estimate(JsonDocument& in);
|
||||||
|
void parse_state(JsonDocument& in);
|
||||||
|
PrinterDataMinimal parse_state_min(JsonDocument& in);
|
||||||
|
Macros parse_macros(JsonDocument &in);
|
||||||
|
int parse_macros_count(JsonDocument &in);
|
||||||
|
PowerDevices parse_power_devices(JsonDocument &in);
|
||||||
|
int parse_power_devices_count(JsonDocument &in);
|
||||||
|
void parse_file_list(JsonDocument &in, std::list<FileSystemFile> &files, int fetch_limit);
|
||||||
|
char *parse_thumbnails(JsonDocument &in);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
float gcode_offset[3]{};
|
float gcode_offset[3]{};
|
||||||
@@ -51,9 +74,6 @@ class KlipperPrinter : public BasePrinter
|
|||||||
Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename);
|
Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename);
|
||||||
bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature);
|
bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature);
|
||||||
bool send_gcode(const char* gcode, bool wait = true);
|
bool send_gcode(const char* gcode, bool wait = true);
|
||||||
int get_slicer_time_estimate_s();
|
|
||||||
void configure_http_client(HTTPClient &client, String url_part, bool stream, int timeout);
|
|
||||||
void init_ui_panels();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ConnectionStatus {
|
enum ConnectionStatus {
|
||||||
|
|||||||
394
CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp
Normal file
394
CYD-Klipper/src/core/klipper/klipper_printer_parsers.cpp
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
#include "../printer_integration.hpp"
|
||||||
|
#include "klipper_printer_integration.hpp"
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
int KlipperPrinter::parse_slicer_time_estimate(JsonDocument &in)
|
||||||
|
{
|
||||||
|
int time_estimate_s = in["result"]["estimated_time"];
|
||||||
|
LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s))
|
||||||
|
return time_estimate_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KlipperPrinter::parse_state(JsonDocument &in)
|
||||||
|
{
|
||||||
|
auto status = in["result"]["status"];
|
||||||
|
|
||||||
|
if (status.containsKey("webhooks"))
|
||||||
|
{
|
||||||
|
const char *state = status["webhooks"]["state"];
|
||||||
|
const char *message = status["webhooks"]["state_message"];
|
||||||
|
|
||||||
|
if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError)
|
||||||
|
{
|
||||||
|
printer_data.state = PrinterStateIdle;
|
||||||
|
}
|
||||||
|
else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError)
|
||||||
|
{
|
||||||
|
printer_data.state = PrinterStateError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message)))
|
||||||
|
{
|
||||||
|
printer_data.state_message = (char *)malloc(strlen(message) + 1);
|
||||||
|
strcpy(printer_data.state_message, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printer_data.state != PrinterStateError)
|
||||||
|
{
|
||||||
|
if (status.containsKey("extruder"))
|
||||||
|
{
|
||||||
|
printer_data.temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["temperature"];
|
||||||
|
printer_data.target_temperatures[PrinterTemperatureDeviceIndexNozzle1] = status["extruder"]["target"];
|
||||||
|
bool can_extrude = status["extruder"]["can_extrude"];
|
||||||
|
printer_data.pressure_advance = status["extruder"]["pressure_advance"];
|
||||||
|
printer_data.smooth_time = status["extruder"]["smooth_time"];
|
||||||
|
printer_data.can_extrude = can_extrude == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("heater_bed"))
|
||||||
|
{
|
||||||
|
printer_data.temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["temperature"];
|
||||||
|
printer_data.target_temperatures[PrinterTemperatureDeviceIndexBed] = status["heater_bed"]["target"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("toolhead"))
|
||||||
|
{
|
||||||
|
const char *homed_axis = status["toolhead"]["homed_axes"];
|
||||||
|
printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("gcode_move"))
|
||||||
|
{
|
||||||
|
printer_data.position[0] = status["gcode_move"]["gcode_position"][0];
|
||||||
|
printer_data.position[1] = status["gcode_move"]["gcode_position"][1];
|
||||||
|
printer_data.position[2] = status["gcode_move"]["gcode_position"][2];
|
||||||
|
gcode_offset[0] = status["gcode_move"]["homing_origin"][0];
|
||||||
|
gcode_offset[1] = status["gcode_move"]["homing_origin"][1];
|
||||||
|
gcode_offset[2] = status["gcode_move"]["homing_origin"][2];
|
||||||
|
bool absolute_coords = status["gcode_move"]["absolute_coordinates"];
|
||||||
|
|
||||||
|
if (lock_absolute_relative_mode_swap > 0)
|
||||||
|
{
|
||||||
|
lock_absolute_relative_mode_swap--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printer_data.absolute_coords = absolute_coords == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
printer_data.speed_mult = status["gcode_move"]["speed_factor"];
|
||||||
|
printer_data.extrude_mult = status["gcode_move"]["extrude_factor"];
|
||||||
|
printer_data.feedrate_mm_per_s = status["gcode_move"]["speed"];
|
||||||
|
printer_data.feedrate_mm_per_s /= 60; // convert mm/m to mm/s
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("fan"))
|
||||||
|
{
|
||||||
|
printer_data.fan_speed = status["fan"]["speed"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("virtual_sdcard"))
|
||||||
|
{
|
||||||
|
printer_data.print_progress = status["virtual_sdcard"]["progress"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("print_stats"))
|
||||||
|
{
|
||||||
|
const char *filename = status["print_stats"]["filename"];
|
||||||
|
|
||||||
|
if (filename != NULL && (printer_data.print_filename == NULL || strcmp(printer_data.print_filename, filename)))
|
||||||
|
{
|
||||||
|
printer_data.print_filename = (char *)malloc(strlen(filename) + 1);
|
||||||
|
strcpy(printer_data.print_filename, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
printer_data.elapsed_time_s = status["print_stats"]["total_duration"];
|
||||||
|
printer_data.printed_time_s = status["print_stats"]["print_duration"];
|
||||||
|
printer_data.filament_used_mm = status["print_stats"]["filament_used"];
|
||||||
|
printer_data.total_layers = status["print_stats"]["info"]["total_layer"];
|
||||||
|
printer_data.current_layer = status["print_stats"]["info"]["current_layer"];
|
||||||
|
|
||||||
|
const char *state = status["print_stats"]["state"];
|
||||||
|
|
||||||
|
if (state == nullptr)
|
||||||
|
{
|
||||||
|
// Continue
|
||||||
|
}
|
||||||
|
else if (strcmp(state, "printing") == 0)
|
||||||
|
{
|
||||||
|
printer_data.state = PrinterStatePrinting;
|
||||||
|
}
|
||||||
|
else if (strcmp(state, "paused") == 0)
|
||||||
|
{
|
||||||
|
printer_data.state = PrinterStatePaused;
|
||||||
|
}
|
||||||
|
else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0)
|
||||||
|
{
|
||||||
|
printer_data.state = PrinterStateIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("display_status"))
|
||||||
|
{
|
||||||
|
printer_data.print_progress = status["display_status"]["progress"];
|
||||||
|
const char *message = status["display_status"]["message"];
|
||||||
|
|
||||||
|
if (message != NULL && (printer_data.popup_message == NULL || strcmp(printer_data.popup_message, message)))
|
||||||
|
{
|
||||||
|
printer_data.popup_message = (char *)malloc(strlen(message) + 1);
|
||||||
|
strcpy(printer_data.popup_message, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printer_data.state == PrinterStatePrinting && printer_data.print_progress > 0)
|
||||||
|
{
|
||||||
|
float remaining_time_s_percentage = (printer_data.printed_time_s / printer_data.print_progress) - printer_data.printed_time_s;
|
||||||
|
float remaining_time_s_slicer = 0;
|
||||||
|
|
||||||
|
if (slicer_estimated_print_time_s > 0)
|
||||||
|
{
|
||||||
|
remaining_time_s_slicer = slicer_estimated_print_time_s - printer_data.printed_time_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remaining_time_s_slicer <= 0 || printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE)
|
||||||
|
{
|
||||||
|
printer_data.remaining_time_s = remaining_time_s_percentage;
|
||||||
|
}
|
||||||
|
else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED)
|
||||||
|
{
|
||||||
|
printer_data.remaining_time_s = remaining_time_s_percentage * printer_data.print_progress + remaining_time_s_slicer * (1 - printer_data.print_progress);
|
||||||
|
}
|
||||||
|
else if (printer_config->remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER)
|
||||||
|
{
|
||||||
|
printer_data.remaining_time_s = remaining_time_s_slicer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printer_data.remaining_time_s < 0)
|
||||||
|
{
|
||||||
|
printer_data.remaining_time_s = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printer_data.state == PrinterStateIdle)
|
||||||
|
{
|
||||||
|
slicer_estimated_print_time_s = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printer_data.state == PrinterStatePrinting && millis() - last_slicer_time_query > 30000 && slicer_estimated_print_time_s <= 0)
|
||||||
|
{
|
||||||
|
last_slicer_time_query = millis();
|
||||||
|
slicer_estimated_print_time_s = get_slicer_time_estimate_s();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrinterDataMinimal KlipperPrinter::parse_state_min(JsonDocument &in)
|
||||||
|
{
|
||||||
|
auto status = in["result"]["status"];
|
||||||
|
PrinterDataMinimal data = {};
|
||||||
|
data.success = true;
|
||||||
|
|
||||||
|
if (status.containsKey("webhooks"))
|
||||||
|
{
|
||||||
|
const char *state = status["webhooks"]["state"];
|
||||||
|
|
||||||
|
if (strcmp(state, "shutdown") == 0)
|
||||||
|
{
|
||||||
|
data.state = PrinterState::PrinterStateError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.state != PrinterStateError)
|
||||||
|
{
|
||||||
|
if (status.containsKey("virtual_sdcard"))
|
||||||
|
{
|
||||||
|
data.print_progress = status["virtual_sdcard"]["progress"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.containsKey("print_stats"))
|
||||||
|
{
|
||||||
|
const char *state = status["print_stats"]["state"];
|
||||||
|
|
||||||
|
if (state == nullptr)
|
||||||
|
{
|
||||||
|
data.state = PrinterState::PrinterStateError;
|
||||||
|
}
|
||||||
|
else if (strcmp(state, "printing") == 0)
|
||||||
|
{
|
||||||
|
data.state = PrinterState::PrinterStatePrinting;
|
||||||
|
}
|
||||||
|
else if (strcmp(state, "paused") == 0)
|
||||||
|
{
|
||||||
|
data.state = PrinterState::PrinterStatePaused;
|
||||||
|
}
|
||||||
|
else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0)
|
||||||
|
{
|
||||||
|
data.state = PrinterState::PrinterStateIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Macros KlipperPrinter::parse_macros(JsonDocument &in)
|
||||||
|
{
|
||||||
|
auto result = in["result"].as<JsonObject>();
|
||||||
|
Macros macros = {0};
|
||||||
|
macros.macros = (char **)malloc(sizeof(char *) * 32);
|
||||||
|
macros.count = 0;
|
||||||
|
macros.success = true;
|
||||||
|
|
||||||
|
for (JsonPair i : result)
|
||||||
|
{
|
||||||
|
const char *key = i.key().c_str();
|
||||||
|
const char *value = i.value().as<String>().c_str();
|
||||||
|
if (strcmp(value, "CYD_SCREEN_MACRO") == 0)
|
||||||
|
{
|
||||||
|
char *macro = (char *)malloc(strlen(key) + 1);
|
||||||
|
strcpy(macro, key);
|
||||||
|
macros.macros[macros.count++] = macro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (global_config.sort_macros)
|
||||||
|
{
|
||||||
|
std::sort(macros.macros, macros.macros + macros.count, [](const char *a, const char *b)
|
||||||
|
{ return strcmp(a, b) < 0; });
|
||||||
|
}
|
||||||
|
|
||||||
|
return macros;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KlipperPrinter::parse_macros_count(JsonDocument &in)
|
||||||
|
{
|
||||||
|
auto result = in["result"].as<JsonObject>();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (JsonPair i : result)
|
||||||
|
{
|
||||||
|
const char *value = i.value().as<String>().c_str();
|
||||||
|
if (strcmp(value, "CYD_SCREEN_MACRO") == 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
PowerDevices KlipperPrinter::parse_power_devices(JsonDocument &in)
|
||||||
|
{
|
||||||
|
PowerDevices power_devices = {0};
|
||||||
|
auto result = in["result"]["devices"].as<JsonArray>();
|
||||||
|
power_devices.power_devices = (char **)malloc(sizeof(char *) * 16);
|
||||||
|
power_devices.power_states = (bool *)malloc(sizeof(bool) * 16);
|
||||||
|
power_devices.count = 0;
|
||||||
|
power_devices.success = true;
|
||||||
|
|
||||||
|
for (auto i : result)
|
||||||
|
{
|
||||||
|
const char *device_name = i["device"];
|
||||||
|
const char *device_state = i["status"];
|
||||||
|
power_devices.power_devices[power_devices.count] = (char *)malloc(strlen(device_name) + 1);
|
||||||
|
strcpy(power_devices.power_devices[power_devices.count], device_name);
|
||||||
|
power_devices.power_states[power_devices.count] = strcmp(device_state, "on") == 0;
|
||||||
|
power_devices.count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return power_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KlipperPrinter::parse_power_devices_count(JsonDocument &in)
|
||||||
|
{
|
||||||
|
auto result = in["result"]["devices"].as<JsonArray>();
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (auto i : result)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KlipperPrinter::parse_file_list(JsonDocument &in, std::list<FileSystemFile> &files, int fetch_limit)
|
||||||
|
{
|
||||||
|
auto result = in["result"].as<JsonArray>();
|
||||||
|
|
||||||
|
for (auto file : result)
|
||||||
|
{
|
||||||
|
FileSystemFile f = {0};
|
||||||
|
const char *path = file["path"];
|
||||||
|
float modified = file["modified"];
|
||||||
|
auto file_iter = files.begin();
|
||||||
|
|
||||||
|
while (file_iter != files.end())
|
||||||
|
{
|
||||||
|
if ((*file_iter).modified < modified)
|
||||||
|
break;
|
||||||
|
|
||||||
|
file_iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_iter == files.end() && files.size() >= fetch_limit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
f.name = (char *)malloc(strlen(path) + 1);
|
||||||
|
if (f.name == NULL)
|
||||||
|
{
|
||||||
|
LOG_LN("Failed to allocate memory");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
strcpy(f.name, path);
|
||||||
|
f.modified = modified;
|
||||||
|
|
||||||
|
if (file_iter != files.end())
|
||||||
|
files.insert(file_iter, f);
|
||||||
|
else
|
||||||
|
files.push_back(f);
|
||||||
|
|
||||||
|
if (files.size() > fetch_limit)
|
||||||
|
{
|
||||||
|
auto last_entry = files.back();
|
||||||
|
|
||||||
|
if (last_entry.name != NULL)
|
||||||
|
free(last_entry.name);
|
||||||
|
|
||||||
|
files.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *KlipperPrinter::parse_thumbnails(JsonDocument &in)
|
||||||
|
{
|
||||||
|
auto result = in["result"].as<JsonArray>();
|
||||||
|
const char *chosen_thumb = NULL;
|
||||||
|
for (auto file : result)
|
||||||
|
{
|
||||||
|
int width = file["width"];
|
||||||
|
int height = file["height"];
|
||||||
|
int size = file["size"];
|
||||||
|
const char *thumbnail = file["thumbnail_path"];
|
||||||
|
|
||||||
|
if (width != height || width != 32)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(thumbnail + strlen(thumbnail) - 4, ".png"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
chosen_thumb = thumbnail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chosen_thumb != NULL)
|
||||||
|
{
|
||||||
|
char* img_filename_path = (char *)malloc(strlen(chosen_thumb) + 1);
|
||||||
|
strcpy(img_filename_path, chosen_thumb);
|
||||||
|
return img_filename_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user