twrecked / pyaarlo

Asynchronous Arlo Component for Python
GNU Lesser General Public License v3.0
50 stars 32 forks source link

How to use #5

Open vzlgdu opened 4 years ago

vzlgdu commented 4 years ago

Hi, can I've some suggest about how to use it? What import and so on. Thanks

twrecked commented 4 years ago

Many apologies. This project has long sat in the shadow of the hass-aarlo project. It was forked from pyarlo and the docs there are still relevant.

It does a lot more so I'll try and get something better put down.

vzlgdu commented 4 years ago

Thanks a lot! I will wait for news!

Pete118 commented 4 years ago

Thanks for great work! Now I'm able to login again. But I can't chanege base-mode,e.g. to armed :-( Ican read the actual mode but can't change it, do you know jow tu use it?

vzlgdu commented 4 years ago

Hi, Pete118; please, could you post the script to read the status? Thanks

twrecked commented 4 years ago

It should just be

print(base.mode)
base.mode = 'armed'
print(base.mode)
vzlgdu commented 4 years ago

My problem is how to assign “base”

Pete118 commented 4 years ago

base = ar.base_stations[0]

Pete118 commented 4 years ago

It should just be

print(base.mode)
base.mode = 'armed'
print(base.mode)

OK, that does not work for me

vzlgdu commented 4 years ago

I'm using this script:

USERNAME = os.environ.get('ARLO_USERNAME','xxxx') PASSWORD = os.environ.get('ARLO_PASSWORD','xxxx') arlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,tfa_type='SMS',tfa_source='console',storage_dir='aarlo' ) base = arlo.base_stations[0] print(base.mode)

but I'm receiving the following:

file not read unknown

Can you help me?

Thanks

twrecked commented 4 years ago

Give me a few minutes. I just noticed a small issue with the authentication finishing too soon and things not being fully ready.

vzlgdu commented 4 years ago

Thanks for your great job! I will wait for you!

shissam commented 4 years ago

Hi @twrecked, I immediate did the same as @vzlgdu, and tried to print 'base.mode' only to get 'unknown' - i suspected there might be a race condition, and after modifying your 'example.py' to wait after the 5 minute sleep timer, i tried printing 'base.mode' then - only to get the same result.

In trying to track this down, I got stuck on the thought where there was nothing I could find in the code that was using MODES_PATH and got suspicious that was used in the API to get mode state (and perhaps other things).

I am thrilled you have 2fa working with Arlo.... i'll cool my heels to see if your small issue is the source as you suspect.

thank you for all this.

twrecked commented 4 years ago

@shissam There's a couple of things going on here.

I'm testing out the new Arlo authentication mechanism and I was missing a call to register a session. This was stopping the event stream from starting quickly and stopping information from arriving quickly. So, as you guessed, there was a race condition.

The other piece is the code is now asynchronous by default, you ask a base to change mode and the request is sent to Arlo and arrives back later. You can provide callbacks to check the mode change but the code to base.mode will not make the change immediately. This change was made to enable motion, audio (etc) detection and to register changes made from other logins.

But, I'm thinking providing synchronous wrappers wouldn't be too hard and it would help with simple python scripts.

Anyway, I'll push a fix and put up some example code to show a mode change later.

shissam commented 4 years ago

very nice! no hurry on my part, but if there is something i can do to help (and if i can), I'd be happy to

shissam commented 4 years ago

Hi @twrecked, ok, i just did a pull, and there is good news and ..., the good news is that i am now getting base.mode for all my modes except modes that are "scheduled" - that is I have one mode which switches between "Day" and "Night" - and I pretty much run that schedule 24/7 except when I Arm/Disarm. Here is what I am seeing (sorry so long):

$ git pull Already up-to-date.

First try; FAIL: expecting "mode=Day" since "Schedule" is set on Arlo App

