diff options
Diffstat (limited to 'tools/websocket.go')
| -rw-r--r-- | tools/websocket.go | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/tools/websocket.go b/tools/websocket.go new file mode 100644 index 0000000..af23959 --- /dev/null +++ b/tools/websocket.go @@ -0,0 +1,158 @@ +// Websocket debug tool +// +// Usage: ./websocket-linux-amd64 ws://<shelly-ip>/rpc +// +// This tools is intended to support development of the Websocket-based +// application programming interface (API) of the Shelly Internet of Things +// (IoT) devices. + +package main + +import ( + "encoding/json" + "log" + "net/url" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "github.com/gorilla/websocket" +) + +func main() { + log.SetFlags(0) + + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt) + + var u url.URL = getURL() + log.Printf("connecting to %s", u.String()) + + c, _, err := websocket.DefaultDialer.Dial(u.String(), nil) + if err != nil { + log.Fatal(err) + } + defer c.Close() + + go rx(c) + + getConfig(c) + coverClose(c) + time.Sleep(1 * time.Second) + coverOpen(c) + + Await(syscall.SIGTERM, syscall.SIGINT) +} + +func getURL() url.URL { + if len(os.Args) != 2 { + log.Fatalf("Exactly one argument expected but got %d.", len(os.Args) - 1) + } + + maybeURL, err := url.Parse(os.Args[1]) + if err != nil { + log.Fatalf("Cannot parse given URL: %s", os.Args[1]) + } + + return *maybeURL +} + +func Await(signals ...os.Signal) { + listener := make(chan os.Signal, 1) + signal.Notify(listener, signals...) + defer signal.Stop(listener) + + sig := <-listener + log.Printf("Received OS signal '%v'\n", sig) +} + +func getConfig(c *websocket.Conn) { + tx(c, ` +{ + "jsonrpc":"2.0", + "id": 1, + "src":"user_1", + "method":"Sys.GetConfig", + "params": { + "id":2 + } +} +`) +} + +func coverClose(c *websocket.Conn) { + tx(c, ` +{ + "jsonrpc":"2.0", + "id": 1, + "src":"user_1", + "method":"Cover.Close", + "params": { + "id":0 + } +} +`) +} + +func coverOpen(c *websocket.Conn) { + tx(c, ` +{ + "jsonrpc":"2.0", + "id": 1, + "src":"user_1", + "method":"Cover.Open", + "params": { + "id":0 + } +} +`) +} + +func rx(c *websocket.Conn) { + for { + _, message, err := c.ReadMessage() + if err != nil { + log.Println("read:", err) + return + } + log.Println("") + log.Println(quote(prettify(string(message)), "< ")) + } +} + +func tx(c *websocket.Conn, d string) { + log.Println(quote(prettify(d), "> ")) + + err := c.WriteMessage(websocket.TextMessage, []byte(d)) + if err != nil { + log.Fatal(err) + } +} + +func prettify(input string) string { + var parsed any + + err := json.Unmarshal([]byte(input), &parsed) + if err != nil { + log.Fatal(err) + } + + pretty, err := json.MarshalIndent(parsed, "", " ") + if err != nil { + log.Fatal(err) + } + + return string(pretty) +} + +func quote(input string, quotation string) string { + lines := strings.Split(input, "\n") + + for i, line := range lines { + lines[i] = quotation + line + } + + return strings.Join(lines, "\n") +} |
