diff --git a/Makefile b/Makefile index 8ba1fa2..16b5815 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ doc: #pydoc -w ../arlo/arlo.py #mv arlo.html arlo_api_doc.md #git add arlo_api_doc.md - pdoc --overwrite --html --html-no-source --html-dir docs arlo.py + #pdoc --overwrite --html --html-no-source --html-dir docs arlo.py + pdoc -f --html -c show_source_code=False --output-dir docs arlo.py sed -i'.bak' 's/#sidebar{width:30%}#content{width:70%;/#sidebar{width:45%}#content{width:55%;/g' docs/arlo.html rm docs/arlo.html.bak python dev/html2text.py docs/arlo.html > docs/README.md diff --git a/docs/README.md b/docs/README.md index 76cc038..d568718 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# `arlo` module +# Module `arlo` Copyright 2016 Jeffrey D. Walter @@ -6,7 +6,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at -http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS ISBASIS, WITHOUT @@ -16,7 +16,7 @@ the License. ## Classes -` class Arlo ` +` class Arlo (username, password) ` @@ -28,12 +28,6 @@ the License. ### Methods -` def __init__(self, username, password) ` - - - -Initialize self. See help(type(self)) for accurate signature. - ` def AddFriend(self, firstname, lastname, email, devices={}, admin=False) ` @@ -61,11 +55,12 @@ email=False, push=False) ` -**`action`** : `disabled` `OR` `recordSnapshot` `OR` `recordVideo` - +action : disabled OR recordSnapshot OR recordVideo + ` def Arm(self, device) ` + ` def BatchDeleteRecordings(self, recordings) ` @@ -116,26 +111,24 @@ call. ` def Disarm(self, device) ` + ` def DownloadRecording(self, url, to) ` Writes a video to a given local file path. -**`url`** : `presignedContentUrl` - -**`to`** : `path` `where` `the` `file` `should` `be` `written` - +url: presignedContentUrl to: path where the file should be written + ` def DownloadSnapshot(self, url, to, chunk_size=4096) ` Writes a snapshot to a given local file path. -**`url`** : `presignedContentUrl` or `presignedFullFrameSnapshotUrl` - -**`to`** : `path` `where` `the` `file` `should` `be` `written` - +url: presignedContentUrl or presignedFullFrameSnapshotUrl to: path where the +file should be written + ` def Geofencing(self, location_id, active=True) ` @@ -149,24 +142,31 @@ calendar mode to inactive. ` def GetAudioPlayback(self, basestation) ` + ` def GetAutomationActivityZones(self, camera) ` + ` def GetAutomationDefinitions(self) ` + ` def GetBaseStationState(self, basestation) ` + ` def GetCalendar(self, basestation) ` + ` def GetCameraState(self, basestation) ` + ` def GetCameraTempReading(self, basestation) ` + ` def GetCvrPlaylist(self, camera, fromDate, toDate) ` @@ -176,9 +176,11 @@ This function downloads a Cvr Playlist file for the period fromDate to toDate. ` def GetDevice(self, device_name) ` + ` def GetDeviceCapabilities(self, device) ` + ` def GetDeviceSupport(self) ` @@ -401,9 +403,11 @@ default both types are returned. ` def GetEmergencyLocations(self) ` + ` def GetFriends(self) ` + ` def GetLibrary(self, from_date, to_date) ` @@ -430,6 +434,7 @@ XXXXXXXX", "reason": "motionRecord", "deviceId": "XXXXXXXXXXXXX", "createdBy": ` def GetLibraryMetaData(self, from_date, to_date) ` + ` def GetLocations(self) ` @@ -463,9 +468,11 @@ Schedules":[]}]} Set a schedule to be active: {"activeAutomations":[{"deviceId ` def GetOCProfile(self) ` + ` def GetPaymentBilling(self) ` + ` def GetPaymentOffers(self) ` @@ -490,9 +497,11 @@ UI anymore. ` def GetPaymentOffersV4(self) ` + ` def GetProfile(self) ` + ` def GetRecording(self, url, chunk_size=4096) ` @@ -502,15 +511,19 @@ Returns the whole video from the presignedContentUrl. ` def GetRules(self, basestation) ` + ` def GetSensorConfig(self, basestation) ` + ` def GetServiceLevel(self) ` + ` def GetServiceLevelSettings(self) ` + ` def GetServiceLevelV2(self) ` @@ -528,6 +541,7 @@ UI anymore. ` def GetServiceLevelV4(self) ` + ` def GetSession(self) ` @@ -542,12 +556,15 @@ true, "arlo": true, "dateCreated": 1463975008658 } ` def GetSmartAlerts(self, camera) ` + ` def GetSmartFeatures(self) ` + ` def GetUpdateFeatures(self) ` + ` def HandleEvents(self, basestation, callback, timeout=120) ` @@ -573,6 +590,7 @@ Wnt9F7D82uN1f4cXXXXX-FMUsWF_6tMBqwn6DpzOaIB7ciJrnr2QJyKewbQouGM6", ` def Logout(self) ` + ` def Notify(self, basestation, body) ` @@ -584,11 +602,9 @@ the Notify() call to interact with Arlo: ###### -**`NOTE`** : `While` `you` `can` `call` `Notify`() `directly`, `responses` `from` `these` `notify` `calls` `are` `sent` `to` `the` `EventStream` (`see` `Subscribe`()), - - -and so it's better to use the Get/Set methods that are implemented using the -NotifyAndGetResponse() method. +NOTE: While you can call Notify() directly, responses from these notify calls +are sent to the EventStream (see Subscribe()), and so it's better to use the +Get/Set methods that are implemented using the NotifyAndGetResponse() method. ###### @@ -655,12 +671,15 @@ Best Video, 2 = Optimized, 1 = Best Battery Life) motionSetupModeEnabled ` def NotifyAndGetResponse(self, basestation, body, timeout=120) ` + ` def PauseTrack(self, basestation) ` + ` def Ping(self, basestation) ` + ` def PlayTrack(self, basestation, track_id='2391d620-e491-4412-99f6-e9a40d6046ed', position=0) ` @@ -672,6 +691,7 @@ the same for all. ` def PushToTalk(self, camera) ` + ` def RemoveFriend(self, email) ` @@ -686,40 +706,52 @@ email: email of user you want to revoke access from. This API will resend an invitation email to a user that you've AddFriend'd. You will need to get the friend object by calling GetFriend() because it -includes a token that must be passed to this API. +includes a token that must be passed to this API. friend: {"ownerId":"XXX- +XXXXXXX","token":"really long string that you get from the GetFriends() +API","firstName":"John","lastName":"Doe","devices":{"XXX- +XXXXXXX_XXXXXXXXXXXX":"Camera1","XXX-XXXXXXX_XXXXXXXXXXXX":"Camera2"},"lastMod +ified":1548470485419,"adminUser":false,"email":"john.doe@example.com"} -**`friend`** : {`"ownerId"`:`"XXX`-`XXXXXXX"`,`"token"`:`"really` `long` `string` `that` `you` `get` `from` `the` `GetFriends`() `API"`,`"firstName"`:`"John"`,`"lastName"`:`"Doe"`,`"devices"`:{`"XXX`-`XXXXXXX_XXXXXXXXXXXX"`:`"Camera1"`,`"XXX`-`XXXXXXX_XXXXXXXXXXXX"`:`"Camera2"`},`"lastModified"`:`1548470485419`,`"adminUser"`:`false`,`"email"`:`"john.doe`@`example.com"`} - ` def Reset(self) ` + ` def RestartBasestation(self, basestation) ` + ` def SetAirQualityAlertOff(self, basestation) ` + ` def SetAirQualityAlertOn(self, basestation) ` + ` def SetAirQualityAlertThresholdMax(self, basestation, number=700) ` + ` def SetAirQualityAlertThresholdMin(self, basestation, number=400) ` + ` def SetAirQualityRecordingOff(self, basestation) ` + ` def SetAirQualityRecordingOn(self, basestation) ` + ` def SetAudioAlertsOff(self, basestation, sensitivity=3) ` + ` def SetAudioAlertsOn(self, basestation, sensitivity=3) ` + ` def SetAutomationActivityZones(self, camera, zone, coords, color) ` @@ -735,39 +767,51 @@ activity zone. color: 45136 - the color for your bounding box. ` def SetHumidityAlertOff(self, basestation) ` + ` def SetHumidityAlertOn(self, basestation) ` + ` def SetHumidityAlertThresholdMax(self, basestation, number=800) ` + ` def SetHumidityAlertThresholdMin(self, basestation, number=400) ` + ` def SetHumidityRecordingOff(self, basestation) ` + ` def SetHumidityRecordingOn(self, basestation) ` + ` def SetLoopBackModeContinuous(self, basestation) ` + ` def SetLoopBackModeSingleTrack(self, basestation) ` + ` def SetMotionAlertsOff(self, basestation, sensitivity=5) ` + ` def SetMotionAlertsOn(self, basestation, sensitivity=5) ` + ` def SetNightLightBrightness(self, basestation, level=200) ` + ` def SetNightLightColor(self, basestation, red=255, green=255, blue=255) ` + ` def SetNightLightMode(self, basestation, mode='rainbow') ` @@ -777,19 +821,24 @@ mode: rainbow or rgb. ` def SetNightLightOff(self, basestation) ` + ` def SetNightLightOn(self, basestation) ` + ` def SetNightLightTimerOff(self, basestation, time=0, timediff=300) ` -` def SetNightLightTimerOn(self, basestation, time=1585592475, timediff=0) ` + +` def SetNightLightTimerOn(self, basestation, time=1602803448, timediff=0) ` + ` def SetOCProfile(self, firstName, lastName, country='United States', language='en', spam_me=0) ` + ` def SetSchedule(self, basestation, schedule) ` @@ -815,48 +864,63 @@ watch the schema that gets sent. ` def SetShuffleOff(self, basestation) ` + ` def SetShuffleOn(self, basestation) ` + ` def SetSleepTimerOff(self, basestation, time=0, timediff=300) ` -` def SetSleepTimerOn(self, basestation, time=1585592475, timediff=0) ` + +` def SetSleepTimerOn(self, basestation, time=1602803448, timediff=0) ` + ` def SetTempAlertOff(self, basestation) ` + ` def SetTempAlertOn(self, basestation) ` + ` def SetTempAlertThresholdMax(self, basestation, number=240) ` + ` def SetTempAlertThresholdMin(self, basestation, number=200) ` + ` def SetTempRecordingOff(self, basestation) ` + ` def SetTempRecordingOn(self, basestation) ` + ` def SetTempUnit(self, uniqueId, unit='C') ` + ` def SetVolume(self, basestation, mute=False, volume=50) ` + ` def SirenOff(self, basestation) ` + ` def SirenOn(self, basestation) ` + ` def SkipTrack(self, basestation) ` + ` def StartRecording(self, basestation, camera) ` @@ -884,6 +948,7 @@ from GetDevices(). ` def StopStream(self, basestation, camera) ` + ` def StreamRecording(self, url, chunk_size=4096) ` @@ -891,8 +956,8 @@ from GetDevices(). Returns a generator that is the chunked video stream from the presignedContentUrl. -**`url`** : `presignedContentUrl` - +url: presignedContentUrl + ` def Subscribe(self, basestation) ` @@ -974,7 +1039,8 @@ NOTE: Use DownloadSnapshot() to download the actual image file. ` def UnPauseTrack(self, basestation) ` -` def Unsubscribe(self, basestation) ` + +` def Unsubscribe(self) ` @@ -984,6 +1050,7 @@ event_stream collection. ` def UpdateDeviceName(self, device, name) ` + ` def UpdateDisplayOrder(self, body) ` @@ -1008,15 +1075,19 @@ This is an example of the json you would pass in the body: { ` def UpdatePassword(self, password) ` + ` def UpdateProfile(self, first_name, last_name) ` + ` def genTransId(self, trans_type='web') ` + ` def interrupt_handler(self, signum, frame) ` + ` def to_timestamp(self, dt) ` @@ -1155,10 +1226,9 @@ This is an example of the json you would pass in the body: { * `UpdateFriend` * `UpdatePassword` * `UpdateProfile` - * `__init__` * `genTransId` * `interrupt_handler` * `to_timestamp` -Generated by [pdoc 0.5.1](https://pdoc3.github.io/pdoc). +Generated by [pdoc 0.9.1](https://pdoc3.github.io/pdoc). diff --git a/docs/arlo.html b/docs/arlo.html index ce7621c..ab995dd 100644 --- a/docs/arlo.html +++ b/docs/arlo.html @@ -3,27 +3,30 @@ - + arlo API documentation - - - - - + + + + + + + +
-