python sahexample.py logging on INFO:pyaarlo:pyaarlo starting base stations base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=unknown,modes=['armed', 'night', 'disarmed', 'schedule.1', 'outside work', 'motion test play', 'armed home with driveway alert', 'day'] sleeping base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=unknown,modes=['armed', 'night', 'disarmed', 'schedule.1', 'outside work', 'motion test play', 'armed home with driveway alert', 'day']

Second try; PASS: expecting "mode=disarmed" since "Disarmed" is set on Arlo App

$ python sahexample.py logging on INFO:pyaarlo:pyaarlo starting base stations base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=disarmed,modes=['outside work', 'motion test play', 'disarmed', 'armed', 'night', 'schedule.1', 'day', 'armed home with driveway alert'] sleeping base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=disarmed,modes=['outside work', 'motion test play', 'disarmed', 'armed', 'night', 'schedule.1', 'day', 'armed home with driveway alert']

Third try; PASS: expecting "mode=armed" since "Armed" is set on Arlo App

$ python sahexample.py logging on INFO:pyaarlo:pyaarlo starting base stations base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=armed,modes=['motion test play', 'outside work', 'night', 'disarmed', 'armed home with driveway alert', 'schedule.1', 'day', 'armed'] sleeping base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=armed,modes=['motion test play', 'outside work', 'night', 'disarmed', 'armed home with driveway alert', 'schedule.1', 'day', 'armed']

Fourth try; PASS: expecting "mode=Day" since "Day" is set on Arlo App

$ python sahexample.py logging on INFO:pyaarlo:pyaarlo starting base stations base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=Day,modes=['day', 'outside work', 'night', 'armed', 'armed home with driveway alert', 'schedule.1', 'motion test play', 'disarmed'] sleeping base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=Day,modes=['day', 'outside work', 'night', 'armed', 'armed home with driveway alert', 'schedule.1', 'motion test play', 'disarmed']

Fifth try; PASS: expecting "mode=Night" since "Night" is set on Arlo App

$ python sahexample.py logging on INFO:pyaarlo:pyaarlo starting base stations base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=Night,modes=['disarmed', 'day', 'armed', 'night', 'armed home with driveway alert', 'motion test play', 'schedule.1', 'outside work'] sleeping base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=Night,modes=['disarmed', 'day', 'armed', 'night', 'armed home with driveway alert', 'motion test play', 'schedule.1', 'outside work']

(same as First) Sixth try; FAIL: expecting "mode=Day" since "Schedule" is set on Arlo App

$ python sahexample.py logging on INFO:pyaarlo:pyaarlo starting base stations base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=unknown,modes=['disarmed', 'motion test play', 'outside work', 'armed home with driveway alert', 'day', 'night', 'armed', 'schedule.1'] sleeping base: name=arloABC,device_id=4RXXXXXXXXXXX,mode=unknown,modes=['disarmed', 'motion test play', 'outside work', 'armed home with driveway alert', 'day', 'night', 'armed', 'schedule.1']

vzlgdu commented 4 years ago

Hi, after an update I can confirm that now it works: I can reade all modes escluding "schedule mode". Great work! Question: why I receive alwais the message "file not read"?

vzlgdu commented 4 years ago

Update: if I execute again the script without exiting (in a cycle) I receive the message:

logged out? did you log in from elsewhere?

Can I use something like a "logout" command to avoid this?

Thnaks

twrecked commented 4 years ago

The schedule is a proper bug. I'll push a fix in a minute. If you change make a change to your schedule while running some code it would have worked but the initial value is wrong.

print(base.mode)
time.sleep(60)    # make change to *scheduled* here in your Arlo phone app.
print(base.mode)

@vzlgdu It could be a file being left behind. The code stores some state to help speed startup. Try the following:

$ ls aarlo

If you have a file called aarlo.pickle try deleting it.

twrecked commented 4 years ago

I just pushed a fix.

shissam commented 4 years ago

@twrecked, yep, that did it! thank you.

