0

Here's what I'd like to do: Process a .gcode file to extract certain data and then create a .csv file containing all this data.

For your information, this .gcode file is used on a 3D printer or laser/CNC machine. This file contains all the information needed by the 3D printer, all the different settings, as well as all the movements that need to be performed by the printer.

For movements, the file is formatted with one line per movement without a delimiter. For settings, the file is formatted with one line per setting but with a ";" as the delimiter.

Here's a small example of a gcode file (it's a small example, because a gcode file can be much larger and contain many more lines of movements):

; HEADER_BLOCK_START
; generated by OrcaSlicer 2.2.0 on 2024-12-12 at 08:50:10
; total layer number: 504
; filament_density: 1.24
; filament_diameter: 1.75
; max_z_height: 121.30
; HEADER_BLOCK_END

; THUMBNAIL_BLOCK_START

;
; thumbnail begin 140x110 1308
; iVBORw0KGgoAAAANSUhEUgAAAIwAAABuCAYAAAD1TPu3AAADm0lEQVR4Ae3dzU4TURTA8VO+HkPjO7
; hTQB/ClTFGVybu+ZJI/di4UDAujWEBqOjGPZryAi58onpPuHdye7kz9AyFTmf+/+REwNIA88uZKW2C
; CBERzUjPZL4vROOkWP7J0lDntvTuCVGuGMpPWRyGt9k2dK4Yy5EsDHdkfrjr/j31cL7IwoBtQ6IIYi
; hbDopOAKPzi21DWrpVFMrf3tLwXQJGZ59t0+30oOvBP3EI9qLNsu/fTsGwbTpabqvkpgxM2DbhPhSe
; UDsbF8tFYMJwimppFigWMJyiWlgdLBYwXBC3JD1o8YXtuFDqgGHbzHh1t8plweS2jVCzi7Hs1cTyti
; aWsm3DKaqBTWKr6CxLr/9c5geXBZM+/OYU1aAmgeWhzA1u+E1QBWY/Gt0i8ZxmJnxdXBA3oLLngeps
; lfh+tx2YFEJ84HPzx90mnmP39aTzw88DmesLXW+T2Cp6jaOfq/cVHlGl89sd/G/uNjrf3Xzys+MvjP
; tuXmXmdcm8cXM/AUpXXMCSPg900Rx5ICeZjRHD+Ojmpbt9OjuZAUyDs26VACTFoWC+uo/rvHC3284M
; YGa8cbCUAQkf3/VA0gFMi7oISg7JoXv/0APZdLeJBzAtrgxLFZJ19/86GwkUwLS43PNAOSQH7v33bt
; Y8kngA05HSrZLbJAceSTyA6WAxlqrTzVpmANOhqqCsZzAApsPlsJRBAUyHiy9sc6cdwFBRvFUClA1/
; kAFDIwUsRwkUwNBI6cPlzQQKYKgo3irxwQMMjRRD2cocPMBQkWJJX68CGMBk04fLuWeWAQOYkXSrVL
; 2wCTCAKbrpfhG3LdWvgAMMYIpW3A9Bf9Af3HzuLQAGMNUFMGwYwIwVYABjCjCAMQUYwJgCDGBMAQYw
; pgADGFOAAYwpwADGFGAAYwowgDEFGMCYAgxgTAEGMKYAAxhTgAGMKcAAxhRgAGMKMIAxBRjAmAIMYE
; wBBjCmAAMYU4ABjCnAAMYUYABjCjCAMQUYwJgCDGBMAeZsnsjcoGye+rnFHwptN5jH7iCvuu9vlc0w
; udoA5pGDsQKK62nWwCwDY7o1GYz+EfO7AGlWTQMDkIY3bTAAmbGmAeYOSGa36wLDJmlJVw0GKC3rKs
; CApMVNEgxQOtAkwAh1p8uAEepedcAIdTcLGCEaBwwXs1RUBYZnhulcMZjj3mKBRYhypRuGrUKVxWCE
; iIiIiIiIiIiIiIiIiIiIiIiIiIioe/0HOzs0hzTYNJwAAAAASUVORK5CYII=
; thumbnail end
; THUMBNAIL_BLOCK_END

; external perimeters extrusion width = 0.42mm
; perimeters extrusion width = 0.45mm
; infill extrusion width = 0.45mm
; solid infill extrusion width = 0.42mm
; top infill extrusion width = 0.42mm
; support material extrusion width = 0.42mm
; first layer extrusion width = 0.50mm

