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",
|
||||
"memory": "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
|
||||
}
|
||||
@@ -35,9 +35,7 @@ int KlipperPrinter::get_slicer_time_estimate_s()
|
||||
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
int time_estimate_s = doc["result"]["estimated_time"];
|
||||
LOG_F(("Got slicer time estimate: %ds\n", time_estimate_s))
|
||||
return time_estimate_s;
|
||||
return parse_slicer_time_estimate(doc);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
HTTPClient client;
|
||||
@@ -112,16 +126,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature)
|
||||
case PrinterFeatureEmergencyStop:
|
||||
LOG_LN("Sending estop");
|
||||
send_gcode("M112", false);
|
||||
configure_http_client(client, "/printer/emergency_stop", false, 5000);
|
||||
|
||||
try
|
||||
{
|
||||
client.GET();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_LN("Failed to send estop");
|
||||
}
|
||||
send_emergency_stop();
|
||||
|
||||
return true;
|
||||
case PrinterFeatureExtrude:
|
||||
@@ -182,177 +187,7 @@ bool KlipperPrinter::fetch()
|
||||
klipper_request_consecutive_fail_count = 0;
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto status = doc["result"]["status"];
|
||||
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();
|
||||
}
|
||||
parse_state(doc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -393,47 +228,7 @@ PrinterDataMinimal KlipperPrinter::fetch_min()
|
||||
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto status = doc["result"]["status"];
|
||||
|
||||
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 parse_state_min(doc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -461,27 +256,7 @@ Macros KlipperPrinter::get_macros()
|
||||
if (http_code == 200){
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto result = doc["result"].as<JsonObject>();
|
||||
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 parse_macros(doc);
|
||||
}
|
||||
|
||||
return macros;
|
||||
@@ -497,18 +272,7 @@ int KlipperPrinter::get_macros_count()
|
||||
if (http_code == 200){
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto result = doc["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;
|
||||
return parse_macros_count(doc);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
@@ -531,20 +295,7 @@ PowerDevices KlipperPrinter::get_power_devices()
|
||||
if (http_code == 200){
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto result = doc["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 parse_power_devices(doc);
|
||||
}
|
||||
|
||||
return power_devices;
|
||||
@@ -560,15 +311,7 @@ int KlipperPrinter::get_power_devices_count()
|
||||
if (http_code == 200){
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto result = doc["result"]["devices"].as<JsonArray>();
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (auto i : result){
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
return parse_power_devices_count(doc);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
@@ -582,11 +325,6 @@ bool KlipperPrinter::set_power_device_state(const char* device_name, bool state)
|
||||
return client.POST("") == 200;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
float modified;
|
||||
} FileSystemFile;
|
||||
|
||||
#define KLIPPER_FILE_FETCH_LIMIT 20
|
||||
|
||||
Files KlipperPrinter::get_files()
|
||||
@@ -606,46 +344,7 @@ Files KlipperPrinter::get_files()
|
||||
JsonDocument doc;
|
||||
auto parseResult = deserializeJson(doc, client.getStream());
|
||||
LOG_F(("Json parse: %s\n", parseResult.c_str()))
|
||||
auto result = doc["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() >= 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();
|
||||
}
|
||||
}
|
||||
parse_file_list(doc, files, KLIPPER_FILE_FETCH_LIMIT);
|
||||
}
|
||||
|
||||
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;
|
||||
deserializeJson(doc, client.getStream());
|
||||
auto result = doc["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){
|
||||
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);
|
||||
}
|
||||
img_filename_path = parse_thumbnails(doc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -759,6 +435,10 @@ Thumbnail KlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filena
|
||||
LOG_LN("No compatible thumbnail found");
|
||||
return thumbnail;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_F(("Found 32x32 PNG gcode img at %s\n", gcode_filename));
|
||||
}
|
||||
|
||||
client.end();
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
#include "../printer_integration.hpp"
|
||||
#include <HTTPClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <list>
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
float modified;
|
||||
} FileSystemFile;
|
||||
|
||||
class KlipperPrinter : public BasePrinter
|
||||
{
|
||||
@@ -10,6 +17,22 @@ class KlipperPrinter : public BasePrinter
|
||||
unsigned char klipper_request_consecutive_fail_count{};
|
||||
unsigned int slicer_estimated_print_time_s{};
|
||||
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:
|
||||
float gcode_offset[3]{};
|
||||
@@ -51,9 +74,6 @@ class KlipperPrinter : public BasePrinter
|
||||
Thumbnail get_32_32_png_image_thumbnail(const char* gcode_filename);
|
||||
bool set_target_temperature(PrinterTemperatureDevice device, unsigned int temperature);
|
||||
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 {
|
||||
|
||||
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