vzlgdu commented 4 years ago

IT WORKS!!! Thanks a lot for your effort! Great job!!

vzlgdu commented 4 years ago

Last question: what about this message?

"logged out? did you log in from elsewhere?"

Thanks!

twrecked commented 4 years ago

You logged into Arlo using the same account you used with pyaarlo. You need a separate account for pyaarlo - see here.

You technically needed it for pyarlo. If you have 2 (or more) base stations pyarlo will fight with itself internally it just never displayed the error. This is one of the reasons I forked out this project.

vzlgdu commented 4 years ago

I'm using an account dedicated to aarlo; I'm calling the script in a while using thread, so the check is performed every 30s without exiting from the while. 2th question: I removed folder "aarlo" but it is recreated generating again the error "file not read".

Please, let me know. Thanks

twrecked commented 4 years ago

Sorry, do you call logout()?

I'll check the file error at this end.

What are you calling pyaarlo.PyArlo with?

vzlgdu commented 4 years ago

no.... should I use ar.logout()?

vzlgdu commented 4 years ago

this is my script:

arlo = pyaarlo.PyArlo( username='xxxx',password="xxxx",tfa_type='SMS',tfa_source='console',storage_dir='aarlo' ) base = arlo.base_stations[0] print(base.mode)

twrecked commented 4 years ago

I can reproduce the 'file not read' error and it's safe to ignore. What I'll do is push a fix to quiet that down and to make saving state optional.

No, you don't need to call logout(), in fact, it's better not to. But that does mean something else is logging in with the same Arlo credentials. It comes from here in the code and has to have happened because we get a logout message in the event stream:

           # in backend.py
           # logged out? signal exited
            if response.get('action') == 'logout':
                with self._lock:
                    self._ev_connected_ = False
                    self._requests = {}
                    self._lock.notify_all()
                self._arlo.warning('logged out? did you log in from elsewhere?')
                break

Do you see the message a lot?

vzlgdu commented 4 years ago

I'm using this script:

import pyaarlo import threading import time

----------------------------------------------------------------------------------------------------------------------------------------

def funzione(): print(time.strftime("%H:%M:%S"), 'thread start ---------------------------') arlo = pyaarlo.PyArlo( username='xxxx',password="xxxx",tfa_type='SMS',tfa_source='console',storage_dir='aarlo' ) base = arlo.base_stations[0] print(time.strftime("%H:%M:%S"), base.mode) print(time.strftime("%H:%M:%S"), 'thread end ---------------------------')

----------------------------------------------------------------------------------------------------------------------------------------

test = None start_time = time.time()

while 1:

----------------------------------------------------------------------------------------------------------------------------------------

    if time.time() - start_time > 10:

            if test == None or not test.isAlive():
                    test = threading.Thread(target=funzione)
                    test.start()

            start_time = time.time()

----------------------------------------------------------------------------------------------------------------------------------------

    time.sleep(1)

and this is the output:

14:01:34 thread start --------------------------- file not read 14:01:45 Giorno 14:01:45 thread end --------------------------- 14:01:54 thread start --------------------------- file not read logged out? did you log in from elsewhere? logged out? did you log in from elsewhere? 14:02:06 Giorno 14:02:06 thread end --------------------------- logged out? did you log in from elsewhere? 14:02:14 thread start --------------------------- file not read logged out? did you log in from elsewhere? logged out? did you log in from elsewhere? 14:02:25 Giorno 14:02:25 thread end --------------------------- 14:02:35 thread start --------------------------- file not read 14:02:45 Giorno 14:02:45 thread end --------------------------- 14:02:55 thread start --------------------------- logged out? did you log in from elsewhere? logged out? did you log in from elsewhere? 14:03:06 Giorno 14:03:06 thread end --------------------------- 14:03:15 thread start --------------------------- logged out? did you log in from elsewhere? logged out? did you log in from elsewhere? 14:03:26 Giorno 14:03:26 thread end ---------------------------

