install go2rtc on bob
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
package hass
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||
"github.com/AlexxIT/go2rtc/pkg/webrtc"
|
||||
pion "github.com/pion/webrtc/v4"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
conn *webrtc.Conn
|
||||
}
|
||||
|
||||
func NewClient(rawURL string) (*Client, error) {
|
||||
u, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := u.Query()
|
||||
|
||||
entityID := query.Get("entity_id")
|
||||
if entityID == "" {
|
||||
return nil, errors.New("hass: no entity_id")
|
||||
}
|
||||
|
||||
var uri, token string
|
||||
|
||||
if u.Host == "supervisor" {
|
||||
uri = "ws://supervisor/core/websocket"
|
||||
token = SupervisorToken()
|
||||
} else {
|
||||
uri = "ws://" + u.Host + "/api/websocket"
|
||||
token = query.Get("token")
|
||||
}
|
||||
|
||||
if token == "" {
|
||||
return nil, errors.New("hass: no token")
|
||||
}
|
||||
|
||||
// 1. Check connection to Hass
|
||||
hassAPI, err := NewAPI(uri, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer hassAPI.Close()
|
||||
|
||||
// 2. Create WebRTC client
|
||||
rtcAPI, err := webrtc.NewAPI()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conf := pion.Configuration{}
|
||||
pc, err := rtcAPI.NewPeerConnection(conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conn := webrtc.NewConn(pc)
|
||||
conn.FormatName = "hass/webrtc"
|
||||
conn.Mode = core.ModeActiveProducer
|
||||
conn.Protocol = "ws"
|
||||
conn.URL = rawURL
|
||||
|
||||
// https://developers.google.com/nest/device-access/traits/device/camera-live-stream#generatewebrtcstream-request-fields
|
||||
medias := []*core.Media{
|
||||
{Kind: core.KindAudio, Direction: core.DirectionRecvonly},
|
||||
{Kind: core.KindVideo, Direction: core.DirectionRecvonly},
|
||||
{Kind: "app"}, // important for Nest
|
||||
}
|
||||
|
||||
// 3. Create offer with candidates
|
||||
offer, err := conn.CreateCompleteOffer(medias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 4. Exchange SDP via Hass
|
||||
answer, err := hassAPI.ExchangeSDP(entityID, offer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 5. Set answer with remote medias
|
||||
if err = conn.SetAnswer(answer); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{conn: conn}, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetMedias() []*core.Media {
|
||||
return c.conn.GetMedias()
|
||||
}
|
||||
|
||||
func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
|
||||
return c.conn.GetTrack(media, codec)
|
||||
}
|
||||
|
||||
func (c *Client) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error {
|
||||
return c.conn.AddTrack(media, codec, track)
|
||||
}
|
||||
|
||||
func (c *Client) Start() error {
|
||||
return c.conn.Start()
|
||||
}
|
||||
|
||||
func (c *Client) Stop() error {
|
||||
return c.conn.Stop()
|
||||
}
|
||||
|
||||
func (c *Client) MarshalJSON() ([]byte, error) {
|
||||
return c.conn.MarshalJSON()
|
||||
}
|
||||
Reference in New Issue
Block a user