예제 #1
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def set_status(self, status):
        """Set device status."""
        if self._json_state['control_url']:
            url = CONST.BASE_URL + self._json_state['control_url']

            status_data = {'status': str(status)}

            response = self._abode.send_request(method="put",
                                                url=url,
                                                data=status_data)
            response_object = json.loads(response.text)

            _LOGGER.debug("Set Status Response: %s", response.text)

            if response_object['id'] != self.device_id:
                raise AbodeException((ERROR.SET_STATUS_DEV_ID))

            if response_object['status'] != str(status):
                raise AbodeException((ERROR.SET_STATUS_STATE))

            # Note: Status result is of int type, not of new status of device.
            # Seriously, why would you do that?
            # So, can't set status here must be done at device level.

            _LOGGER.info("Set device %s status to: %s", self.device_id, status)

            return True

        return False
예제 #2
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def set_level(self, level):
        """Set device level."""
        if self._json_state['control_url']:
            url = CONST.BASE_URL + self._json_state['control_url']

            level_data = {'level': str(level)}

            response = self._abode.send_request("put", url, data=level_data)
            response_object = json.loads(response.text)

            _LOGGER.debug("Set Level Response: %s", response.text)

            if response_object['id'] != self.device_id:
                raise AbodeException((ERROR.SET_STATUS_DEV_ID))

            if response_object['level'] != str(level):
                raise AbodeException((ERROR.SET_STATUS_STATE))

            # TODO: Figure out where level is indicated in device json object
            self.update(response_object)

            _LOGGER.info("Set device %s level to: %s", self.device_id, level)

            return True

        return False
예제 #3
0
    def set_mode(self, mode):
        """Set Abode alarm mode."""
        if not mode:
            raise AbodeException(ERROR.MISSING_ALARM_MODE)
        elif mode.lower() not in CONST.ALL_MODES:
            raise AbodeException(ERROR.INVALID_ALARM_MODE, CONST.ALL_MODES)

        mode = mode.lower()

        response = self._abode.send_request(
            "put", CONST.get_panel_mode_url(self._area, mode))

        _LOGGER.debug("Set Alarm Home Response: %s", response.text)

        response_object = json.loads(response.text)

        if response_object['area'] != self._area:
            raise AbodeException(ERROR.SET_MODE_AREA)

        if response_object['mode'] != mode:
            raise AbodeException(ERROR.SET_MODE_MODE)

        self._json_state['mode'][(self.device_id)] = response_object['mode']

        _LOGGER.info("Set alarm %s mode to: %s", self._device_id,
                     response_object['mode'])

        return True
예제 #4
0
    def set_color_temp(self, color_temp):
        """Set device color."""
        if self._json_state['control_url']:
            url = CONST.INTEGRATIONS_URL + self._device_uuid

            color_data = {
                'action': 'setcolortemperature',
                'colorTemperature': int(color_temp)
            }

            response = self._abode.send_request("post", url, data=color_data)
            response_object = json.loads(response.text)

            _LOGGER.debug("Set Color Temp Response: %s", response.text)

            if response_object['idForPanel'] != self.device_id:
                raise AbodeException((ERROR.SET_STATUS_DEV_ID))

            if response_object['colorTemperature'] != int(color_temp):
                raise AbodeException((ERROR.SET_STATUS_STATE))

            self.update(response_object)

            _LOGGER.info("Set device %s color_temp to: %s", self.device_id,
                         color_temp)
            return True

        return False
예제 #5
0
    def set_color(self, color):
        """Set device color."""
        if self._json_state['control_url']:
            url = CONST.INTEGRATIONS_URL + self._device_uuid

            hue, saturation = color
            color_data = {
                'action': 'setcolor',
                'hue': int(hue),
                'saturation': int(saturation)
            }

            response = self._abode.send_request("post", url, data=color_data)
            response_object = json.loads(response.text)

            _LOGGER.debug("Set Color Response: %s", response.text)

            if response_object['idForPanel'] != self.device_id:
                raise AbodeException((ERROR.SET_STATUS_DEV_ID))

            if (response_object['hue'] != int(hue)
                    or response_object['saturation'] != int(saturation)):
                raise AbodeException((ERROR.SET_STATUS_STATE))

            self.update(response_object)

            _LOGGER.info("Set device %s hue to: %s", self.device_id, hue)

            return True

        return False