arlo module

+

Module arlo

Copyright 2016 Jeffrey D. Walter

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

-

http://www.apache.org/licenses/LICENSE-2.0

+

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS ISBASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -41,38 +44,32 @@

Classes

class Arlo +(username, password)
-
+

Class variables

var TRANSID_PREFIX
-
+

Methods

-
-def __init__(self, username, password) -
-
-

Initialize self. -See help(type(self)) for accurate signature.

-
def AddFriend(self, firstname, lastname, email, devices={}, admin=False)
-

This API will send an email to a user and if they accept, will give them access to the devices you specify. +

This API will send an email to a user and if they accept, will give them access to the devices you specify. NOTE: XXX-XXXXXXX_XXXXXXXXXXXX is the uniqueId field in your device object.

-

{adminUser:false,firstName:John,lastName:Doe,email:john.doe@example.com,devices:{XXX-XXXXXXX_XXXXXXXXXXXX:Camera1,XXX-XXXXXXX_XXXXXXXXXXXX:Camera2}}

+

{adminUser:false,firstName:John,lastName:Doe,email:john.doe@example.com,devices:{XXX-XXXXXXX_XXXXXXXXXXXX:Camera1,XXX-XXXXXXX_XXXXXXXXXXXX:Camera2}}

def AdjustBrightness(self, basestation, camera, brightness=0)
-

