mirror of
https://github.com/suchmememanyskill/CYD-Klipper.git
synced 2026-03-20 21:23:25 +00:00
Gcode images, fixes to serial
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ out/
|
|||||||
lib
|
lib
|
||||||
lib64
|
lib64
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
@@ -110,6 +110,83 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned char* data;
|
||||||
|
} BinaryResponse;
|
||||||
|
|
||||||
|
bool make_binary_request(BinaryResponse* data, int timeout_ms, HttpRequestType requestType, const char* endpoint)
|
||||||
|
{
|
||||||
|
semaphore_init_serial();
|
||||||
|
freeze_serial_thread();
|
||||||
|
serial_console::global_disable_serial_console = true;
|
||||||
|
temporary_config.debug = false;
|
||||||
|
char buff[10];
|
||||||
|
clear_serial_buffer();
|
||||||
|
|
||||||
|
// TODO: Add semaphore here
|
||||||
|
if (!Serial.availableForWrite() || timeout_ms <= 0)
|
||||||
|
{
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("HTTP_BINARY %d %s %s\n", timeout_ms, requestType == HttpGet ? "GET" : "POST", endpoint);
|
||||||
|
|
||||||
|
unsigned long _m = millis();
|
||||||
|
while (!Serial.available() && millis() < _m + timeout_ms + 10) delay(1);
|
||||||
|
|
||||||
|
if (!Serial.available())
|
||||||
|
{
|
||||||
|
Serial.println("Timeout...");
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.readBytes(buff, 8);
|
||||||
|
buff[9] = 0;
|
||||||
|
|
||||||
|
if (buff[0] < '0' || buff[0] > '9')
|
||||||
|
{
|
||||||
|
Serial.println("Invalid length");
|
||||||
|
clear_serial_buffer();
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int data_length = atoi(buff);
|
||||||
|
|
||||||
|
if (data_length <= 0)
|
||||||
|
{
|
||||||
|
Serial.println("0 Length");
|
||||||
|
clear_serial_buffer();
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->len = data_length;
|
||||||
|
data->data = (unsigned char*)malloc(data_length);
|
||||||
|
|
||||||
|
if (data->data == NULL)
|
||||||
|
{
|
||||||
|
Serial.println("Failed to allocate memory");
|
||||||
|
clear_serial_buffer();
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = Serial.readBytes((char*)data->data, data_length) == data_length;
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
free(data->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool make_serial_request_nocontent(HttpRequestType requestType, const char* endpoint)
|
bool make_serial_request_nocontent(HttpRequestType requestType, const char* endpoint)
|
||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
@@ -285,14 +362,38 @@ bool SerialKlipperPrinter::start_file(const char* filename)
|
|||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
String request = "/printer/print/start?filename=" + urlEncode(filename);
|
String request = "/printer/print/start?filename=" + urlEncode(filename);
|
||||||
return make_serial_request_nocontent(HttpGet, request.c_str());;
|
return make_serial_request_nocontent(HttpPost, request.c_str());;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thumbnail SerialKlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename)
|
Thumbnail SerialKlipperPrinter::get_32_32_png_image_thumbnail(const char* gcode_filename)
|
||||||
{
|
{
|
||||||
// TODO: Stubbed
|
|
||||||
Thumbnail thumbnail = {0};
|
Thumbnail thumbnail = {0};
|
||||||
thumbnail.success = false;
|
JsonDocument doc;
|
||||||
|
char* img_filename_path = NULL;
|
||||||
|
|
||||||
|
String request = "/server/files/thumbnails?filename=" + urlEncode(gcode_filename);
|
||||||
|
if (make_serial_request(doc, 1000, HttpGet, request.c_str()))
|
||||||
|
{
|
||||||
|
img_filename_path = parse_thumbnails(doc);
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
doc.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (img_filename_path == NULL)
|
||||||
|
{
|
||||||
|
return thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
request = "/server/files/gcodes/" + urlEncode(img_filename_path);
|
||||||
|
BinaryResponse data = {0};
|
||||||
|
if (make_binary_request(&data, 2000, HttpGet, request.c_str()))
|
||||||
|
{
|
||||||
|
thumbnail.png = data.data;
|
||||||
|
thumbnail.size = data.len;
|
||||||
|
thumbnail.success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(img_filename_path);
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +412,30 @@ bool SerialKlipperPrinter::send_gcode(const char* gcode, bool wait)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SerialKlipperPrinter::send_emergency_stop()
|
||||||
|
{
|
||||||
|
return make_serial_request_nocontent(HttpGet, "/printer/emergency_stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
int SerialKlipperPrinter::get_slicer_time_estimate_s()
|
||||||
|
{
|
||||||
|
if (printer_data.state != PrinterStatePrinting && printer_data.state != PrinterStatePaused)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
String request = "/server/files/metadata?filename=" + urlEncode(printer_data.print_filename);
|
||||||
|
JsonDocument doc;
|
||||||
|
|
||||||
|
if (!make_serial_request(doc, 2000, HttpGet, request.c_str()))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int estimate = parse_slicer_time_estimate(doc);
|
||||||
|
unfreeze_serial_thread();
|
||||||
|
|
||||||
|
return estimate;
|
||||||
|
}
|
||||||
|
|
||||||
KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config)
|
KlipperConnectionStatus connection_test_serial_klipper(PrinterConfiguration* config)
|
||||||
{
|
{
|
||||||
serial_console::global_disable_serial_console = true;
|
serial_console::global_disable_serial_console = true;
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
class SerialKlipperPrinter : public KlipperPrinter
|
class SerialKlipperPrinter : public KlipperPrinter
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
bool send_emergency_stop();
|
||||||
|
int get_slicer_time_estimate_s();
|
||||||
public:
|
public:
|
||||||
SerialKlipperPrinter(int index) : KlipperPrinter(index)
|
SerialKlipperPrinter(int index) : KlipperPrinter(index)
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_current_printer()->printer_config->custom_filament_move_macros)
|
if (printer_config->custom_filament_move_macros)
|
||||||
{
|
{
|
||||||
return send_gcode("FILAMENT_RETRACT");
|
return send_gcode("FILAMENT_RETRACT");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ class KlipperPrinter : public BasePrinter
|
|||||||
unsigned char lock_absolute_relative_mode_swap{};
|
unsigned char lock_absolute_relative_mode_swap{};
|
||||||
unsigned char klipper_request_consecutive_fail_count{};
|
unsigned char klipper_request_consecutive_fail_count{};
|
||||||
|
|
||||||
bool send_emergency_stop();
|
virtual bool send_emergency_stop();
|
||||||
int get_slicer_time_estimate_s();
|
virtual int get_slicer_time_estimate_s();
|
||||||
void init_ui_panels();
|
void init_ui_panels();
|
||||||
|
|
||||||
int parse_slicer_time_estimate(JsonDocument& in);
|
int parse_slicer_time_estimate(JsonDocument& in);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ def main():
|
|||||||
# Read a line from the serial port
|
# Read a line from the serial port
|
||||||
if ser.in_waiting > 0:
|
if ser.in_waiting > 0:
|
||||||
line = ser.readline().decode('utf-8').strip()
|
line = ser.readline().decode('utf-8').strip()
|
||||||
if line.startswith("HTTP_REQUEST"):
|
if line.startswith("HTTP_REQUEST") or line.startswith("HTTP_BINARY"):
|
||||||
print(f">>> {line}")
|
print(f">>> {line}")
|
||||||
# Parse the parameters
|
# Parse the parameters
|
||||||
try:
|
try:
|
||||||
@@ -38,6 +38,7 @@ def main():
|
|||||||
timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3]
|
timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3]
|
||||||
|
|
||||||
ignore_timeout = timeout_ms <= 0
|
ignore_timeout = timeout_ms <= 0
|
||||||
|
binary = line.startswith("HTTP_BINARY")
|
||||||
|
|
||||||
if ignore_timeout:
|
if ignore_timeout:
|
||||||
timeout_ms = 1000;
|
timeout_ms = 1000;
|
||||||
@@ -57,10 +58,19 @@ def main():
|
|||||||
|
|
||||||
# Send response back over serial
|
# Send response back over serial
|
||||||
if response != None:
|
if response != None:
|
||||||
status_code = response.status_code
|
if binary:
|
||||||
body = response.text.replace('\n', ' ') # Trim and sanitize body for serial
|
if response.status_code != 200:
|
||||||
message = f"{status_code} {body}"
|
write("00000000", not ignore_timeout)
|
||||||
write(message, not ignore_timeout)
|
else:
|
||||||
|
length = len(response.content)
|
||||||
|
ser.write(f"{length:>08}".encode('utf-8'))
|
||||||
|
ser.write(response.content)
|
||||||
|
print(f"<<< (Binary data of {length} bytes)")
|
||||||
|
else:
|
||||||
|
status_code = response.status_code
|
||||||
|
body = response.text.replace('\n', ' ') # Trim and sanitize body for serial
|
||||||
|
message = f"{status_code} {body}"
|
||||||
|
write(message, not ignore_timeout)
|
||||||
except (IndexError, ValueError) as e:
|
except (IndexError, ValueError) as e:
|
||||||
write(f"400 Malformed request {str(e)}", not ignore_timeout)
|
write(f"400 Malformed request {str(e)}", not ignore_timeout)
|
||||||
except requests.exceptions.ReadTimeout as e:
|
except requests.exceptions.ReadTimeout as e:
|
||||||
Reference in New Issue
Block a user