diff --git a/multi-upload.pl b/multi-upload.pl new file mode 100644 index 0000000..a300eba --- /dev/null +++ b/multi-upload.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl +use strict; +use warnings; +use autodie; +use Time::HiRes qw(sleep); +use POSIX qw(strftime); + +if (!@ARGV or $ARGV[0] ne "--please-destroy-my-data") { + print "DANGER! Please read and understand the source code before using.\n"; + print "Regular users do not need to use this program. Use 'pio run' instead.\n"; + exit 1; +} + +my %pane; +my $command = ""; + +sub printlog { + print strftime("%Y-%m-%d %H:%M:%S", localtime), " @_\n"; +} + +sub spawn { + my ($dev) = @_; + + printlog "Spawning $dev"; + + my $c = $command; + + $c =~ s[ttyUSB\w+][$dev]; + $c =~ s/^/time /; + $c =~ s[$][| perl -pe"BEGIN { \$/ = \\1 } s/\\r/\\n/"; echo "-- $dev done --"; read a]; + + $pane{$dev} = readpipe qq{tmux split-window -d -h -P -F '#{pane_id}' '$c'}; + chomp $pane{$dev}; + + system "tmux select-layout even-horizontal"; +} + +if (1 < (() = glob("/dev/ttyUSB*"))) { + die "Disconnect USB serial devices except one target device.\n"; +} + +if ($ARGV[-1] ne "it's-a-me") { + exec qw[tmux new perl], $0, @ARGV, "it's-a-me"; +} + +my $pio_pid = open my $pio, "-|", "pio run -v -t upload"; +while (defined(my $line = readline $pio)) { + print $line; + if ($line =~ /esptool/ && $line =~ /write_flash/) { + $command = $line; + system "pkill -9 -P $pio_pid"; # kill upload process. + kill 9, $pio_pid; + last; + } +} + +if ($command =~ /(ttyUSB\d+)/) { + spawn $1; +} else { + warn "Could not snatch upload command.\nMake sure a single target device is already connected.\nPress enter to exit.\n"; + scalar ; + die; +} + +open my $monitor, "-|", "udevadm monitor --kernel --subsystem-match=usb-serial"; + +printlog "Started monitoring for new usb-serial devices."; + + +while (defined(my $line = readline $monitor)) { + my ($event) = $line =~ /\b(remove|add)\b/ or next; + my ($dev) = $line =~ /(ttyUSB\d+)/ or next; + + if ($event eq 'add') { + while (!-w "/dev/$dev") { + sleep .1; + # wait for permissions to settle; + } + + spawn($dev); + } else { + if (exists $pane{$dev}) { + printlog "Killing $dev"; + system "tmux kill-pane -t $pane{$dev}"; + } + } +}