diff options
Diffstat (limited to 'shelly.go')
| -rw-r--r-- | shelly.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/shelly.go b/shelly.go new file mode 100644 index 0000000..508b393 --- /dev/null +++ b/shelly.go @@ -0,0 +1,90 @@ +package main + +import ( + "fmt" + "log" + "net" + "strings" + + "github.com/gorilla/websocket" +) + +func ShellyRun(config ShellyConfigs, route Route) { + for message := range route.Destination { + ip, command, err := parseMessage(config, message) + if err != nil { + log.Println(err) + continue + } + + err = shellySendCommand(ip, command) + if err != nil { + log.Printf("Could not send command '%s' to %v: %v", command, ip, err) + } + } +} + +func parseMessage(config ShellyConfigs, m MQTTMessage) (ip *net.IP, command string, err error) { + elements := strings.Split(m.Topic, "/") + + if len(elements) != 3 { + return nil, "", fmt.Errorf( + "Expected three topic levels but got %d in '%s'.", + len(elements), m.Topic, + ) + } + + if elements[0] != "cover" || elements[2] != "movement" { + return nil, "", fmt.Errorf("Expected cover/<id>/movement but got: %s", m.Topic) + } + + switch string(m.Payload) { + case "extend": + command = "Cover.Close" + case "retract": + command = "Cover.Open" + case "stop": + command = "Cover.Stop" + default: + return nil, "", fmt.Errorf("Invalid payload '%s'.", m.Payload) + } + + id := elements[1] + + for _, c := range config { + if c.ID == id { + ip := net.ParseIP(c.IP) + return &ip, command, nil + } + } + + return nil, "", fmt.Errorf("Got message for unknown cover '%s'", id) +} + +func shellySendCommand(ip *net.IP, command string) error { + template := ` +{ + "jsonrpc":"2.0", + "id": 1, + "src":"user_1", + "method":"%s", + "params": { + "id":0 + } +} +` + message := fmt.Appendf([]byte{}, template, command) + + c, _, err := websocket.DefaultDialer.Dial("ws://" + ip.String() + "/rpc", nil) + if err != nil { + return fmt.Errorf("Could not connect to Shelly: %w", err) + } + defer c.Close() + + err = c.WriteMessage(websocket.TextMessage, message) + if err != nil { + return fmt.Errorf("Failed writing websocket message to Shelly: %w", err) + } + + return nil +} |