예제 #6
0
파일: camera.py 프로젝트: thedeany/abodepy
    def privacy_mode(self, enable):
        """Set camera privacy mode (camera on/off)."""
        if self._json_state['privacy']:
            privacy = '1' if enable else '0'

            url = CONST.PARAMS_URL + self.device_id

            camera_data = {
                'mac': self._json_state['camera_mac'],
                'privacy': privacy,
                'action': 'setParam',
                'id': self.device_id
            }

            response = self._abode.send_request(method="put",
                                                url=url,
                                                data=camera_data)
            response_object = json.loads(response.text)

            _LOGGER.debug("Camera Privacy Mode Response: %s", response.text)

            if response_object['id'] != self.device_id:
                raise AbodeException((ERROR.SET_STATUS_DEV_ID))

            if response_object['privacy'] != str(privacy):
                raise AbodeException((ERROR.SET_PRIVACY_MODE))

            _LOGGER.info("Set camera %s privacy mode to: %s", self.device_id,
                         privacy)

            return True

        return False
예제 #7
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def _area_settings(area, setting, value, validate_value):
        """Will validate area settings and values, returns data packet."""
        if validate_value:
            # Exit delay has some specific limitations apparently
            if (setting == CONST.SETTING_EXIT_DELAY_AWAY
                    and value not in CONST.VALID_SETTING_EXIT_AWAY):
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.VALID_SETTING_EXIT_AWAY)
            elif value not in CONST.ALL_SETTING_ENTRY_EXIT_DELAY:
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.ALL_SETTING_ENTRY_EXIT_DELAY)

        return {'area': area, setting: value}
예제 #8
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def _panel_settings(setting, value, validate_value):
        """Will validate panel settings and values, returns data packet."""
        if validate_value:
            if (setting == CONST.SETTING_CAMERA_RESOLUTION
                    and value not in CONST.SETTING_ALL_CAMERA_RES):
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.SETTING_ALL_CAMERA_RES)
            elif (setting in [
                    CONST.SETTING_CAMERA_GRAYSCALE,
                    CONST.SETTING_SILENCE_SOUNDS
            ] and value not in CONST.SETTING_DISABLE_ENABLE):
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.SETTING_DISABLE_ENABLE)

        return {setting: value}
예제 #9
0
    def enable(self, enable):
        """Enable or disable the automation."""
        url = str.replace(CONST.AUTOMATION_ID_URL, '$AUTOMATIONID$',
                          self.automation_id)

        self._automation['enabled'] = enable

        response = self._abode.send_request(method="patch",
                                            url=url,
                                            data={'enabled': enable})

        response_object = json.loads(response.text)

        if isinstance(response_object, (tuple, list)):
            response_object = response_object[0]

        if (str(response_object['id']) != str(self._automation['id'])
                or str(response_object['enabled']) != str(
                    self._automation['enabled'])):
            raise AbodeException((ERROR.INVALID_AUTOMATION_EDIT_RESPONSE))

        self.update(response_object)

        _LOGGER.info("Set automation %s enable to: %s", self.name,
                     self.is_enabled)
        _LOGGER.debug("Automation response: %s", response.text)

        return True
예제 #10
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def send_request(self,
                     method,
                     url,
                     headers=None,
                     data=None,
                     is_retry=False):
        """Send requests to Abode."""
        if not self._token:
            self.login()

        if not headers:
            headers = {}

        headers['ABODE-API-KEY'] = self._token

        try:
            response = getattr(self._session, method)(url,
                                                      headers=headers,
                                                      data=data)

            if response and response.status_code < 400:
                return response
        except RequestException:
            _LOGGER.info("Abode connection reset...")

        if not is_retry:
            # Delete our current token and try again -- will force a login
            # attempt.
            self._token = None

            return self.send_request(method, url, headers, data, True)

        raise AbodeException((ERROR.REQUEST))
