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//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 }