; EXECUTABLE_BLOCK_START
M73 P0 R102
M106 S0
M106 P2 S0
;TYPE:Custom
M190 S55
M104 S220
G90
M83
G1 Z5 F6000
G1 E-0.2 F800
G1 X110 Y-110 F6000
M73 P0 R101
G1 E2 F800
M73 P0 R101
G1 Y-110 X55 Z0.25 F4800
G1 X-55 E8 F2400
G1 Y-109.6 F2400
G1 X55 E5 F2400
G1 Y-110 X55 Z0.45 F4800
G1 X-55 E8 F2400
G1 Y-109.6 F2400
G1 X55 E5 F2400
G92 E0
G90
G21
M83 ; use relative distances for extrusion
; filament start gcode
;right_extruder_material: PLA
SET_PRESSURE_ADVANCE ADVANCE=0.025; Override pressure advance value
M106 S0
M106 P2 S0
;LAYER_CHANGE
;Z:0.3
;HEIGHT:0.3
;BEFORE_LAYER_CHANGE
;0.3
G1 E-.8 F2100
;AFTER_LAYER_CHANGE
;0.3
;_SET_FAN_SPEED_CHANGING_LAYER
SET_VELOCITY_LIMIT ACCEL=500
G1 X-28.348 Y38.998 F30000
G1 Z.7
G1 Z.3
G1 E.8 F2100
;TYPE:Skirt
;WIDTH:0.5
G1 F3000
G1 E-.8 F2100
;WIPE_START
G1 F3000
G1 X-26.416 Y38.62
;WIPE_END
G1 X-19.273 Y35.931 Z.7 F30000
G1 X65.043 Y4.182 Z.7
G1 Z.3
G1 E.8 F2100
;TYPE:Support
G1 F3000
G1 X65.043 Y66.239 E3.30428
G1 X64.018 Y67.264 E.07719
G1 X-64.014 Y67.264 E6.81722
G1 X-65.039 Y66.239 E.07719
G1 X-65.039 Y58.683 E.40229
G1 X-64.014 Y57.658 E.07719
G1 X-50.697 Y57.658 E.7091
G1 X-50.697 Y55.815 E.09815
G1 X-49.672 Y54.79 E.07719
G1 X-30.617 Y54.79 E1.01457
G1 X-30.617 Y52.946 E.09815
G1 X-29.592 Y51.921 E.07719
G1 X-19.143 Y51.921 E.55636
G1 X-19.143 Y50.078 E.09815
G1 X-18.118 Y49.053 E.07719
G1 X-10.538 Y49.053 E.40363
G1 X-10.538 Y47.209 E.09815
G1 X-9.513 Y46.184 E.07719
G1 X-1.932 Y46.184 E.40363
G1 X-1.932 Y44.341 E.09815
G1 X-.907 Y43.316 E.07719
G1 X3.805 Y43.316 E.25089
G1 X3.805 Y41.472 E.09815
G1 X4.83 Y40.447 E.07719
G1 X9.542 Y40.447 E.25089
G1 X9.542 Y38.604 E.09815
G1 X10.567 Y37.579 E.07719
G1 X15.279 Y37.579 E.25089
G1 X15.279 Y35.736 E.09815
G1 X16.304 Y34.71 E.07719
G1 X21.016 Y34.71 E.25089
G1 X21.016 Y32.867 E.09815
G1 X22.041 Y31.842 E.07719
G1 X26.753 Y31.842 E.25089
G1 E-.8 F2100
;WIPE_START
G1 F3000
G1 X64.018 Y3.157
G1 X63.402 Y3.157
;WIPE_END
G1 X60.135 Y10.055 Z.7 F30000
G1 X50.701 Y29.973 Z.7
G1 Z.3
G1 E.8 F2100
G1 F3000
G1 E-.8 F2100
;WIPE_START
G1 F3000
G1 X52.569 Y29.973
G1 X52.569 Y30.17
;WIPE_END
G1 X45.262 Y32.376 Z.7 F30000
G1 X-30.274 Y55.182 Z.7
G1 Z.3
G1 E.8 F2100
G1 F3000
G1 X-30.225 Y55.182 E.00258
G1 X-30.225 Y53.109 E.11038
G1 E-.8 F2100
;WIPE_START
G1 F3000
G1 X-30.225 Y55.109
;WIPE_END
G1 X-23.488 Y51.522 Z.7 F30000
G1 X64.651 Y4.596 Z.7
G1 Z.3
G1 E.8 F2100
G1 F3000
G1 X60.021 Y3.549 E3.3717
G1 X59.536 Y3.549 E.02577
G1 X59.536 Y66.872 E3.3717
G1 X59.052 Y66.872 E.02577
G1 X59.052 Y3.99 E3.34821
G1 X58.698 Y4.344 E.02668
G1 X58.698 Y6.417 E.11038
G1 X58.568 Y6.417 E.0069
G1 X58.568 Y66.872 E3.21896
G1 X58.084 Y66.872 E.02577
G1 X58.084 Y6.417 E3.21896
G1 X57.6 Y6.417 E.02577
G1 X57.6 Y66.872 E3.21896
G1 X57.116 Y66.872 E.02577
G1 X57.116 Y6.417 E3.21896
G1 X56.632 Y6.417 E.02577
G1 X56.632 Y66.872 E3.21896
G1 X56.148 Y66.872 E.02577
G1 X56.148 Y6.894 E3.19358
G1 X55.83 Y7.213 E.024
G1 X55.83 Y7.494 E.01496
G1 E-.8 F2100
;WIPE_START
G1 F3000
G1 X55.83 Y7.213
G1 X56.148 Y6.894
G1 X56.148 Y8.163
;WIPE_END
G1 X55.664 Y9.286 Z.7 F30000
G1 Z.3
G1 E.8 F2100
G1 F3000
G1 X55.664 Y66.872 E3.06623
G1 X55.18 Y66.872 E.02577
G1 X55.18 Y9.286 E3.06623
G1 X54.696 Y9.286 E.02577
G1 X54.696 Y66.872 E3.06623
G1 X54.212 Y66.872 E.02577
G1 X54.212 Y9.286 E3.06623
G1 X53.757 Y9.286 E.02426
G1 X53.728 Y9.314 E.00214
G1 X53.728 Y66.872 E3.06472
G1 X53.244 Y66.872 E.02577
G1 X53.244 Y9.798 E3.03894
G1 X52.961 Y10.081 E.02132
G1 X52.961 Y10.336 E.01354
G1 E-.8 F2100
;WIPE_START
G1 F3000
G1 X52.961 Y10.081
G1 X53.244 Y9.798
G1 X53.244 Y11.144
;WIPE_END
G1 X53.16 Y18.776 Z.7 F30000
G1 X52.76 Y55.182 Z.7
G1 Z.3
G1 E.8 F2100
G1 F3000
; EXECUTABLE_BLOCK_END