예제 #11
0
    def remove_all_device_callbacks(self, devices):
        """Unregister all callbacks for a device."""
        if not devices:
            return False

        if not isinstance(devices, (tuple, list)):
            devices = [devices]

        for device in devices:
            device_id = device

            if isinstance(device, AbodeDevice):
                device_id = device.device_id

            if not self._abode.get_device(device_id):
                raise AbodeException((ERROR.EVENT_DEVICE_INVALID))

            if device_id not in self._device_callbacks:
                return False

            _LOGGER.debug(
                "Unsubscribing from all updates for device_id: %s", device_id)

            self._device_callbacks[device_id].clear()

        return True
예제 #12
0
파일: __init__.py 프로젝트: vickyg3/abodepy
def new_device(device_json, abode):
    """Create new device object for the given type."""
    type_tag = device_json.get('type_tag')

    if not type_tag:
        raise AbodeException((ERROR.UNABLE_TO_MAP_DEVICE))

    generic_type = CONST.get_generic_type(type_tag.lower())
    device_json['generic_type'] = generic_type

    if generic_type == CONST.TYPE_CONNECTIVITY or \
       generic_type == CONST.TYPE_MOISTURE or \
       generic_type == CONST.TYPE_OPENING or \
       generic_type == CONST.TYPE_VIBRATION:
        return AbodeBinarySensor(device_json, abode)
    elif generic_type == CONST.TYPE_CAMERA:
        return AbodeCamera(device_json, abode)
    elif generic_type == CONST.TYPE_COVER:
        return AbodeCover(device_json, abode)
    elif generic_type == CONST.TYPE_LIGHT:
        return AbodeLight(device_json, abode)
    elif generic_type == CONST.TYPE_LOCK:
        return AbodeLock(device_json, abode)
    elif generic_type == CONST.TYPE_SWITCH:
        return AbodeSwitch(device_json, abode)
    elif generic_type == CONST.TYPE_UNKNOWN_SENSOR:
        return _new_sensor(device_json, abode)
    return AbodeDevice(device_json, abode)
예제 #13
0
    def add_device_callback(self, devices, callback):
        """Register a device callback."""
        if not devices:
            return False

        if not isinstance(devices, (tuple, list)):
            devices = [devices]

        for device in devices:
            # Device may be a device_id
            device_id = device

            # If they gave us an actual device, get that devices ID
            if isinstance(device, AbodeDevice):
                device_id = device.device_id

            # Validate the device is valid
            if not self._abode.get_device(device_id):
                raise AbodeException((ERROR.EVENT_DEVICE_INVALID))

            _LOGGER.debug("Subscribing to updated for device_id: %s",
                          device_id)

            self._device_callbacks[device_id].append((callback))

        return True
예제 #14
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def _siren_settings(setting, value, validate_value):
        """Will validate siren settings and values, returns data packet."""
        if validate_value:
            if value not in CONST.SETTING_DISABLE_ENABLE:
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.SETTING_DISABLE_ENABLE)

        return {'action': setting, 'option': value}
예제 #15
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def _sound_settings(area, setting, value, validate_value):
        """Will validate sound settings and values, returns data packet."""
        if validate_value:
            if (setting in CONST.VALID_SOUND_SETTINGS
                    and value not in CONST.ALL_SETTING_SOUND):
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.ALL_SETTING_SOUND)
            elif (setting == CONST.SETTING_ALARM_LENGTH
                  and value not in CONST.ALL_SETTING_ALARM_LENGTH):
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.ALL_SETTING_ALARM_LENGTH)
            elif (setting == CONST.SETTING_FINAL_BEEPS
                  and value not in CONST.ALL_SETTING_FINAL_BEEPS):
                raise AbodeException(ERROR.INVALID_SETTING_VALUE,
                                     CONST.ALL_SETTING_FINAL_BEEPS)

        return {'area': area, setting: value}
예제 #16
0
    def trigger(self, only_manual=True):
        """Trigger a quick-action automation."""
        if not self.is_quick_action and only_manual:
            raise AbodeException((ERROR.TRIGGER_NON_QUICKACTION))

        url = CONST.AUTOMATION_APPLY_URL
        url = url.replace('$AUTOMATIONID$', self.automation_id)

        self._abode.send_request(method="put", url=url, data=self._automation)

        return True
