From 581aa970c80e1ae87917920e949445334176d64a Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 11 Nov 2025 17:47:13 +0100 Subject: [PATCH 1/2] Added a start callback flag to the router --- main.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/main.go b/main.go index afdbea4..b3ea68a 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,7 @@ import ( "net" "os" "os/signal" + "strings" "sync" "syscall" "time" @@ -35,6 +36,7 @@ import ( networkapi "github.com/arduino/arduino-router/internal/network-api" "github.com/arduino/arduino-router/msgpackrpc" + "github.com/arduino/go-paths-helper" "github.com/spf13/cobra" "go.bug.st/f" "go.bug.st/serial" @@ -51,6 +53,7 @@ type Config struct { SerialPortAddr string SerialBaudRate int MonitorPortAddr string + StartCallback string } func main() { @@ -80,6 +83,7 @@ func main() { cmd.Flags().StringVarP(&cfg.SerialPortAddr, "serial-port", "p", "", "Serial port address") cmd.Flags().IntVarP(&cfg.SerialBaudRate, "serial-baudrate", "b", 115200, "Serial port baud rate") cmd.Flags().StringVarP(&cfg.MonitorPortAddr, "monitor-port", "m", "127.0.0.1:7500", "Listening port for MCU monitor proxy") + cmd.Flags().StringVar(&cfg.StartCallback, "after-start", "", "Command to execute when the router has successfully completed startup") cmd.AddCommand(&cobra.Command{ Use: "version", @@ -224,6 +228,10 @@ func startRouter(cfg Config) error { return true, nil }) f.Assert(err == nil, "Failed to register $/serial/close method") + + var started sync.WaitGroup + started.Add(1) + initialized := sync.OnceFunc(started.Done) go func() { for { serialOpened.L.Lock() @@ -246,6 +254,7 @@ func startRouter(cfg Config) error { time.Sleep(5 * time.Second) continue } + initialized() slog.Info("Opened serial connection", "serial", cfg.SerialPortAddr) wr := &MsgpackDebugStream{Name: cfg.SerialPortAddr, Upstream: serialPort} @@ -262,6 +271,7 @@ func startRouter(cfg Config) error { <-routerExit } }() + started.Wait() } // Wait for incoming connections on all listeners @@ -280,6 +290,20 @@ func startRouter(cfg Config) error { }() } + // Execute start callback if specified + if cfg.StartCallback != "" { + slog.Info("Executing start callback", "cmd", cfg.StartCallback) + cb, err := paths.NewProcess(nil, strings.Split(cfg.StartCallback, " ")...) + if err != nil { + slog.Error("Failed to start callback process", "err", err) + return err + } + if err := cb.Run(); err != nil { + slog.Error("Start callback process failed", "err", err) + return err + } + } + // Sleep forever until interrupted signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) From befa4c8dd6377726f0178e58d90d7e72685a9f5a Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 11 Nov 2025 17:50:13 +0100 Subject: [PATCH 2/2] Execute gpio-set internally --- .../arduino-router/etc/systemd/system/arduino-router.service | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/debian/arduino-router/etc/systemd/system/arduino-router.service b/debian/arduino-router/etc/systemd/system/arduino-router.service index 5a4aed5..1b7e303 100644 --- a/debian/arduino-router/etc/systemd/system/arduino-router.service +++ b/debian/arduino-router/etc/systemd/system/arduino-router.service @@ -7,9 +7,8 @@ Requires= [Service] # Put the micro in a ready state. ExecStartPre=-/usr/bin/gpioset -c /dev/gpiochip1 -t0 37=0 -ExecStart=/usr/bin/arduino-router --unix-port /var/run/arduino-router.sock --serial-port /dev/ttyHS1 --serial-baudrate 115200 -# End the boot animation after the router is started. -ExecStartPost=/usr/bin/gpioset -c /dev/gpiochip1 -t0 70=1 +# Launch router and end the boot animation after the router is started (--after-start). +ExecStart=/usr/bin/arduino-router --unix-port /var/run/arduino-router.sock --serial-port /dev/ttyHS1 --serial-baudrate 115200 --after-start "/usr/bin/gpioset -c /dev/gpiochip1 -t0 70=1" StandardOutput=journal StandardError=journal Restart=always