Added Commandline interface
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@ -1,9 +0,0 @@
|
|||||||
FROM golang:1.11 as builder
|
|
||||||
WORKDIR /go/gomie
|
|
||||||
COPY . .
|
|
||||||
RUN make build
|
|
||||||
|
|
||||||
# Create a minimal container to run a Golang static binary
|
|
||||||
FROM scratch
|
|
||||||
COPY --from=builder /go/gomie/gomie .
|
|
||||||
ENTRYPOINT ["/gomie"]
|
|
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
|||||||
default: build
|
default: build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
go build -v
|
go build
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
go mod download
|
go mod download
|
||||||
|
101
app.go
101
app.go
@ -1,101 +0,0 @@
|
|||||||
package main
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"bytes"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
"github.com/eclipse/paho.mqtt.golang"
|
|
||||||
"github.com/shirou/gopsutil/host"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
// Get 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
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
//Publish a message 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")
|
|
||||||
log.Fatal(token.Error())
|
|
||||||
os.Exit(3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
opts := mqtt.NewClientOptions().AddBroker("tcp://mqtt.jcktrue.dk:1883").SetClientID("gotrivial")
|
|
||||||
hostname, _ := os.Hostname()
|
|
||||||
opts.SetWill("homie/" + hostname + "/$state", "lost", 0, true);
|
|
||||||
|
|
||||||
c := mqtt.NewClient(opts)
|
|
||||||
if token := c.Connect(); token.Wait() && token.Error() != nil {
|
|
||||||
panic(token.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncPublish(c, "$state", 0, true, "init")
|
|
||||||
SyncPublish(c, "$homie", 0, true, "3.0.1")
|
|
||||||
SyncPublish(c, "$name", 0, true, hostname)
|
|
||||||
|
|
||||||
SyncPublish(c, "$localip", 0, true, GetOutboundIP().String())
|
|
||||||
SyncPublish(c, "$mac", 0, true, getMacAddr())
|
|
||||||
SyncPublish(c, "$fw/name", 0, true, "gomie")
|
|
||||||
SyncPublish(c, "$fw/version", 0, true, "1.0")
|
|
||||||
SyncPublish(c, "$implementation", 0, true, "gomie")
|
|
||||||
|
|
||||||
SyncPublish(c, "$stats", 0, true, "uptime")
|
|
||||||
uptimeSeconds, _ := host.Uptime()
|
|
||||||
SyncPublish(c, "$stats/uptime", 0, true, strconv.FormatUint(uptimeSeconds,10))
|
|
||||||
SyncPublish(c, "$stats/interval", 0, true, "0")
|
|
||||||
|
|
||||||
SyncPublish(c, "leax-backup/$name", 0, true, "LEAX Backup")
|
|
||||||
SyncPublish(c, "leax-backup/$type", 0, true, "script")
|
|
||||||
SyncPublish(c, "leax-backup/$properties", 0, true, "lastrun,output")
|
|
||||||
|
|
||||||
SyncPublish(c, "trueserver-backup/$name", 0, true, "TRUESERVER Backup")
|
|
||||||
SyncPublish(c, "trueserver-backup/$type", 0, true, "script")
|
|
||||||
SyncPublish(c, "trueserver-backup/$properties", 0, true, "lastrun,output")
|
|
||||||
|
|
||||||
SyncPublish(c, "$state", 0, true, "ready")
|
|
||||||
//Done with initialization
|
|
||||||
|
|
||||||
SyncPublish(c, "leax-backup/lastrun", 0, true, strconv.FormatInt(time.Now().Unix(),10))
|
|
||||||
SyncPublish(c, "leax-backup/output", 0, true, "Backup successful")
|
|
||||||
|
|
||||||
SyncPublish(c, "trueserver-backup/lastrun", 0, true, strconv.FormatInt(time.Now().Unix(),10))
|
|
||||||
SyncPublish(c, "trueserver-backup/output", 0, true, "Backup successful")
|
|
||||||
|
|
||||||
//All done
|
|
||||||
SyncPublish(c, "$state", 0, true, "disconnected")
|
|
||||||
|
|
||||||
c.Disconnect(1000) //Wait one second to disconnect
|
|
||||||
}
|
|
||||||
|
|
5
go.mod
5
go.mod
@ -4,7 +4,12 @@ require (
|
|||||||
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect
|
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect
|
||||||
github.com/eclipse/paho.mqtt.golang v1.1.1
|
github.com/eclipse/paho.mqtt.golang v1.1.1
|
||||||
github.com/go-ole/go-ole v1.2.4 // indirect
|
github.com/go-ole/go-ole v1.2.4 // indirect
|
||||||
|
github.com/google/uuid v1.1.1
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/shirou/gopsutil v2.18.12+incompatible
|
github.com/shirou/gopsutil v2.18.12+incompatible
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
|
||||||
|
github.com/spf13/cobra v0.0.3
|
||||||
|
github.com/spf13/pflag v1.0.3 // indirect
|
||||||
|
github.com/urfave/cli v1.20.0
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
|
||||||
)
|
)
|
||||||
|
36
main.go
Normal file
36
main.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Name = "gomie"
|
||||||
|
app.Usage = "Simulating a Homie IOT device through Go"
|
||||||
|
app.Version = "0.0.1"
|
||||||
|
|
||||||
|
app.Flags = []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "mqtt, m",
|
||||||
|
Usage: "mqtt connection string",
|
||||||
|
Value: "tcp://localhost:1883",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Commands = []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "run",
|
||||||
|
Usage: "Run a script and report to the Homie server",
|
||||||
|
Action: mqttstuff,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := app.Run(os.Args)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
124
run.go
Normal file
124
run.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// Get 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
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the 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
|
||||||
|
}
|
||||||
|
|
||||||
|
//Publish a message 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mqttstuff(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")
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user