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
|
||||
lib64
|
||||
|
||||
__pycache__/
|
||||
@@ -110,6 +110,83 @@ bool make_serial_request(JsonDocument &out, int timeout_ms, HttpRequestType requ
|
||||
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)
|
||||
{
|
||||
JsonDocument doc;
|
||||
@@ -285,14 +362,38 @@ bool SerialKlipperPrinter::start_file(const char* filename)
|
||||
{
|
||||
JsonDocument doc;
|
||||
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)
|
||||
{
|
||||
// TODO: Stubbed
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -311,6 +412,30 @@ bool SerialKlipperPrinter::send_gcode(const char* gcode, bool wait)
|
||||
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)
|
||||
{
|
||||
serial_console::global_disable_serial_console = true;
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
class SerialKlipperPrinter : public KlipperPrinter
|
||||
{
|
||||
protected:
|
||||
bool send_emergency_stop();
|
||||
int get_slicer_time_estimate_s();
|
||||
public:
|
||||
SerialKlipperPrinter(int index) : KlipperPrinter(index)
|
||||
{}
|
||||
|
||||
@@ -147,7 +147,7 @@ bool KlipperPrinter::execute_feature(PrinterFeatures feature)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (get_current_printer()->printer_config->custom_filament_move_macros)
|
||||
if (printer_config->custom_filament_move_macros)
|
||||
{
|
||||
return send_gcode("FILAMENT_RETRACT");
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ class KlipperPrinter : public BasePrinter
|
||||
unsigned char lock_absolute_relative_mode_swap{};
|
||||
unsigned char klipper_request_consecutive_fail_count{};
|
||||
|
||||
bool send_emergency_stop();
|
||||
int get_slicer_time_estimate_s();
|
||||
virtual bool send_emergency_stop();
|
||||
virtual int get_slicer_time_estimate_s();
|
||||
void init_ui_panels();
|
||||
|
||||
int parse_slicer_time_estimate(JsonDocument& in);
|
||||
|
||||
@@ -30,7 +30,7 @@ def main():
|
||||
# Read a line from the serial port
|
||||
if ser.in_waiting > 0:
|
||||
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}")
|
||||
# Parse the parameters
|
||||
try:
|
||||
@@ -38,6 +38,7 @@ def main():
|
||||
timeout_ms, request_type, url_path = int(parts[1]), parts[2], parts[3]
|
||||
|
||||
ignore_timeout = timeout_ms <= 0
|
||||
binary = line.startswith("HTTP_BINARY")
|
||||
|
||||
if ignore_timeout:
|
||||
timeout_ms = 1000;
|
||||
@@ -57,6 +58,15 @@ def main():
|
||||
|
||||
# Send response back over serial
|
||||
if response != None:
|
||||
if binary:
|
||||
if response.status_code != 200:
|
||||
write("00000000", 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}"
|
||||
Reference in New Issue
Block a user