mirror of
https://github.com/koush/scrypted.git
synced 2026-02-12 18:12:04 +00:00
Merge branch 'main' of github.com:koush/scrypted
This commit is contained in:
6
plugins/arlo/package-lock.json
generated
6
plugins/arlo/package-lock.json
generated
@@ -1,19 +1,19 @@
|
||||
{
|
||||
"name": "@scrypted/arlo",
|
||||
"version": "0.2.9",
|
||||
"version": "0.2.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/arlo",
|
||||
"version": "0.2.9",
|
||||
"version": "0.2.13",
|
||||
"devDependencies": {
|
||||
"@scrypted/sdk": "file:../../sdk"
|
||||
}
|
||||
},
|
||||
"../../sdk": {
|
||||
"name": "@scrypted/sdk",
|
||||
"version": "0.0.192",
|
||||
"version": "0.0.196",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/arlo",
|
||||
"version": "0.2.9",
|
||||
"version": "0.2.13",
|
||||
"description": "Arlo Plugin for Scrypted",
|
||||
"keywords": [
|
||||
"scrypted",
|
||||
|
||||
@@ -94,6 +94,7 @@ class Arlo(object):
|
||||
def UseExistingAuth(self, user_id, headers):
|
||||
self.user_id = user_id
|
||||
self.request.session.headers.update(headers)
|
||||
self.BASE_URL = 'myapi.arlo.com'
|
||||
|
||||
def LoginMFA(self):
|
||||
self.request = Request()
|
||||
@@ -1580,7 +1581,7 @@ class Arlo(object):
|
||||
return await self.TriggerAndHandleEvent(basestation, resource, ["is"], trigger, callback)
|
||||
|
||||
def StopStream(self, basestation, camera):
|
||||
return self.request.post(f'https://{self.BASE_URL}/hmsweb/users/devices/stopStream', {"to":camera.get('parentId'),"from":self.user_id+"_web","resource":"cameras/"+camera. get('deviceId'),"action":"set","responseUrl":"", "publishResponse":True,"transId":self.genTransId(),"properties":{"activityState":"stopUserStream","cameraId":camera.get('deviceId')}}, headers={"xcloudId": camera.get('xCloudId')})
|
||||
return self.request.post(f'https://{self.BASE_URL}/hmsweb/users/devices/stopStream', {"to":camera.get('parentId'),"from":self.user_id+"_web","resource":"cameras/"+camera.get('deviceId'),"action":"set","responseUrl":"", "publishResponse":True,"transId":self.genTransId(),"properties":{"activityState":"stopUserStream","cameraId":camera.get('deviceId')}}, headers={"xcloudId": camera.get('xCloudId')})
|
||||
|
||||
# nonlocal variable hack for Python 2.x.
|
||||
class nl:
|
||||
@@ -1630,15 +1631,19 @@ class Arlo(object):
|
||||
resource = f"cameras/{camera.get('deviceId')}"
|
||||
|
||||
def trigger(self):
|
||||
self.request.post("https://my.arlo.com/hmsweb/users/devices/fullFrameSnapshot", {"to":camera.get("parentId"),"from":self.user_id+"_web","resource":"cameras/"+camera.get("deviceId"),"action":"set","publishResponse":True,"transId":self.genTransId(),"properties":{"activityState":"fullFrameSnapshot"}}, headers={"xcloudId":camera.get("xCloudId")})
|
||||
self.request.post(f"https://{self.BASE_URL}/hmsweb/users/devices/fullFrameSnapshot", {"to":camera.get("parentId"),"from":self.user_id+"_web","resource":"cameras/"+camera.get("deviceId"),"action":"set","publishResponse":True,"transId":self.genTransId(),"properties":{"activityState":"fullFrameSnapshot"}}, headers={"xcloudId":camera.get("xCloudId")})
|
||||
|
||||
def callback(self, event):
|
||||
url = event.get("properties", {}).get("presignedFullFrameSnapshotUrl")
|
||||
properties = event.get("properties", {})
|
||||
url = properties.get("presignedFullFrameSnapshotUrl")
|
||||
if url:
|
||||
return url
|
||||
url = properties.get("presignedLastImageUrl")
|
||||
if url:
|
||||
return url
|
||||
return None
|
||||
|
||||
return await self.TriggerAndHandleEvent(basestation, resource, ["fullFrameSnapshotAvailable", "is"], trigger, callback)
|
||||
return await self.TriggerAndHandleEvent(basestation, resource, ["fullFrameSnapshotAvailable", "lastImageSnapshotAvailable", "is"], trigger, callback)
|
||||
|
||||
# def StartRecording(self, basestation, camera):
|
||||
# """
|
||||
|
||||
@@ -32,7 +32,7 @@ from .logging import logger
|
||||
|
||||
class EventStream:
|
||||
"""This class provides a queue-based EventStream object."""
|
||||
def __init__(self, arlo, expire=15):
|
||||
def __init__(self, arlo, expire=30):
|
||||
self.event_stream = None
|
||||
self.initializing = True
|
||||
self.connected = False
|
||||
|
||||
@@ -2,11 +2,12 @@ import asyncio
|
||||
|
||||
import scrypted_sdk
|
||||
from scrypted_sdk import ScryptedDeviceBase
|
||||
from scrypted_sdk.types import Camera, VideoCamera, MotionSensor, Battery, Refresh, ScryptedMimeTypes
|
||||
from scrypted_sdk.types import Camera, VideoCamera, MotionSensor, Battery, ScryptedMimeTypes
|
||||
|
||||
from .logging import ScryptedDeviceLoggerMixin
|
||||
|
||||
class ArloCamera(ScryptedDeviceBase, Camera, VideoCamera, MotionSensor, Battery, Refresh, ScryptedDeviceLoggerMixin):
|
||||
class ArloCamera(ScryptedDeviceBase, Camera, VideoCamera, MotionSensor, Battery, ScryptedDeviceLoggerMixin):
|
||||
timeout = 30
|
||||
nativeId = None
|
||||
arlo_device = None
|
||||
arlo_basestation = None
|
||||
@@ -22,7 +23,7 @@ class ArloCamera(ScryptedDeviceBase, Camera, VideoCamera, MotionSensor, Battery,
|
||||
self.provider = provider
|
||||
self.logger.setLevel(self.provider.get_current_log_level())
|
||||
|
||||
self.update_device_details(arlo_device)
|
||||
self._update_device_details(arlo_device)
|
||||
|
||||
self.stop_motion_subscription = False
|
||||
self.start_motion_subscription()
|
||||
@@ -49,7 +50,7 @@ class ArloCamera(ScryptedDeviceBase, Camera, VideoCamera, MotionSensor, Battery,
|
||||
self.logger.info("Getting snapshot from prebuffer")
|
||||
return await real_device.getVideoStream({"refresh": False})
|
||||
|
||||
pic_url = await asyncio.wait_for(self.provider.arlo.TriggerFullFrameSnapshot(self.arlo_basestation, self.arlo_device), timeout=30)
|
||||
pic_url = await asyncio.wait_for(self.provider.arlo.TriggerFullFrameSnapshot(self.arlo_basestation, self.arlo_device), timeout=self.timeout)
|
||||
self.logger.debug(f"Got snapshot URL for at {pic_url}")
|
||||
|
||||
if pic_url is None:
|
||||
@@ -78,29 +79,10 @@ class ArloCamera(ScryptedDeviceBase, Camera, VideoCamera, MotionSensor, Battery,
|
||||
async def getVideoStream(self, options=None):
|
||||
self.logger.info("Requesting stream")
|
||||
|
||||
rtsp_url = await asyncio.wait_for(self.provider.arlo.StartStream(self.arlo_basestation, self.arlo_device), timeout=30)
|
||||
rtsp_url = await asyncio.wait_for(self.provider.arlo.StartStream(self.arlo_basestation, self.arlo_device), timeout=self.timeout)
|
||||
self.logger.debug(f"Got stream URL at {rtsp_url}")
|
||||
|
||||
return await scrypted_sdk.mediaManager.createMediaObject(str.encode(rtsp_url), ScryptedMimeTypes.Url.value)
|
||||
|
||||
async def getRefreshFrequency(self):
|
||||
return 60
|
||||
|
||||
async def refresh(self, refreshInterface, userInitiated):
|
||||
self.logger.info(f"{refreshInterface} requested refresh" + userInitiated * " (user initiated)")
|
||||
|
||||
devices = self.provider.arlo.GetDevices('camera')
|
||||
arlo_device = None
|
||||
for device in devices:
|
||||
if device["deviceId"] == self.nativeId:
|
||||
arlo_device = device
|
||||
break
|
||||
|
||||
if arlo_device is None:
|
||||
raise Exception(f"Device {self.nativeId} not found in GetDevices call to Arlo")
|
||||
|
||||
self.update_device_details(arlo_device)
|
||||
self.arlo_device = arlo_device
|
||||
|
||||
def update_device_details(self, arlo_device):
|
||||
def _update_device_details(self, arlo_device):
|
||||
self.batteryLevel = arlo_device["properties"].get("batteryLevel")
|
||||
@@ -93,13 +93,13 @@ class ArloProvider(ScryptedDeviceBase, Settings, DeviceProvider, DeviceDiscovery
|
||||
headers = self.arlo_auth_headers
|
||||
if headers:
|
||||
self._arlo.UseExistingAuth(self.arlo_user_id, json.loads(headers))
|
||||
self.logger.info(f"Initialized Arlo client for {self.arlo_username}, reusing stored auth headers")
|
||||
self.logger.info(f"Initialized Arlo client, reusing stored auth headers")
|
||||
|
||||
asyncio.get_event_loop().create_task(self.do_arlo_setup())
|
||||
return self._arlo
|
||||
else:
|
||||
self._arlo_mfa_complete_auth = self._arlo.LoginMFA()
|
||||
self.logger.info(f"Initialized Arlo client for {self.arlo_username}, waiting for MFA code")
|
||||
self.logger.info(f"Initialized Arlo client, waiting for MFA code")
|
||||
return None
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error initializing Arlo client: {type(e)} with message {str(e)}")
|
||||
@@ -219,7 +219,6 @@ class ArloProvider(ScryptedDeviceBase, Settings, DeviceProvider, DeviceDiscovery
|
||||
ScryptedInterface.VideoCamera.value,
|
||||
ScryptedInterface.Camera.value,
|
||||
ScryptedInterface.MotionSensor.value,
|
||||
ScryptedInterface.Refresh.value,
|
||||
],
|
||||
"type": ScryptedDeviceType.Camera.value,
|
||||
"providerNativeId": self.nativeId,
|
||||
|
||||
Reference in New Issue
Block a user