mqtt2exec/main.go

76 lines
1.8 KiB
Go

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 <broker> <client_id> <username> <password>", 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")
}