Clon1998 / mobileraker

A Flutter mobile app for Klipper/Moonraker
Other
474 stars 52 forks source link

Exception: type 'Null' is not a subtype of type 'String' #205

Closed Turge08 closed 1 year ago

Turge08 commented 1 year ago

Describe the bug I get this error when accessing one of my printers. Other one is fine. I have tried removing the printer and re-adding it and it appears to be an error with my config but I have compared it with the config on my other printer and couldn't find anything that stands out. Exception.txt

I still get notifications for the printer but can't load up the Dashboard for it.

I have taken a look at config_stepper.dart and the only non null string fields are stepper name, stepPin and dirPin and these are all defined.

Smartphone (please complete the following information):

**Mobileraker-Version Version 2.4.2

Additional context Screenshot 2023-07-29 145633 Screenshot 2023-07-29 145700

To simplify things, here's my config file: https://codebeautify.org/jsonviewer/y23739d84

Clon1998 commented 1 year ago

Thanks for the report and also including the error log and config already! I will look into that and get back to you.

Clon1998 commented 1 year ago

Could you temporary try to exclude the stepper_fan drivers_fan config, seems like I have an error in my parsing mobileraker tries to parse the stepper_fan as stepper.

Turge08 commented 1 year ago

Oops. I created that component (based on controller_fan) in Klipper so that my fan would only come on based on the steppers without needing to define a heater. I created it about 2 months ago and haven't used the printer until recently which is why I didn't link the 2.

I'll remove it. Sorry about that!

Turge08 commented 1 year ago

It's working now without it :)

Clon1998 commented 1 year ago

Thats Great! However, the app still has a problem. It should be fine to have a fan configured as steper_fan :)

Turge08 commented 1 year ago

True. As a developer, I probably would've implemented it the same way but I guess the best way to future-proof it would be to use a regex.

Clon1998 commented 1 year ago

Fixed in android2.5.0

busheezy commented 1 year ago

This is still happening to me with 2.5.3-249.

I've added a heater_generic and now I can no longer use the app to control my printer.

Exception:

 type 'Null' is not a subtype of type 'String' in type cast

#0      _$$_ConfigHeaterGenericFromJson (package:mobileraker/data/dto/config/config_heater_generic.g.dart:14)
#1      new _$_ConfigHeaterGeneric.fromJson (package:mobileraker/data/dto/config/config_heater_generic.freezed.dart:196)
#2      _$ConfigHeaterGenericFromJson (package:mobileraker/data/dto/config/config_heater_generic.freezed.dart:18)
#3      new ConfigHeaterGeneric.fromJson (package:mobileraker/data/dto/config/config_heater_generic.dart:45)
#4      new ConfigFile.parse (package:mobileraker/data/dto/config/config_file.dart:102)
#5      PrinterService._updateConfigFile (package:mobileraker/service/moonraker/printer_service.dart:697)
#6      PrinterService._parseObjectType (package:mobileraker/service/moonraker/printer_service.dart:529)
#7      PrinterService._temperatureStore.<anonymous closure> (package:mobileraker/service/moonraker/printer_service.dart:478)
#8      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625)
#9      PrinterService._parseQueriedObjects (package:mobileraker/service/moonraker/printer_service.dart:614)
#10     PrinterService._printerObjectsQuery (package:mobileraker/service/moonraker/printer_service.dart:773)
<asynchronous suspension>
#11     PrinterService.refreshPrinter (package:mobileraker/service/moonraker/printer_service.dart:203)
<asynchronous suspension>

Failed-Key: configfile Raw Json:

