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

Add support for Blink Minis #290

Merged
merged 6 commits into from
Jun 9, 2020
Merged

Add support for Blink Minis #290

merged 6 commits into from
Jun 9, 2020

Conversation

fronzbot
Copy link
Owner

@fronzbot fronzbot commented Jun 9, 2020

Description:

Adds rough support for blink minis. Untested (as I don't own any) so will not merge until someone is able to test and verify. To help out:

Clone this repo and checkout the PR

Fork this repo in github and then do the following:

git clone https://github.com/<YOUR_GIT_USERNAME>/blinkpy.git
cd blinkpy
git remote add upstream https://github.com/fronzbot/blinkpy.git
git fetch upstream
git checkout -b add-minis upstream/add-minis

Run the following code to start up your blink instance

Will prompt for username, password, and possibly 2FA key

from blinkpy.blinkpy import Blink
blink = Blink()
blink.start()

Check that homescreen property contains cameras

No longer needed, thank you!

print(blink.homescreen)

Check that cameras are in sync and camera dictionaries

print("Sync Modules:")
for name in blink.sync:
    print(name)
print("Cameras:")
for name in blink.cameras:
    print(name)

Verify thumbnail is correct (returns a url)

print(blink.cameras["NAME OF MINI CAMERA"].thumbnail)

Verify arming/disarming cameras works

First, make sure the camera is disarmed in the blink app. Then run the following code and wait (up to 60s) to see the state change in the app (usually closer to 5s/10s, but Blink can be slow...)

blink.refresh()
# Following print statement should print 'False'
print(blink.sync["NAME OF MINI CAMERA"].arm)
blink.sync["NAME OF MINI CAMERA"].arm = True

Now wait 60s or so and double check that you can read the status back after a refresh (print statement should print 'True')

blink.refresh()
print(blink.sync["NAME OF MINI CAMERA"].arm)

Report back results

Please comment on this PR with your results if you run through theses tests. If you run into any problems, please let me know with as much detail as you can provide so I can fix it!

Related issue (if applicable): fixes #224

Checklist:

  • Local tests with tox run successfully PR cannot be meged unless tests pass
  • Changes tested locally to ensure platform still works as intended
  • Tests added to verify new code works

@fronzbot fronzbot mentioned this pull request Jun 9, 2020
@codecov
Copy link

codecov bot commented Jun 9, 2020

Codecov Report

Merging #290 into dev will increase coverage by 0.53%.
The diff coverage is 78.99%.

Impacted file tree graph

@@            Coverage Diff             @@
##              dev     #290      +/-   ##
==========================================
+ Coverage   81.55%   82.09%   +0.53%     
==========================================
  Files           8        8              
  Lines         808      899      +91     
==========================================
+ Hits          659      738      +79     
- Misses        149      161      +12     
Flag Coverage Δ
#unittests 82.09% <78.99%> (+0.53%) ⬆️
Impacted Files Coverage Δ
blinkpy/camera.py 77.39% <71.05%> (-4.12%) ⬇️
blinkpy/sync_module.py 86.91% <80.64%> (+4.27%) ⬆️
blinkpy/blinkpy.py 77.66% <89.47%> (+1.47%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 31de65f...b8da6e2. Read the comment docs.

@HughAndersonNUS
Copy link

HughAndersonNUS commented Jun 9, 2020

Hi - I tried out this, on my system with 4 other cameras, on two sync modules, and the Blink Mini:
`Hughs-MacBook-4:blinkpy hugh$ python3
Python 3.7.4 (default, Oct 10 2019, 08:46:34)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

from blinkpy.blinkpy import Blink
blink = Blink()
blink.start()
Username:XXXX@YYYY
Password:
Enter code sent to XXXX@YYYY: XXXXXXX
True
print(blink.homescreen)
{'account': {'id': ID-1, 'email_verified': True, 'email_verification_required': False}, 'networks': [{'id': NW-1, 'created_at': '2018-01-05T07:29:52+00:00', 'updated_at': '2020-06-06T20:10:47+00:00', 'name': 'DBInside', 'time_zone': 'Pacific/Auckland', 'dst': True, 'armed': False, 'lv_save': False}, {'id': NW-2, 'created_at': '2018-01-06T10:04:58+00:00', 'updated_at': '2020-05-31T19:52:51+00:00', 'name': 'DB', 'time_zone': 'Pacific/Auckland', 'dst': True, 'armed': True, 'lv_save': False}, {'id': YY, 'created_at': '2020-05-20T06:21:48+00:00', 'updated_at': '2020-06-06T20:17:40+00:00', 'name': 'Home', 'time_zone': 'Pacific/Auckland', 'dst': True, 'armed': False, 'lv_save': False}], 'sync_modules': [{'id': XXX, 'created_at': '2018-01-05T07:31:22+00:00', 'updated_at': '2020-06-06T20:55:45+00:00', 'onboarded': True, 'status': 'offline', 'name': 'My Blink Sync Module', 'serial': 'ZZZZZZZZZ', 'fw_version': '2.13.18', 'last_hb': '2020-06-06T20:10:58+00:00', 'wifi_strength': 1, 'network_id': NW-1, 'enable_temp_alerts': True}, {'id': XX, 'created_at': '2018-01-06T10:05:15+00:00', 'updated_at': '2020-06-09T04:55:23+00:00', 'onboarded': True, 'status': 'online', 'name': 'My Blink Sync Module', 'serial': 'ZZZZZZZZ', 'fw_version': '2.13.18', 'last_hb': '2020-06-09T05:18:45+00:00', 'wifi_strength': 2, 'network_id': NW-2, 'enable_temp_alerts': True}], 'cameras': [{'id': CAM-1, 'created_at': '2018-01-05T07:36:59+00:00', 'updated_at': '2020-06-06T20:10:50+00:00', 'name': 'Frontdoor-DH', 'serial': 'ZZZZZZZZ', 'fw_version': '2.151', 'type': 'white', 'enabled': True, 'thumbnail': '/media/production/account/ID-1/network/NW-1/camera/CAM-1/clip_gDp_n13V_2020_05_25__05_40AM', 'status': 'done', 'battery': 'ok', 'usage_rate': False, 'network_id': NW-1, 'issues': [], 'signals': {'lfr': 4, 'wifi': 5, 'temp': 43, 'battery': 3}}, {'id': CAM-2, 'created_at': '2018-01-05T07:39:52+00:00', 'updated_at': '2020-06-06T20:10:51+00:00', 'name': 'Livingarea-DJ', 'serial': 'ZZZZZZZZ', 'fw_version': '2.151', 'type': 'white', 'enabled': True, 'thumbnail': '/media/production/account/ID-1/network/NW-1/camera/CAM-2/clip_Na_6TECv_2020_06_04__22_12PM', 'status': 'done', 'battery': 'ok', 'usage_rate': False, 'network_id': NW-1, 'issues': [], 'signals': {'lfr': 5, 'wifi': 5, 'temp': 44, 'battery': 3}}, {'id': CAM-3, 'created_at': '2018-01-06T10:08:42+00:00', 'updated_at': '2020-06-09T05:08:44+00:00', 'name': 'Driveway-DF', 'serial': 'ZZZZZZZZZZZ', 'fw_version': '2.151', 'type': 'xt', 'enabled': True, 'thumbnail': '/media/production/account/ID-1/network/NW-2/camera/CAM-3/clip_5FK7kfUV_2020_06_09__03_31AM', 'status': 'done', 'battery': 'ok', 'usage_rate': False, 'network_id': NW-2, 'issues': [], 'signals': {'lfr': 5, 'wifi': 1, 'temp': 42, 'battery': 3}}, {'id': CAM-4, 'created_at': '2018-01-06T10:10:51+00:00', 'updated_at': '2020-06-09T05:08:45+00:00', 'name': 'Kitchen-DE', 'serial': 'ZZZZZZZ', 'fw_version': '2.151', 'type': 'xt', 'enabled': True, 'thumbnail': '/media/production/account/ID-1/network/NW-2/camera/CAM-4/clip_17rsJ8Zs_2020_06_09__03_31AM', 'status': 'done', 'battery': 'ok', 'usage_rate': False, 'network_id': NW-2, 'issues': [], 'signals': {'lfr': 5, 'wifi': 1, 'temp': 42, 'battery': 3}}], 'sirens': [], 'chimes': [], 'video_stats': {'storage': 1, 'auto_delete_days': 0}, 'doorbell_buttons': [], 'owls': [{'id': OWL-ID-1, 'created_at': '2020-05-20T06:22:10+00:00', 'updated_at': '2020-06-09T04:58:09+00:00', 'name': 'Living Room', 'type': 'owl', 'onboarded': True, 'serial': 'ZZZZZZZZZ', 'fw_version': '9.63', 'enabled': True, 'thumbnail': '/media/production/account/ID-1/network/NW-OWL/owl/OWL-ID-1/thumbnail/fw_9.63__BmdcL7LZ_2020_06_09__03_29AM', 'status': 'online', 'network_id': NW-OWL}], 'app_updates': {'message': 'An app update is required', 'code': 105, 'update_available': True, 'update_required': True}, 'device_limits': {'total_devices': 20, 'owl': 10, 'camera': 10, 'siren': 5, 'doorbell_button': 2, 'chime': 5}, 'whats_new': {'updated_at': 20200415, 'url': 'https://blinkforhome.com/blogs/updates'}}
`

So - from there on things dont seem to work. The blink mini does not have a "name" and "network" like the others, but there does appear to be information about it in the OWL tags above.
I hope I have deleted everything that is important up there :)

`>>> print("Sync Modules:")
Sync Modules:

for name in blink.sync:
... print(name)
...
DBInside
DB
Living Room
print("Cameras:")
Cameras:
for name in blink.cameras:
... print(name)
...
Driveway-DF
Kitchen-DE`

So I get two cameras in the DB sync module. The other one is offline at the moment, and no cameras from the "Living Room" Blink Mini (virtual) sync module.

CHeers Hugh

@HughAndersonNUS
Copy link

Hi Kevin, looking at the value returned by blink.homescreen, there is an entry for the Blink Mini in the networks section:
'networks': [
{'id': NW-1, ..... },
{'id': NW-2, ...},
{'id': NW-OWL, 'created_at': '2020-05-20T06:21:48+00:00', 'updated_at': '2020-06-06T20:17:40+00:00', 'name': 'Home', 'time_zone': 'Pacific/Auckland', 'dst': True, 'armed': False, 'lv_save': False}],

And, NO entry in the cameras section, but the new 'Owls" section has the details:

'owls': [{'id': OWL-ID-1,
'created_at': '2020-05-20T06:22:10+00:00',
'updated_at': '2020-06-09T04:58:09+00:00',
'name': 'Living Room',
'type': 'owl',
'onboarded': True,
'serial': 'ZZZZZZZZ',
'fw_version': '9.63',
'enabled': True,
'thumbnail': '/media/production/account/ID-1/network/NW-OWL/owl/OWL-ID-1/thumbnail/fw_9.63__BmdcL7LZ_2020_06_09__03_29AM',
'status': 'online',
'network_id': NW-OWL}],

Cheers Hugh

@chbndrhnns
Copy link

This is how it looks for my mini:

>>> print(b.homescreen)
{'account': {'id': x, 'email_verified': True, 'email_verification_required': True}, 'networks': [{'id': x, 'created_at': '2020-04-20T17:13:48+00:00', 'updated_at': '2020-06-03T17:31:16+00:00', 'name': 'Home', 'time_zone': 'Europe/Berlin', 'dst': True, 'armed': False, 'lv_save': False}], 'sync_modules': [], 'cameras': [], 'sirens': [], 'chimes': [], 'video_stats': {'storage': 1, 'auto_delete_days': 14}, 'doorbell_buttons': [], 'owls': [{'id': 280, 'created_at': '2020-04-20T17:14:36+00:00', 'updated_at': '2020-06-07T18:36:18+00:00', 'name': 'G8T1-9400-0135-1HVM', 'type': 'owl', 'onboarded': True, 'serial': 'x', 'fw_version': '9.63', 'enabled': True, 'thumbnail': '/media/e002/account/x/network/x/owl/280/thumbnail/x', 'status': 'online', 'network_id': x}], 'app_updates': {'message': 'An app update is required', 'code': 105, 'update_available': True, 'update_required': True}, 'device_limits': {'total_devices': 20, 'owl': 10, 'camera': 10, 'siren': 5, 'doorbell_button': 2, 'chime': 5}, 'whats_new': {'updated_at': 20200416, 'url': 'https://blinkforhome.com/blogs/updates'}}
>
>>> print(b.cameras)
{}

@benleb
Copy link

benleb commented Jun 9, 2020

>>> pprint(blink.homescreen)
{'account': {'email_verification_required': True,
             'email_verified': True,
             'id': <account id>},
 'app_updates': {'code': 105,
                 'message': 'An app update is required',
                 'update_available': True,
                 'update_required': True},
 'cameras': [],
 'chimes': [],
 'device_limits': {'camera': 10,
                   'chime': 5,
                   'doorbell_button': 2,
                   'owl': 10,
                   'siren': 5,
                   'total_devices': 20},
 'doorbell_buttons': [],
 'networks': [{'armed': False,
               'created_at': '2020-05-13T11:11:21+00:00',
               'dst': True,
               'id': <network id>,
               'lv_save': False,
               'name': '<network name>',
               'time_zone': 'Europe/Berlin',
               'updated_at': '2020-05-29T10:30:58+00:00'}],
 'owls': [{'created_at': '2020-05-13T11:11:47+00:00',
           'enabled': True,
           'fw_version': '9.63',
           'id': <owl id>,
           'name': 'blimi',
           'network_id': <network id>,
           'onboarded': True,
           'serial': 'G8T19400013513TS',
           'status': 'online',
           'thumbnail': '/media/e002/account/<account id>/network/<network id>/owl/<owl id>/thumbnail/fw_9.63__SseVTsm1_2020_06_08__15_02PM',
           'type': 'owl',
           'updated_at': '2020-06-08T23:28:19+00:00'}],
 'sirens': [],
 'sync_modules': [],
 'video_stats': {'auto_delete_days': 30, 'storage': 0},
 'whats_new': {'updated_at': 20200416,
               'url': 'https://blinkforhome.com/blogs/updates'}}
>>> print("Sync Modules:")
Sync Modules:
>>> for name in blink.sync:
...     print(name)
...
blimi
>>> print("Cameras:")
Cameras:
>>> for name in blink.cameras:
...     print(name)
...
>>>

@fronzbot
Copy link
Owner Author

fronzbot commented Jun 9, 2020

Thank you all, very helpful!

So it looks like I missed some initialization and merging of camera lists. I just added those now so hopefully we have better luck with the cameras. To get the update, you can just do the following:

git pull upstream add-minis

And then re-run the python code if you could!

@benleb
Copy link

benleb commented Jun 9, 2020

seems like before...

{'account': {'email_verification_required': True,
             'email_verified': True,
             'id': <account id>},
 'app_updates': {'code': 105,
                 'message': 'An app update is required',
                 'update_available': True,
                 'update_required': True},
 'cameras': [],
 'chimes': [],
 'device_limits': {'camera': 10,
                   'chime': 5,
                   'doorbell_button': 2,
                   'owl': 10,
                   'siren': 5,
                   'total_devices': 20},
 'doorbell_buttons': [],
 'networks': [{'armed': False,
               'created_at': '2020-05-13T11:11:21+00:00',
               'dst': True,
               'id': <network id>,
               'lv_save': False,
               'name': '<network name>',
               'time_zone': 'Europe/Berlin',
               'updated_at': '2020-05-29T10:30:58+00:00'}],
 'owls': [{'created_at': '2020-05-13T11:11:47+00:00',
           'enabled': True,
           'fw_version': '9.63',
           'id': <owl id>,
           'name': 'blimi',
           'network_id': <network id>,
           'onboarded': True,
           'serial': 'G8T19400013513TS',
           'status': 'online',
           'thumbnail': '/media/e002/account/<account id>/network/<network id>/owl/<owl id>/thumbnail/fw_9.63__SseVTsm1_2020_06_08__15_02PM',
           'type': 'owl',
           'updated_at': '2020-06-08T23:28:19+00:00'}],
 'sirens': [],
 'sync_modules': [],
 'video_stats': {'auto_delete_days': 30, 'storage': 0},
 'whats_new': {'updated_at': 20200416,
               'url': 'https://blinkforhome.com/blogs/updates'}}

Sync Modules:
  blimi

Cameras:

Traceback (most recent call last):
  File "dbg.py", line 25, in <module>
    print(blink.cameras[owl_name].thumbnail)
KeyError: 'blimi'

@benleb
Copy link

benleb commented Jun 9, 2020

python3 owlinfo.py <owl name>
import sys

from pprint import pprint

from blinkpy.blinkpy import Blink


owl_name = sys.argv[1] if len(sys.argv) >= 2 else "blimi"


blink = Blink()
blink.start()

pprint(blink.homescreen)
print()

print("Sync Modules:")
for name in blink.sync:
    print(f"  {name}")
print()

print("Cameras:")
for name in blink.cameras:
    print(f"  {name}")
print()

try:
    print(f"{blink.cameras[owl_name].thumbnail = }")
except Exception as error:
    print(error)
print()

try:
    blink.refresh()
    print(f"{blink.sync[owl_name].arm = }")
except Exception as error:
    print(error)
print()

try:
    blink.sync[owl_name].arm = True
except Exception as error:
    print(error)
print()

try:
    blink.refresh()
    print(f"{blink.sync[owl_name].arm = }")
except Exception as error:
    print(error)
print()

@fronzbot
Copy link
Owner Author

fronzbot commented Jun 9, 2020

@benleb Thanks, I appreciate it! Looks like I still was missing some initialization. Added that in and added a test to make sure a camera was actually being created so I'm, like, 60% sure you'll get something now 🤞 🤞

@benleb
Copy link

benleb commented Jun 9, 2020

:D we are on the right way... (it is really disarmed in the blink app)

{'account': {'email_verification_required': True,
             'email_verified': True,
             'id': <account id>},
 'app_updates': {'code': 105,
                 'message': 'An app update is required',
                 'update_available': True,
                 'update_required': True},
 'cameras': [],
 'chimes': [],
 'device_limits': {'camera': 10,
                   'chime': 5,
                   'doorbell_button': 2,
                   'owl': 10,
                   'siren': 5,
                   'total_devices': 20},
 'doorbell_buttons': [],
 'networks': [{'armed': False,
               'created_at': '2020-05-13T11:11:21+00:00',
               'dst': True,
               'id': <network id>,
               'lv_save': False,
               'name': '<network name>',
               'time_zone': 'Europe/Berlin',
               'updated_at': '2020-05-29T10:30:58+00:00'}],
 'owls': [{'created_at': '2020-05-13T11:11:47+00:00',
           'enabled': True,
           'fw_version': '9.63',
           'id': <owl id>,
           'name': 'blimi',
           'network_id': <network id>,
           'onboarded': True,
           'serial': 'G8T19400013513TS',
           'status': 'online',
           'thumbnail': '/media/e002/account/<account id>/network/<network id>/owl/<owl id>/thumbnail/fw_9.63__SseVTsm1_2020_06_08__15_02PM',
           'type': 'owl',
           'updated_at': '2020-06-08T23:28:19+00:00'}],
 'sirens': [],
 'sync_modules': [],
 'video_stats': {'auto_delete_days': 30, 'storage': 0},
 'whats_new': {'updated_at': 20200416,
               'url': 'https://blinkforhome.com/blogs/updates'}}

Sync Modules:
  blimi

Cameras:
  blimi

blink.cameras[owl_name].thumbnail = 'https://rest-e002.immedia-semi.com/media/e002/account/<account id>/network/<network id>/owl/<owl id>/thumbnail/fw_9.63__SseVTsm1_2020_06_08__15_02PM.jpg'

blink.sync[owl_name].arm = True

Connection error. Endpoint https://rest-e002.immedia-semi.com/network/<network id>/camera/<owl id>/enable possibly down or throttled. 404: Not Found

sleeping for 60s now

blink.sync[owl_name].arm = True

@fronzbot
Copy link
Owner Author

fronzbot commented Jun 9, 2020

Awesome! So there's a different arm/disarm endpoint for the minis (of course 😞). Figured there was a slim chance I could re-use that endpoint.

Could you just do one more check? I want to make sure the thumbnail can be downloaded and a new one generated (I assume it won't work and that there's a different endpoint, but worth trying):

# Check if we can take a picture with existing endpoints
thumbnail = blink.cameras["CAMERA NAME"].snap_picture()
print(thumbnail)

# Check that we can successfully download an image
print(blink.cameras["CAMERA NAME"].thumbnail
blink.cameras["CAMERA NAME"].image_to_file("/path/to/file")

@benleb
Copy link

benleb commented Jun 9, 2020

POST (empty payload) to
https://rest-e002.immedia-semi.com/api/v1/accounts/<account id>/networks/<network id>/state/arm
https://rest-e002.immedia-semi.com/api/v1/accounts/<account id>/networks/<network id>/state/disarm
to arm/disarm

Connection error. Endpoint https://rest-e002.immedia-semi.com/network/<network id>/camera/<owl id>/thumbnail possibly down or throttled. 404: Not Found
thumbnail = None

blink.cameras[owl_name].thumbnail = 'https://rest-e002.immedia-semi.com/media/e002/account/<account id>/network/<network id>/owl/<owl id>/thumbnail/fw_9.63__SseVTsm1_2020_06_08__15_02PM.jpg'

downloaded picture is valid :) (but not “fresh”)

@fronzbot
Copy link
Owner Author

fronzbot commented Jun 9, 2020

OK, cool. Just realized your post in the issue included a new thumbnail endpoint, so I added that. Could you give the snap_picture endpoint a shot again? If that works, I think this will be clear to merge

@benleb
Copy link

benleb commented Jun 9, 2020

works :)

...
thumbnail = {'id': 11328080, 'network_id': <network id>, 'command': 'thumbnail', 'state': 'new'}
...

nice job 👍

@fronzbot fronzbot merged commit 93d498a into dev Jun 9, 2020
@fronzbot fronzbot deleted the add-minis branch June 9, 2020 17:38
@chbndrhnns
Copy link

chbndrhnns commented Jun 10, 2020

I get this message when trying to arm/disarm my mini:

>>> blink.sync["entrance"].arm = False
Connection error. Endpoint https://rest-e002.immedia-semi.com/network/x/camera/x/disable possibly down or throttled. 404: Not Found

@fronzbot
Copy link
Owner Author

@chbndrhnns - two issues here. First is known: endpoint for arming blink minis is unknown right now (#293 ).That issue was known prior to merging. However, my intent was to have a warning message pop up telling you that...instead I absent-mindedly put the warning in the wrong spot so now regular sync modules are broken so I just raised that issue here #298

Some time today I'm going to do a quick cut to fix those two for another rc release. Arming the mini will still be unsupported until i (or someone) discovers the endpoint but at least it will tell you rather than attempting a futile http request

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

Successfully merging this pull request may close these issues.

Support for Mini
4 participants