; filament used [mm] = 33328.51
; filament used [cm3] = 80.16
; filament used [g] = 99.40
; filament cost = 1.99
; total filament used [g] = 99.40
; total filament cost = 1.99
; total layers count = 504
; estimated printing time (normal mode) = 1h 42m 0s

; CONFIG_BLOCK_START
; accel_to_decel_enable = 0
; accel_to_decel_factor = 50%
; activate_air_filtration = 0
; activate_chamber_temp_control = 0
; adaptive_bed_mesh_margin = 0
; adaptive_pressure_advance = 0
; adaptive_pressure_advance_bridges = 0
; adaptive_pressure_advance_model = "0,0,0\n0,0,0"
; adaptive_pressure_advance_overhangs = 0
; additional_cooling_fan_speed = 100
; alternate_extra_wall = 0
; auxiliary_fan = 1
; bbl_calib_mark_logo = 1
; bbl_use_printhost = 0
; bed_custom_model = 
; bed_custom_texture = 
; bed_exclude_area = 0x0
; bed_mesh_max = 99999,99999
; bed_mesh_min = -99999,-99999
; bed_mesh_probe_distance = 50,50
; before_layer_change_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]
; best_object_pos = 0.5,0.5
; bottom_shell_layers = 3
; bottom_shell_thickness = 0
; bottom_solid_infill_flow_ratio = 1
; bottom_surface_pattern = monotonic
; bridge_acceleration = 50%
; bridge_angle = 0
; bridge_density = 100%
; bridge_flow = 1
; bridge_no_support = 0
; bridge_speed = 25
; brim_ears_detection_length = 1
; brim_ears_max_angle = 125
; brim_object_gap = 0.1
; brim_type = no_brim
; brim_width = 5
; chamber_temperature = 0
; change_extrusion_role_gcode = 
; change_filament_gcode = 
; close_fan_the_first_x_layers = 1
; complete_print_exhaust_fan_speed = 80
; cool_plate_temp = 60
; cool_plate_temp_initial_layer = 55
; cooling_tube_length = 5
; cooling_tube_retraction = 91.5
; counterbore_hole_bridging = none
; curr_bed_type = Textured PEI Plate
; default_acceleration = 10000
; default_filament_colour = #000000
; default_filament_profile = "Flashforge Generic PLA"
; default_jerk = 0
; default_print_profile = 0.20mm Standard @Flashforge AD5M 0.4 Nozzle
; deretraction_speed = 35
; detect_narrow_internal_solid_infill = 1
; detect_overhang_wall = 1
; detect_thin_wall = 0
; different_settings_to_system = raft_layers;seam_position;sparse_infill_density;wall_loops;default_filament_colour;filament_notes;filament_retraction_length;filament_vendor;filament_z_hop;host_type;print_host;support_multi_bed_types
; disable_m73 = 0
; dont_filter_internal_bridges = disabled
; dont_slow_down_outer_wall = 0
; draft_shield = disabled
; during_print_exhaust_fan_speed = 60
; elefant_foot_compensation = 0.15
; elefant_foot_compensation_layers = 1
; emit_machine_limits_to_gcode = 1
; enable_arc_fitting = 0
; enable_filament_ramming = 1
; enable_long_retraction_when_cut = 0
; enable_overhang_bridge_fan = 1
; enable_overhang_speed = 1
; enable_pressure_advance = 1
; enable_prime_tower = 0
; enable_support = 0
; enforce_support_layers = 0
; eng_plate_temp = 60
; eng_plate_temp_initial_layer = 55
; ensure_vertical_shell_thickness = ensure_all
; exclude_object = 0
; extra_loading_move = -2
; extra_perimeters_on_overhangs = 0
; extruder_clearance_height_to_lid = 150
; extruder_clearance_height_to_rod = 27
; extruder_clearance_radius = 76
; extruder_colour = #E30006
; extruder_offset = 0x0
; fan_cooling_layer_time = 100
; fan_kickstart = 0
; fan_max_speed = 100
; fan_min_speed = 100
; fan_speedup_overhangs = 1
; fan_speedup_time = 0
; filament_colour = #E30006
; filament_cooling_final_speed = 3.4
; filament_cooling_initial_speed = 2.2
; filament_cooling_moves = 4
; filament_cost = 20
; filament_density = 1.24
; filament_diameter = 1.75
; filament_end_gcode = "; filament end gcode\n"
; filament_flow_ratio = 0.98
; filament_ids = GFL99
; filament_is_support = 0
; filament_loading_speed = 28
; filament_loading_speed_start = 3
; filament_max_volumetric_speed = 25
; filament_minimal_purge_on_wipe_tower = 15
; filament_multitool_ramming = 0
; filament_multitool_ramming_flow = 10
; filament_multitool_ramming_volume = 10
; filament_notes = "Custom settings for Flashforge PLA/PLA PRO - (Updated 01/10/24) - Not tested - Settings from Orca Flashforge"
; filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
; filament_retraction_length = 0.8
; filament_settings_id = "Flashforge PLA - BullzLabz"
; filament_shrink = 100%
; filament_shrinkage_compensation_z = 100%
; filament_soluble = 0
; filament_stamping_distance = 0
; filament_stamping_loading_speed = 0
; filament_start_gcode = "; filament start gcode\n;right_extruder_material: PLA\n"
; filament_toolchange_delay = 0
; filament_type = PLA
; filament_unloading_speed = 90
; filament_unloading_speed_start = 100
; filament_vendor = Flashforge
; filament_z_hop = 0.4
; filename_format = {input_filename_base}.gcode
; filter_out_gap_fill = 0.5
; first_layer_print_sequence = 0
; flush_into_infill = 0
; flush_into_objects = 0
; flush_into_support = 1
; flush_multiplier = 1
; flush_volumes_matrix = 0
; flush_volumes_vector = 140,140
; full_fan_speed_layer = 0
; fuzzy_skin = none
; fuzzy_skin_first_layer = 0
; fuzzy_skin_point_distance = 0.8
; fuzzy_skin_thickness = 0.3
; gap_fill_target = nowhere
; gap_infill_speed = 200
; gcode_add_line_number = 0
; gcode_comments = 0
; gcode_flavor = klipper
; gcode_label_objects = 0
; has_scarf_joint_seam = 0
; head_wrap_detect_zone = 
; high_current_on_filament_swap = 0
; hole_to_polyhole = 0
; hole_to_polyhole_threshold = 0.01
; hole_to_polyhole_twisted = 1
; host_type = flashforge
; hot_plate_temp = 50
; hot_plate_temp_initial_layer = 55
; idle_temperature = 0
; independent_support_layer_height = 1
; infill_anchor = 400%
; infill_anchor_max = 20
; infill_combination = 0
; infill_combination_max_layer_height = 100%
; infill_direction = 45
; infill_jerk = 9
; infill_wall_overlap = 25%
; inherits_group = ;"Flashforge Generic PLA";"Flashforge Adventurer 5M 0.4 Nozzle"
; initial_layer_acceleration = 500
; initial_layer_infill_speed = 80
; initial_layer_jerk = 9
; initial_layer_line_width = 0.5
; initial_layer_min_bead_width = 85%
; initial_layer_print_height = 0.3
; initial_layer_speed = 50
; initial_layer_travel_speed = 100%
; inner_wall_acceleration = 5000
; inner_wall_jerk = 9
; inner_wall_line_width = 0.45
; inner_wall_speed = 300
; interface_shells = 0
; interlocking_beam = 0
; interlocking_beam_layer_count = 2
; interlocking_beam_width = 0.8
; interlocking_boundary_avoidance = 2
; interlocking_depth = 2
; interlocking_orientation = 22.5
; internal_bridge_flow = 1
; internal_bridge_speed = 50
; internal_solid_infill_acceleration = 7000
; internal_solid_infill_line_width = 0.42
; internal_solid_infill_pattern = monotonic
; internal_solid_infill_speed = 250
; ironing_angle = -1
; ironing_flow = 15%
; ironing_pattern = zig-zag
; ironing_spacing = 0.1
; ironing_speed = 15
; ironing_type = no ironing
; is_infill_first = 0
; layer_change_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
; layer_height = 0.24
; line_width = 0.42
; long_retractions_when_cut = 0
; machine_end_gcode = G1 E-3 F3600\nG0 X50 Y50 F30000\nM104 S0 ; turn off temperature
; machine_load_filament_time = 0
; machine_max_acceleration_e = 5000,5000
; machine_max_acceleration_extruding = 20000,20000
; machine_max_acceleration_retracting = 5000,5000
; machine_max_acceleration_travel = 20000,20000
; machine_max_acceleration_x = 20000,20000
; machine_max_acceleration_y = 20000,20000
; machine_max_acceleration_z = 500,500
; machine_max_jerk_e = 2.5,2.5
; machine_max_jerk_x = 9,9
; machine_max_jerk_y = 9,9
; machine_max_jerk_z = 3,3
; machine_max_speed_e = 30,30
; machine_max_speed_x = 600,600
; machine_max_speed_y = 600,600
; machine_max_speed_z = 20,20
; machine_min_extruding_rate = 0,0
; machine_min_travel_rate = 0,0
; machine_pause_gcode = M25
; machine_start_gcode = M190 S[bed_temperature_initial_layer_single]\nM104 S[nozzle_temperature_initial_layer]\nG90\nM83\nG1 Z5 F6000\nG1 E-0.2 F800\nG1 X110 Y-110 F6000\nG1 E2 F800\nG1 Y-110 X55 Z0.25 F4800\nG1 X-55 E8 F2400\nG1 Y-109.6 F2400\nG1 X55 E5 F2400\nG1 Y-110 X55 Z0.45 F4800\nG1 X-55 E8 F2400\nG1 Y-109.6 F2400\nG1 X55 E5 F2400\nG92 E0
; machine_tool_change_time = 0
; machine_unload_filament_time = 0
; make_overhang_printable = 0
; make_overhang_printable_angle = 55
; make_overhang_printable_hole_size = 0
; manual_filament_change = 0
; max_bridge_length = 10
; max_layer_height = 0.28
; max_travel_detour_distance = 0
; max_volumetric_extrusion_rate_slope = 0
; max_volumetric_extrusion_rate_slope_segment_length = 3
; min_bead_width = 85%
; min_feature_size = 25%
; min_layer_height = 0.08
; min_length_factor = 0.5
; min_skirt_length = 0
; min_width_top_surface = 300%
; minimum_sparse_infill_area = 15
; mmu_segmented_region_interlocking_depth = 0
; mmu_segmented_region_max_width = 0
; notes = 
; nozzle_diameter = 0.4
; nozzle_height = 2.5
; nozzle_hrc = 0
; nozzle_temperature = 220
; nozzle_temperature_initial_layer = 220
; nozzle_temperature_range_high = 230
; nozzle_temperature_range_low = 190
; nozzle_type = stainless_steel
; nozzle_volume = 0
; only_one_wall_first_layer = 0
; only_one_wall_top = 0
; ooze_prevention = 0
; other_layers_print_sequence = 0
; other_layers_print_sequence_nums = 0
; outer_wall_acceleration = 5000
; outer_wall_jerk = 9
; outer_wall_line_width = 0.42
; outer_wall_speed = 200
; overhang_1_4_speed = 0
; overhang_2_4_speed = 40
; overhang_3_4_speed = 20
; overhang_4_4_speed = 10
; overhang_fan_speed = 100
; overhang_fan_threshold = 50%
; overhang_reverse = 0
; overhang_reverse_internal_only = 0
; overhang_reverse_threshold = 50%
; overhang_speed_classic = 0
; parking_pos_retraction = 92
; pellet_flow_coefficient = 0.4157
; pellet_modded_printer = 0
; post_process = 
; precise_outer_wall = 0
; precise_z_height = 0
; preferred_orientation = 0
; preheat_steps = 1
; preheat_time = 30
; pressure_advance = 0.025
; prime_tower_brim_width = 3
; prime_tower_width = 60
; prime_volume = 45
; print_compatible_printers = "Flashforge Adventurer 5M 0.4 Nozzle"
; print_flow_ratio = 1
; print_order = default
; print_sequence = by layer
; print_settings_id = 0.24mm Draft @Flashforge AD5M 0.4 Nozzle
; printable_area = -110x-110,110x-110,110x110,-110x110
; printable_height = 220
; printer_model = Flashforge Adventurer 5M
; printer_notes = 
; printer_settings_id = Flashforge Adventurer 5M 0.4 Nozzle - Orca
; printer_structure = undefine
; printer_technology = FFF
; printer_variant = 0.4
; printhost_authorization_type = key
; printhost_ssl_ignore_revoke = 0
; printing_by_object_gcode = 
; purge_in_prime_tower = 1
; raft_contact_distance = 0.1
; raft_expansion = 1.5
; raft_first_layer_density = 90%
; raft_first_layer_expansion = 2
; raft_layers = 4
; reduce_crossing_wall = 0
; reduce_fan_stop_start_freq = 1
; reduce_infill_retraction = 1
; required_nozzle_HRC = 0
; resolution = 0.012
; retract_before_wipe = 100%
; retract_length_toolchange = 2
; retract_lift_above = 0
; retract_lift_below = 0
; retract_lift_enforce = All Surfaces
; retract_restart_extra = 0
; retract_restart_extra_toolchange = 0
; retract_when_changing_layer = 1
; retraction_distances_when_cut = 18
; retraction_length = 0.8
; retraction_minimum_travel = 1
; retraction_speed = 35
; role_based_wipe_speed = 1
; rotate_solid_infill_direction = 1
; scan_first_layer = 0
; scarf_angle_threshold = 155
; scarf_joint_flow_ratio = 1
; scarf_joint_speed = 100%
; scarf_overhang_threshold = 40%
; seam_gap = 10%
; seam_position = back
; seam_slope_conditional = 0
; seam_slope_entire_loop = 0
; seam_slope_inner_walls = 0
; seam_slope_min_length = 20
; seam_slope_start_height = 0
; seam_slope_steps = 10
; seam_slope_type = none
; silent_mode = 0
; single_extruder_multi_material = 0
; single_extruder_multi_material_priming = 0
; skirt_distance = 2
; skirt_height = 1
; skirt_loops = 2
; skirt_speed = 50
; skirt_start_angle = -135
; skirt_type = combined
; slice_closing_radius = 0.049
; slicing_mode = regular
; slow_down_for_layer_cooling = 1
; slow_down_layer_time = 6
; slow_down_layers = 1
; slow_down_min_speed = 20
; slowdown_for_curled_perimeters = 1
; small_area_infill_flow_compensation = 0
; small_area_infill_flow_compensation_model = 0,0;"\n0.2,0.4444";"\n0.4,0.6145";"\n0.6,0.7059";"\n0.8,0.7619";"\n1.5,0.8571";"\n2,0.8889";"\n3,0.9231";"\n5,0.9520";"\n10,1"
; small_perimeter_speed = 50%
; small_perimeter_threshold = 0
; solid_infill_direction = 45
; solid_infill_filament = 1
; sparse_infill_acceleration = 100%
; sparse_infill_density = 100%
; sparse_infill_filament = 1
; sparse_infill_line_width = 0.45
; sparse_infill_pattern = grid
; sparse_infill_speed = 270
; spiral_mode = 0
; spiral_mode_max_xy_smoothing = 200%
; spiral_mode_smooth = 0
; staggered_inner_seams = 0
; standby_temperature_delta = -5
; start_end_points = 30x-3,54x245
; support_air_filtration = 1
; support_angle = 0
; support_base_pattern = rectilinear
; support_base_pattern_spacing = 2.5
; support_bottom_interface_spacing = 0.3
; support_bottom_z_distance = 0.15
; support_chamber_temp_control = 1
; support_critical_regions_only = 0
; support_expansion = 0
; support_filament = 0
; support_interface_bottom_layers = 0
; support_interface_filament = 0
; support_interface_loop_pattern = 0
; support_interface_not_for_body = 1
; support_interface_pattern = auto
; support_interface_spacing = 0.3
; support_interface_speed = 40
; support_interface_top_layers = 2
; support_line_width = 0.42
; support_material_interface_fan_speed = 100
; support_multi_bed_types = 1
; support_object_xy_distance = 0.3
; support_on_build_plate_only = 0
; support_remove_small_overhang = 1
; support_speed = 100
; support_style = default
; support_threshold_angle = 30
; support_top_z_distance = 0.15
; support_type = normal(auto)
; temperature_vitrification = 60
; template_custom_gcode = 
; textured_cool_plate_temp = 40
; textured_cool_plate_temp_initial_layer = 40
; textured_plate_temp = 60
; textured_plate_temp_initial_layer = 55
; thick_bridges = 0
; thick_internal_bridges = 1
; thumbnails = 140x110/PNG
; thumbnails_format = PNG
; time_cost = 0
; time_lapse_gcode = 
; timelapse_type = 0
; top_bottom_infill_wall_overlap = 25%
; top_shell_layers = 5
; top_shell_thickness = 1
; top_solid_infill_flow_ratio = 1
; top_surface_acceleration = 2000
; top_surface_jerk = 9
; top_surface_line_width = 0.42
; top_surface_pattern = monotonicline
; top_surface_speed = 200
; travel_acceleration = 10000
; travel_jerk = 12
; travel_slope = 3
; travel_speed = 500
; travel_speed_z = 0
; tree_support_adaptive_layer_height = 1
; tree_support_angle_slow = 25
; tree_support_auto_brim = 1
; tree_support_branch_angle = 45
; tree_support_branch_angle_organic = 40
; tree_support_branch_diameter = 5
; tree_support_branch_diameter_angle = 5
; tree_support_branch_diameter_double_wall = 3
; tree_support_branch_diameter_organic = 2
; tree_support_branch_distance = 5
; tree_support_branch_distance_organic = 1
; tree_support_brim_width = 3
; tree_support_tip_diameter = 0.8
; tree_support_top_rate = 30%
; tree_support_wall_count = 0
; upward_compatible_machine = 
; use_firmware_retraction = 0
; use_relative_e_distances = 1
; wall_direction = auto
; wall_distribution_count = 1
; wall_filament = 1
; wall_generator = classic
; wall_loops = 4
; wall_sequence = inner wall/outer wall
; wall_transition_angle = 10
; wall_transition_filter_deviation = 25%
; wall_transition_length = 100%
; wipe = 1
; wipe_before_external_loop = 0
; wipe_distance = 2
; wipe_on_loops = 0
; wipe_speed = 200
; wipe_tower_bridging = 10
; wipe_tower_cone_angle = 0
; wipe_tower_extra_flow = 100%
; wipe_tower_extra_spacing = 100%
; wipe_tower_filament = 0
; wipe_tower_max_purge_speed = 90
; wipe_tower_no_sparse_layers = 0
; wipe_tower_rotation_angle = 0
; wipe_tower_x = 165.000
; wipe_tower_x = 165
; wipe_tower_y = 250.000
; wipe_tower_y = 250
; wiping_volumes_extruders = 70,70,70,70,70,70,70,70,70,70
; xy_contour_compensation = 0
; xy_hole_compensation = 0
; z_hop = 0.4
; z_hop_types = Auto Lift
; z_offset = 0
; first_layer_bed_temperature = 55
; bed_shape = -110x-110,110x-110,110x110,-110x110
; first_layer_temperature = 220
; first_layer_height = 0.300
; CONFIG_BLOCK_END