NOTE: Brightness is between -2 and 2 in increments of 1 (-2, -1, 0, 1, 2). +

NOTE: Brightness is between -2 and 2 in increments of 1 (-2, -1, 0, 1, 2). Setting it to an invalid value has no effect.

Returns: { @@ -84,28 +81,25 @@

Methods

"resource": "cameras/XXXXXXXXXXXXX", "to": "336-XXXXXXX_web", "transId": "web!XXXXXXXX.389518!1514956240683" -}

+}

-def AlertNotificationMethods(self, basestation, action='disabled', email=False, push=False) +def AlertNotificationMethods(self, basestation, action='disabled', email=False, push=False)
-
-
action : disabled OR recordSnapshot OR recordVideo
-
 
-
+

action : disabled OR recordSnapshot OR recordVideo

def Arm(self, device)
-
+
def BatchDeleteRecordings(self, recordings)
-

Delete a batch of video recordings from Arlo.

+

Delete a batch of video recordings from Arlo.

The GetLibrary() call response json can be passed directly to this method if you'd like to delete the same list of videos you queried for. If you want to delete some other batch of videos, then you need to send an array of objects representing each video you want to delete.

[ @@ -119,138 +113,130 @@

Methods

"utcCreatedDate":1473010280395, "deviceId":"XXXXXXXXXXXXX" } -]