예제 #17
0
async def test_raise_config_entry_not_ready_when_offline(hass):
    """Config entry state is SETUP_RETRY when abode is offline."""
    with patch(
            "homeassistant.components.abode.Abode",
            side_effect=AbodeException("any"),
    ):
        config_entry = await setup_platform(hass, ALARM_DOMAIN)
        await hass.async_block_till_done()

    assert config_entry.state is ConfigEntryState.SETUP_RETRY

    assert hass.config_entries.flow.async_progress() == []
예제 #18
0
파일: camera.py 프로젝트: thedeany/abodepy
    def update_image_location(self, timeline_json):
        """Update the image location."""
        if not timeline_json:
            return False

        # If we get a list of objects back (likely)
        # then we just want the first one as it should be the "newest"
        if isinstance(timeline_json, (tuple, list)):
            timeline_json = timeline_json[0]

        # Verify that the event code is of the "CAPTURE IMAGE" event
        event_code = timeline_json.get('event_code')
        if event_code != TIMELINE.CAPTURE_IMAGE['event_code']:
            raise AbodeException((ERROR.CAM_TIMELINE_EVENT_INVALID))

        # The timeline response has an entry for "file_path" that acts as the
        # location of the image within the Abode servers.
        file_path = timeline_json.get('file_path')
        if not file_path:
            raise AbodeException((ERROR.CAM_IMAGE_REFRESH_NO_FILE))

        # Perform a "head" request for the image and look for a
        # 302 Found response
        url = CONST.BASE_URL + file_path
        response = self._abode.send_request("head", url)

        if response.status_code != 302:
            _LOGGER.warning("Unexected response code %s with body: %s",
                            str(response.status_code), response.text)
            raise AbodeException((ERROR.CAM_IMAGE_UNEXPECTED_RESPONSE))

        # The response should have a location header that is the actual
        # location of the image stored on AWS
        location = response.headers.get('location')
        if not location:
            raise AbodeException((ERROR.CAM_IMAGE_NO_LOCATION_HEADER))

        self._image_url = location

        return True
예제 #19
0
    def add_timeline_callback(self, timeline_events, callback):
        """Register a callback for a specific timeline event."""
        if not timeline_events:
            return False

        if not isinstance(timeline_events, (tuple, list)):
            timeline_events = [timeline_events]

        for timeline_event in timeline_events:
            if not isinstance(timeline_event, dict):
                raise AbodeException((ERROR.EVENT_CODE_MISSING))

            event_code = timeline_event.get('event_code')

            if not event_code:
                raise AbodeException((ERROR.EVENT_CODE_MISSING))

            _LOGGER.debug("Subscribing to timeline event: %s", timeline_event)

            self._timeline_callbacks[event_code].append((callback))

        return True
예제 #20
0
    def refresh(self):
        """Refresh the automation."""
        url = str.replace(CONST.AUTOMATION_ID_URL, '$AUTOMATIONID$',
                          self.automation_id)

        response = self._abode.send_request(method="get", url=url)
        response_object = json.loads(response.text)

        if isinstance(response_object, (tuple, list)):
            response_object = response_object[0]

        if str(response_object['id']) != self.automation_id:
            raise AbodeException((ERROR.INVALID_AUTOMATION_REFRESH_RESPONSE))

        self.update(response_object)
예제 #21
0
    def add_event_callback(self, event_groups, callback):
        """Register callback for a group of timeline events."""
        if not event_groups:
            return False

        if not isinstance(event_groups, (tuple, list)):
            event_groups = [event_groups]

        for event_group in event_groups:
            if event_group not in TIMELINE.ALL_EVENT_GROUPS:
                raise AbodeException(ERROR.EVENT_GROUP_INVALID,
                                     TIMELINE.ALL_EVENT_GROUPS)

            _LOGGER.debug("Subscribing to event group: %s", event_group)

            self._event_callbacks[event_group].append((callback))

        return True
예제 #22
0
파일: camera.py 프로젝트: thedeany/abodepy
    def image_to_file(self, path, get_image=True):
        """Write the image to a file."""
        if not self.image_url or get_image:
            if not self.refresh_image():
                return False

        response = requests.get(self.image_url, stream=True)

        if response.status_code != 200:
            _LOGGER.warning(
                "Unexpected response code %s when requesting image: %s",
                str(response.status_code), response.text)
            raise AbodeException((ERROR.CAM_IMAGE_REQUEST_INVALID))

        with open(path, 'wb') as imgfile:
            copyfileobj(response.raw, imgfile)

        return True
