Skip to content

Commit

Permalink
webrtc troubleshooting and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
bjia56 committed Dec 22, 2022
1 parent b2e9ece commit 909341b
Showing 1 changed file with 41 additions and 28 deletions.
69 changes: 41 additions & 28 deletions plugins/arlo/src/arlo_plugin/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ async def stopIntercom(self):
self.logger.info("Stopping intercom")
real_speaker = await self.speaker.real_speaker()
await real_speaker.stopIntercom()
self.speaker.close()

def _update_device_details(self, arlo_device):
"""For updating device details from the Arlo dictionary retrieved from Arlo's REST API.
Expand All @@ -156,31 +157,37 @@ def __init__(self, nativeId, arlo_device, arlo_basestation, provider):

self.rtc_session = None
self.rtc_setup = None
self.rtc_answered = False

def __del__(self):
self.stop_subscriptions = True

def start_sdp_answer_subscription(self):
def callback(sdp):
if self.rtc_session:
self.logger.info(f"Arlo response sdp: {sdp}")
if self.rtc_session and not self.rtc_answered:
if "a=mid:" not in sdp:
# arlo appears to not return a mux id in the response, which
# doesn't play nicely with our webrtc peers. let's add it
sdp += "a=mid:0av\r\n"
self.logger.info(f"Arlo response sdp:\n{sdp}")
asyncio.get_event_loop().create_task(self.rtc_session.setRemoteDescription(
{ "sdp": sdp, "type": "answer" },
self.rtc_setup
))
self.rtc_answered = True
return self.stop_subscriptions

self.provider.arlo.SubscribeToSDPAnswers(self.arlo_basestation, self.arlo_device, callback)

def start_candidate_answer_subscription(self):
def callback(candidate):
if self.rtc_session:
prefix = "a=candidate:"
if candidate.startswith(prefix):
candidate = candidate[len(prefix):]
#prefix = "a="
#if candidate.startswith(prefix):
# candidate = candidate[len(prefix):]
self.logger.info(f"Arlo response candidate: {candidate}")
asyncio.get_event_loop().create_task(self.rtc_session.addIceCandidate(
{ "candidate": candidate }
{ "candidate": candidate, "sdpMid": "0av", "sdpMLineIndex": 0 }
))
return self.stop_subscriptions

Expand All @@ -189,39 +196,45 @@ def callback(candidate):
async def startRTCSignalingSession(self, session):
self.logger.info("Starting RTC signaling")

self.rtc_session = session
session_id, ice_servers = self.provider.arlo.StartPushToTalk(self.arlo_basestation, self.arlo_device)

self.rtc_setup = {
"type": "offer",
"audio": {
"direction": "sendonly",
},
"configuration": {
"iceServers": [
dict(urls=ice["url"], credential=ice.get("credential"), username=ice.get("username"))
for ice in ice_servers
]
},
}
try:
self.rtc_session = session
self.rtc_answered = False
session_id, ice_servers = self.provider.arlo.StartPushToTalk(self.arlo_basestation, self.arlo_device)

self.rtc_setup = {
"type": "offer",
"audio": {
"direction": "sendonly",
},
"configuration": {
"iceServers": [
dict(urls=ice["url"], credential=ice.get("credential"), username=ice.get("username"))
for ice in ice_servers
]
},
}

async def on_ice_candidate(candidate):
self.logger.info(f"Arlo offer candidate: {candidate.candidate}")
self.provider.arlo.NotifyPushToTalkCandidate(self.arlo_basestation, self.arlo_device, session_id, candidate.candidate)
async def on_ice_candidate(candidate):
self.logger.info(f"Arlo offer candidate: {candidate.candidate}")
self.provider.arlo.NotifyPushToTalkCandidate(self.arlo_basestation, self.arlo_device, session_id, candidate.candidate)

offer = await session.createLocalDescription("offer", self.rtc_setup, on_ice_candidate)
self.logger.info(f"Arlo offer sdp: {offer.sdp}")
offer = await session.createLocalDescription("offer", self.rtc_setup, on_ice_candidate)
self.logger.info(f"Arlo offer sdp:\n{offer['sdp']}")

self.provider.arlo.NotifyPushToTalkSDP(self.arlo_basestation, self.arlo_device, session_id, offer.sdp)
self.provider.arlo.NotifyPushToTalkSDP(self.arlo_basestation, self.arlo_device, session_id, offer["sdp"])

return ArloCameraSpeakerSessionControl(self)
return ArloCameraSpeakerSessionControl(self)
except Exception as e:
self.logger.error(e, exc_info=True)

async def real_speaker(self):
return await scrypted_sdk.systemManager.api.getDeviceById(self.getScryptedProperty("id"))

def close(self):
self.logger.info("Closing speaker session")
self.rtc_session = None
self.rtc_setup = None
self.rtc_answered = False

class ArloCameraSpeakerSessionControl:
def __init__(self, speaker):
Expand Down

0 comments on commit 909341b

Please sign in to comment.