+]

def Calendar(self, basestation, active=True)
-

DEPRECATED: This API appears to still do stuff, but I don't see it called in the web UI anymore when switching the mode to a schedule.

+

DEPRECATED: This API appears to still do stuff, but I don't see it called in the web UI anymore when switching the mode to a schedule.

NOTE: The Arlo API seems to disable calendar mode when switching to other modes, if it's enabled. -You should probably do the same, although, the UI reflects the switch from calendar mode to say armed mode without explicitly setting calendar mode to inactive.

+You should probably do the same, although, the UI reflects the switch from calendar mode to say armed mode without explicitly setting calendar mode to inactive.

def CustomMode(self, device, mode, schedules=[])
-

device can be any object that has parentId == deviceId. i.e., not a camera

+

device can be any object that has parentId == deviceId. i.e., not a camera

def DeleteMode(self, device, mode)
-

device can be any object that has parentId == deviceId. i.e., not a camera

+

device can be any object that has parentId == deviceId. i.e., not a camera

def DeleteRecording(self, recording)
-

Delete a single video recording from Arlo. -All of the date info and device id you need to pass into this method are given in the results of the GetLibrary() call.

+

Delete a single video recording from Arlo. +All of the date info and device id you need to pass into this method are given in the results of the GetLibrary() call.

def Disarm(self, device)
-
+
def DownloadRecording(self, url, to)
-

Writes a video to a given local file path.

-
-
url : presignedContentUrl
-
 
-
to : path where the file should be written
-
 
-
+

Writes a video to a given local file path.

+

url: presignedContentUrl +to: path where the file should be written

def DownloadSnapshot(self, url, to, chunk_size=4096)
-

Writes a snapshot to a given local file path.

-
-
url : presignedContentUrl or presignedFullFrameSnapshotUrl
-
 
-
to : path where the file should be written
-
 
-
+

Writes a snapshot to a given local file path.

+

url: presignedContentUrl or presignedFullFrameSnapshotUrl +to: path where the file should be written

def Geofencing(self, location_id, active=True)
-

Get location_id is the id field from the return of GetLocations() +

Get location_id is the id field from the return of GetLocations() NOTE: The Arlo API seems to disable geofencing mode when switching to other modes, if it's enabled. -You should probably do the same, although, the UI reflects the switch from calendar mode to say armed mode without explicitly setting calendar mode to inactive.

+You should probably do the same, although, the UI reflects the switch from calendar mode to say armed mode without explicitly setting calendar mode to inactive.

def GetAudioPlayback(self, basestation)
-
+
def GetAutomationActivityZones(self, camera)
-
+
def GetAutomationDefinitions(self)
-
+
def GetBaseStationState(self, basestation)
-
+
def GetCalendar(self, basestation)
-
+
def GetCameraState(self, basestation)
-
+
def GetCameraTempReading(self, basestation)
-
+
def GetCvrPlaylist(self, camera, fromDate, toDate)
-

This function downloads a Cvr Playlist file for the period fromDate to toDate.

+

This function downloads a Cvr Playlist file for the period fromDate to toDate.

def GetDevice(self, device_name)
-
+
def GetDeviceCapabilities(self, device)
-
+
def GetDeviceSupport(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

This API looks like it's mainly used by the website, but I'm including it for completeness sake. It returns something like the following: { @@ -293,13 +279,13 @@

Methods

} } ] -}

+}

def GetDeviceSupportV3(self)
-

This is the latest version of the device support api. +

This is the latest version of the device support api. It returns something like the following: { "data": { @@ -457,13 +443,13 @@

Methods

} }, "success":true -}

+}