twrecked commented 4 years ago

Each time you started the thread it would log back in and the error you were seeing was from the previous PyArlo instance shutting down. You could try adding a logout() (or I could add a destructor...)

But, try this version of the code. It keeps you logged in so does less work. The mode will update in the background so base.mode will always show the right value. (I couldn't test this piece of code because the auth servers for Arlo have died for me...)

#!/usr/bin/env python
#

import threading
import time
import pyaarlo

def funzione(arlo):
    print(time.strftime("%H:%M:%S"), 'thread start ---------------------------')
    base = arlo.base_stations[0]
    print(time.strftime("%H:%M:%S"), base.mode)
    print(time.strftime("%H:%M:%S"), 'thread end ---------------------------')

arlo = pyaarlo.PyArlo( username='xxxx',password="xxxx",
                       tfa_type='SMS',tfa_source='console',storage_dir='aarlo')
test = None
start_time = time.time()

while 1:
    if time.time() - start_time > 10:
        if test == None or not test.isAlive():
            test = threading.Thread(target=funzione,args=(arlo,))
            test.start()
            start_time = time.time()
    time.sleep(1)
vzlgdu commented 4 years ago

Hi, thanks for the suggest: now the script works without errors!

Thanks again for your support!

twrecked commented 4 years ago

My login started again... This is another way to track changes. Run it and try changing state from your app.

#!/usr/bin/env python
#

import threading
import time

import pyaarlo

def mode_changed(device, attr, value):
    print(time.strftime("%H:%M:%S"), device.name + ':' + attr + ':' + str(value)[:80])

arlo = pyaarlo.PyArlo( username='xxxx',password="xxxx",
                       tfa_type='SMS',tfa_source='console',storage_dir='aarlo')

for base in arlo.base_stations:
    print("base: name={},device_id={},mode={}".format(base.name,base.device_id,base.mode))
    base.add_attr_callback('activeMode', mode_changed)

time.sleep(300)
vzlgdu commented 4 years ago

Hi, I tried to execute your script, but it reports always the actual status without change it; following the section modified:

for base in arlo.base_stations: print("base: name={},device_id={},mode={}".format(base.name,base.device_id,base.mode)) base.add_attr_callback('disarmed', mode_changed)

The actuals mode is "Giorno" but after ran the script with mode "disarmed" the status doesn't change...

twrecked commented 4 years ago

add_attr_callback doesn't change the mode it just reports attribute changes and activeMode is the attribute that tracks the current mode. The following code will watch all attribute changes for a given base station and then cycles through some mode changes.

#!/usr/bin/env python
#

import os
import time

import pyaarlo

USERNAME = os.environ.get('ARLO_USERNAME','test.login@gmail.com')
PASSWORD = os.environ.get('ARLO_PASSWORD','test-password')

# this is called when any attribute changes
def attribute_changed(device, attr, value):
    print('attribute_changed', time.strftime("%H:%M:%S"), device.name + ':' + attr + ':' + str(value)[:80])

arlo = pyaarlo.PyArlo( username=USERNAME,password=PASSWORD,
                        tfa_type='SMS',tfa_source='console',
                        save_state=False,dump=False,storage_dir='aarlo' )

print('logged in')
first_base = None
original_mode = None
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)
    if first_base is None:
        first_base = base
        original_mode = base.mode

# arm the base station, change armed to Giorno if you want
time.sleep(30)
print('arming')
first_base.mode = 'armed'

# disarm the base station
time.sleep(10)
print('disarming')
first_base.mode = 'disarmed'

# set base station to the original mode
time.sleep(10)
print('setting original mode')
first_base.mode = original_mode

time.sleep(10)
twrecked commented 4 years ago

I'll leave this open a bit longer because I added a synchronous_mode so it works more like the original Pyarlo project. See here for how to turn it on.