package main import ( "encoding/json" mqtt "github.com/eclipse/paho.mqtt.golang" "log" "os" "os/exec" "time" ) type Result struct { Command string Output string Error string } func main() { var msgchan = make(chan mqtt.Message, 4) if len(os.Args) < 5 { log.Fatalf("Usage: %s ", os.Args[0]) } opts := mqtt.NewClientOptions() opts.AddBroker(os.Args[1]) opts.SetClientID(os.Args[2]) opts.SetUsername(os.Args[3]) opts.SetPassword(os.Args[4]) opts.SetDefaultPublishHandler(func(client mqtt.Client, msg mqtt.Message) { msgchan <- msg }) opts.OnConnect = connectHandler opts.SetKeepAlive(20 * time.Second) opts.SetAutoReconnect(true) opts.SetWill("mqtt2exec/"+os.Args[2]+"/state", "offline", 1, true) client := mqtt.NewClient(opts) sleep := 1 * time.Second for { if token := client.Connect(); token.Wait() && token.Error() != nil { log.Printf("Initial connection failed: %s", token.Error()) sleep *= 2 time.Sleep(sleep) } else { log.Printf("Connected to broker: %s", os.Args[1]) break } } for { msg := <-msgchan if msg.Topic() == "mqtt2exec/"+os.Args[2]+"/run" { cmd := exec.Command("/system/xbin/busybox", "ash", "-c", string(msg.Payload())) cmd.Stdin = nil out, err := cmd.CombinedOutput() result := Result{ Command: string(msg.Payload()), Output: string(out), } if err != nil { result.Error = err.Error() } resultJSON, _ := json.Marshal(result) client.Publish("mqtt2exec/"+os.Args[2]+"/result", 0, false, resultJSON) } } } func connectHandler(c mqtt.Client) { token := c.Subscribe("mqtt2exec/"+os.Args[2]+"/run", 2, nil) token.Wait() if token.Error() != nil { log.Printf("mqtt2exec: Error subscribing to topic: %s", token.Error()) } c.Publish("mqtt2exec/"+os.Args[2]+"/state", 1, true, "online") }