#!/usr/bin/perl -w ###################################################################### # Read a (Cura) gcode file and output a very short summary like: # 2019-01-28? Mistral-E_v1.3_Leo_N.stl # 037-Mistral-E_v1.3.gcode (35m, 0.2mm, 10% gyroid, NO SUPPORT) ###################################################################### use strict; # ALWAYS ALWAYS ALWAYS use JSON::PP; my (%setting, %mesh, $setting_3, $fn); while (<>) { unless ($fn && $fn eq $ARGV) { op(); $fn = $ARGV; %setting = %mesh = (); $setting_3 = ''; } # Fast skip actual gcode (for now), look only at comments: next unless /^;/; # +++ Consider a more generic way to parse templates for {setting}s? if (/^;MESH:(.+)/) { $mesh{$1}++; } elsif (/^;TIME:(\d+)/) { $setting{print_time} = $1; # already in seconds } elsif (/^\;Print time: (\d\d):(\d\d):(\d\d)/) { $setting{print_time} ||= 60*60*$1 + 60*$2 + $3; # convert to secs } elsif (/^;Sliced at: \w+ (\d+)-(\d+)-(\d+) \d+:\d+:\d+/) { $setting{date} = "$3-$2-$1"; # DD-MM-YYYY -> ISO } elsif (/^;Layer height: ([.0-9]+)/) { $setting{layer_height} = $1; } elsif (/^;Basic settings: Layer height: ([.0-9]+) Walls: ([.0-9]+)/) { $setting{layer_height} ||= $1; $setting{wall_thickness} ||= $2; } elsif (/^;Fill: ([.0-9]+)/) { $setting{infill_sparse_density} = $1; } elsif (/^;SETTING_3 (.+)/) { # are there other SETTING_\d+ ? $setting_3 .= $1; } # +++++ Do something about unprintable M117 00:35:54 $[0.06885498580078125] ? } op(); sub parse_settings { my ($from, $setting) = @_; if (ref $setting eq 'ARRAY') { my $n = 0; for (@$setting) { parse_settings($from . '.' . $n++, $_); } return; } elsif (ref $setting eq 'HASH') { for (sort keys %$setting) { parse_settings("$from.$_", $setting->{$_}); } return; } elsif (ref $setting) { die "Not sure what to do with $from $setting"; } # got a string of settings to parse: my $vals = 0; for (split '\\\\n', $setting) { if ($_ eq '[values]') { $vals = 1; # start reading values! } elsif (/^\[/) { $vals = 0; } elsif ($vals && /^(\w+) = (.+)/) { $setting{$1} = $2; } elsif ($vals && $_) { print ";UNPARSED $from $_\n"; } } } sub op { parse_settings(';SETTING_3', decode_json $setting_3 || '{}'); print ";MESH", map(":$_($mesh{$_})", sort keys %mesh), "\n" if %mesh; for (sort keys %setting) { print ";$_ = $setting{$_}\n"; } print "#"x70, "\n"; }