Carry protocol info in stream URL

This commit is contained in:
Jamal Fanaian
2024-07-11 18:47:05 -07:00
parent e1021a96af
commit 13dd3084c2
3 changed files with 24 additions and 40 deletions

View File

@@ -2,6 +2,7 @@ package nest
import ( import (
"net/http" "net/http"
"strings"
"github.com/AlexxIT/go2rtc/internal/api" "github.com/AlexxIT/go2rtc/internal/api"
"github.com/AlexxIT/go2rtc/internal/streams" "github.com/AlexxIT/go2rtc/internal/streams"
@@ -38,11 +39,12 @@ func apiNest(w http.ResponseWriter, r *http.Request) {
var items []*api.Source var items []*api.Source
for name, deviceID := range devices { for _, device := range devices {
query.Set("device_id", deviceID) query.Set("device_id", device.DeviceID)
query.Set("protocols", strings.Join(device.Protocols, ","))
items = append(items, &api.Source{ items = append(items, &api.Source{
Name: name, URL: "nest:?" + query.Encode(), Name: device.Name, URL: "nest:?" + query.Encode(),
}) })
} }

View File

@@ -33,6 +33,12 @@ type Auth struct {
AccessToken string AccessToken string
} }
type DeviceInfo struct {
Name string
DeviceID string
Protocols []string
}
var cache = map[string]*API{} var cache = map[string]*API{}
var cacheMu sync.Mutex var cacheMu sync.Mutex
@@ -84,7 +90,7 @@ func NewAPI(clientID, clientSecret, refreshToken string) (*API, error) {
return api, nil 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" uri := "https://smartdevicemanagement.googleapis.com/v1/enterprises/" + projectID + "/devices"
req, err := http.NewRequest("GET", uri, nil) req, err := http.NewRequest("GET", uri, nil)
if err != nil { if err != nil {
@@ -111,7 +117,7 @@ func (a *API) GetDevices(projectID string) (map[string]string, error) {
return nil, err return nil, err
} }
devices := map[string]string{} devices := make([]DeviceInfo, 0, len(resv.Devices))
for _, device := range resv.Devices { for _, device := range resv.Devices {
if len(device.Traits.SdmDevicesTraitsCameraLiveStream.SupportedProtocols) == 0 { 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 { if name == "" && len(device.ParentRelations) > 0 {
name = device.ParentRelations[0].DisplayName 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 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) { func (a *API) ExchangeSDP(projectID, deviceID, offer string) (string, error) {
var reqv struct { var reqv struct {
Command string `json:"command"` Command string `json:"command"`

View File

@@ -3,6 +3,7 @@ package nest
import ( import (
"errors" "errors"
"net/url" "net/url"
"strings"
"github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/core"
"github.com/AlexxIT/go2rtc/pkg/rtsp" "github.com/AlexxIT/go2rtc/pkg/rtsp"
@@ -32,6 +33,12 @@ func Dial(rawURL string) (core.Producer, error) {
refreshToken := query.Get("refresh_token") refreshToken := query.Get("refresh_token")
projectID := query.Get("project_id") projectID := query.Get("project_id")
deviceID := query.Get("device_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 == "" { if cliendID == "" || cliendSecret == "" || refreshToken == "" || projectID == "" || deviceID == "" {
return nil, errors.New("nest: wrong query") return nil, errors.New("nest: wrong query")
@@ -42,12 +49,8 @@ func Dial(rawURL string) (core.Producer, error) {
return nil, err return nil, err
} }
device, err := nestAPI.GetDevice(projectID, deviceID) // Pick the first supported protocol in order of priority (WEB_RTC, RTSP)
if err != nil { for _, proto := range protocols {
return nil, err
}
for _, proto := range device.Traits.SdmDevicesTraitsCameraLiveStream.SupportedProtocols {
if proto == "WEB_RTC" { if proto == "WEB_RTC" {
return rtcConn(nestAPI, rawURL, projectID, deviceID) return rtcConn(nestAPI, rawURL, projectID, deviceID)
} else if proto == "RTSP" { } else if proto == "RTSP" {