As a beginner, I don't know if Applescript is the best way to process the file, so I'm looking forward to your advice and ideas.

The principle of this applescript would be:

  1. Step 1 : Request the file to process.
  2. Step 2 : Create a copy of the file for backup purposes.
  3. Step 3 : Delete all movement lines (without delimiters).
  4. Step 4 : Create a .csv file that will collect all the lines extracted from the .gcode file.
  5. Step 5 : Search for the "; thumbnail begin" and "; thumbnail end" tags and copy all lines between these two tags into the .csv file.
  6. Step 6 : Search for approximately 22 lines of specific settings and then copy them into the .csv file (Example: search for the line "; sparse_infill_density = 100%" and copy/paste it into the .csv file, removing the ";" delimiter and placing "sparse_infill_density" in a row with "100%" as the value.)

I'm a complete beginner, and with the help of some contributors, I managed to create a small applescript that replicates steps 1, 2, and 3. Unfortunately, my limited knowledge prevents me from going any further, even though I've done a lot of research, experimenting, and learning.

I hope to find a kind soul here who would be willing to help me. Thank you in advance.

9
  • Personally I wouldn't even bother attempting this in applescript which is rather verbose and awkward and will only ever run on macOS. I would use a bash script, dipping into awk and sed which will run on macOS, any Linux and WSL on Windows. Is applescript a necessity? Commented Jun 2 at 0:18
  • Yes and no, as long as it offers a GUI! I could consider coding it in HTML/CSS/JS, but that would take much longer than with AppleScript. Commented Jun 2 at 0:48
  • 1
    Just to clarify… the csv will ultimately end up with the lines resulting from step 5 and 6, is that correct? Re step 6… how does the script know which ~22 lines to search for? Is there a list somewhere or do they need to be gleaned from the source file in some way? And as an example, would a resulting line in the csv have two fields with sparse_infill_density and 100% as the values therein? Finally, will the resulting csv have basically 23 records in it? And does the source file actually need to be modified in any way? Commented Jun 2 at 2:27
  • 1
    @Mockman Yes, that's right! The result will be a .csv file containing only steps 5 and 6. The 22 lines that need to be searched for will be hard-coded in the applescript. And yes, each extracted line has a name + a value, so yes, there will be two fields for each entry, so a total of 44 fields. No, the source file doesn't really need to be modified since the result will be contained in the .csv file. Commented Jun 2 at 3:00
  • 1
    Let me try to create a png. I've done the rest of the script and will post it momentarily and then add the base64 stuff shortly. So, in the case of base64 code, would that be to a separate text file (and without the semi-colons)? Commented Jun 2 at 3:53