{
    "configfile": {
        "config": {
            "virtual_sdcard": {
                "path": "/home/bush/sv01_data/gcodes"
            },
            "pause_resume": {},
            "display_status": {},
            "menu __main __octoprint": {
                "type": "disabled"
            },
            "menu __main __sdcard": {
                "type": "disabled"
            },
            "menu __main __macros": {
                "type": "list",
                "name": "Macros"
            },
            "menu __main __macros __resume": {
                "type": "command",
                "enable": "{printer.print_stats.state == \"paused\"}",
                "name": "Resume printing",
                "gcode": "\nRESUME"
            },
            "menu __main __macros __pause": {
                "type": "command",
                "enable": "{printer.print_stats.state == \"printing\"}",
                "name": "Pause printing",
                "gcode": "\nPAUSE"
            },
            "menu __main __macros __cancel": {
                "type": "command",
                "enable": "{(printer.print_stats.state == \"printing\" or printer.print_stats.state == \"paused\")}",
                "name": "Cancel printing",
                "gcode": "\nCANCEL_PRINT"
            },
            "stepper_x": {
                "step_pin": "PF0",
                "dir_pin": "PF1",
                "enable_pin": "!PD7",
                "microsteps": "16",
                "rotation_distance": "40",
                "endstop_pin": "^PE5",
                "position_endstop": "0",
                "position_max": "300",
                "homing_speed": "50"
            },
            "stepper_y": {
                "step_pin": "PF6",
                "dir_pin": "PF7",
                "enable_pin": "!PF2",
                "microsteps": "16",
                "rotation_distance": "40",
                "endstop_pin": "^PJ1",
                "position_endstop": "0",
                "position_max": "255",
                "homing_speed": "50"
            },
            "stepper_z": {
                "step_pin": "PL3",
                "dir_pin": "!PL1",
                "enable_pin": "!PK0",
                "microsteps": "16",
                "rotation_distance": "8",
                "endstop_pin": "probe:z_virtual_endstop",
                "position_max": "300"
            },
            "extruder": {
                "max_extrude_only_distance": "100.0",
                "max_extrude_cross_section": "5.0",
                "step_pin": "PA4",
                "dir_pin": "!PA6",
                "enable_pin": "!PA2",
                "microsteps": "16",
                "rotation_distance": "7.680",
                "nozzle_diameter": "0.400",
                "filament_diameter": "1.750",
                "heater_pin": "PB4",
                "sensor_type": "EPCOS 100K B57560G104F",
                "sensor_pin": "PK5",
                "min_temp": "0",
                "max_temp": "265",
                "control": "pid",
                "pid_kp": "30.170",
                "pid_ki": "3.409",
                "pid_kd": "66.751"
            },
            "heater_bed": {
                "heater_pin": "PH5",
                "sensor_type": "EPCOS 100K B57560G104F",
                "sensor_pin": "PK6",
                "min_temp": "0",
                "max_temp": "110",
                "control": "pid",
                "pid_kp": "72.630",
                "pid_ki": "1.664",
                "pid_kd": "792.579"
            },
            "fan": {
                "pin": "PH6"
            },
            "bltouch": {
                "sensor_pin": "^PD3",
                "control_pin": "PB5",
                "x_offset": "-34.0",
                "y_offset": "-3.5",
                "z_offset": "2.30",
                "samples": "3",
                "samples_result": "median",
                "sample_retract_dist": "5.0",
                "samples_tolerance": "0.01",
                "samples_tolerance_retries": "3"
            },
            "gcode_macro CANCEL_PRINT": {
                "description": "Cancel the actual running print",
                "rename_existing": "CANCEL_PRINT_BASE",
                "gcode": "\nTURN_OFF_HEATERS\nCANCEL_PRINT_BASE"
            },
            "gcode_macro PAUSE": {
                "description": "Pause the actual running print",
                "rename_existing": "PAUSE_BASE",
                "variable_extrude": "1.0",
                "gcode": "\n\n{% set E = printer[\"gcode_macro PAUSE\"].extrude|float %}\n\n\n{% set x_park = printer.toolhead.axis_maximum.x|float - 5.0 %}\n{% set y_park = printer.toolhead.axis_maximum.y|float - 5.0 %}\n\n{% set max_z = printer.toolhead.axis_maximum.z|float %}\n{% set act_z = printer.toolhead.position.z|float %}\n{% if act_z < (max_z - 2.0) %}\n{% set z_safe = 2.0 %}\n{% else %}\n{% set z_safe = max_z - act_z %}\n{% endif %}\n\nPAUSE_BASE\nG91\n{% if printer.extruder.can_extrude|lower == 'true' %}\nG1 E-{E} F2100\n{% else %}\n{action_respond_info(\"Extruder not hot enough\")}\n{% endif %}\n{% if \"xyz\" in printer.toolhead.homed_axes %}\nG1 Z{z_safe} F900\nG90\nG1 X{x_park} Y{y_park} F6000\n{% else %}\n{action_respond_info(\"Printer not homed\")}\n{% endif %}"
            },
            "gcode_macro RESUME": {
                "description": "Resume the actual running print",
                "rename_existing": "RESUME_BASE",
                "gcode": "\n\n{% set E = printer[\"gcode_macro PAUSE\"].extrude|float %}\n\n{% if 'VELOCITY' in params|upper %}\n{% set get_params = ('VELOCITY=' + params.VELOCITY)  %}\n{%else %}\n{% set get_params = \"\" %}\n{% endif %}\n\n{% if printer.extruder.can_extrude|lower == 'true' %}\nG91\nG1 E{E} F2100\n{% else %}\n{action_respond_info(\"Extruder not hot enough\")}\n{% endif %}\nRESUME_BASE {get_params}"
            },
            "gcode_macro M600": {
                "gcode": "\n{% set X = params.X|default(50)|float %}\n{% set Y = params.Y|default(0)|float %}\n{% set Z = params.Z|default(10)|float %}\nSAVE_GCODE_STATE NAME=M600_state\nPAUSE\nG91\nG1 E-.8 F2700\nG1 Z{Z}\nG90\nG1 X{X} Y{Y} F3000\nG91\nG1 E-50 F1000\nRESTORE_GCODE_STATE NAME=M600_state"
            },
            "gcode_macro START_PRINT": {
                "gcode": "\n{% set BED_TEMP = params.BED_TEMP|default(60)|float %}\n{% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(190)|float %}\n\nM190 S{BED_TEMP}\n\nG90\n\nG28\n\nBED_MESH_CALIBRATE\n\nSmart_Park\n\nM109 S{EXTRUDER_TEMP}\n\nLINE_PURGE"
            },
            "gcode_macro END_PRINT": {
                "gcode": "\nTURN_OFF_HEATERS\n\nG91\n\nG1 E-18 F800\n\nG1 Z10 F3000\n\nM106 S0\n\nG90\n\nG28 X\n\nM84"
            },
            "gcode_macro POWER_OFF_PRINTER": {
                "gcode": "\n{action_call_remote_method(\n\"set_device_power\", device=\"sv01\", state=\"off\"\n)}"
            },
            "gcode_macro BED_MESH_CALIBRATE": {
                "rename_existing": "_BED_MESH_CALIBRATE",
                "gcode": "\n\n{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}\n{% set bed_mesh_min = printer.configfile.settings.bed_mesh.mesh_min %}\n{% set bed_mesh_max = printer.configfile.settings.bed_mesh.mesh_max %}\n{% set probe_count = printer.configfile.settings.bed_mesh.probe_count %}\n{% set verbose_enable = printer[\"gcode_macro _KAMP_Settings\"].verbose_enable | abs %}\n{% set probe_dock_enable = printer[\"gcode_macro _KAMP_Settings\"].probe_dock_enable | abs %}\n{% set attach_macro = printer[\"gcode_macro _KAMP_Settings\"].attach_macro | string %}\n{% set detach_macro = printer[\"gcode_macro _KAMP_Settings\"].detach_macro | string %}\n{% set mesh_margin = printer[\"gcode_macro _KAMP_Settings\"].mesh_margin | float %}\n{% set fuzz_amount = printer[\"gcode_macro _KAMP_Settings\"].fuzz_amount | float %}\n{% set probe_count = probe_count if probe_count|length > 1 else probe_count * 2  %}\n{% set max_probe_point_distance_x = ( bed_mesh_max[0] - bed_mesh_min[0] ) / (probe_count[0] - 1)  %}\n{% set max_probe_point_distance_y = ( bed_mesh_max[1] - bed_mesh_min[1] ) / (probe_count[1] - 1)  %}\n{% set x_min = all_points | map(attribute=0) | min | default(bed_mesh_min[0]) %}\n{% set y_min = all_points | map(attribute=1) | min | default(bed_mesh_min[1]) %}\n{% set x_max = all_points | map(attribute=0) | max | default(bed_mesh_max[0]) %}\n{% set y_max = all_points | map(attribute=1) | max | default(bed_mesh_max[1]) %}\n\n{% set fuzz_range = range((0) | int, (fuzz_amount * 100) | int + 1) %}\n{% set adapted_x_min = (bed_mesh_min[0] + fuzz_amount - mesh_margin, x_min) | max - (fuzz_range | random / 100.0) %}\n{% set adapted_y_min = (bed_mesh_min[1] + fuzz_amount - mesh_margin, y_min) | max - (fuzz_range | random / 100.0) %}\n{% set adapted_x_max = (bed_mesh_max[0] - fuzz_amount + mesh_margin, x_max) | min + (fuzz_range | random / 100.0) %}\n{% set adapted_y_max = (bed_mesh_max[1] - fuzz_amount + mesh_margin, y_max) | min + (fuzz_range | random / 100.0) %}\n\n{% set adapted_x_min = [adapted_x_min , bed_mesh_min[0]] | max %}\n{% set adapted_y_min = [adapted_y_min , bed_mesh_min[1]] | max %}\n{% set adapted_x_max = [adapted_x_max , bed_mesh_max[0]] | min %}\n{% set adapted_y_max = [adapted_y_max , bed_mesh_max[1]] | min %}\n\n{% set points_x = (((adapted_x_max - adapted_x_min) / max_probe_point_distance_x) | round(method='ceil') | int) + 1 %}\n{% set points_y = (((adapted_y_max - adapted_y_min) / max_probe_point_distance_y) | round(method='ceil') | int) + 1 %}\n\n{% if (([points_x, points_y]|max) > 6) %}\n{% set algorithm = \"bicubic\" %}\n{% set min_points = 4 %}\n{% else %}\n{% set algorithm = \"lagrange\" %}\n{% set min_points = 3 %}\n{% endif %}\n\n{% set points_x = [points_x , min_points]|max %}\n{% set points_y = [points_y , min_points]|max %}\n{% set points_x = [points_x , probe_count[0]]|min %}\n{% set points_y = [points_y , probe_count[1]]|min %}\n\n{% if verbose_enable == True %}\n\n{ action_respond_info( \"Algorithm: {}.\".format(\n(algorithm),\n)) }\n\n{ action_respond_info(\"Default probe count: {},{}.\".format(\n(probe_count[0]),\n(probe_count[1]),\n)) }\n\n{ action_respond_info(\"Adapted probe count: {},{}.\".format(\n(points_x),\n(points_y),\n)) }\n\n{action_respond_info(\"Default mesh bounds: {}, {}.\".format(\n(bed_mesh_min[0],bed_mesh_min[1]),\n(bed_mesh_max[0],bed_mesh_max[1]),\n)) }\n\n{% if mesh_margin > 0 %}\n{action_respond_info(\"Mesh margin is {}, mesh bounds extended by {}mm.\".format(\n(mesh_margin),\n(mesh_margin),\n)) }\n{% else %}\n{action_respond_info(\"Mesh margin is 0, margin not increased.\")}\n{% endif %}\n\n{% if fuzz_amount > 0 %}\n{action_respond_info(\"Mesh point fuzzing enabled, points fuzzed up to {}mm.\".format(\n(fuzz_amount),\n)) }\n{% else %}\n{action_respond_info(\"Fuzz amount is 0, mesh points not fuzzed.\")}\n{% endif %}\n\n{ action_respond_info(\"Adapted mesh bounds: {}, {}.\".format(\n(adapted_x_min, adapted_y_min),\n(adapted_x_max, adapted_y_max),\n)) }\n\n{action_respond_info(\"KAMP adjustments successful. Happy KAMPing!\")}\n\n{% endif %}\n\n{% if probe_dock_enable == True %}\n{attach_macro}\n{% endif %}\n\n_BED_MESH_CALIBRATE mesh_min={adapted_x_min},{adapted_y_min} mesh_max={adapted_x_max},{adapted_y_max} ALGORITHM={algorithm} PROBE_COUNT={points_x},{points_y}\n\n{% if probe_dock_enable == True %}\n{detach_macro}\n{% endif %}"
            },
            "gcode_macro LINE_PURGE": {
                "description": "A purge macro that adapts to be near your actual printed objects",
                "gcode": "\n\n{% set travel_speed = (printer.toolhead.max_velocity) * 60 | float %}\n{% set cross_section = printer.configfile.settings.extruder.max_extrude_cross_section | float %}\n\n\n{% if printer.firmware_retraction is defined %}\n{% set RETRACT = G10 | string %}\n{% set UNRETRACT = G11 | string %}\n{% else %}\n{% set RETRACT = 'G1 E-.5 F2100' | string %}\n{% set UNRETRACT = 'G1 E.5 F2100' | string %}\n{% endif %}\n\n\n{% set verbose_enable = printer[\"gcode_macro _KAMP_Settings\"].verbose_enable | abs %}\n{% set purge_height = printer[\"gcode_macro _KAMP_Settings\"].purge_height | float %}\n{% set tip_distance = printer[\"gcode_macro _KAMP_Settings\"].tip_distance | float %}\n{% set purge_margin = printer[\"gcode_macro _KAMP_Settings\"].purge_margin | float %}\n{% set purge_amount = printer[\"gcode_macro _KAMP_Settings\"].purge_amount | float %}\n{% set flow_rate = printer[\"gcode_macro _KAMP_Settings\"].flow_rate | float %}\n\n\n\n{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}\n{% set purge_x_min = (all_points | map(attribute=0) | min | default(0)) %}\n{% set purge_x_max = (all_points | map(attribute=0) | max | default(0)) %}\n{% set purge_y_min = (all_points | map(attribute=1) | min | default(0)) %}\n{% set purge_y_max = (all_points | map(attribute=1) | max | default(0)) %}\n\n{% set purge_x_center = ([((purge_x_max + purge_x_min) / 2) - (purge_amount / 2), 0] | max) %}\n{% set purge_y_center = ([((purge_y_max + purge_y_min) / 2) - (purge_amount / 2), 0] | max) %}\n\n{% set purge_x_origin = ([purge_x_min - purge_margin, 0] | max) %}\n{% set purge_y_origin = ([purge_y_min - purge_margin, 0] | max) %}\n\n\n{% set purge_move_speed = (flow_rate / 5.0) * 60 | float %}\n\n{% if cross_section < 5 %}\n\n{action_respond_info(\"[Extruder] max_extrude_cross_section is insufficient for purge, please set it to 5 or greater. Purge skipped.\")}\n\n{% else %}\n\n{% if verbose_enable == True %}\n\n{action_respond_info(\"Moving filament tip {}mms\".format(\n(tip_distance),\n)) }\n{% endif %}\n\n{% if printer.firmware_retraction is defined %}\n{action_respond_info(\"KAMP purge is using firmware retraction.\")}\n{% else %}\n{action_respond_info(\"KAMP purge is not using firmware retraction, it is recommended to configure it.\")}\n{% endif %}\n\n{% if purge_y_origin > 0 %}\n\n{action_respond_info(\"KAMP purge starting at {}, {} and purging {}mm of filament, requested flow rate is {}mm/s3.\".format(\n(purge_x_center),\n(purge_y_origin),\n(purge_amount),\n(flow_rate),\n)) }\n\n{% else %}\n\n{action_respond_info(\"KAMP purge starting at {}, {} and purging {}mm of filament, requested flow rate is {}mm/s3.\".format(\n(purge_x_origin),\n(purge_y_center),\n(purge_amount),\n(flow_rate),\n)) }\n\n{% endif %}\n\nSAVE_GCODE_STATE NAME=Prepurge_State\n\n{% if purge_y_origin > 0 %}\n\nG92 E0\nG0 F{travel_speed}\nG90\nG0 X{purge_x_center} Y{purge_y_origin}\nG0 Z{purge_height}\nM83\nG1 E{tip_distance} F{purge_move_speed}\nG1 X{purge_x_center + purge_amount} E{purge_amount} F{purge_move_speed}\n{RETRACT}\nG0 X{purge_x_center + purge_amount + 10} F{travel_speed}\nG92 E0\nM82\nG0 Z{purge_height * 2} F{travel_speed}\n\n{% else %}\n\nG92 E0\nG0 F{travel_speed}\nG90\nG0 X{purge_x_origin} Y{purge_y_center}\nG0 Z{purge_height}\nM83\nG1 E{tip_distance} F{purge_move_speed}\nG1 Y{purge_y_center + purge_amount} E{purge_amount} F{purge_move_speed}\n{RETRACT}\nG0 Y{purge_y_center + purge_amount + 10} F{travel_speed}\nG92 E0\nM82\nG0 Z{purge_height * 2} F{travel_speed}\n\n{% endif %}\n\nRESTORE_GCODE_STATE NAME=Prepurge_State\n\n{% endif %}"
            },
            "gcode_macro Smart_Park": {
                "description": "Parks your printhead near the print area for pre-print hotend heating.",
                "gcode": "\n\n{% set kamp_settings = printer[\"gcode_macro _KAMP_Settings\"] %}\n{% set z_height = kamp_settings.smart_park_height | float %}\n{% set purge_margin = kamp_settings.purge_margin | float %}\n{% set verbose_enable = kamp_settings.verbose_enable | abs %}\n{% set center_x = printer.toolhead.axis_maximum.x / 2 | float %}\n{% set center_y = printer.toolhead.axis_maximum.y / 2 | float %}\n{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}\n{% set x_min = all_points | map(attribute=0) | min | default(center_x) %}\n{% set y_min = all_points | map(attribute=1) | min | default(center_y) %}\n{% set travel_speed = (printer.toolhead.max_velocity) * 60 | float %}\n\n{% if purge_margin > 0 and x_min != center_x and y_min != center_y %}\n{% set x_min = [ x_min - purge_margin , x_min ] | max %}\n{% set y_min = [ y_min - purge_margin , y_min ] | max %}\n{% endif %}\n\n\n{% if verbose_enable == True %}\n\n{ action_respond_info(\"Smart Park location: {},{}.\".format(\n(x_min),\n(y_min),\n)) }\n\n{% endif %}\n\nG0 X{x_min} Y{y_min} F{travel_speed}\nG0 Z{z_height}"
            },
            "gcode_macro _KAMP_Settings": {
                "description": "This macro contains all adjustable settings for KAMP",
                "variable_verbose_enable": "True",
                "variable_mesh_margin": "0",
                "variable_fuzz_amount": "0",
                "variable_probe_dock_enable": "False",
                "variable_attach_macro": "'Attach_Probe'",
                "variable_detach_macro": "'Dock_Probe'",
                "variable_purge_height": "0.8",
                "variable_tip_distance": "15",
                "variable_purge_margin": "40",
                "variable_purge_amount": "40",
                "variable_flow_rate": "8",
                "variable_smart_park_height": ".42",
                "gcode": "\n\n{action_respond_info(\" Running the KAMP_Settings macro does nothing, it is only used for storing KAMP settings. \")}"
            },
            "menu __main __setup": {
                "type": "disabled"
            },
            "mcu": {
                "serial": "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A10K2RB1-if00-port0",
                "restart_method": "arduino"
            },
            "printer": {
                "kinematics": "cartesian",
                "max_velocity": "300",
                "max_accel": "3000",
                "max_z_velocity": "5",
                "max_z_accel": "100"
            },
            "display": {
                "lcd_type": "st7920",
                "cs_pin": "PH1",
                "sclk_pin": "PA1",
                "sid_pin": "PH0",
                "encoder_pins": "^PC4, ^PC6",
                "click_pin": "^!PC2"
            },
            "exclude_object": {},
            "gcode_arcs": {
                "resolution": "0.1"
            },
            "bed_mesh": {
                "speed": "150",
                "horizontal_move_z": "5",
                "mesh_min": "38, 35",
                "mesh_max": "242, 214",
                "probe_count": "7, 7",
                "algorithm": "bicubic"
            },
            "safe_z_home": {
                "home_xy_position": "150, 127",
                "speed": "100",
                "z_hop": "10",
                "z_hop_speed": "10"
            },
            "delayed_gcode delayed_printer_off": {
                "initial_duration": "0.",
                "gcode": "\n{% if printer.idle_timeout.state == \"Idle\" %}\nPOWER_OFF_PRINTER\n{% endif %}"
            },
            "idle_timeout": {
                "gcode": "\nUPDATE_DELAYED_GCODE ID=delayed_printer_off DURATION=60"
            },
            "bed_screws": {
                "screw1": "38,35",
                "screw2": "242,35",
                "screw3": "242,214",
                "screw4": "38,214"
            },
            "screws_tilt_adjust": {
                "screw1": "69,43",
                "screw1_name": "front left screw",
                "screw2": "276,43",
                "screw2_name": "front right screw",
                "screw3": "276,217",
                "screw3_name": "rear right screw",
                "screw4": "69,217",
                "screw4_name": "rear left screw",
                "horizontal_move_z": "10.",
                "speed": "50.",
                "screw_thread": "CW-M4"
            },
            "mcu pico": {
                "serial": "/dev/serial/by-id/usb-Klipper_rp2040_E6605838836F9A30-if00"
            },
            "multi_pin heater_pin": {
                "pins": "pico:gpio9,pico:gpio26"
            },
            "multi_pin fan_pin": {
                "pins": "pico:gpio5,pico:gpio27"
            },
            "heater_generic my_heater": {
                "sensor_type": "BME280",
                "gcode_id": "ENC",
                "i2c_mcu": "pico",
                "i2c_speed": "400000",
                "heater_pin": "multi_pin:heater_pin",
                "max_power": "1",
                "control": "watermark",
                "min_temp": "0",
                "max_temp": "55"
            },
            "verify_heater my_heater": {
                "check_gain_time": "120"
            },
            "heater_fan my_heater_fan": {
                "pin": "multi_pin:fan_pin",
                "max_power": "1",
                "heater": "my_heater",
                "heater_temp": "30.0",
                "fan_speed": "1.0"
            },
            "bed_mesh default": {
                "version": "1",
                "points": "\n-0.007500, 0.007500, 0.045000\n-0.007500, 0.017500, 0.020000\n-0.007500, 0.007500, 0.007500",
                "x_count": "3",
                "y_count": "3",
                "mesh_x_pps": "0",
                "mesh_y_pps": "0",
                "algo": "direct",
                "tension": "0.2",
                "min_x": "110.0",
                "max_x": "170.0",
                "min_y": "104.5",
                "max_y": "135.5"
            }
        },
        "settings": {
            "mcu": {
                "serial": "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A10K2RB1-if00-port0",
                "baud": 250000,
                "restart_method": "arduino",
                "max_stepper_error": 0.000025
            },
            "mcu pico": {
                "serial": "/dev/serial/by-id/usb-Klipper_rp2040_E6605838836F9A30-if00",
                "baud": 250000,
                "max_stepper_error": 0.000025
            },
            "virtual_sdcard": {
                "path": "/home/bush/sv01_data/gcodes",
                "on_error_gcode": ""
            },
            "pause_resume": {
                "recover_velocity": 50.0
            },
            "heater_bed": {
                "sensor_type": "EPCOS 100K B57560G104F",
                "pullup_resistor": 4700.0,
                "inline_resistor": 0.0,
                "sensor_pin": "PK6",
                "min_temp": 0.0,
                "max_temp": 110.0,
                "min_extrude_temp": 170.0,
                "max_power": 1.0,
                "smooth_time": 1.0,
                "control": "pid",
                "pid_kp": 72.63,
                "pid_ki": 1.664,
                "pid_kd": 792.579,
                "heater_pin": "PH5",
                "pwm_cycle_time": 0.1
            },
            "verify_heater heater_bed": {
                "hysteresis": 5.0,
                "max_error": 120.0,
                "heating_gain": 2.0,
                "check_gain_time": 60.0
            },
            "fan": {
                "max_power": 1.0,
                "kick_start_time": 0.1,
                "off_below": 0.0,
                "cycle_time": 0.01,
                "hardware_pwm": false,
                "shutdown_speed": 0.0,
                "pin": "PH6"
            },
            "bltouch": {
                "z_offset": 2.3,
                "stow_on_each_sample": true,
                "probe_with_touch_mode": false,
                "control_pin": "PB5",
                "sensor_pin": "^PD3",
                "pin_up_reports_not_triggered": true,
                "pin_up_touch_mode_reports_triggered": true,
                "pin_move_time": 0.68,
                "speed": 5.0,
                "lift_speed": 5.0,
                "x_offset": -34.0,
                "y_offset": -3.5,
                "samples": 3,
                "sample_retract_dist": 5.0,
                "samples_result": "median",
                "samples_tolerance": 0.01,
                "samples_tolerance_retries": 3
            },
            "gcode_macro cancel_print": {
                "gcode": "\nTURN_OFF_HEATERS\nCANCEL_PRINT_BASE",
                "rename_existing": "CANCEL_PRINT_BASE",
                "description": "Cancel the actual running print"
            },
            "gcode_macro pause": {
                "gcode": "\n\n{% set E = printer[\"gcode_macro PAUSE\"].extrude|float %}\n\n\n{% set x_park = printer.toolhead.axis_maximum.x|float - 5.0 %}\n{% set y_park = printer.toolhead.axis_maximum.y|float - 5.0 %}\n\n{% set max_z = printer.toolhead.axis_maximum.z|float %}\n{% set act_z = printer.toolhead.position.z|float %}\n{% if act_z < (max_z - 2.0) %}\n{% set z_safe = 2.0 %}\n{% else %}\n{% set z_safe = max_z - act_z %}\n{% endif %}\n\nPAUSE_BASE\nG91\n{% if printer.extruder.can_extrude|lower == 'true' %}\nG1 E-{E} F2100\n{% else %}\n{action_respond_info(\"Extruder not hot enough\")}\n{% endif %}\n{% if \"xyz\" in printer.toolhead.homed_axes %}\nG1 Z{z_safe} F900\nG90\nG1 X{x_park} Y{y_park} F6000\n{% else %}\n{action_respond_info(\"Printer not homed\")}\n{% endif %}",
                "rename_existing": "PAUSE_BASE",
                "description": "Pause the actual running print",
                "variable_extrude": "1.0"
            },
            "gcode_macro resume": {
                "gcode": "\n\n{% set E = printer[\"gcode_macro PAUSE\"].extrude|float %}\n\n{% if 'VELOCITY' in params|upper %}\n{% set get_params = ('VELOCITY=' + params.VELOCITY)  %}\n{%else %}\n{% set get_params = \"\" %}\n{% endif %}\n\n{% if printer.extruder.can_extrude|lower == 'true' %}\nG91\nG1 E{E} F2100\n{% else %}\n{action_respond_info(\"Extruder not hot enough\")}\n{% endif %}\nRESUME_BASE {get_params}",
                "rename_existing": "RESUME_BASE",
                "description": "Resume the actual running print"
            },
            "gcode_macro m600": {
                "gcode": "\n{% set X = params.X|default(50)|float %}\n{% set Y = params.Y|default(0)|float %}\n{% set Z = params.Z|default(10)|float %}\nSAVE_GCODE_STATE NAME=M600_state\nPAUSE\nG91\nG1 E-.8 F2700\nG1 Z{Z}\nG90\nG1 X{X} Y{Y} F3000\nG91\nG1 E-50 F1000\nRESTORE_GCODE_STATE NAME=M600_state",
                "description": "G-Code macro"
            },
            "gcode_macro start_print": {
                "gcode": "\n{% set BED_TEMP = params.BED_TEMP|default(60)|float %}\n{% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(190)|float %}\n\nM190 S{BED_TEMP}\n\nG90\n\nG28\n\nBED_MESH_CALIBRATE\n\nSmart_Park\n\nM109 S{EXTRUDER_TEMP}\n\nLINE_PURGE",
                "description": "G-Code macro"
            },
            "gcode_macro end_print": {
                "gcode": "\nTURN_OFF_HEATERS\n\nG91\n\nG1 E-18 F800\n\nG1 Z10 F3000\n\nM106 S0\n\nG90\n\nG28 X\n\nM84",
                "description": "G-Code macro"
            },
            "gcode_macro power_off_printer": {
                "gcode": "\n{action_call_remote_method(\n\"set_device_power\", device=\"sv01\", state=\"off\"\n)}",
                "description": "G-Code macro"
            },
            "gcode_macro bed_mesh_calibrate": {
                "gcode": "\n\n{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}\n{% set bed_mesh_min = printer.configfile.settings.bed_mesh.mesh_min %}\n{% set bed_mesh_max = printer.configfile.settings.bed_mesh.mesh_max %}\n{% set probe_count = printer.configfile.settings.bed_mesh.probe_count %}\n{% set verbose_enable = printer[\"gcode_macro _KAMP_Settings\"].verbose_enable | abs %}\n{% set probe_dock_enable = printer[\"gcode_macro _KAMP_Settings\"].probe_dock_enable | abs %}\n{% set attach_macro = printer[\"gcode_macro _KAMP_Settings\"].attach_macro | string %}\n{% set detach_macro = printer[\"gcode_macro _KAMP_Settings\"].detach_macro | string %}\n{% set mesh_margin = printer[\"gcode_macro _KAMP_Settings\"].mesh_margin | float %}\n{% set fuzz_amount = printer[\"gcode_macro _KAMP_Settings\"].fuzz_amount | float %}\n{% set probe_count = probe_count if probe_count|length > 1 else probe_count * 2  %}\n{% set max_probe_point_distance_x = ( bed_mesh_max[0] - bed_mesh_min[0] ) / (probe_count[0] - 1)  %}\n{% set max_probe_point_distance_y = ( bed_mesh_max[1] - bed_mesh_min[1] ) / (probe_count[1] - 1)  %}\n{% set x_min = all_points | map(attribute=0) | min | default(bed_mesh_min[0]) %}\n{% set y_min = all_points | map(attribute=1) | min | default(bed_mesh_min[1]) %}\n{% set x_max = all_points | map(attribute=0) | max | default(bed_mesh_max[0]) %}\n{% set y_max = all_points | map(attribute=1) | max | default(bed_mesh_max[1]) %}\n\n{% set fuzz_range = range((0) | int, (fuzz_amount * 100) | int + 1) %}\n{% set adapted_x_min = (bed_mesh_min[0] + fuzz_amount - mesh_margin, x_min) | max - (fuzz_range | random / 100.0) %}\n{% set adapted_y_min = (bed_mesh_min[1] + fuzz_amount - mesh_margin, y_min) | max - (fuzz_range | random / 100.0) %}\n{% set adapted_x_max = (bed_mesh_max[0] - fuzz_amount + mesh_margin, x_max) | min + (fuzz_range | random / 100.0) %}\n{% set adapted_y_max = (bed_mesh_max[1] - fuzz_amount + mesh_margin, y_max) | min + (fuzz_range | random / 100.0) %}\n\n{% set adapted_x_min = [adapted_x_min , bed_mesh_min[0]] | max %}\n{% set adapted_y_min = [adapted_y_min , bed_mesh_min[1]] | max %}\n{% set adapted_x_max = [adapted_x_max , bed_mesh_max[0]] | min %}\n{% set adapted_y_max = [adapted_y_max , bed_mesh_max[1]] | min %}\n\n{% set points_x = (((adapted_x_max - adapted_x_min) / max_probe_point_distance_x) | round(method='ceil') | int) + 1 %}\n{% set points_y = (((adapted_y_max - adapted_y_min) / max_probe_point_distance_y) | round(method='ceil') | int) + 1 %}\n\n{% if (([points_x, points_y]|max) > 6) %}\n{% set algorithm = \"bicubic\" %}\n{% set min_points = 4 %}\n{% else %}\n{% set algorithm = \"lagrange\" %}\n{% set min_points = 3 %}\n{% endif %}\n\n{% set points_x = [points_x , min_points]|max %}\n{% set points_y = [points_y , min_points]|max %}\n{% set points_x = [points_x , probe_count[0]]|min %}\n{% set points_y = [points_y , probe_count[1]]|min %}\n\n{% if verbose_enable == True %}\n\n{ action_respond_info( \"Algorithm: {}.\".format(\n(algorithm),\n)) }\n\n{ action_respond_info(\"Default probe count: {},{}.\".format(\n(probe_count[0]),\n(probe_count[1]),\n)) }\n\n{ action_respond_info(\"Adapted probe count: {},{}.\".format(\n(points_x),\n(points_y),\n)) }\n\n{action_respond_info(\"Default mesh bounds: {}, {}.\".format(\n(bed_mesh_min[0],bed_mesh_min[1]),\n(bed_mesh_max[0],bed_mesh_max[1]),\n)) }\n\n{% if mesh_margin > 0 %}\n{action_respond_info(\"Mesh margin is {}, mesh bounds extended by {}mm.\".format(\n(mesh_margin),\n(mesh_margin),\n)) }\n{% else %}\n{action_respond_info(\"Mesh margin is 0, margin not increased.\")}\n{% endif %}\n\n{% if fuzz_amount > 0 %}\n{action_respond_info(\"Mesh point fuzzing enabled, points fuzzed up to {}mm.\".format(\n(fuzz_amount),\n)) }\n{% else %}\n{action_respond_info(\"Fuzz amount is 0, mesh points not fuzzed.\")}\n{% endif %}\n\n{ action_respond_info(\"Adapted mesh bounds: {}, {}.\".format(\n(adapted_x_min, adapted_y_min),\n(adapted_x_max, adapted_y_max),\n)) }\n\n{action_respond_info(\"KAMP adjustments successful. Happy KAMPing!\")}\n\n{% endif %}\n\n{% if probe_dock_enable == True %}\n{attach_macro}\n{% endif %}\n\n_BED_MESH_CALIBRATE mesh_min={adapted_x_min},{adapted_y_min} mesh_max={adapted_x_max},{adapted_y_max} ALGORITHM={algorithm} PROBE_COUNT={points_x},{points_y}\n\n{% if probe_dock_enable == True %}\n{detach_macro}\n{% endif %}",
                "rename_existing": "_BED_MESH_CALIBRATE",
                "description": "G-Code macro"
            },
            "gcode_macro line_purge": {
                "gcode": "\n\n{% set travel_speed = (printer.toolhead.max_velocity) * 60 | float %}\n{% set cross_section = printer.configfile.settings.extruder.max_extrude_cross_section | float %}\n\n\n{% if printer.firmware_retraction is defined %}\n{% set RETRACT = G10 | string %}\n{% set UNRETRACT = G11 | string %}\n{% else %}\n{% set RETRACT = 'G1 E-.5 F2100' | string %}\n{% set UNRETRACT = 'G1 E.5 F2100' | string %}\n{% endif %}\n\n\n{% set verbose_enable = printer[\"gcode_macro _KAMP_Settings\"].verbose_enable | abs %}\n{% set purge_height = printer[\"gcode_macro _KAMP_Settings\"].purge_height | float %}\n{% set tip_distance = printer[\"gcode_macro _KAMP_Settings\"].tip_distance | float %}\n{% set purge_margin = printer[\"gcode_macro _KAMP_Settings\"].purge_margin | float %}\n{% set purge_amount = printer[\"gcode_macro _KAMP_Settings\"].purge_amount | float %}\n{% set flow_rate = printer[\"gcode_macro _KAMP_Settings\"].flow_rate | float %}\n\n\n\n{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}\n{% set purge_x_min = (all_points | map(attribute=0) | min | default(0)) %}\n{% set purge_x_max = (all_points | map(attribute=0) | max | default(0)) %}\n{% set purge_y_min = (all_points | map(attribute=1) | min | default(0)) %}\n{% set purge_y_max = (all_points | map(attribute=1) | max | default(0)) %}\n\n{% set purge_x_center = ([((purge_x_max + purge_x_min) / 2) - (purge_amount / 2), 0] | max) %}\n{% set purge_y_center = ([((purge_y_max + purge_y_min) / 2) - (purge_amount / 2), 0] | max) %}\n\n{% set purge_x_origin = ([purge_x_min - purge_margin, 0] | max) %}\n{% set purge_y_origin = ([purge_y_min - purge_margin, 0] | max) %}\n\n\n{% set purge_move_speed = (flow_rate / 5.0) * 60 | float %}\n\n{% if cross_section < 5 %}\n\n{action_respond_info(\"[Extruder] max_extrude_cross_section is insufficient for purge, please set it to 5 or greater. Purge skipped.\")}\n\n{% else %}\n\n{% if verbose_enable == True %}\n\n{action_respond_info(\"Moving filament tip {}mms\".format(\n(tip_distance),\n)) }\n{% endif %}\n\n{% if printer.firmware_retraction is defined %}\n{action_respond_info(\"KAMP purge is using firmware retraction.\")}\n{% else %}\n{action_respond_info(\"KAMP purge is not using firmware retraction, it is recommended to configure it.\")}\n{% endif %}\n\n{% if purge_y_origin > 0 %}\n\n{action_respond_info(\"KAMP purge starting at {}, {} and purging {}mm of filament, requested flow rate is {}mm/s3.\".format(\n(purge_x_center),\n(purge_y_origin),\n(purge_amount),\n(flow_rate),\n)) }\n\n{% else %}\n\n{action_respond_info(\"KAMP purge starting at {}, {} and purging {}mm of filament, requested flow rate is {}mm/s3.\".format(\n(purge_x_origin),\n(purge_y_center),\n(purge_amount),\n(flow_rate),\n)) }\n\n{% endif %}\n\nSAVE_GCODE_STATE NAME=Prepurge_State\n\n{% if purge_y_origin > 0 %}\n\nG92 E0\nG0 F{travel_speed}\nG90\nG0 X{purge_x_center} Y{purge_y_origin}\nG0 Z{purge_height}\nM83\nG1 E{tip_distance} F{purge_move_speed}\nG1 X{purge_x_center + purge_amount} E{purge_amount} F{purge_move_speed}\n{RETRACT}\nG0 X{purge_x_center + purge_amount + 10} F{travel_speed}\nG92 E0\nM82\nG0 Z{purge_height * 2} F{travel_speed}\n\n{% else %}\n\nG92 E0\nG0 F{travel_speed}\nG90\nG0 X{purge_x_origin} Y{purge_y_center}\nG0 Z{purge_height}\nM83\nG1 E{tip_distance} F{purge_move_speed}\nG1 Y{purge_y_center + purge_amount} E{purge_amount} F{purge_move_speed}\n{RETRACT}\nG0 Y{purge_y_center + purge_amount + 10} F{travel_speed}\nG92 E0\nM82\nG0 Z{purge_height * 2} F{travel_speed}\n\n{% endif %}\n\nRESTORE_GCODE_STATE NAME=Prepurge_State\n\n{% endif %}",
                "description": "A purge macro that adapts to be near your actual printed objects"
            },
            "gcode_macro smart_park": {
                "gcode": "\n\n{% set kamp_settings = printer[\"gcode_macro _KAMP_Settings\"] %}\n{% set z_height = kamp_settings.smart_park_height | float %}\n{% set purge_margin = kamp_settings.purge_margin | float %}\n{% set verbose_enable = kamp_settings.verbose_enable | abs %}\n{% set center_x = printer.toolhead.axis_maximum.x / 2 | float %}\n{% set center_y = printer.toolhead.axis_maximum.y / 2 | float %}\n{% set all_points = printer.exclude_object.objects | map(attribute='polygon') | sum(start=[]) %}\n{% set x_min = all_points | map(attribute=0) | min | default(center_x) %}\n{% set y_min = all_points | map(attribute=1) | min | default(center_y) %}\n{% set travel_speed = (printer.toolhead.max_velocity) * 60 | float %}\n\n{% if purge_margin > 0 and x_min != center_x and y_min != center_y %}\n{% set x_min = [ x_min - purge_margin , x_min ] | max %}\n{% set y_min = [ y_min - purge_margin , y_min ] | max %}\n{% endif %}\n\n\n{% if verbose_enable == True %}\n\n{ action_respond_info(\"Smart Park location: {},{}.\".format(\n(x_min),\n(y_min),\n)) }\n\n{% endif %}\n\nG0 X{x_min} Y{y_min} F{travel_speed}\nG0 Z{z_height}",
                "description": "Parks your printhead near the print area for pre-print hotend heating."
            },
            "gcode_macro _kamp_settings": {
                "gcode": "\n\n{action_respond_info(\" Running the KAMP_Settings macro does nothing, it is only used for storing KAMP settings. \")}",
                "description": "This macro contains all adjustable settings for KAMP",
                "variable_verbose_enable": "True",
                "variable_mesh_margin": "0",
                "variable_fuzz_amount": "0",
                "variable_probe_dock_enable": "False",
                "variable_attach_macro": "'Attach_Probe'",
                "variable_detach_macro": "'Dock_Probe'",
                "variable_purge_height": "0.8",
                "variable_tip_distance": "15",
                "variable_purge_margin": "40",
                "variable_purge_amount": "40",
                "variable_flow_rate": "8",
                "variable_smart_park_height": ".42"
            },
            "display": {
                "lcd_type": "st7920",
                "cs_pin": "PH1",
                "sclk_pin": "PA1",
                "sid_pin": "PH0",
                "menu_root": "__main",
                "menu_timeout": 0,
                "menu_reverse_navigation": false,
                "encoder_pins": "^PC4, ^PC6",
                "encoder_steps_per_detent": 4,
                "encoder_fast_rate": 0.03,
                "click_pin": "^!PC2",
                "display_group": "_default_16x4"
            },
            "menu __main __octoprint": {
                "type": "disabled",
                "name": "",
                "enable": true
            },
            "menu __main __sdcard": {
                "type": "disabled",
                "name": "",
                "enable": true
            },
            "menu __main __macros": {
                "type": "list",
                "name": "Macros",
                "enable": true
            },
            "menu __main __macros __resume": {
                "type": "command",
                "name": "Resume printing",
                "enable": "{printer.print_stats.state == \"paused\"}",
                "gcode": "\nRESUME"
            },
            "menu __main __macros __pause": {
                "type": "command",
                "name": "Pause printing",
                "enable": "{printer.print_stats.state == \"printing\"}",
                "gcode": "\nPAUSE"
            },
            "menu __main __macros __cancel": {
                "type": "command",
                "name": "Cancel printing",
                "enable": "{(printer.print_stats.state == \"printing\" or printer.print_stats.state == \"paused\")}",
                "gcode": "\nCANCEL_PRINT"
            },
            "menu __main __setup": {
                "type": "disabled",
                "name": "",
                "enable": true
            },
            "gcode_arcs": {
                "resolution": 0.1
            },
            "bed_mesh": {
                "probe_count": [
                    7,
                    7
                ],
                "mesh_min": [
                    38.0,
                    35.0
                ],
                "mesh_max": [
                    242.0,
                    214.0
                ],
                "mesh_pps": [
                    2,
                    2
                ],
                "algorithm": "bicubic",
                "bicubic_tension": 0.2,
                "horizontal_move_z": 5.0,
                "speed": 150.0,
                "fade_start": 1.0,
                "fade_end": 0.0,
                "split_delta_z": 0.025,
                "move_check_distance": 5.0
            },
            "bed_mesh default": {
                "version": 1,
                "points": [
                    [
                        -0.0075,
                        0.0075,
                        0.045
                    ],
                    [
                        -0.0075,
                        0.0175,
                        0.02
                    ],
                    [
                        -0.0075,
                        0.0075,
                        0.0075
                    ]
                ],
                "min_x": 110.0,
                "max_x": 170.0,
                "min_y": 104.5,
                "max_y": 135.5,
                "x_count": 3,
                "y_count": 3,
                "mesh_x_pps": 0,
                "mesh_y_pps": 0,
                "algo": "direct",
                "tension": 0.2
            },
            "safe_z_home": {
                "home_xy_position": [
                    150.0,
                    127.0
                ],
                "z_hop": 10.0,
                "z_hop_speed": 10.0,
                "speed": 100.0,
                "move_to_previous": false
            },
            "delayed_gcode delayed_printer_off": {
                "gcode": "\n{% if printer.idle_timeout.state == \"Idle\" %}\nPOWER_OFF_PRINTER\n{% endif %}",
                "initial_duration": 0.0
            },
            "idle_timeout": {
                "timeout": 600.0,
                "gcode": "\nUPDATE_DELAYED_GCODE ID=delayed_printer_off DURATION=60"
            },
            "bed_screws": {
                "screw1": [
                    38.0,
                    35.0
                ],
                "screw1_name": "screw at 38.000,35.000",
                "screw2": [
                    242.0,
                    35.0
                ],
                "screw2_name": "screw at 242.000,35.000",
                "screw3": [
                    242.0,
                    214.0
                ],
                "screw3_name": "screw at 242.000,214.000",
                "screw4": [
                    38.0,
                    214.0
                ],
                "screw4_name": "screw at 38.000,214.000",
                "speed": 50.0,
                "probe_speed": 5.0,
                "horizontal_move_z": 5.0,
                "probe_height": 0.0
            },
            "screws_tilt_adjust": {
                "screw1": [
                    69.0,
                    43.0
                ],
                "screw1_name": "front left screw",
                "screw2": [
                    276.0,
                    43.0
                ],
                "screw2_name": "front right screw",
                "screw3": [
                    276.0,
                    217.0
                ],
                "screw3_name": "rear right screw",
                "screw4": [
                    69.0,
                    217.0
                ],
                "screw4_name": "rear left screw",
                "screw_thread": "CW-M4",
                "horizontal_move_z": 10.0,
                "speed": 50.0
            },
            "multi_pin heater_pin": {
                "pins": [
                    "pico:gpio9",
                    "pico:gpio26"
                ]
            },
            "multi_pin fan_pin": {
                "pins": [
                    "pico:gpio5",
                    "pico:gpio27"
                ]
            },
            "heater_generic my_heater": {
                "sensor_type": "BME280",
                "i2c_mcu": "pico",
                "i2c_speed": 400000,
                "i2c_address": 118,
                "bme280_iir_filter": 1,
                "bme280_oversample_temp": 2,
                "bme280_oversample_hum": 2,
                "bme280_oversample_pressure": 2,
                "bme280_gas_target_temp": 320,
                "bme280_gas_heat_duration": 150,
                "min_temp": 0.0,
                "max_temp": 55.0,
                "min_extrude_temp": 170.0,
                "max_power": 1.0,
                "smooth_time": 1.0,
                "control": "watermark",
                "max_delta": 2.0,
                "heater_pin": "multi_pin:heater_pin",
                "pwm_cycle_time": 0.1,
                "gcode_id": "ENC"
            },
            "verify_heater my_heater": {
                "hysteresis": 5.0,
                "max_error": 120.0,
                "heating_gain": 2.0,
                "check_gain_time": 120.0
            },
            "heater_fan my_heater_fan": {
                "heater": [
                    "my_heater"
                ],
                "heater_temp": 30.0,
                "max_power": 1.0,
                "kick_start_time": 0.1,
                "off_below": 0.0,
                "cycle_time": 0.01,
                "hardware_pwm": false,
                "shutdown_speed": 1.0,
                "pin": "multi_pin:fan_pin",
                "fan_speed": 1.0
            },
            "printer": {
                "max_velocity": 300.0,
                "max_accel": 3000.0,
                "max_accel_to_decel": 1500.0,
                "square_corner_velocity": 5.0,
                "buffer_time_low": 1.0,
                "buffer_time_high": 2.0,
                "buffer_time_start": 0.25,
                "move_flush_time": 0.05,
                "kinematics": "cartesian",
                "max_z_velocity": 5.0,
                "max_z_accel": 100.0
            },
            "stepper_x": {
                "step_pin": "PF0",
                "dir_pin": "PF1",
                "rotation_distance": 40.0,
                "microsteps": 16,
                "full_steps_per_rotation": 200,
                "gear_ratio": [],
                "enable_pin": "!PD7",
                "endstop_pin": "^PE5",
                "position_endstop": 0.0,
                "position_min": 0.0,
                "position_max": 300.0,
                "homing_speed": 50.0,
                "second_homing_speed": 25.0,
                "homing_retract_speed": 50.0,
                "homing_retract_dist": 5.0,
                "homing_positive_dir": false
            },
            "force_move": {
                "enable_force_move": false
            },
            "stepper_y": {
                "step_pin": "PF6",
                "dir_pin": "PF7",
                "rotation_distance": 40.0,
                "microsteps": 16,
                "full_steps_per_rotation": 200,
                "gear_ratio": [],
                "enable_pin": "!PF2",
                "endstop_pin": "^PJ1",
                "position_endstop": 0.0,
                "position_min": 0.0,
                "position_max": 255.0,
                "homing_speed": 50.0,
                "second_homing_speed": 25.0,
                "homing_retract_speed": 50.0,
                "homing_retract_dist": 5.0,
                "homing_positive_dir": false
            },
            "stepper_z": {
                "step_pin": "PL3",
                "dir_pin": "!PL1",
                "rotation_distance": 8.0,
                "microsteps": 16,
                "full_steps_per_rotation": 200,
                "gear_ratio": [],
                "enable_pin": "!PK0",
                "endstop_pin": "probe:z_virtual_endstop",
                "position_min": 0.0,
                "position_max": 300.0,
                "homing_speed": 5.0,
                "second_homing_speed": 2.5,
                "homing_retract_speed": 5.0,
                "homing_retract_dist": 5.0,
                "homing_positive_dir": false
            },
            "extruder": {
                "sensor_type": "EPCOS 100K B57560G104F",
                "pullup_resistor": 4700.0,
                "inline_resistor": 0.0,
                "sensor_pin": "PK5",
                "min_temp": 0.0,
                "max_temp": 265.0,
                "min_extrude_temp": 170.0,
                "max_power": 1.0,
                "smooth_time": 1.0,
                "control": "pid",
                "pid_kp": 30.17,
                "pid_ki": 3.409,
                "pid_kd": 66.751,
                "heater_pin": "PB4",
                "pwm_cycle_time": 0.1,
                "nozzle_diameter": 0.4,
                "filament_diameter": 1.75,
                "max_extrude_cross_section": 5.0,
                "max_extrude_only_velocity": 79.82432411074329,
                "max_extrude_only_accel": 798.2432411074329,
                "max_extrude_only_distance": 100.0,
                "instantaneous_corner_velocity": 1.0,
                "step_pin": "PA4",
                "pressure_advance": 0.0,
                "pressure_advance_smooth_time": 0.04,
                "dir_pin": "!PA6",
                "rotation_distance": 7.68,
                "microsteps": 16,
                "full_steps_per_rotation": 200,
                "gear_ratio": [],
                "enable_pin": "!PA2"
            },
            "verify_heater extruder": {
                "hysteresis": 5.0,
                "max_error": 120.0,
                "heating_gain": 2.0,
                "check_gain_time": 20.0
            }
        },
        "warnings": [],
        "save_config_pending": false,
        "save_config_pending_items": {}
    },
    "gcode_move": {
        "speed_factor": 1.0,
        "speed": 1500.0,
        "extrude_factor": 1.0,
        "absolute_coordinates": true,
        "absolute_extrude": true,
        "homing_origin": [
            0.0,
            0.0,
            0.0,
            0.0
        ],
        "position": [
            0.0,
            0.0,
            0.0,
            0.0
        ],
        "gcode_position": [
            0.0,
            0.0,
            0.0,
            0.0
        ]
    },
    "print_stats": {
        "filename": "",
        "total_duration": 0.0,
        "print_duration": 0.0,
        "filament_used": 0.0,
        "state": "standby",
        "message": "",
        "info": {
            "total_layer": null,
            "current_layer": null
        }
    },
    "virtual_sdcard": {
        "file_path": null,
        "progress": 0.0,
        "is_active": false,
        "file_position": 0,
        "file_size": 0
    },
    "display_status": {
        "progress": 0.0,
        "message": null
    },
    "heater_bed": {
        "temperature": 22.36,
        "target": 0.0,
        "power": 0.0
    },
    "fan": {
        "speed": 0.0,
        "rpm": null
    },
    "exclude_object": {
        "objects": [],
        "excluded_objects": [],
        "current_object": null
    },
    "bed_screws": {
        "is_active": false,
        "state": null,
        "current_screw": 0,
        "accepted_screws": 0
    },
    "heater_generic my_heater": {
        "temperature": 22.19,
        "target": 0.0,
        "power": 0.0
    },
    "heater_fan my_heater_fan": {
        "speed": 0.0,
        "rpm": null
    },
    "motion_report": {
        "live_position": [
            0.0,
            0.0,
            0.0,
            0.0
        ],
        "live_velocity": 0.0,
        "live_extruder_velocity": 0.0,
        "steppers": [
            "extruder",
            "stepper_x",
            "stepper_y",
            "stepper_z"
        ],
        "trapq": [
            "extruder",
            "toolhead"
        ]
    },
    "manual_probe": {
        "is_active": false,
        "z_position": null,
        "z_position_lower": null,
        "z_position_upper": null
    },
    "toolhead": {
        "homed_axes": "",
        "axis_minimum": [
            0.0,
            0.0,
            0.0,
            0.0
        ],
        "axis_maximum": [
            300.0,
            255.0,
            300.0,
            0.0
        ],
        "print_time": 0.001,
        "stalls": 0,
        "estimated_print_time": 62717.8476845,
        "extruder": "extruder",
        "position": [
            0.0,
            0.0,
            0.0,
            0.0
        ],
        "max_velocity": 300.0,
        "max_accel": 3000.0,
        "max_accel_to_decel": 1500.0,
        "square_corner_velocity": 5.0
    },
    "extruder": {
        "temperature": 22.36,
        "target": 0.0,
        "power": 0.0,
        "can_extrude": false,
        "pressure_advance": 0.0,
        "smooth_time": 0.04,
        "motion_queue": null
    }
}