mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-10-06 00:37:00 +08:00
remove unnecessary prints and use mutex for ws
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AlexxIT/go2rtc/pkg/core"
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
||||||
@@ -12,7 +13,6 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
pion "github.com/pion/webrtc/v3"
|
pion "github.com/pion/webrtc/v3"
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@@ -22,6 +22,7 @@ type Client struct {
|
|||||||
camera *CameraData
|
camera *CameraData
|
||||||
dialogID string
|
dialogID string
|
||||||
sessionID string
|
sessionID string
|
||||||
|
wsMutex sync.Mutex
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,10 +121,6 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
return nil, fmt.Errorf("ring: invalid refresh token encoding: %w", err)
|
return nil, fmt.Errorf("ring: invalid refresh token encoding: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Connecting to Ring WebSocket")
|
|
||||||
println("Refresh Token: ", refreshToken)
|
|
||||||
println("Device ID: ", deviceID)
|
|
||||||
|
|
||||||
// Initialize Ring API client
|
// Initialize Ring API client
|
||||||
ringAPI, err := NewRingRestClient(RefreshTokenAuth{RefreshToken: refreshToken}, nil)
|
ringAPI, err := NewRingRestClient(RefreshTokenAuth{RefreshToken: refreshToken}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -153,15 +150,10 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
println("WebSocket Ticket: ", ticket.Ticket)
|
|
||||||
println("WebSocket ResponseTimestamp: ", ticket.ResponseTimestamp)
|
|
||||||
|
|
||||||
// Create WebSocket connection
|
// Create WebSocket connection
|
||||||
wsURL := fmt.Sprintf("wss://api.prod.signalling.ring.devices.a2z.com/ws?api_version=4.0&auth_type=ring_solutions&client_id=ring_site-%s&token=%s",
|
wsURL := fmt.Sprintf("wss://api.prod.signalling.ring.devices.a2z.com/ws?api_version=4.0&auth_type=ring_solutions&client_id=ring_site-%s&token=%s",
|
||||||
uuid.NewString(), url.QueryEscape(ticket.Ticket))
|
uuid.NewString(), url.QueryEscape(ticket.Ticket))
|
||||||
|
|
||||||
println("WebSocket URL: ", wsURL)
|
|
||||||
|
|
||||||
ws, _, err := websocket.DefaultDialer.Dial(wsURL, map[string][]string{
|
ws, _, err := websocket.DefaultDialer.Dial(wsURL, map[string][]string{
|
||||||
"User-Agent": {"android:com.ringapp"},
|
"User-Agent": {"android:com.ringapp"},
|
||||||
})
|
})
|
||||||
@@ -169,11 +161,7 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
println("WebSocket handshake completed successfully")
|
|
||||||
|
|
||||||
// 3. Create Peer Connection
|
// 3. Create Peer Connection
|
||||||
println("Creating Peer Connection")
|
|
||||||
|
|
||||||
conf := pion.Configuration{
|
conf := pion.Configuration{
|
||||||
ICEServers: []pion.ICEServer{
|
ICEServers: []pion.ICEServer{
|
||||||
{URLs: []string{
|
{URLs: []string{
|
||||||
@@ -193,20 +181,16 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
|
|
||||||
api, err := webrtc.NewAPI()
|
api, err := webrtc.NewAPI()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Failed to create WebRTC API")
|
|
||||||
ws.Close()
|
ws.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pc, err := api.NewPeerConnection(conf)
|
pc, err := api.NewPeerConnection(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Failed to create Peer Connection")
|
|
||||||
ws.Close()
|
ws.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Peer Connection created")
|
|
||||||
|
|
||||||
// protect from sending ICE candidate before Offer
|
// protect from sending ICE candidate before Offer
|
||||||
var sendOffer core.Waiter
|
var sendOffer core.Waiter
|
||||||
|
|
||||||
@@ -292,14 +276,10 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
// 4. Create offer
|
// 4. Create offer
|
||||||
offer, err := prod.CreateOffer(medias)
|
offer, err := prod.CreateOffer(medias)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Failed to create offer")
|
|
||||||
client.Stop()
|
client.Stop()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Offer created")
|
|
||||||
println(offer)
|
|
||||||
|
|
||||||
// 5. Send offer
|
// 5. Send offer
|
||||||
offerPayload := map[string]interface{}{
|
offerPayload := map[string]interface{}{
|
||||||
"stream_options": map[string]bool{
|
"stream_options": map[string]bool{
|
||||||
@@ -310,7 +290,6 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = client.sendSessionMessage("live_view", offerPayload); err != nil {
|
if err = client.sendSessionMessage("live_view", offerPayload); err != nil {
|
||||||
println("Failed to send live_view message")
|
|
||||||
client.Stop()
|
client.Stop()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -329,7 +308,6 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if pc.ConnectionState() == pion.PeerConnectionStateConnected {
|
if pc.ConnectionState() == pion.PeerConnectionStateConnected {
|
||||||
if err := client.sendSessionMessage("ping", nil); err != nil {
|
if err := client.sendSessionMessage("ping", nil); err != nil {
|
||||||
println("Failed to send ping:", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,43 +336,30 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
if websocket.IsCloseError(err, websocket.CloseNormalClosure) {
|
client.Stop()
|
||||||
println("WebSocket closed normally")
|
|
||||||
} else {
|
|
||||||
println("Failed to read JSON message:", err)
|
|
||||||
client.Stop()
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := json.Marshal(res.Body)
|
// check if "doorbot_id" is present
|
||||||
bodyStr := string(body)
|
|
||||||
|
|
||||||
println("Received message:", res.Method)
|
|
||||||
println("Message body:", bodyStr)
|
|
||||||
|
|
||||||
// check if "doorbot_id" is present and matches the camera ID
|
|
||||||
if _, ok := res.Body["doorbot_id"]; !ok {
|
if _, ok := res.Body["doorbot_id"]; !ok {
|
||||||
println("Received message without doorbot_id")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the message is from the correct doorbot
|
||||||
doorbotID := res.Body["doorbot_id"].(float64)
|
doorbotID := res.Body["doorbot_id"].(float64)
|
||||||
if doorbotID != float64(client.camera.ID) {
|
if doorbotID != float64(client.camera.ID) {
|
||||||
println("Received message from unknown doorbot:", doorbotID)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the message is from the correct session
|
||||||
if res.Method == "session_created" || res.Method == "session_started" {
|
if res.Method == "session_created" || res.Method == "session_started" {
|
||||||
if _, ok := res.Body["session_id"]; ok && client.sessionID == "" {
|
if _, ok := res.Body["session_id"]; ok && client.sessionID == "" {
|
||||||
client.sessionID = res.Body["session_id"].(string)
|
client.sessionID = res.Body["session_id"].(string)
|
||||||
println("Session established:", client.sessionID)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := res.Body["session_id"]; ok {
|
if _, ok := res.Body["session_id"]; ok {
|
||||||
if res.Body["session_id"].(string) != client.sessionID {
|
if res.Body["session_id"].(string) != client.sessionID {
|
||||||
println("Received message with wrong session ID")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -406,17 +371,14 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
// 6. Get answer
|
// 6. Get answer
|
||||||
var msg AnswerMessage
|
var msg AnswerMessage
|
||||||
if err = json.Unmarshal(rawMsg, &msg); err != nil {
|
if err = json.Unmarshal(rawMsg, &msg); err != nil {
|
||||||
println("Failed to parse SDP message:", err)
|
|
||||||
client.Stop()
|
client.Stop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = prod.SetAnswer(msg.Body.SDP); err != nil {
|
if err = prod.SetAnswer(msg.Body.SDP); err != nil {
|
||||||
println("Failed to set answer:", err)
|
|
||||||
client.Stop()
|
client.Stop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = client.activateSession(); err != nil {
|
if err = client.activateSession(); err != nil {
|
||||||
println("Failed to activate session:", err)
|
|
||||||
client.Stop()
|
client.Stop()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -425,15 +387,12 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
// 7. Continue to receiving candidates
|
// 7. Continue to receiving candidates
|
||||||
var msg IceCandidateMessage
|
var msg IceCandidateMessage
|
||||||
if err = json.Unmarshal(rawMsg, &msg); err != nil {
|
if err = json.Unmarshal(rawMsg, &msg); err != nil {
|
||||||
println("Failed to parse ICE message:", err)
|
break
|
||||||
client.Stop()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for empty ICE candidate
|
// check for empty ICE candidate
|
||||||
if msg.Body.Ice == "" {
|
if msg.Body.Ice == "" {
|
||||||
println("Received empty ICE candidate")
|
break
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = prod.AddCandidate(msg.Body.Ice); err != nil {
|
if err = prod.AddCandidate(msg.Body.Ice); err != nil {
|
||||||
@@ -461,8 +420,6 @@ func Dial(rawURL string) (*Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) activateSession() error {
|
func (c *Client) activateSession() error {
|
||||||
println("Activating session")
|
|
||||||
|
|
||||||
if err := c.sendSessionMessage("activate_session", nil); err != nil {
|
if err := c.sendSessionMessage("activate_session", nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -476,12 +433,13 @@ func (c *Client) activateSession() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Session activated")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) sendSessionMessage(method string, body map[string]interface{}) error {
|
func (c *Client) sendSessionMessage(method string, body map[string]interface{}) error {
|
||||||
|
c.wsMutex.Lock()
|
||||||
|
defer c.wsMutex.Unlock()
|
||||||
|
|
||||||
if body == nil {
|
if body == nil {
|
||||||
body = make(map[string]interface{})
|
body = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
@@ -497,10 +455,7 @@ func (c *Client) sendSessionMessage(method string, body map[string]interface{})
|
|||||||
"body": body,
|
"body": body,
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Sending session message:", method)
|
|
||||||
|
|
||||||
if err := c.ws.WriteJSON(msg); err != nil {
|
if err := c.ws.WriteJSON(msg); err != nil {
|
||||||
log.Error().Err(err).Msg("Failed to send JSON message")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,28 +463,27 @@ func (c *Client) sendSessionMessage(method string, body map[string]interface{})
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetMedias() []*core.Media {
|
func (c *Client) GetMedias() []*core.Media {
|
||||||
println("Getting medias")
|
|
||||||
return c.prod.GetMedias()
|
return c.prod.GetMedias()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
|
func (c *Client) GetTrack(media *core.Media, codec *core.Codec) (*core.Receiver, error) {
|
||||||
println("Getting track")
|
|
||||||
return c.prod.GetTrack(media, codec)
|
return c.prod.GetTrack(media, codec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error {
|
func (c *Client) AddTrack(media *core.Media, codec *core.Codec, track *core.Receiver) error {
|
||||||
// Enable speaker
|
if media.Kind == core.KindAudio {
|
||||||
speakerPayload := map[string]interface{}{
|
// Enable speaker
|
||||||
"stealth_mode": false,
|
speakerPayload := map[string]interface{}{
|
||||||
}
|
"stealth_mode": false,
|
||||||
|
}
|
||||||
|
|
||||||
_ = c.sendSessionMessage("camera_options", speakerPayload);
|
_ = c.sendSessionMessage("camera_options", speakerPayload);
|
||||||
|
}
|
||||||
|
|
||||||
return c.prod.AddTrack(media, codec, track)
|
return c.prod.AddTrack(media, codec, track)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Start() error {
|
func (c *Client) Start() error {
|
||||||
println("Starting client")
|
|
||||||
return c.prod.Start()
|
return c.prod.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +492,6 @@ func (c *Client) Stop() error {
|
|||||||
case <-c.done:
|
case <-c.done:
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
println("Stopping client")
|
|
||||||
close(c.done)
|
close(c.done)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user