gomie/run.go
Jens Christian True 0e809715e3
All checks were successful
continuous-integration/drone/push Build is passing
Added code documentation
2019-04-25 09:37:34 +02:00

125 lines
3.5 KiB
Go

package main
import (
"strconv"
"bytes"
"log"
"net"
"os"
"time"
"os/exec"
"github.com/eclipse/paho.mqtt.golang"
"github.com/shirou/gopsutil/host"
"github.com/google/uuid"
"github.com/urfave/cli"
)
//GetOutboundIP Gets the preferred outbound ip of this machine
func GetOutboundIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP
}
//getMacAddr fetches the first avaible Mac address
func getMacAddr() (addr string) {
interfaces, err := net.Interfaces()
if err == nil {
for _, i := range interfaces {
if i.Flags&net.FlagUp != 0 && bytes.Compare(i.HardwareAddr, nil) != 0 {
// Don't use random as we have a real address
addr = i.HardwareAddr.String()
break
}
}
}
return
}
//SyncPublish Synchronous publish an MQTT topic and wait for confirmation
func SyncPublish(client mqtt.Client, topic string, qos byte, retained bool, payload interface{}) {
hostname, _ := os.Hostname()
prefix := "homie/" + hostname + "/"
token := client.Publish(prefix + topic, qos, retained, payload)
if(!token.Wait()) {
log.Fatal("Timeout on publish")
os.Exit(1)
}
}
//cmdRun Command handler for the run command
func cmdRun(cli *cli.Context) {
clientid := uuid.New()
command := "";
if cli.NArg() > 0 {
command = cli.Args()[0]
} else {
log.Fatal("You must provide a command to run")
os.Exit(1)
}
log.Printf("Connection string: %s\n",cli.GlobalString("mqtt"))
opts := mqtt.NewClientOptions().AddBroker(cli.GlobalString("mqtt")).SetClientID(clientid.String())
hostname, _ := os.Hostname()
opts.SetWill("homie/" + hostname + "/$state", "lost", 0, true);
client := mqtt.NewClient(opts)
log.Println("Connecting...")
if token := client.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
os.Exit(1)
}
log.Println("Connected")
SyncPublish(client, "$state", 0, true, "init")
log.Println("$state -> init")
SyncPublish(client, "$homie", 0, true, "3.0.1")
SyncPublish(client, "$name", 0, true, hostname)
SyncPublish(client, "$localip", 0, true, GetOutboundIP().String())
SyncPublish(client, "$mac", 0, true, getMacAddr())
SyncPublish(client, "$fw/name", 0, true, "gomie")
SyncPublish(client, "$fw/version", 0, true, "1.0")
SyncPublish(client, "$implementation", 0, true, "gomie")
SyncPublish(client, "$stats", 0, true, "uptime")
uptimeSeconds, _ := host.Uptime()
SyncPublish(client, "$stats/uptime", 0, true, strconv.FormatUint(uptimeSeconds,10))
SyncPublish(client, "$stats/interval", 0, true, "0")
SyncPublish(client, "leax-backup/$name", 0, true, "LEAX Backup")
SyncPublish(client, "leax-backup/$type", 0, true, "script")
SyncPublish(client, "leax-backup/$properties", 0, true, "lastrun,stdout,errorcode")
SyncPublish(client, "$state", 0, true, "ready")
log.Println("$state -> ready")
//Done with initialization
SyncPublish(client, "leax-backup/started", 0, true, strconv.FormatInt(time.Now().Unix(),10))
SyncPublish(client, "leax-backup/stdout", 0, true, "")
out, err := exec.Command(command).Output()
if err != nil {
log.Fatal(err)
}
SyncPublish(client, "leax-backup/ended", 0, true, strconv.FormatInt(time.Now().Unix(),10))
SyncPublish(client, "leax-backup/stdout", 0, true, out)
//All done
SyncPublish(client, "$state", 0, true, "disconnected")
log.Println("$state -> disconnected")
client.Disconnect(1000) //Wait one second to disconnect
log.Println("Disconnected")
}