def GetDeviceSupportv2(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

It returns something like the following: { "devices": [ @@ -645,33 +631,33 @@

Methods

"selectLights": "selectBgLt.html" }, "baseUrl": "https://vzs3-prod-common.s3.amazonaws.com/static/v2/html/en/" -}

+}

def GetDevices(self, device_type=None, filter_provisioned=None)
-

This method returns an array that contains the basestation, cameras, etc. and their metadata. +

This method returns an array that contains the basestation, cameras, etc. and their metadata. If you pass in a valid device type, as a string or a list, this method will return an array of just those devices that match that type. An example would be ['basestation', 'camera'] -To filter provisioned or unprovisioned devices pass in a True/False value for filter_provisioned. By default both types are returned.

+To filter provisioned or unprovisioned devices pass in a True/False value for filter_provisioned. By default both types are returned.

def GetEmergencyLocations(self)
-
+
def GetFriends(self)
-
+
def GetLibrary(self, from_date, to_date)
-

This call returns the following: +

This call returns the following: presignedContentUrl is a link to the actual video in Amazon AWS. presignedThumbnailUrl is a link to the thumbnail .jpg of the actual video in Amazon AWS.

[ @@ -693,19 +679,19 @@

Methods

"currentState": "new", "mediaDuration": "00:00:30" } -]

+]

def GetLibraryMetaData(self, from_date, to_date)
-
+
def GetLocations(self)
-

This call returns the following: +

This call returns the following: { "id":"XXX-XXXXXXX_20160823042047", "name":"Home", @@ -727,117 +713,117 @@

Methods

"pushNotifyDevices":[ "XXXXXXXXXX" ] -}

+}

def GetModes(self, basestation)
-

DEPRECATED: This is the older API for getting the "mode". It still works, but GetModesV2 is the way the Arlo software does it these days.

+

DEPRECATED: This is the older API for getting the "mode". It still works, but GetModesV2 is the way the Arlo software does it these days.

def GetModesV2(self)
-

This is the newer API for getting the "mode". This method also returns the schedules. +

This is the newer API for getting the "mode". This method also returns the schedules. Set a non-schedule mode to be active: {"activeAutomations":[{"deviceId":"XXXXXXXXXXXXX","timestamp":1532015622105,"activeModes":["mode1"],"activeSchedules":[]}]} -Set a schedule to be active: {"activeAutomations":[{"deviceId":"XXXXXXXXXXXXX","timestamp":1532015790139,"activeModes":[],"activeSchedules":["schedule.1"]}]}

+Set a schedule to be active: {"activeAutomations":[{"deviceId":"XXXXXXXXXXXXX","timestamp":1532015790139,"activeModes":[],"activeSchedules":["schedule.1"]}]}