1 Answer 1

1

Here is something you can try. I revised many variable names.

Updated

  • It assumes the original gcode name and location but these can be requested instead
  • creates a backup in the same folder; will abort with alert if file exists; but these options can be changed
  • reads original file
  • cycles through list of settings and generates comma-separated key/value pairs
  • saves settings pairs to CSV
  • saves base64 code to file, waits until complete, decodes to png
use scripting additions

-- get original file and backup to desktop
tell application "Finder"
    set gcodeFile to ((path to desktop as text) & "code.gcode")
    set repository to (path to desktop as text) -- where to deposit backup and CSV
    set dupeReference to duplicate file gcodeFile to folder repository
end tell

-- use 'try' to halt script if file with backup name already exists
try
    try -- remove in final version; trashes backup file automatically;
        tell application "Finder" to move file (repository & "backup.gcode" as text) to trash
    end try
    tell application "Finder" to set name of dupeReference to "backup.gcode" -- rename backup
    
    -- read original
    set intake to read file gcodeFile as «class utf8» --> 722 paragraph text file
    
    -- §
    -- process CONFIG_BLOCK §
    set text item delimiters to "; CONFIG_BLOCK_"
    set configBlock to text item 2 of intake
    set text item delimiters to linefeed
    set configBlockList to text items 2 thru -2 of configBlock -- list of 483 items (all settings)
    -- set configBlockList to text items of configBlock -- list of 485 items, includes 'start' and ""
    set configLength to length of configBlockList -- count of settings
    
    -- specified settings entries to extract
    set targetList to {"; raft_layers", "; seam_position", "; sparse_infill_density", "; wall_loops"}
    set targetLength to length of targetList -- count of target settings
    
    set cc to 0 -- counter for config list cycling - inner loop
    set tt to 0 -- counter for target list cycling - outer loop
    set loopTotal to 0
    set keepList to {}
    
    -- NB I have commented out the logging as it slows things down considerably
    -- enable the log commands to see what values were compared on each cycle
    repeat -- cycle through specified settings
        set tt to tt + 1 -- counter for target list cycling
        set loopTotal to loopTotal + 1 -- total loops required - outer loop
        repeat -- cycle through config settings
            set cc to cc + 1 -- counter for config list cycling
            set loopTotal to loopTotal + 1 -- total loops required - inner loop
            
            -- log cc
            -- log "config-used: " & item cc of configBlockList -- compare item in config list
            -- log "search-master: " & item tt of targetList -- compare item in target list
            
            -- compare item from each list
            if (item cc of configBlockList) begins with (item tt of targetList) then
                set end of keepList to item cc of configBlockList -- compile setting list
                exit repeat -- exit inner loop when matching to begin next outer loop item
            end if
            
            -- log "cc: " & cc
            if cc is equal to configLength then exit repeat -- exit inner loop when unmatched
        end repeat
        if tt is equal to targetLength then exit repeat -- exit outer loop once all matches made
    end repeat
    -- log loopTotal -- log combined inner and outer loop cycles
    keepList --> list of matched settings (including key and value); will be written to CSV;
    
    -- extract matching specified entries to list 
    set recordList to {}
    repeat with setting in keepList
        set text item delimiters to {"; ", " = "} -- bits to exclude
        set loops to text items of setting -- split on bits
        --> "(, sparse_infill_density, 100%" -- NB list of 3 items, first item is "" before first comma
        set text item delimiters to "," -- csv separator
        set end of recordList to items 2 thru 3 of loops as text -- join on csv separator
    end repeat
    
    -- write settings pairs to csv §
    set text item delimiters to linefeed
    set tin to (recordList as text) & linefeed -- default text input
    
    -- name and location for csv (dp is currently the desktop)
    set newf to (choose file name with prompt "Enter name for CSV file" default location alias repository default name "fields.csv")
    
    set frn to open for access newf with write permission
    set eof frn to 0
    write (tin & linefeed) to frn starting at 0 as «class utf8»
    close access frn
    
    -- §
    -- process THUMBNAIL_BLOCK §
    
    -- extract encoded thumbnail to field,value
    set text item delimiters to {"; thumbnail begin", "; thumbnail end"}
    set thumbBlock to text item 2 of intake
    set thumbLines to paragraphs 2 thru -2 of thumbBlock
    set text item delimiters to linefeed
    set thumbText to thumbLines as text -- encoded lines but still with '; '
    
    -- write base64-encoded image to file
    set text item delimiters to ";" & space
    set base64 to text items of thumbText -- encoded lines sans '; '
    set text item delimiters to ""
    set base64 to base64 as text -- encoded text as single string, suitable for decoding;
    
    set baseFile to ((path to desktop as text) & "image") -- file reference of location for pending base64-encoded text file
    set brn to open for access baseFile with write permission
    set eof brn to 0
    write base64 to brn starting at 0 as «class utf8» -- write encoded text to file for decoding
    close access brn
    delay 1
    
    -- test that base64 file exists and then decode to png
    my nowWhat(baseFile)
    
    
