From 13dd3084c20b3bea53506382f0820ea2c8203415 Mon Sep 17 00:00:00 2001 From: Jamal Fanaian Date: Thu, 11 Jul 2024 18:47:05 -0700 Subject: [PATCH] Carry protocol info in stream URL --- internal/nest/init.go | 8 +++++--- pkg/nest/api.go | 41 ++++++++++------------------------------- pkg/nest/client.go | 15 +++++++++------ 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/internal/nest/init.go b/internal/nest/init.go index 01682414..8289af73 100644 --- a/internal/nest/init.go +++ b/internal/nest/init.go @@ -2,6 +2,7 @@ package nest import ( "net/http" + "strings" "github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/streams" @@ -38,11 +39,12 @@ func apiNest(w http.ResponseWriter, r *http.Request) { var items []*api.Source - for name, deviceID := range devices { - query.Set("device_id", deviceID) + for _, device := range devices { + query.Set("device_id", device.DeviceID) + query.Set("protocols", strings.Join(device.Protocols, ",")) items = append(items, &api.Source{ - Name: name, URL: "nest:?" + query.Encode(), + Name: device.Name, URL: "nest:?" + query.Encode(), }) } diff --git a/pkg/nest/api.go b/pkg/nest/api.go index 80a421ba..9e32cbcf 100644 --- a/pkg/nest/api.go +++ b/pkg/nest/api.go @@ -33,6 +33,12 @@ type Auth struct { AccessToken string } +type DeviceInfo struct { + Name string + DeviceID string + Protocols []string +} + var cache = map[string]*API{} var cacheMu sync.Mutex @@ -84,7 +90,7 @@ func NewAPI(clientID, clientSecret, refreshToken string) (*API, error) { return api, nil } -func (a *API) GetDevices(projectID string) (map[string]string, error) { +func (a *API) GetDevices(projectID string) ([]DeviceInfo, error) { uri := "https://smartdevicemanagement.googleapis.com/v1/enterprises/" + projectID + "/devices" req, err := http.NewRequest("GET", uri, nil) if err != nil { @@ -111,7 +117,7 @@ func (a *API) GetDevices(projectID string) (map[string]string, error) { return nil, err } - devices := map[string]string{} + devices := make([]DeviceInfo, 0, len(resv.Devices)) for _, device := range resv.Devices { if len(device.Traits.SdmDevicesTraitsCameraLiveStream.SupportedProtocols) == 0 { @@ -139,40 +145,13 @@ func (a *API) GetDevices(projectID string) (map[string]string, error) { if name == "" && len(device.ParentRelations) > 0 { name = device.ParentRelations[0].DisplayName } - devices[name] = device.Name[i+1:] + + devices = append(devices, DeviceInfo{Name: name, DeviceID: device.Name[i+1:], Protocols: device.Traits.SdmDevicesTraitsCameraLiveStream.SupportedProtocols}) } return devices, nil } -func (a *API) GetDevice(projectID, deviceID string) (Device, error) { - uri := "https://smartdevicemanagement.googleapis.com/v1/enterprises/" + projectID + "/devices/" + deviceID - req, err := http.NewRequest("GET", uri, nil) - if err != nil { - return Device{}, err - } - - req.Header.Set("Authorization", "Bearer "+a.Token) - - client := &http.Client{Timeout: time.Second * 5000} - res, err := client.Do(req) - if err != nil { - return Device{}, err - } - - if res.StatusCode != 200 { - return Device{}, errors.New("nest: wrong status: " + res.Status) - } - - var device Device - - if err = json.NewDecoder(res.Body).Decode(&device); err != nil { - return Device{}, err - } - - return device, nil -} - func (a *API) ExchangeSDP(projectID, deviceID, offer string) (string, error) { var reqv struct { Command string `json:"command"` diff --git a/pkg/nest/client.go b/pkg/nest/client.go index 6d867dea..e692359c 100644 --- a/pkg/nest/client.go +++ b/pkg/nest/client.go @@ -3,6 +3,7 @@ package nest import ( "errors" "net/url" + "strings" "github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/rtsp" @@ -32,6 +33,12 @@ func Dial(rawURL string) (core.Producer, error) { refreshToken := query.Get("refresh_token") projectID := query.Get("project_id") deviceID := query.Get("device_id") + protocols := strings.Split(query.Get("protocols"), ",") + + // Default to WEB_RTC for backwards compataiility + if len(protocols) == 0 { + protocols = append(protocols, "WEB_RTC") + } if cliendID == "" || cliendSecret == "" || refreshToken == "" || projectID == "" || deviceID == "" { return nil, errors.New("nest: wrong query") @@ -42,12 +49,8 @@ func Dial(rawURL string) (core.Producer, error) { return nil, err } - device, err := nestAPI.GetDevice(projectID, deviceID) - if err != nil { - return nil, err - } - - for _, proto := range device.Traits.SdmDevicesTraitsCameraLiveStream.SupportedProtocols { + // Pick the first supported protocol in order of priority (WEB_RTC, RTSP) + for _, proto := range protocols { if proto == "WEB_RTC" { return rtcConn(nestAPI, rawURL, projectID, deviceID) } else if proto == "RTSP" {