예제 #23
0
    def set_color(self, color):
        """Set device color."""
        if self._json_state['control_url']:
            url = CONST.INTEGRATIONS_URL + self._device_uuid

            hue, saturation = color
            color_data = {
                'action': 'setcolor',
                'hue': int(hue),
                'saturation': int(saturation)
            }

            response = self._abode.send_request("post", url, data=color_data)
            response_object = json.loads(response.text)

            _LOGGER.debug("Set Color Response: %s", response.text)

            if response_object['idForPanel'] != self.device_id:
                raise AbodeException((ERROR.SET_STATUS_DEV_ID))

            # Abode will sometimes return hue value off by 1 (rounding error)
            hue_comparison = math.isclose(response_object["hue"],
                                          int(hue),
                                          abs_tol=1)
            if not hue_comparison or (response_object["saturation"] !=
                                      int(saturation)):
                _LOGGER.warning(
                    ("Set color mismatch for device %s. "
                     "Request val: %s, Response val: %s "), self.device_id,
                    (hue, saturation),
                    (response_object['hue'], response_object['saturation']))

                hue = response_object['hue']
                saturation = response_object['saturation']

            self.update({'statuses': {'hue': hue, 'saturation': saturation}})

            _LOGGER.info("Set device %s color to: %s", self.device_id,
                         (hue, saturation))

            return True

        return False
예제 #24
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def set_setting(self, setting, value, area='1', validate_value=True):
        """Set an abode system setting to a given value."""
        setting = setting.lower()

        if setting not in CONST.ALL_SETTINGS:
            raise AbodeException(ERROR.INVALID_SETTING, CONST.ALL_SETTINGS)

        if setting in CONST.PANEL_SETTINGS:
            url = CONST.SETTINGS_URL
            data = self._panel_settings(setting, value, validate_value)
        elif setting in CONST.AREA_SETTINGS:
            url = CONST.AREAS_URL
            data = self._area_settings(area, setting, value, validate_value)
        elif setting in CONST.SOUND_SETTINGS:
            url = CONST.SOUNDS_URL
            data = self._sound_settings(area, setting, value, validate_value)
        elif setting in CONST.SIREN_SETTINGS:
            url = CONST.SIREN_URL
            data = self._siren_settings(setting, value, validate_value)

        return self.send_request(method="put", url=url, data=data)
예제 #25
0
    def set_active(self, active):
        """Activate and deactivate an automation."""
        url = CONST.AUTOMATION_EDIT_URL
        url = url.replace('$AUTOMATIONID$', self.automation_id)

        self._automation['is_active'] = str(int(active))

        response = self._abode.send_request(method="put",
                                            url=url,
                                            data=self._automation)

        response_object = json.loads(response.text)

        if isinstance(response_object, (tuple, list)):
            response_object = response_object[0]

        if (str(response_object['id']) != str(self._automation['id']) or
                response_object['is_active'] != self._automation['is_active']):
            raise AbodeException((ERROR.INVALID_AUTOMATION_EDIT_RESPONSE))

        self.update(response_object)

        return True
예제 #26
0
파일: camera.py 프로젝트: thedeany/abodepy
    def capture(self):
        """Request a new camera image."""
        # Abode IP cameras use a different URL for image captures.
        if 'control_url_snapshot' in self._json_state:
            url = CONST.BASE_URL + self._json_state['control_url_snapshot']

        elif 'control_url' in self._json_state:
            url = CONST.BASE_URL + self._json_state['control_url']

        else:
            raise AbodeException((ERROR.MISSING_CONTROL_URL))

        try:
            response = self._abode.send_request("put", url)

            _LOGGER.debug("Capture image response: %s", response.text)

            return True

        except AbodeException as exc:
            _LOGGER.warning("Failed to capture image: %s", exc)

        return False
예제 #27
0
파일: __init__.py 프로젝트: vickyg3/abodepy
    def set_default_mode(self, default_mode):
        """Set the default mode when alarms are turned 'on'."""
        if default_mode.lower() not in (CONST.MODE_AWAY, CONST.MODE_HOME):
            raise AbodeException(ERROR.INVALID_DEFAULT_ALARM_MODE)

        self._default_alarm_mode = default_mode.lower()