Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arlo Q Plus support #23

Closed
imopen opened this issue Oct 25, 2017 · 23 comments
Closed

Arlo Q Plus support #23

imopen opened this issue Oct 25, 2017 · 23 comments

Comments

@imopen
Copy link

imopen commented Oct 25, 2017

Hi Jeffrey,
I'm looking for an api for my Arlo Q Plus, I've tried a little your library but, if I don't missing something, I'm able to list my camera but not to arm it (Arlo Q Plus works without a base).
Am I doing something wrong or Arlo Q Plus will be supported in future?
Thanks in advance and keep up the good work,
imopen

@jeffreydwalter
Copy link
Owner

Hi @imopen,

I'm open to support Arlo Q Plus. I don't own one, so I will need your help...

If you want to help, I need the log of the http request traffic created when you arm/disarm your camera.

To do this:

  1. Use Chrome.
  2. Right-click anywhere on the page and choose "Inspect" from the context menu. This will open the developer console.
  3. Click on the Network tab.
  4. Check the "Preserve log" checkbox.
  5. Click the "Clear" icon (it looks like a circle with a slash through it).
  6. Arm your camera from the browser.
  7. Copy the http requests which show up in the developer console and paste them to me here. Please include the "Request Payload" from the "Headers" tab for each http request.
    It will look something like this:
{"from":"336-XXXXXXX_web","to":"XXXXXXXXXXXXX","action":"set","resource":"modes","transId":"web!baf3e5e8.a1353!XXXXXXXXXXXXXX","publishResponse":true,"properties":{"active":"mode1"}}

Also, if Arlo is treating your Arlo Q Plus camera as a basestation, you might be able to call:

arlo.Arm(camera)

instead of:

arlo.Arm(basestation)

@imopen
Copy link
Author

imopen commented Oct 25, 2017

Hi Jeffrey,
thanks for the prompt reply.

I've collected the request headers and request payload, I've censured it for privacy reasons, I hope it is still clear, let me know if I should be more explicit

"CAMERA_SN" is the replacement for camera serial number, a string of the form: 0N1234SY5C67D for example

POST /hmsweb/users/devices/notify/CAMERA_SN HTTP/1.1
Host: arlo.netgear.com
Connection: keep-alive
Content-Length: 189
Authorization: xxxxxxxxxxx
Origin: https://arlo.netgear.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, /
xcloudId: xxxxxxxxxxx
Referer: https://arlo.netgear.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: it,en-US;q=0.8,en;q=0.6
Cookie: xxxxxxxxxxx

{"from":"xxxxxxxxxxx_web","to":"CAMERA_SN","action":"set","resource":"modes","transId":"web!xxxxxxxxxxx.xxxxxxxxxxx!xxxxxxxxxxx","publishResponse":true,"properties":{"active":"mode1"}}

I've tried to arm the camera with arlo.Arm(camera) but I got an exception.

Thanks again,
imopen

@imopen
Copy link
Author

imopen commented Oct 25, 2017

My code:

arlo = Arlo(USERNAME, PASSWORD)
basestation = [device for device in arlo.GetDevices() if device['deviceType'] == 'arloqs']
arlo.Arm(basestation[0])

Here the exception:

Traceback (most recent call last):
File "./arlo-imopen.py", line 32, in
arlo.Arm(basestation[0])
File "/root/arlo/Arlo.py", line 383, in Arm
return self.NotifyAndGetResponse(basestation, {"action":"set","resource":"modes","publishResponse":True,"properties":{"active":"mode1"}})
File "/root/arlo/Arlo.py", line 327, in NotifyAndGetResponse
self.Subscribe(basestation)
File "/root/arlo/Arlo.py", line 257, in Subscribe
event_stream = sseclient.SSEClient('https://arlo.netgear.com/hmsweb/client/subscribe?token='+self.headers['Authorization'], cookies=self.cookies)
TypeError: init() got an unexpected keyword argument 'cookies'

Thank you very much,
imopen

@jeffreydwalter
Copy link
Owner

okay, just pushed some changes that should fix the exception you had. Please let me know how it goes.

Try this code:

arlo = Arlo(USERNAME, PASSWORD)
basestation = arlo.GetDevices('arloqs')
arlo.Arm(basestation[0])

@imopen
Copy link
Author

imopen commented Oct 25, 2017

Hi @jeffreydwalter
here we go:

Traceback (most recent call last):
File "./examples/arlo-imopen.py", line 9, in
arlo.Arm(basestation[0])
File "/root/arlo/Arlo.py", line 385, in Arm
return self.NotifyAndGetResponse(basestation, {"action":"set","resource":"modes","publishResponse":True,"properties":{"active":"mode1"}})
File "/root/arlo/Arlo.py", line 323, in NotifyAndGetResponse
self.Subscribe(basestation)
File "/root/arlo/Arlo.py", line 253, in Subscribe
event_stream = sseclient.SSEClient('https://arlo.netgear.com/hmsweb/client/subscribe?token='+self.request.session.headers.get('Authorization'), session=self.request.session)
TypeError: init() got an unexpected keyword argument 'session'

thanks for the support,
imopen

@jeffreydwalter
Copy link
Owner

jeffreydwalter commented Oct 25, 2017 via email

@jeffreydwalter
Copy link
Owner

*sseclient library... Stupid autocorrect got me. 😀

@imopen
Copy link
Author

imopen commented Oct 25, 2017

I check immediately, I'm running python on a raspberry, I'll upgrade and return to you ;-)

@imopen
Copy link
Author

imopen commented Oct 25, 2017

Python 2.7.9

certifi (2017.7.27.1)
chardet (3.0.4)
colorama (0.3.2)
dnspython (1.12.0)
html5lib (0.999)
idna (2.6)
monotonic (1.3)
pip (9.0.1)
pyarlo (0.0.8)
pycrypto (2.6.1)
requests (2.18.4)
setuptools (33.1.1)
six (1.11.0)
sseclient (0.0.18)
sseclient-py (1.7)
urllib3 (1.22)

should I upgrade?

@jeffreydwalter
Copy link
Owner

jeffreydwalter commented Oct 25, 2017 via email

@imopen
Copy link
Author

imopen commented Oct 25, 2017

it works like a charm, I'll donate you a beer to thank you :)

@jeffreydwalter
Copy link
Owner

jeffreydwalter commented Oct 25, 2017 via email

@imopen
Copy link
Author

imopen commented Oct 26, 2017

Hi @jeffreydwalter
please apologize my dummy question: what's the fastest way to get current status (armed. disarmed)?
I'm at first approach with Python and I think I'm complicating too much my code.
Thanks,
imopen

@jeffreydwalter
Copy link
Owner

jeffreydwalter commented Oct 26, 2017

Hey @imopen, thanks again for the beer! I enjoyed it last night.

You can get the current mode by getting all of the modes, like this:

arlo = Arlo(USERNAME, PASSWORD)

basestations = arlo.GetDevices('basestation')
current_mode = arlo.GetModes(basestations[0]).get("properties").get("active")

GetModes() returns an object that contains all of the modes and their associated rules. It also includes which one is selected, like this:

    "action": "is", 
    "from": "XXXXXXXXXXXXX", 
    "properties": {
        "active": "mode1", 
        "modes": [
            {
                "id": "mode0", 
                "name": "", 
                "rules": [], 
                "type": "disarmed"
            }, 
            {
                "id": "mode1", 
                "name": "", 
                "rules": [
                    "rule5", 
                    "rule2", 
                    "rule3"
                ], 
                "type": "armed"
            }, 
            {
                "id": "mode2", 
                "name": "*****_DEFAULT_MODE_ARMED_*****", 
                "rules": [
                    "rule0", 
                    "rule1"
                ]
            }, 
            {
                "id": "mode3", 
                "name": "Test Mode", 
                "rules": [
                    "rule6"
                ]
            }
        ]
    }, 
    "resource": "modes", 
    "to": "XXX-XXXXXXXX", 
    "transId": "web!1d94d764.ea8c58!XXXXXXXXXX"
}

@imopen
Copy link
Author

imopen commented Oct 26, 2017