on error number -48 -- triggered when 'backup.gcode' already exists
    display dialog "Conflict: A file with the backup name already exists" buttons {"cancel"} default button "cancel" with icon stop with title "Chaos"
end try

-- §
-- handlers §

-- does file exist yet
on existo(fil)
    tell application "Finder"
        try
            exists alias fil
        end try
    end tell
end existo

-- test that base64 file exists and then decode to png
on nowWhat(baseFile)
    set trueFalse to false
    repeat until trueFalse is true
        try
            set trueFalse to existo(baseFile)
            set qbaseFile to quoted form of POSIX path of baseFile
            do shell script "/usr/bin/base64 --decode -i " & qbaseFile & " -o ~/Desktop/base.png"
            -- can change resulting image name above
            exit repeat
        end try
        delay 0.2 -- depending upon computer performance could be reduced or possibly removed
    end repeat
end nowWhat

Okay, this should also handle the base64 to png conversion

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you, Works great, but there are a few details to sort out! I might be able to fix some, but I think I'll need help with others. For example, where is the "thumbnail" or the code extracted from the file? I don't see it in the .csv file. How should I proceed to "on run" the application? For now, I've only just discovered it; I'll study the code to find the answers myself.
Oo, one important thing I forgot to mention: the value of each line (parameters) can change so when we say "; nozzle_diameter = 0.4" it's not totally true, it would be more like "; nozzle_diameter = " that we would have to search for and then extract the "0.4" that follows after the = symbol! It's possible ?
This is a bit complicated. So the section extract encoded thumbnail… is where the encoded text is captured in the variable thut (short for 'thumbnail text'). It is held there until the write base64 encode to file section wherein the unwanted parts (eg semi-colons, spaces, linefeed) are removed and the desired string is saved to a text file in the write base to brn… line. Finally, the nowWhat(mewf) line calls a handler which waits until the base64 text file is created and then uses the base64 shell command to decode the text into a png. Roundabout because of latency in file save.
Thanks a lot ! Work fine now, I get a file containing all the base64 code and I also get the PNG file! Now I'm pushing my learning curve to successfully place the "on run" command so I can select the file to process! The ideal for me would be to get a GUI like this ---> latenightsw.com/enhanced-applets
Regarding the enhanced applet stuff, this should be asked as a separate question. FWIW, it's not something I've attempted myself. You might also consider looking around at macscripter where I think there would be people with that experience.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.