ACTIVITY_STATE_KEY = 'activityState' BRIGHTNESS_KEY = 'brightness' CAPTURED_TODAY_KEY = 'capturedToday' FLIP_KEY = 'flip' IDLE_SNAPSHOT_PATH = '/hmsweb/users/devices/fullFrameSnapshot' LAST_CAPTURE_KEY = 'lastCapture' LAST_IMAGE_DATA_KEY = 'presignedLastImageData' LAST_IMAGE_KEY = 'presignedLastImageUrl' LAST_IMAGE_SRC_KEY = 'lastImageSource' MEDIA_COUNT_KEY = 'mediaObjectCount' MEDIA_UPLOAD_KEYS = [MEDIA_COUNT_KEY, LAST_IMAGE_KEY] MIRROR_KEY = 'mirror' MOTION_SENS_KEY = 'motionSetupModeSensitivity' POWER_SAVE_KEY = 'powerSaveMode' PRELOAD_DAYS = 30 PRIVACY_KEY = 'privacyActive' RECORD_START_PATH = "/hmsweb/users/devices/startRecord" RECORD_STOP_PATH = "/hmsweb/users/devices/stopRecord" SNAPSHOT_KEY = 'presignedFullFrameSnapshotUrl' SIREN_STATE_KEY = 'sirenState' STREAM_SNAPSHOT_KEY = 'presignedContentUrl' STREAM_SNAPSHOT_PATH = '/hmsweb/users/devices/takeSnapshot' STREAM_START_PATH = '/hmsweb/users/devices/startStream' CAMERA_MEDIA_DELAY = MEDIA_LIBRARY_DELAY + 10 AUDIO_POSITION_KEY = 'position' AUDIO_TRACK_KEY = 'trackId' DEFAULT_TRACK_ID = '229dca67-7e3c-4a5f-8f43-90e1a9bffc38' MEDIA_PLAYER_RESOURCE_ID = "audioPlayback/player" class ArloChildDevice(ArloDevice):

    def __init__(self, name, arlo, attrs):
        super().__init__(name, arlo, attrs)

        self._parent_id = attrs.get('parentId', None)
        self._arlo.debug('parent is {}'.format(self._parent_id))
        self._arlo.debug('resource is {}'.format(self.resource_id))

    @property
    def resource_type(self):
        return "child"

    @property
    def resource_id(self):
        """ Shortcut for mostly used resource id.

        Some devices - certain cameras - can provide other types.
        """
        return self.resource_type + "/" + self._device_id

    @property
    def parent_id(self):
        if self._parent_id is not None:
            # self._arlo.debug('real parent is {}'.format(self._parent_id))
            return self._parent_id
        # self._arlo.debug('fake parent is {}'.format(self.device_id))
        return self.device_id

    @property
    def base_station(self):
        # look for real parents
        for base in self._arlo.base_stations:
            if base.device_id == self.parent_id:
                return base
        # some cameras don't have base stations... it's its own basestation...
        for base in self._arlo.base_stations:
            if base.device_id == self.device_id:
                return base
        # no idea!
        return self._arlo.base_stations[0]

    @property
    def battery_level(self):
        return self._arlo.st.get([self._device_id, BATTERY_KEY], 100)

    @property
    def battery_tech(self):
        return self._arlo.st.get([self._device_id, BATTERY_TECH_KEY], 'None')

    @property
    def charging(self):
        return self._arlo.st.get([self._device_id, CHARGING_KEY], 'off').lower() == 'on'

    @property
    def charger_type(self):
        return self._arlo.st.get([self._device_id, CHARGER_KEY], 'None')

    @property
    def wired(self):
        return self.charger_type.lower() != 'none'

    @property
    def wired_only(self):
        return self.battery_tech.lower() == 'none' and self.wired

    @property
    def signal_strength(self):
        return self._arlo.st.get([self._device_id, SIGNAL_STR_KEY], 3)

    @property
    def is_unavailable(self):
        return self._arlo.st.get([self._device_id, CONNECTION_KEY], 'unknown') == 'unavailable'

    @property
    def too_cold(self):
        return self._arlo.st.get([self._device_id, CONNECTION_KEY], 'unknown') == 'thermalShutdownCold'

    @property
    def state(self):
        if self.is_unavailable:
            return 'unavailable'
        if not self.is_on:
            return 'turned off'
        if self.too_cold:
            return 'offline, too cold'
        return 'idle' def http_get(url, filename=None):
    # make request
    ret = _http_get(url)
    if ret is None:
        return False

    if filename is None:
        return ret.content

    with open(filename, 'wb') as data:
        data.write(ret.content)
    return True def http_get_img(url):
    # make request
    ret = _http_get(url)
    if ret is None:
        return None, datetime.now()

    date = ret.headers.get('Last-Modified', None)
    if date is not None:
        date = httptime_to_datetime(date)
    else:
        date = datetime.now()
    return ret.content, date
import base64
import threading
import time
import zlib
from .constant import (ACTIVITY_STATE_KEY, BRIGHTNESS_KEY,
                       CAPTURED_TODAY_KEY, FLIP_KEY, IDLE_SNAPSHOT_PATH, LAST_CAPTURE_KEY,
                       LAST_IMAGE_DATA_KEY, LAST_IMAGE_KEY,
                       LAST_IMAGE_SRC_KEY, MEDIA_COUNT_KEY,
                       MEDIA_UPLOAD_KEYS, MIRROR_KEY, MOTION_SENS_KEY,
                       POWER_SAVE_KEY, PRELOAD_DAYS, PRIVACY_KEY,
                       RECORD_START_PATH, RECORD_STOP_PATH,
                       SNAPSHOT_KEY, SIREN_STATE_KEY, STREAM_SNAPSHOT_KEY,
                       STREAM_SNAPSHOT_PATH, STREAM_START_PATH, CAMERA_MEDIA_DELAY,
                       AUDIO_POSITION_KEY, AUDIO_TRACK_KEY, DEFAULT_TRACK_ID, MEDIA_PLAYER_RESOURCE_ID)
from .device import ArloChildDevice
from .util import http_get, http_get_img



class ArloCamera(ArloChildDevice):

    def __init__(self, name, arlo, attrs):
        super().__init__(name, arlo, attrs)
        self._recent = False
        self._recent_job = None
        self._cache_count = None
        self._cached_videos = None
        self._min_days_vdo_cache = PRELOAD_DAYS
        self._lock = threading.Condition()
        self._snapshot_state = 'idle'
        self._clear_snapshot_cb = None

        self._arlo.bg.run_in(self._update_media, CAMERA_MEDIA_DELAY)