thank you @jeffreydwalter
I'm on my way, I almost finished a first prototype of autoarm/autodisarm Arlo... instead of buggy geofence, I'll use the lan connection (pinging devices and dhcp sniffing), it seems very very more reliable... and your lib is essential to dialogate with Arlo.
When it'll be finished maybe I'll publish it ;-)

@jeffreydwalter
Copy link
Owner

jeffreydwalter commented Oct 26, 2017

That sounds like a really cool project! I would definitely be interested in checking it out!

I've been wanting to apply some machine learning to replace Netgear's "Arlo Smart". I was thinking it would be cool to turn off the notifications Arlo generates, and instead have the AI only send alerts when a real human (or whatever) is detected. Maybe even apply facial and voice recognition to make it recognize certain people so it wouldn't alert and also to allow those individuals to control home automation tasks (or trigger other things).

If we wanted to go really crazy, it might be a cool project to build a platform and make all of these features "plugins" so you could pick and choose what features you want.

@imopen
Copy link
Author

imopen commented Oct 27, 2017

Hi @jeffreydwalter
I got an error from library, basically I did a multithread program, one thread pings devices and other sniffs dhcp request to collect devices' status.
Both of them can arm o disarm Arlo but when a thread tries it obtains:

File "/root/arlo_autoarm//arlo_autoarm.py", line 60, in notification
status=arlo_arm_disarm("arm")
File "/root/arlo_autoarm//arlo_autoarm.py", line 164, in arlo_arm_disarm
arlo = Arlo(USERNAME, PASSWORD)
File "/root/arlo_autoarm/Arlo.py", line 126, in init
signal.signal(signal.SIGINT, self.interrupt_handler)
ValueError: signal only works in main thread

Can you help me somehow?
Thanks again,
imopen

@imopen
Copy link
Author

imopen commented Oct 27, 2017

For the moment I just commented line 126 and it seems to work
Probably can I have some concurrent problems?

@jeffreydwalter
Copy link
Owner

jeffreydwalter commented Oct 27, 2017 via email

@imopen
Copy link
Author

imopen commented Oct 30, 2017

Hi Jeffrey,
one more question, when I arm Arlo I begin to receive this GET every 4 seconds:

2017/10/30 13:52:23 | DEBUG | https://arlo.netgear.com:443 "GET /hmsweb/client/subscribe?token=2_[...]H HTTP/1.1" 200 None

Is there a way to arm the camera without subscribe to some event?

Or better, what is the cleanest mode to use your library? Is it ok to use the arlo object globally or is it better to instance an object in every call and then forcing logout on it?

I did a method like this, is it wrong?

def arlo_arm_disarm (mode):
    arlo = Arlo(USERNAME, PASSWORD)
    basestation = arlo.GetDevices(ARLO_BASENAME)
    if mode=="arm":
        arlo.Arm(basestation[0])
    else:
        arlo.Disarm(basestation[0])
    current_mode = arlo.GetModes(basestation[0]).get("properties").get("active")
    return current_mode

Thanks in advance,
imopen

@jeffreydwalter
Copy link
Owner

Hey @imopen,

There is no way to arm/disarm without that subscribe GET. Netgear chose to use a streaming protocol called "Server-side Events".

I would just instantiate the Arlo object once and use it globally.

arlo = Arlo(USERNAME, PASSWORD)
basestation = arlo.GetDevices(ARLO_BASENAME)

def arlo_arm_disarm (mode):
    if mode=="arm":
        arlo.Arm(basestation[0])
    else:
        arlo.Disarm(basestation[0])
    return arlo.GetModes(basestation[0]).get("properties").get("active")

@jeffreydwalter
Copy link
Owner

@imopen Did that work for you?

@imopen
Copy link
Author

imopen commented Nov 14, 2017

Hello @jeffreydwalter for my needs it's ok to arm/disarm and then logout.
These operations are made once/twice a day and I don't need to keep a connection estabilished.
Your lib works well and my project is almost mature, I automatically arm and disarm my Arlo as soon as I leave or enter at my home. Without using the pretty unstable geofencing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants