From bd9bcef3a932714b89024e4dae89d5dda48a2332 Mon Sep 17 00:00:00 2001 From: Sergey Krashevich Date: Sat, 29 Apr 2023 19:00:36 +0300 Subject: [PATCH 1/4] Add WebSocket functionality to HomeKit API for device discovery --- cmd/homekit/api.go | 94 +++++++++++++++++++++++++++------------------- www/add.html | 56 +++++++++++++++++---------- 2 files changed, 91 insertions(+), 59 deletions(-) diff --git a/cmd/homekit/api.go b/cmd/homekit/api.go index a055871a..cde3aeb3 100644 --- a/cmd/homekit/api.go +++ b/cmd/homekit/api.go @@ -1,60 +1,39 @@ package homekit import ( - "encoding/json" "fmt" "github.com/AlexxIT/go2rtc/cmd/app/store" "github.com/AlexxIT/go2rtc/cmd/streams" "github.com/AlexxIT/go2rtc/pkg/hap" "github.com/AlexxIT/go2rtc/pkg/hap/mdns" + "github.com/gorilla/websocket" "net/http" - "net/url" + "strings" + "time" ) +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { + return true + }, +} + func apiHandler(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": - items := make([]any, 0) - for name, src := range store.GetDict("streams") { - if src := src.(string); strings.HasPrefix(src, "homekit") { - u, err := url.Parse(src) - if err != nil { - continue - } - device := Device{ - Name: name, - Addr: u.Host, - Paired: true, - } - items = append(items, device) - } - } - - for info := range mdns.GetAll() { - if !strings.HasSuffix(info.Name, mdns.Suffix) { - continue - } - name := info.Name[:len(info.Name)-len(mdns.Suffix)] - device := Device{ - Name: strings.ReplaceAll(name, "\\", ""), - Addr: fmt.Sprintf("%s:%d", info.AddrV4, info.Port), - } - for _, field := range info.InfoFields { - switch field[:2] { - case "id": - device.ID = field[3:] - case "md": - device.Model = field[3:] - case "sf": - device.Paired = field[3] == '0' - } - } - items = append(items, device) + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Error().Err(err).Caller().Send() + _, err = w.Write([]byte(err.Error())) + return } + defer conn.Close() - _ = json.NewEncoder(w).Encode(items) + hkDiscoverDevices(conn) case "POST": // TODO: post params... @@ -76,6 +55,43 @@ func apiHandler(w http.ResponseWriter, r *http.Request) { } } +func hkDiscoverDevices(conn *websocket.Conn) { + for { + entries := mdns.GetAll() + + for entry := range entries { + if !strings.HasSuffix(entry.Name, mdns.Suffix) { + continue + } + + name := entry.Name[:len(entry.Name)-len(mdns.Suffix)] + device := Device{ + Name: strings.ReplaceAll(name, "\\", ""), + Addr: fmt.Sprintf("%s:%d", entry.AddrV4, entry.Port), + } + for _, field := range entry.InfoFields { + switch field[:2] { + case "id": + device.ID = field[3:] + case "md": + device.Model = field[3:] + case "sf": + device.Paired = field[3] == '0' + } + } + + err := conn.WriteJSON(device) + if err != nil { + log.Error().Err(err).Caller().Send() + + return + } + } + + time.Sleep(1 * time.Second) + } +} + func hkPair(deviceID, pin, name string) (err error) { var conn *hap.Conn diff --git a/www/add.html b/www/add.html index 476c65c5..ed1226d9 100644 --- a/www/add.html +++ b/www/add.html @@ -124,29 +124,45 @@