def GetOCProfile(self)
-
+
def GetPaymentBilling(self)
-
+
def GetPaymentOffers(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

def GetPaymentOffersV2(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

def GetPaymentOffersV3(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

def GetPaymentOffersV4(self)
-
+
def GetProfile(self)
-
+
def GetRecording(self, url, chunk_size=4096)
-

Returns the whole video from the presignedContentUrl.

+

Returns the whole video from the presignedContentUrl.

def GetRules(self, basestation)
-
+
def GetSensorConfig(self, basestation)
-
+
def GetServiceLevel(self)
-
+
def GetServiceLevelSettings(self)
-
+
def GetServiceLevelV2(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

def GetServiceLevelV3(self)
-

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

+

DEPRECATED: This API still works, but I don't see it being called in the web UI anymore.

def GetServiceLevelV4(self)
-
+
def GetSession(self)
-

Returns something like the following: +

Returns something like the following: { "userId": "XXX-XXXXXXX", "email": "jeffreydwalter@gmail.com", @@ -851,38 +837,38 @@

Methods

"validEmail": true, "arlo": true, "dateCreated": 1463975008658 -}

+}

def GetSmartAlerts(self, camera)
-
+
def GetSmartFeatures(self)
-
+
def GetUpdateFeatures(self)
-
+
def HandleEvents(self, basestation, callback, timeout=120)
-

Use this method to subscribe to the event stream and provide a callback that will be called for event event received. -This function will allow you to potentially write a callback that can handle all of the events received from the event stream.

+

Use this method to subscribe to the event stream and provide a callback that will be called for event event received. +This function will allow you to potentially write a callback that can handle all of the events received from the event stream.

def Login(self, username, password)
-

This call returns the following: +

This call returns the following: { "userId":"XXX-XXXXXXX", "email":"user@example.com", @@ -895,26 +881,23 @@

Methods

"tocUpdate":false, "policyUpdate":false, "validEmail":true -}

+}

def Logout(self)
-
+
def Notify(self, basestation, body)
-

The following are examples of the json you would need to pass in the body of the Notify() call to interact with Arlo:

+

The following are examples of the json you would need to pass in the body of the Notify() call to interact with Arlo:

-
-
NOTE : While you can call Notify() directly, responses from these notify calls are sent to the EventStream (see Subscribe()),
-
 
-
-

and so it's better to use the Get/Set methods that are implemented using the NotifyAndGetResponse() method.

+

NOTE: While you can call Notify() directly, responses from these notify calls are sent to the EventStream (see Subscribe()), +and so it's better to use the Get/Set methods that are implemented using the NotifyAndGetResponse() method.

Set System Mode (Armed, Disarmed) - {"from":"XXX-XXXXXXX_web","to":"XXXXXXXXXXXXX","action":"set","resource":"modes","transId":"web!XXXXXXXX.XXXXXXXXXXXXXXXXXXXX","publishResponse":true,"properties":{"active":"mode0"}} @@ -940,239 +923,236 @@

nightVisionMode (int) - Night Mode Enabled/Disabled (1, 0) powerSaveMode (int) - PowerSaver Mode (3 = Best Video, 2 = Optimized, 1 = Best Battery Life) motionSetupModeEnabled (bool) - Motion Detection Setup Enabled/Disabled -motionSetupModeSensitivity (int 0-100) - Motion Detection Sensitivity

+motionSetupModeSensitivity (int 0-100) - Motion Detection Sensitivity

def NotifyAndGetResponse(self, basestation, body, timeout=120)
-
+
def PauseTrack(self, basestation)
-
+
def Ping(self, basestation)
-
+
-def PlayTrack(self, basestation, track_id='2391d620-e491-4412-99f6-e9a40d6046ed', position=0) +def PlayTrack(self, basestation, track_id='2391d620-e491-4412-99f6-e9a40d6046ed', position=0)
-

Defaulting to 'hugh little baby', which is a supplied track. I hope the ID is the same for all.

+

Defaulting to 'hugh little baby', which is a supplied track. I hope the ID is the same for all.

def PushToTalk(self, camera)
-
+
def RemoveFriend(self, email)
-

Removes a person you've granted access to.

-

email: email of user you want to revoke access from.

+

Removes a person you've granted access to.

+

email: email of user you want to revoke access from.

def ResendFriendInvite(self, friend)
-
-
This API will resend an invitation email to a user that you've AddFriend'd. You will need to get the friend object by calling GetFriend() because it includes a token that must be passed to this API.
-
friend : {"ownerId":"XXX-XXXXXXX","token":"really long string that you get from the GetFriends() API","firstName":"John","lastName":"Doe","devices":{"XXX-XXXXXXX_XXXXXXXXXXXX":"Camera1","XXX-XXXXXXX_XXXXXXXXXXXX":"Camera2"},"lastModified":1548470485419,"adminUser":false,"email":"john.doe@example.com"}
-
 
-
+

This API will resend an invitation email to a user that you've AddFriend'd. You will need to get the friend object by calling GetFriend() because it includes a token that must be passed to this API. +friend: {"ownerId":"XXX-XXXXXXX","token":"really long string that you get from the GetFriends() API","firstName":"John","lastName":"Doe","devices":{"XXX-XXXXXXX_XXXXXXXXXXXX":"Camera1","XXX-XXXXXXX_XXXXXXXXXXXX":"Camera2"},"lastModified":1548470485419,"adminUser":false,"email":"john.doe@example.com"}

def Reset(self)
-
+
def RestartBasestation(self, basestation)
-
+
def SetAirQualityAlertOff(self, basestation)
-
+
def SetAirQualityAlertOn(self, basestation)
-
+
def SetAirQualityAlertThresholdMax(self, basestation, number=700)
-
+
def SetAirQualityAlertThresholdMin(self, basestation, number=400)
-
+
def SetAirQualityRecordingOff(self, basestation)
-
+
def SetAirQualityRecordingOn(self, basestation)
-
+
def SetAudioAlertsOff(self, basestation, sensitivity=3)
-
+
def SetAudioAlertsOn(self, basestation, sensitivity=3)
-
+
def SetAutomationActivityZones(self, camera, zone, coords, color)
-

An activity zone is the area you draw in your video in the UI to tell Arlo what part of the scene to "watch". +

An activity zone is the area you draw in your video in the UI to tell Arlo what part of the scene to "watch". This method takes 4 arguments. camera: the camera you want to set an activity zone for. name: "Zone 1" - the name of your activity zone. coords: [{"x":0.37946943483275664,"y":0.3790983606557377},{"x":0.8685121107266436,"y":0.3790983606557377},{"x":0.8685121107266436,"y":1},{"x":0.37946943483275664,"y":1}] - these coordinates are the bonding box for the activity zone. -color: 45136 - the color for your bounding box.

+color: 45136 - the color for your bounding box.

def SetHumidityAlertOff(self, basestation)
-
+
def SetHumidityAlertOn(self, basestation)
-
+
def SetHumidityAlertThresholdMax(self, basestation, number=800)
-
+
def SetHumidityAlertThresholdMin(self, basestation, number=400)
-
+
def SetHumidityRecordingOff(self, basestation)
-
+
def SetHumidityRecordingOn(self, basestation)
-
+
def SetLoopBackModeContinuous(self, basestation)
-
+
def SetLoopBackModeSingleTrack(self, basestation)
-
+
def SetMotionAlertsOff(self, basestation, sensitivity=5)
-
+
def SetMotionAlertsOn(self, basestation, sensitivity=5)
-
+
def SetNightLightBrightness(self, basestation, level=200)
-
+
def SetNightLightColor(self, basestation, red=255, green=255, blue=255)
-
+
-def SetNightLightMode(self, basestation, mode='rainbow') +def SetNightLightMode(self, basestation, mode='rainbow')
-

mode: rainbow or rgb.

+

mode: rainbow or rgb.

def SetNightLightOff(self, basestation)
-
+
def SetNightLightOn(self, basestation)
-
+
def SetNightLightTimerOff(self, basestation, time=0, timediff=300)
-
+
-def SetNightLightTimerOn(self, basestation, time=1585592475, timediff=0) +def SetNightLightTimerOn(self, basestation, time=1602803448, timediff=0)
-
+
-def SetOCProfile(self, firstName, lastName, country='United States', language='en', spam_me=0) +def SetOCProfile(self, firstName, lastName, country='United States', language='en', spam_me=0)
-
+
def SetSchedule(self, basestation, schedule)
-

The following json is what was sent to the API when I edited my schedule. It contains all of the data necessary to configure a whole week. It's a little convoluted, but you can just play around with the scheduler in Chrome and watch the schema that gets sent.

+

The following json is what was sent to the API when I edited my schedule. It contains all of the data necessary to configure a whole week. It's a little convoluted, but you can just play around with the scheduler in Chrome and watch the schema that gets sent.

{ "schedule": [ { @@ -1263,142 +1243,139 @@

"name": "", "id": "schedule.1", "enabled": true -}

+}

def SetShuffleOff(self, basestation)
-
+
def SetShuffleOn(self, basestation)
-
+
def SetSleepTimerOff(self, basestation, time=0, timediff=300)
-
+
-def SetSleepTimerOn(self, basestation, time=1585592475, timediff=0) +def SetSleepTimerOn(self, basestation, time=1602803448, timediff=0)
-
+
def SetTempAlertOff(self, basestation)
-
+
def SetTempAlertOn(self, basestation)
-
+
def SetTempAlertThresholdMax(self, basestation, number=240)
-
+
def SetTempAlertThresholdMin(self, basestation, number=200)
-
+
def SetTempRecordingOff(self, basestation)
-
+
def SetTempRecordingOn(self, basestation)
-
+
-def SetTempUnit(self, uniqueId, unit='C') +def SetTempUnit(self, uniqueId, unit='C')
-
+
def SetVolume(self, basestation, mute=False, volume=50)
-
+
def SirenOff(self, basestation)
-
+
def SirenOn(self, basestation)
-
+
def SkipTrack(self, basestation)
-
+
def StartRecording(self, basestation, camera)
-

This function causes the camera to start recording. -You can get the timezone from GetDevices().

+

This function causes the camera to start recording. +You can get the timezone from GetDevices().

def StartStream(self, basestation, camera)
-

This function returns the url of the rtsp video stream. +

This function returns the url of the rtsp video stream. This stream needs to be called within 30 seconds or else it becomes invalid. It can be streamed with: ffmpeg -re -i 'rtsps://' -acodec copy -vcodec copy test.mp4 -The request to /users/devices/startStream returns: { url:rtsp://:443/vzmodulelive?egressToken=b&userAgent=iOS&cameraId=}

+The request to /users/devices/startStream returns: { url:rtsp://:443/vzmodulelive?egressToken=b&userAgent=iOS&cameraId=}

def StopRecording(self, camera)
-

This function causes the camera to stop recording. -You can get the timezone from GetDevices().

+

This function causes the camera to stop recording. +You can get the timezone from GetDevices().

def StopStream(self, basestation, camera)
-
+
def StreamRecording(self, url, chunk_size=4096)
-

Returns a generator that is the chunked video stream from the presignedContentUrl.

-
-
url : presignedContentUrl
-
 
-
+

Returns a generator that is the chunked video stream from the presignedContentUrl.

+

url: presignedContentUrl

def Subscribe(self, basestation)
-

Arlo uses the EventStream interface in the browser to do pub/sub style messaging. +

Arlo uses the EventStream interface in the browser to do pub/sub style messaging. Unfortunately, this appears to be the only way Arlo communicates these messages.

This function makes the initial GET request to /subscribe, which returns the EventStream socket. Once we have that socket, the API requires a POST request to /notify with the "subscriptionsresource. @@ -1407,76 +1384,76 @@

Since this interface is asynchronous, and this is a quick and dirty hack to get this working, I'm using a thread to listen to the EventStream. This thread puts events into a queue. Some polling is required (see NotifyAndGetResponse()) because the event messages aren't guaranteed to be delivered in any specific order, but I wanted to maintain a synchronous style API.

-

You generally shouldn't need to call Subscribe() directly, although I'm leaving it "publicfor now.

+

You generally shouldn't need to call Subscribe() directly, although I'm leaving it "publicfor now.

def SubscribeToMotionEvents(self, basestation, callback, timeout=120)
-

Use this method to subscribe to motion events. You must provide a callback function which will get called once per motion event.

+

Use this method to subscribe to motion events. You must provide a callback function which will get called once per motion event.

The callback function should have the following signature: def callback(self, event)

This is an example of handling a specific event, in reality, you'd probably want to write a callback for HandleEvents() -that has a big switch statement in it to handle all the various events Arlo produces.

+that has a big switch statement in it to handle all the various events Arlo produces.

def ToggleCamera(self, basestation, camera, active=True)
-

active: True - Camera is off. -active: False - Camera is on.

+

active: True - Camera is off. +active: False - Camera is on.

def TriggerAndHandleEvent(self, basestation, trigger, callback, timeout=120)
-

Use this method to subscribe to the event stream and provide a callback that will be called for event event received. +

Use this method to subscribe to the event stream and provide a callback that will be called for event event received. This function will allow you to potentially write a callback that can handle all of the events received from the event stream. -NOTE: Use this function if you need to run some code after subscribing to the eventstream, but before your callback to handle the events runs.

+NOTE: Use this function if you need to run some code after subscribing to the eventstream, but before your callback to handle the events runs.

def TriggerFullFrameSnapshot(self, basestation, camera)
-

This function causes the camera to record a fullframe snapshot. +

This function causes the camera to record a fullframe snapshot. The presignedFullFrameSnapshotUrl url is returned. -Use DownloadSnapshot() to download the actual image file.

+Use DownloadSnapshot() to download the actual image file.

def TriggerStreamSnapshot(self, basestation, camera)
-

This function causes the camera to snapshot while recording. +

This function causes the camera to snapshot while recording. NOTE: You MUST call StartStream() before calling this function. If you call StartStream(), you have to start reading data from the stream, or streaming will be cancelled and taking a snapshot may fail (since it requires the stream to be active).

NOTE: You should not use this function is you just want a snapshot and aren't intending to stream. Use TriggerFullFrameSnapshot() instead.

-

NOTE: Use DownloadSnapshot() to download the actual image file.

+

NOTE: Use DownloadSnapshot() to download the actual image file.

def UnPauseTrack(self, basestation)
-
+
-def Unsubscribe(self, basestation) +def Unsubscribe(self)
-

This method stops the EventStream subscription and removes it from the event_stream collection.

+

This method stops the EventStream subscription and removes it from the event_stream collection.

def UpdateDeviceName(self, device, name)
-
+
def UpdateDisplayOrder(self, body)
-

This is an example of the json you would pass in the body to UpdateDisplayOrder() of your devices in the UI.

+

This is an example of the json you would pass in the body to UpdateDisplayOrder() of your devices in the UI.

XXXXXXXXXXXXX is the device id of each camera. You can get this from GetDevices(). { "devices":{ @@ -1484,13 +1461,13 @@

"XXXXXXXXXXXXX":2, "XXXXXXXXXXXXX":3 } -}

+}

def UpdateFriend(self, body)
-

This is an example of the json you would pass in the body: +

This is an example of the json you would pass in the body: { "firstName":"Some", "lastName":"Body", @@ -1503,37 +1480,37 @@

"adminUser":true, "email":"user@example.com", "id":"XXX-XXXXXXX" -}

+}

def UpdatePassword(self, password)
-
+
def UpdateProfile(self, first_name, last_name)
-
+
-def genTransId(self, trans_type='web') +def genTransId(self, trans_type='web')
-
+
def interrupt_handler(self, signum, frame)
-
+
def to_timestamp(self, dt)
-
+
@@ -1550,7 +1527,7 @@

Index

diff --git a/setup.py b/setup.py index 7cf4b6f..fe7a1a8 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ def readme(): setup( name='arlo', py_modules=['arlo', 'request', 'eventstream'], - version='1.2.35', + version='1.2.38', description='Python Arlo is a library written in Python 2.7/3x ' + 'which exposes the Netgear Arlo cameras via the apis that are consumed by their website.', long_description=readme(),