Source code for blinkpy.blinkpy

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
blinkpy by Kevin Fronczak - A Blink camera Python library.

https://github.com/fronzbot/blinkpy
Original protocol hacking by MattTW :
https://github.com/MattTW/BlinkMonitorProtocol
Published under the MIT license - See LICENSE file for more details.
"Blink Wire-Free HS Home Monitoring & Alert Systems" is a trademark
owned by Immedia Inc., see www.blinkforhome.com for more information.
I am in no way affiliated with Blink, nor Immedia Inc.
"""

import json
import getpass
from shutil import copyfileobj
import requests
from requests.structures import CaseInsensitiveDict
import blinkpy.helpers.errors as ERROR
from blinkpy.helpers.constants import (
    BLINK_URL, LOGIN_URL, LOGIN_BACKUP_URL,
    DEFAULT_URL, ONLINE
)


[docs]def _attempt_reauthorization(blink): """Attempt to refresh auth token and links.""" headers = blink.get_auth_token() blink.set_links() return headers
[docs]def _request(blink, url='http://google.com', data=None, headers=None, reqtype='get', stream=False, json_resp=True, is_retry=False): """Perform server requests and check if reauthorization neccessary.""" if reqtype == 'post': response = requests.post(url, headers=headers, data=data) elif reqtype == 'get': response = requests.get(url, headers=headers, stream=stream) else: raise BlinkException(ERROR.REQUEST) if json_resp and 'code' in response.json(): if is_retry: raise BlinkAuthenticationException( (response.json()['code'], response.json()['message'])) else: headers = _attempt_reauthorization(blink) return _request(blink, url=url, data=data, headers=headers, reqtype=reqtype, stream=stream, json_resp=json_resp, is_retry=True) # pylint: disable=no-else-return if json_resp: return response.json() else: return response
# pylint: disable=super-init-not-called class BlinkException(Exception): """Class to throw general blink exception.""" def __init__(self, errcode): """Initialize BlinkException.""" self.errid = errcode[0] self.message = errcode[1] class BlinkAuthenticationException(BlinkException): """Class to throw authentication exception.""" pass
[docs]class BlinkURLHandler(object): """Class that handles Blink URLS.""" def __init__(self, region_id): """Initialize the urls.""" self.base_url = "https://rest.{}.{}".format(region_id, BLINK_URL) self.home_url = "{}/homescreen".format(self.base_url) self.event_url = "{}/events/network".format(self.base_url) self.network_url = "{}/network".format(self.base_url) self.networks_url = "{}/networks".format(self.base_url) self.video_url = "{}/api/v2/videos".format(self.base_url)
[docs]class BlinkCamera(object): """Class to initialize individual camera.""" def __init__(self, config, blink): """Initiailize BlinkCamera.""" self.blink = blink self.urls = self.blink.urls self.id = str(config['device_id']) # pylint: disable=invalid-name self.name = config['name'] self._status = config['armed'] self.thumbnail = "{}{}.jpg".format(self.urls.base_url, config['thumbnail']) self.clip = "{}{}".format(self.urls.base_url, config['video']) self.temperature = config['temp'] self.battery = config['battery'] self.notifications = config['notifications'] self.motion = {} self.header = None self.image_link = None self.arm_link = None self.region_id = config['region_id'] @property def armed(self): """Return camera arm status.""" return self._status @property def battery_string(self): """Return string indicating battery status.""" status = "Unknown" if self.battery > 1 and self.battery <= 3: status = "OK" elif self.battery >= 0: status = "Low" return status
[docs] def snap_picture(self): """Take a picture with camera to create a new thumbnail.""" _request(self.blink, url=self.image_link, headers=self.header, reqtype='post')
[docs] def set_motion_detect(self, enable): """Set motion detection.""" url = self.arm_link if enable: _request(self.blink, url=url + 'enable', headers=self.header, reqtype='post') else: _request(self.blink, url=url + 'disable', headers=self.header, reqtype='post')
[docs] def update(self, values): """Update camera information.""" self.name = values['name'] self._status = values['armed'] self.thumbnail = "{}{}.jpg".format( self.urls.base_url, values['thumbnail']) self.clip = "{}{}".format( self.urls.base_url, values['video']) self.temperature = values['temp'] self.battery = values['battery'] self.notifications = values['notifications']
[docs] def image_refresh(self): """Refresh current thumbnail.""" url = self.urls.home_url response = _request(self.blink, url=url, headers=self.header, reqtype='get')['devices'] for element in response: try: if str(element['device_id']) == self.id: self.thumbnail = ( "{}{}.jpg".format( self.urls.base_url, element['thumbnail']) ) return self.thumbnail except KeyError: pass return None
[docs] def image_to_file(self, path): """Write image to file.""" thumb = self.image_refresh() response = _request(self.blink, url=thumb, headers=self.header, reqtype='get', stream=True, json_resp=False) if response.status_code == 200: with open(path, 'wb') as imgfile: copyfileobj(response.raw, imgfile)
[docs] def video_to_file(self, path): """Write video to file.""" response = _request(self.blink, url=self.clip, headers=self.header, reqtype='get', stream=True, json_resp=False) with open(path, 'wb') as vidfile: copyfileobj(response.raw, vidfile)