# Pyaarlo
## Alpha Build
Welcome to the Pyaarlo alpha build. I'm using the 0.8.x stream to split
`pyaarlo` out from `hass-aarlo`. This is partly motivated by thinking about
getting `hass-aarlo` back into Home Assistant and partly motivated by my
desire to stop having to commit bug fixes in 2 places.
### Breaking Changes
#### Cached Session
The code will now save the session details and reuse the authentication token
when possible. This can drastically reduce the number of authentication
requests the code will make (and 2FA requests if needed). If this doesn't work
for you pass `save_session=False` as a parameter to `PyArlo()`.
## Table of Contents
- [Introduction](#introduction)
- [Installation](#installation)
- [Usage](#usage)
- [Pyaarlo Executable](#executable)
- [User Agent](#user-agent)
- [Saving Media](#saving-media)
- [2 Factor Authentication](#2fa)
* [Manual](#2fa-manual)
* [IMAP](#2fa-imap)
- [Error Reporting](#errors)
- [Limitations](#limitations)
- [Other 2 Factor Authentication](#2fa-other)
<a name="introduction"></a>
## Introduction
Pyaarlo is a module for Python that provides asynchronous access to Netgear
Arlo cameras.
When you start Pyaarlo, it starts a background thread that opens a single,
persistent connection, an *event stream*, to the Arlo servers. As things happen
to the Arlo devices - motion detected, battery level changes, mode changes,
etc... - the Arlo servers post these events onto the event stream. The
background thread reads these events from the stream, updates Pyaarlo's internal
state and calls any user registered callbacks.
#### Differences from Pyarlo
The biggest difference is Pyaarlo defaults to asynchronous mode by default. The
following code brought from Pyarlo might not work:
```python
base.mode = 'armed'
if base.mode == 'armed':
print('it worked!')
```
This is because between setting `mode` and reading `mode` the code has to:
* build and send a mode change packet to Arlo
* read the mode change packet back from the Arlo event stream
* update its internal state for `base`
I say "might" not work because it might work, it all depends on timing, and
context switches and network speed...
To enable synchronous mode you need to specify it when starting PyArlo.
```python
# login, use console for 2FA if needed
arlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,
tfa_type='SMS',tfa_source='console',
synchronous_mode=True)
```
<a name="introduction-thanks"></a>
#### Thanks
Many thanks to:
* [Pyarlo](https://github.com/tchellomello/python-arlo) and
[Arlo](https://github.com/jeffreydwalter/arlo) for doing the original heavy
lifting and the free Python lesson!
* [sseclient](https://github.com/btubbs/sseclient) for reading from the event
stream
* [JetBrains](https://www.jetbrains.com/?from=hass-aarlo) for the excellent
**PyCharm IDE** and providing me with an open source license to speed up the
project development.
[![JetBrains](/images/jetbrains.svg)](https://www.jetbrains.com/?from=hass-aarlo)
<a name="installation"></a>
## Installation
Proper PIP support is coming but for now, this will install the latest version.
```bash
pip install git+https://github.com/twrecked/pyaarlo
```
<a name="usage"></a>
## Usage
You can read the developer documentation here:
[https://pyaarlo.readthedocs.io/](https://pyaarlo.readthedocs.io/)
The following example will login to your Arlo system, use 2FA if needed,
register callbacks for all events on all base stations and cameras and then wait
10 minutes printing out any events that arrive during that time.
```python
# code to trap when attributes change
def attribute_changed(device, attr, value):
print('attribute_changed', time.strftime("%H:%M:%S"), device.name + ':' + attr + ':' + str(value)[:80])
# login, use console for 2FA if needed
arlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,
tfa_type='SMS',tfa_source='console')
# get base stations, list their statuses, register state change callbacks
for base in arlo.base_stations:
print("base: name={},device_id={},state={}".format(base.name,base.device_id,base.state))
base.add_attr_callback('*', attribute_changed)
# get cameras, list their statuses, register state change callbacks
# * is any callback, you can use motionDetected just to get motion events
for camera in arlo.cameras:
print("camera: name={},device_id={},state={}".format(camera.name,camera.device_id,camera.state))
camera.add_attr_callback('*', attribute_changed)
# disarm then arm the first base station
base = arlo.base_stations[0]
base.mode = 'disarmed'
time.sleep(5)
base.mode = 'armed'
# wait 10 minutes, try moving in front of a camera to see motionDetected events
time.sleep(600)
```
As mentioned, it uses the [Pyarlo](https://github.com/tchellomello/python-arlo)
API where possible so the following code from the original
[Usage](https://github.com/tchellomello/python-arlo#usage) will still work:
```python
# login, use console for 2FA if needed, turn on synchronous_mode for maximum compatibility
arlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,
tfa_type='SMS',tfa_source='console',synchronous_mode=True)
# listing devices
arlo.devices
# listing base stations
arlo.base_stations
# get base station handle
# assuming only 1 base station is available
base = arlo.base_stations[0]
# get the current base station mode
base.mode # 'disarmed'
# listing Arlo modes
base.available_modes # ['armed', 'disarmed', 'schedule', 'custom']
# Updating the base station mode
base.mode = 'custom'
# listing all cameras
arlo.cameras
# showing camera preferences
cam = arlo.cameras[0]
# check if camera is connected to base station
cam.is_camera_connected # True
# printing camera attributes
cam.serial_number
cam.model_id
cam.unseen_videos
# get brightness value of camera
cam.brightness
```
<a name="user-agent"></a>
## User Agent
The `user_agent` option will control what kind of stream Arlo sends to you.
The options are:
- `arlo`; the original user agent, returns an `rtsps` stream.
- `ipad`; returns a `HLS` stream
- `mac`; returns a `HLS` stream
- `linux`; returns a `MPEG-DASH` stream
<a name="saving-media"></a>
## Saving Media
If you use the `save_media_to` parameter to specify a file naming scheme
`praarlo` will use that to save all media - videos and snapshots - locally. You
can use the following substitutions:
- `SN`; the device serial number
- `N`; the device name
- `NN`; the device name, lower case with _ replacing spaces
- `Y`; the year of the recording, include century
- `m`; the month of the year as a number (range 01 to 12)
- `d`; the day of the month as a number (range 01 to 31)
- `H`; the hour of the day (range 00 to 23)
- `M`; the minute of the hour (range 00 to 59)
- `S`; the seconds of the minute (range 00 to 59)
- `F`; a short cut for `Y-m-d`
- `T`; a short cut for `H:M:S`
- `t`; a short cut for `H-M-S`
- `s`; the number of seconds since the epoch
You specify the substitution by prefixing it with a `$` in the format string.
You can optionally use curly brackets to remove any ambiguity. For example,
the following configuration will save all media under `/config/media`
organised by serial number then date. The code will add the correct file
extension.
```yaml
save_media_to: "/config/media/${SN}/${Y}/${m}/${d}/${T}"
```
The first time you configure `save_media_to` the system can take several
minutes to download all the currently available media. The download is
throttled to not overload Home Assistant or Arlo. Once the initial download is
completed updates should happen a lot faster.
The code doesn't provide any management of the downloads, it will keep
downloading them until your device is full. It also doesn't provide a NAS
interface, you need to mount the NAS device and point `save_media_to` at it.
<a name="2fa"></a>
## 2FA
Pyaarlo supports 2 factor authentication.
<a name="2fa-manual"></a>
#### Manual
Start `PyArlo` specifying `tfa_source` as `console`. Whenever `PyArlo` needs a
secondary code it will prompt you for it.
```python
ar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,
tfa_source='console', tfa_type='SMS')
```
<a name="2fa-imap"></a>
#### IMAP
__I recommend using `IMAP`, it's well tested now and it works. The other
methods haven't been tested or looked at in a while.__
Automatic is trickier. Support is there but needs testing. For automatic 2FA
PyArlo needs to access and your email account form where it reads the token Arlo
sent.
```python
ar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,
tfa_source='imap',tfa_type='email',
tfa_host='imap.host.com',
tfa_username='your-user-name',
tfa_password='your-imap-password' )
```
If you have multiple e-mail addresses associated with Arlo, you might also try configuring `tfa_nickname` to ensure that the correct factor is triggered:
```python
ar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,
tfa_source='imap',tfa_type='email',
tfa_host='imap.host.com',
tfa_username='your-user-name',
tfa_password='your-imap-password',
tfa_nickname='your-user-name@your-domain.com' )
```
It's working well with my gmail account, see
[here](https://support.google.com/mail/answer/185833?hl=en) for help setting up
single app passwords. If needed, you can specify a port by appending it to the
host.
```python
ar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,
tfa_source='imap',tfa_type='email',
tfa_host='imap.host.com:1234',
tfa_username='your-user-name',
tfa_password='your-imap-password' )
```
<a name="executable"></a>
## Pyaarlo Executable
The pip installation adds an executable `pyaarlo`. You can use this to list
devices, perform certain simple actions and anonymize and encrypt logs for
debugging purposes. _Device operations are currently limited..._
The git installation has `bin/pyaarlo` which functions in a similar manner.
```bash
# To show the currently available actions:
pyaarlo --help
# To list all the known devices:
pyaarlo -u 'your-user-name' -p 'your-password' list all
# this version will anonymize the output
pyaarlo -u 'your-user-name' -p 'your-password' --anonymize list all
# this version will anonymize and encrypt the output
pyaarlo -u 'your-user-name' -p 'your-password' --anonymize --encrypt list all
```
<a name="errors"></a>
## Error Reporting
When reporting errors please include the version of Pyaarlo you are using and
what Arlo devices you have. Please turn on DEBUG level logging, capture the
output and include as much information as possible about what you were trying to
do.
You can use the `pyaarlo` executable to anonymize and encrypt feature on
arbitrary data like log files or source code. If you are only encrypting you
don't need your username and password.
```bash
# encrypt an existing file
cat output-file | pyaarlo encrypt
# anonymize and then encrypt a file
cat output-file | pyaarlo -u 'your-user-name' -p 'your-password' anonymize | pyaarlo encrypt
```
If you installed from git you can use a shell script in `bin/` to encrypt your
logs. No anonymizing is possible this way.
```bash
# encrypt an existing file
cat output-file | ./bin/pyaarlo-encrypt encrypt
```
`pyaarlo-encrypt` is a fancy wrapper around:
```bash
curl -s -F 'plain_text_file=@-;filename=clear.txt' https://pyaarlo-tfa.appspot.com/encrypt
```
You can also encrypt your output on this [webpage](https://pyaarlo-tfa.appspot.com/).
<a name="limitations"></a>
## Limitations
The component uses the Arlo webapi.
* There is no documentation so the API has been reverse engineered using browser
debug tools.
* There is no support for smart features, you only get motion detection
notifications, not what caused the notification. (Although, you can pipe a
snapshot into deepstack...) This isn't strictly true, you can get "what
caused" the notifications but only after Arlo has analysed the footage.
* Streaming times out after 30 minutes.
* The webapi doesn't seem like it was really designed for permanent connections
so the system will sometimes appear to lock up. Various work arounds are in
the code and can be configured at the `arlo` component level. See next
paragraph.
If you do find the component locks up after a while (I've seen reports of hours,
days or weeks), you can add the following to the main configuration. Start from
the top and work down:
* `refresh_devices_every`, tell Pyaarlo to request the device list every so
often. This will sometimes prevent the back end from aging you out. The value
is in hours and a good starting point is 3.
* `stream_timeout`, tell Pyaarlo to close and reopen the event stream after a
certain period of inactivity. Pyaarlo will send keep alive every minute so a
good starting point is 180 seconds.
* `reconnect_every`, tell Pyaarlo to logout and back in every so often. This
establishes a new session at the risk of losing an event notification. The
value is minutes and a good starting point is 90.
* `request_timeout`, the amount of time to allow for a http request to work. A
good starting point is 120 seconds.
Alro will allow shared accounts to give cameras their own name. If you find
cameras appearing with unexpected names (or not appearing at all), log into the
Arlo web interface with your Home Assistant account and make sure the camera
names are correct.
You can change the brightness on the light but not while it's turned on. You
need to turn it off and back on again for the change to take. This is how the
web interface does it.
<a name="2fa-other"></a>
## Other 2 Factor Authentication
__I recommend using `IMAP`, it's well tested now and it works. These following
methods haven't been tested or looked at in a while.__
<a name="2fa-rest-api"></a>
#### Rest API
This mechanism allows you to an external website. When you start authenticating
Pyarlo makes a `clear` request and repeated `look-up` requests to a website to
retrieve your TFA code. The format of these requests and their responses are well
defined but the host Pyarlo uses is configurable.
```python
ar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,
tfa_source='rest-api',tfa_type='email',
tfa_host='custom-host',
tfa_username='test@test.com',
tfa_password='1234567890' )
```
* Pyaarlo will clear the current code with this HTTP GET request:
```http request
https://custom-host/clear?email=test@test.com&token=1234567890
```
* And the server will respond with this on success:
```json
{ "meta": { "code": 200 },
"data": { "success": True, "email": "test@test.com" } }
```
* Pyaarlo will look up the current code with this HTTP GET request:
```http request
https://custom-host/get?email=test@test.com&token=1234567890
```
* And the server will respond with this on success:
```json
{ "meta": { "code": 200 },
"data": { "success": True, "email": "test@test.com", "code": "123456", "timestamp": "123445666" } }
```
* Failures always have `code` value of anything other than 200.
```json
{ "meta": { "code": 400 },
"data": { "success": False, "error": "permission denied" }}
```
Pyaarlo doesn't care how you get the codes into the system only that they are
there. Feel free to roll your own server or...
##### Using My Server
I have a website running at https://pyaarlo-tfa.appspot.com that can provide
this service. It's provided as-is, it's running as a Google app so it should be
pretty reliable and the only information I have access to is your email address,
access token for my website and whatever your last code was. (_Note:_ if you're
not planning on using email forwarding the `email` value isn't strictly
enforced, a unique ID is sufficient.)
_If you don't trust me and my server - and I won't be offended - you can get the
source from [here](https://github.com/twrecked/pyaarlo-tfa-helper) and set up
your own._
To use the REST API with my website do the following:
* Register with my website. You only need to do this once and I'm sorry for the
crappy interface. Go to [registration
page](https://pyaarlo-tfa.appspot.com/register) and enter your email address
(or unique ID). The website will reply with a json document containing your
_token_, keep this _token_ and use it in all REST API interactions.
```json
{"email":"testing@testing.com",
"fwd-to":"pyaarlo@thewardrobe.ca",
"success":true,
"token":"4f529ea4dd20ca65e102e743e7f18914bcf8e596b909c02d"}
```
* To add a code send the following HTTP GET request:
```http request
https://custom-host/add?email=test@test.com&token=4f529ea4dd20ca65e102e743e7f18914bcf8e596b909c02d&code=123456
```
You can replace `code` with `msg` and the server will try and parse the code out
value of `msg`, use it for picking apart SMS messages.
##### Using IFTTT
You have your server set up or are using mine, one way to send codes is to use
[IFTTT](https://ifttt.com/) to forward SMS messages to the server. I have an
Android phone so use the `New SMS received from phone number` trigger and match
to the Arlo number sending me SMS codes. (I couldn't get the match message to
work, maybe somebody else will have better luck.)
I pair this with `Make a web request` action to forward the SMS code into my
server, I use the following recipe. Modify the email and token as necessary.
```
URL: https://pyaarlo-tfa.appspot.com/add?email=test@test.com&token=4f529ea4dd20ca65e102e743e7f18914bcf8e596b909c02d&msg={{Text}}
Method: GET
Content Type: text/plain
```
Make sure to configure Pyaarlo to request a token over SMS with `tfa_type='SMS`.
Now, when you login in, Arlo will send an SMS to your phone, the IFTTT app will
forward this to the server and Pyaarlo will read it from the server.
##### Using EMAIL
If you run your own `postfix` server you can use [this
script](https://github.com/twrecked/pyaarlo-tfa-helper/blob/master/postfix/pyaarlo-fwd.in)
to set up an email forwarding alias. Use an alias like this:
```text
pyaarlo: "|/home/test/bin/pyaarlo-fwd"
```
Make sure to configure Pyaarlo to request a token over SMS with
`tfa_type='EMAIL`. Then set up your email service to forward Arlo code message
to your email forwarding alias.
Raw data
{
"_id": null,
"home_page": "https://github.com/twrecked/pyaarlo.git",
"name": "pyaarlo",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "arlo, netgear, camera, home automation, python",
"author": "Steve Herrell",
"author_email": "steve.herrell@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/e1/52/8dd16cab269eb9abe4a6171c709fb5514788371fc760d6ee47d60522165a/pyaarlo-0.8.0.12.tar.gz",
"platform": null,
"description": "# Pyaarlo\n\n## Alpha Build\n\nWelcome to the Pyaarlo alpha build. I'm using the 0.8.x stream to split\n`pyaarlo` out from `hass-aarlo`. This is partly motivated by thinking about\ngetting `hass-aarlo` back into Home Assistant and partly motivated by my\ndesire to stop having to commit bug fixes in 2 places.\n\n### Breaking Changes\n\n#### Cached Session\nThe code will now save the session details and reuse the authentication token\nwhen possible. This can drastically reduce the number of authentication\nrequests the code will make (and 2FA requests if needed). If this doesn't work\nfor you pass `save_session=False` as a parameter to `PyArlo()`.\n\n\n## Table of Contents\n- [Introduction](#introduction)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Pyaarlo Executable](#executable)\n- [User Agent](#user-agent)\n- [Saving Media](#saving-media)\n- [2 Factor Authentication](#2fa)\n * [Manual](#2fa-manual)\n * [IMAP](#2fa-imap)\n- [Error Reporting](#errors)\n- [Limitations](#limitations)\n- [Other 2 Factor Authentication](#2fa-other)\n\n\n<a name=\"introduction\"></a>\n## Introduction\n\nPyaarlo is a module for Python that provides asynchronous access to Netgear\nArlo cameras.\n\nWhen you start Pyaarlo, it starts a background thread that opens a single,\npersistent connection, an *event stream*, to the Arlo servers. As things happen\nto the Arlo devices - motion detected, battery level changes, mode changes,\netc... - the Arlo servers post these events onto the event stream. The\nbackground thread reads these events from the stream, updates Pyaarlo's internal\nstate and calls any user registered callbacks.\n\n#### Differences from Pyarlo\n\nThe biggest difference is Pyaarlo defaults to asynchronous mode by default. The\nfollowing code brought from Pyarlo might not work:\n\n```python\nbase.mode = 'armed'\nif base.mode == 'armed':\n print('it worked!')\n```\n\nThis is because between setting `mode` and reading `mode` the code has to:\n* build and send a mode change packet to Arlo\n* read the mode change packet back from the Arlo event stream\n* update its internal state for `base`\n\nI say \"might\" not work because it might work, it all depends on timing, and\ncontext switches and network speed...\n\nTo enable synchronous mode you need to specify it when starting PyArlo.\n\n```python\n# login, use console for 2FA if needed\narlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,\n tfa_type='SMS',tfa_source='console',\n synchronous_mode=True)\n```\n\n<a name=\"introduction-thanks\"></a>\n#### Thanks \nMany thanks to:\n* [Pyarlo](https://github.com/tchellomello/python-arlo) and\n [Arlo](https://github.com/jeffreydwalter/arlo) for doing the original heavy\n lifting and the free Python lesson!\n* [sseclient](https://github.com/btubbs/sseclient) for reading from the event\n stream\n* [JetBrains](https://www.jetbrains.com/?from=hass-aarlo) for the excellent\n **PyCharm IDE** and providing me with an open source license to speed up the\n project development.\n\n [![JetBrains](/images/jetbrains.svg)](https://www.jetbrains.com/?from=hass-aarlo)\n\n\n<a name=\"installation\"></a>\n## Installation\n\nProper PIP support is coming but for now, this will install the latest version.\n\n```bash\npip install git+https://github.com/twrecked/pyaarlo\n```\n\n<a name=\"usage\"></a>\n## Usage\n\nYou can read the developer documentation here:\n[https://pyaarlo.readthedocs.io/](https://pyaarlo.readthedocs.io/)\n\nThe following example will login to your Arlo system, use 2FA if needed,\nregister callbacks for all events on all base stations and cameras and then wait\n10 minutes printing out any events that arrive during that time.\n\n```python\n# code to trap when attributes change\ndef attribute_changed(device, attr, value):\n print('attribute_changed', time.strftime(\"%H:%M:%S\"), device.name + ':' + attr + ':' + str(value)[:80])\n\n# login, use console for 2FA if needed\narlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,\n tfa_type='SMS',tfa_source='console')\n\n# get base stations, list their statuses, register state change callbacks\nfor base in arlo.base_stations:\n print(\"base: name={},device_id={},state={}\".format(base.name,base.device_id,base.state))\n base.add_attr_callback('*', attribute_changed)\n\n# get cameras, list their statuses, register state change callbacks\n# * is any callback, you can use motionDetected just to get motion events\nfor camera in arlo.cameras:\n print(\"camera: name={},device_id={},state={}\".format(camera.name,camera.device_id,camera.state))\n camera.add_attr_callback('*', attribute_changed)\n\n# disarm then arm the first base station\nbase = arlo.base_stations[0]\nbase.mode = 'disarmed'\ntime.sleep(5)\nbase.mode = 'armed'\n\n# wait 10 minutes, try moving in front of a camera to see motionDetected events\ntime.sleep(600)\n\n```\n\nAs mentioned, it uses the [Pyarlo](https://github.com/tchellomello/python-arlo)\nAPI where possible so the following code from the original\n[Usage](https://github.com/tchellomello/python-arlo#usage) will still work:\n\n```python\n\n# login, use console for 2FA if needed, turn on synchronous_mode for maximum compatibility\narlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,\n tfa_type='SMS',tfa_source='console',synchronous_mode=True)\n\n# listing devices\narlo.devices\n\n# listing base stations\narlo.base_stations\n\n# get base station handle\n# assuming only 1 base station is available\nbase = arlo.base_stations[0]\n\n# get the current base station mode\nbase.mode # 'disarmed'\n\n# listing Arlo modes\nbase.available_modes # ['armed', 'disarmed', 'schedule', 'custom']\n\n# Updating the base station mode\nbase.mode = 'custom'\n\n# listing all cameras\narlo.cameras\n\n# showing camera preferences\ncam = arlo.cameras[0]\n\n# check if camera is connected to base station\ncam.is_camera_connected # True\n\n# printing camera attributes\ncam.serial_number\ncam.model_id\ncam.unseen_videos\n\n# get brightness value of camera\ncam.brightness\n```\n\n\n<a name=\"user-agent\"></a>\n## User Agent\n\nThe `user_agent` option will control what kind of stream Arlo sends to you.\nThe options are:\n- `arlo`; the original user agent, returns an `rtsps` stream.\n- `ipad`; returns a `HLS` stream\n- `mac`; returns a `HLS` stream\n- `linux`; returns a `MPEG-DASH` stream\n\n\n<a name=\"saving-media\"></a>\n## Saving Media\n\nIf you use the `save_media_to` parameter to specify a file naming scheme\n`praarlo` will use that to save all media - videos and snapshots - locally. You\ncan use the following substitutions:\n\n- `SN`; the device serial number\n- `N`; the device name\n- `NN`; the device name, lower case with _ replacing spaces\n- `Y`; the year of the recording, include century\n- `m`; the month of the year as a number (range 01 to 12)\n- `d`; the day of the month as a number (range 01 to 31)\n- `H`; the hour of the day (range 00 to 23)\n- `M`; the minute of the hour (range 00 to 59)\n- `S`; the seconds of the minute (range 00 to 59)\n- `F`; a short cut for `Y-m-d`\n- `T`; a short cut for `H:M:S`\n- `t`; a short cut for `H-M-S`\n- `s`; the number of seconds since the epoch\n\nYou specify the substitution by prefixing it with a `$` in the format string.\nYou can optionally use curly brackets to remove any ambiguity. For example,\nthe following configuration will save all media under `/config/media`\norganised by serial number then date. The code will add the correct file\nextension.\n\n```yaml\n save_media_to: \"/config/media/${SN}/${Y}/${m}/${d}/${T}\"\n```\n\nThe first time you configure `save_media_to` the system can take several\nminutes to download all the currently available media. The download is\nthrottled to not overload Home Assistant or Arlo. Once the initial download is\ncompleted updates should happen a lot faster.\n\nThe code doesn't provide any management of the downloads, it will keep\ndownloading them until your device is full. It also doesn't provide a NAS\ninterface, you need to mount the NAS device and point `save_media_to` at it.\n\n\n<a name=\"2fa\"></a>\n## 2FA\n\nPyaarlo supports 2 factor authentication.\n\n\n<a name=\"2fa-manual\"></a>\n#### Manual\n\nStart `PyArlo` specifying `tfa_source` as `console`. Whenever `PyArlo` needs a\nsecondary code it will prompt you for it.\n\n```python\nar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,\n tfa_source='console', tfa_type='SMS')\n```\n\n<a name=\"2fa-imap\"></a>\n#### IMAP\n\n__I recommend using `IMAP`, it's well tested now and it works. The other\nmethods haven't been tested or looked at in a while.__\n\nAutomatic is trickier. Support is there but needs testing. For automatic 2FA\nPyArlo needs to access and your email account form where it reads the token Arlo\nsent.\n\n```python\nar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,\n tfa_source='imap',tfa_type='email',\n tfa_host='imap.host.com',\n tfa_username='your-user-name',\n tfa_password='your-imap-password' )\n```\n\nIf you have multiple e-mail addresses associated with Arlo, you might also try configuring `tfa_nickname` to ensure that the correct factor is triggered:\n\n```python\nar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,\n tfa_source='imap',tfa_type='email',\n tfa_host='imap.host.com',\n tfa_username='your-user-name',\n tfa_password='your-imap-password',\n tfa_nickname='your-user-name@your-domain.com' )\n```\n\nIt's working well with my gmail account, see\n[here](https://support.google.com/mail/answer/185833?hl=en) for help setting up\nsingle app passwords. If needed, you can specify a port by appending it to the\nhost.\n\n```python\nar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,\n tfa_source='imap',tfa_type='email',\n tfa_host='imap.host.com:1234',\n tfa_username='your-user-name',\n tfa_password='your-imap-password' )\n```\n\n\n<a name=\"executable\"></a>\n## Pyaarlo Executable\n\nThe pip installation adds an executable `pyaarlo`. You can use this to list\ndevices, perform certain simple actions and anonymize and encrypt logs for\ndebugging purposes. _Device operations are currently limited..._\n\nThe git installation has `bin/pyaarlo` which functions in a similar manner.\n\n```bash\n# To show the currently available actions:\npyaarlo --help\n\n# To list all the known devices:\npyaarlo -u 'your-user-name' -p 'your-password' list all\n\n# this version will anonymize the output\npyaarlo -u 'your-user-name' -p 'your-password' --anonymize list all\n\n# this version will anonymize and encrypt the output\npyaarlo -u 'your-user-name' -p 'your-password' --anonymize --encrypt list all\n```\n\n\n<a name=\"errors\"></a>\n## Error Reporting\n\nWhen reporting errors please include the version of Pyaarlo you are using and\nwhat Arlo devices you have. Please turn on DEBUG level logging, capture the\noutput and include as much information as possible about what you were trying to\ndo.\n\nYou can use the `pyaarlo` executable to anonymize and encrypt feature on\narbitrary data like log files or source code. If you are only encrypting you\ndon't need your username and password.\n\n```bash\n# encrypt an existing file\ncat output-file | pyaarlo encrypt\n\n# anonymize and then encrypt a file\ncat output-file | pyaarlo -u 'your-user-name' -p 'your-password' anonymize | pyaarlo encrypt\n```\n\nIf you installed from git you can use a shell script in `bin/` to encrypt your\nlogs. No anonymizing is possible this way.\n \n```bash\n# encrypt an existing file\ncat output-file | ./bin/pyaarlo-encrypt encrypt\n```\n\n`pyaarlo-encrypt` is a fancy wrapper around:\n\n```bash\ncurl -s -F 'plain_text_file=@-;filename=clear.txt' https://pyaarlo-tfa.appspot.com/encrypt\n```\n\nYou can also encrypt your output on this [webpage](https://pyaarlo-tfa.appspot.com/).\n\n\n<a name=\"limitations\"></a>\n## Limitations\nThe component uses the Arlo webapi.\n* There is no documentation so the API has been reverse engineered using browser\n debug tools.\n* There is no support for smart features, you only get motion detection\n notifications, not what caused the notification. (Although, you can pipe a\n snapshot into deepstack...) This isn't strictly true, you can get \"what\n caused\" the notifications but only after Arlo has analysed the footage.\n* Streaming times out after 30 minutes.\n* The webapi doesn't seem like it was really designed for permanent connections\n so the system will sometimes appear to lock up. Various work arounds are in\n the code and can be configured at the `arlo` component level. See next\n paragraph.\n\nIf you do find the component locks up after a while (I've seen reports of hours,\ndays or weeks), you can add the following to the main configuration. Start from\nthe top and work down: \n* `refresh_devices_every`, tell Pyaarlo to request the device list every so\n often. This will sometimes prevent the back end from aging you out. The value\n is in hours and a good starting point is 3.\n* `stream_timeout`, tell Pyaarlo to close and reopen the event stream after a\n certain period of inactivity. Pyaarlo will send keep alive every minute so a\n good starting point is 180 seconds.\n* `reconnect_every`, tell Pyaarlo to logout and back in every so often. This\n establishes a new session at the risk of losing an event notification. The\n value is minutes and a good starting point is 90.\n* `request_timeout`, the amount of time to allow for a http request to work. A\n good starting point is 120 seconds.\n\nAlro will allow shared accounts to give cameras their own name. If you find\ncameras appearing with unexpected names (or not appearing at all), log into the\nArlo web interface with your Home Assistant account and make sure the camera\nnames are correct.\n\nYou can change the brightness on the light but not while it's turned on. You\nneed to turn it off and back on again for the change to take. This is how the\nweb interface does it.\n\n\n<a name=\"2fa-other\"></a>\n## Other 2 Factor Authentication\n\n__I recommend using `IMAP`, it's well tested now and it works. These following\nmethods haven't been tested or looked at in a while.__\n\n<a name=\"2fa-rest-api\"></a>\n#### Rest API\n\nThis mechanism allows you to an external website. When you start authenticating\nPyarlo makes a `clear` request and repeated `look-up` requests to a website to\nretrieve your TFA code. The format of these requests and their responses are well\ndefined but the host Pyarlo uses is configurable.\n\n```python\nar = pyaarlo.PyArlo(username=USERNAME, password=PASSWORD,\n tfa_source='rest-api',tfa_type='email',\n tfa_host='custom-host',\n tfa_username='test@test.com',\n tfa_password='1234567890' )\n```\n\n* Pyaarlo will clear the current code with this HTTP GET request:\n```http request\nhttps://custom-host/clear?email=test@test.com&token=1234567890\n``` \n\n* And the server will respond with this on success:\n```json\n{ \"meta\": { \"code\": 200 },\n \"data\": { \"success\": True, \"email\": \"test@test.com\" } }\n```\n\n* Pyaarlo will look up the current code with this HTTP GET request:\n```http request\nhttps://custom-host/get?email=test@test.com&token=1234567890\n``` \n\n* And the server will respond with this on success:\n```json\n{ \"meta\": { \"code\": 200 },\n \"data\": { \"success\": True, \"email\": \"test@test.com\", \"code\": \"123456\", \"timestamp\": \"123445666\" } }\n```\n\n* Failures always have `code` value of anything other than 200.\n```json\n{ \"meta\": { \"code\": 400 },\n \"data\": { \"success\": False, \"error\": \"permission denied\" }}\n```\n\nPyaarlo doesn't care how you get the codes into the system only that they are\nthere. Feel free to roll your own server or...\n\n##### Using My Server\n\nI have a website running at https://pyaarlo-tfa.appspot.com that can provide\nthis service. It's provided as-is, it's running as a Google app so it should be\npretty reliable and the only information I have access to is your email address,\naccess token for my website and whatever your last code was. (_Note:_ if you're\nnot planning on using email forwarding the `email` value isn't strictly\nenforced, a unique ID is sufficient.)\n\n_If you don't trust me and my server - and I won't be offended - you can get the\nsource from [here](https://github.com/twrecked/pyaarlo-tfa-helper) and set up\nyour own._\n\nTo use the REST API with my website do the following:\n\n* Register with my website. You only need to do this once and I'm sorry for the\n crappy interface. Go to [registration\n page](https://pyaarlo-tfa.appspot.com/register) and enter your email address\n (or unique ID). The website will reply with a json document containing your\n _token_, keep this _token_ and use it in all REST API interactions.\n```json\n{\"email\":\"testing@testing.com\",\n \"fwd-to\":\"pyaarlo@thewardrobe.ca\",\n \"success\":true,\n \"token\":\"4f529ea4dd20ca65e102e743e7f18914bcf8e596b909c02d\"}\n```\n\n* To add a code send the following HTTP GET request:\n```http request\nhttps://custom-host/add?email=test@test.com&token=4f529ea4dd20ca65e102e743e7f18914bcf8e596b909c02d&code=123456\n```\n\nYou can replace `code` with `msg` and the server will try and parse the code out\nvalue of `msg`, use it for picking apart SMS messages.\n\n##### Using IFTTT\n\nYou have your server set up or are using mine, one way to send codes is to use\n[IFTTT](https://ifttt.com/) to forward SMS messages to the server. I have an\nAndroid phone so use the `New SMS received from phone number` trigger and match\nto the Arlo number sending me SMS codes. (I couldn't get the match message to\nwork, maybe somebody else will have better luck.)\n\nI pair this with `Make a web request` action to forward the SMS code into my\nserver, I use the following recipe. Modify the email and token as necessary.\n```\nURL: https://pyaarlo-tfa.appspot.com/add?email=test@test.com&token=4f529ea4dd20ca65e102e743e7f18914bcf8e596b909c02d&msg={{Text}}\nMethod: GET\nContent Type: text/plain\n```\n\nMake sure to configure Pyaarlo to request a token over SMS with `tfa_type='SMS`.\nNow, when you login in, Arlo will send an SMS to your phone, the IFTTT app will\nforward this to the server and Pyaarlo will read it from the server.\n\n##### Using EMAIL\n\nIf you run your own `postfix` server you can use [this\nscript](https://github.com/twrecked/pyaarlo-tfa-helper/blob/master/postfix/pyaarlo-fwd.in)\nto set up an email forwarding alias. Use an alias like this:\n```text\npyaarlo: \"|/home/test/bin/pyaarlo-fwd\"\n```\n\nMake sure to configure Pyaarlo to request a token over SMS with\n`tfa_type='EMAIL`. Then set up your email service to forward Arlo code message\nto your email forwarding alias.\n\n",
"bugtrack_url": null,
"license": "LGPLv3+",
"summary": "PyAarlo is a library that provides asynchronous access to Arlo security cameras.",
"version": "0.8.0.12",
"project_urls": {
"Bug Tracker": "https://github.com/twrecked/pyaarlo/issues",
"Documentation": "https://github.com/twrecked/pyaarlo/blob/master/README.md",
"Homepage": "https://github.com/twrecked/pyaarlo.git",
"Source Code": "https://github.com/twrecked/pyaarlo"
},
"split_keywords": [
"arlo",
" netgear",
" camera",
" home automation",
" python"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9d6bd892a3d88a05f230a85d24d4031731aea8a12926c2a144851b34d2304b71",
"md5": "1d2e7bcadb1cab109cff74710d861856",
"sha256": "5aea7d29c0663799dbb7d49494729a2921e4db418bbfed6a5a1f6c21496a5bda"
},
"downloads": -1,
"filename": "pyaarlo-0.8.0.12-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1d2e7bcadb1cab109cff74710d861856",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 80738,
"upload_time": "2024-10-10T01:53:19",
"upload_time_iso_8601": "2024-10-10T01:53:19.584711Z",
"url": "https://files.pythonhosted.org/packages/9d/6b/d892a3d88a05f230a85d24d4031731aea8a12926c2a144851b34d2304b71/pyaarlo-0.8.0.12-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e1528dd16cab269eb9abe4a6171c709fb5514788371fc760d6ee47d60522165a",
"md5": "a503b096c8af9ffa151cc393f0f2120c",
"sha256": "8754c493f5738b4e04ab0639bdf8fcc54ae5b93fa588cb6fa006e8ac057db9d1"
},
"downloads": -1,
"filename": "pyaarlo-0.8.0.12.tar.gz",
"has_sig": false,
"md5_digest": "a503b096c8af9ffa151cc393f0f2120c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 80675,
"upload_time": "2024-10-10T01:53:21",
"upload_time_iso_8601": "2024-10-10T01:53:21.332679Z",
"url": "https://files.pythonhosted.org/packages/e1/52/8dd16cab269eb9abe4a6171c709fb5514788371fc760d6ee47d60522165a/pyaarlo-0.8.0.12.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-10 01:53:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "twrecked",
"github_project": "pyaarlo",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "requests",
"specs": []
},
{
"name": "click",
"specs": []
},
{
"name": "pycryptodome",
"specs": []
},
{
"name": "unidecode",
"specs": []
},
{
"name": "cloudscraper",
"specs": [
[
">=",
"1.2.71"
]
]
},
{
"name": "paho-mqtt",
"specs": []
},
{
"name": "cryptography",
"specs": []
},
{
"name": "slugify",
"specs": []
}
],
"lcname": "pyaarlo"
}