diff --git a/.devcontainer/configuration.yaml b/.devcontainer/configuration.yaml index 3984f8e..5b7d39a 100644 --- a/.devcontainer/configuration.yaml +++ b/.devcontainer/configuration.yaml @@ -4,7 +4,8 @@ default_config: logger: default: info logs: - custom_components.comelit: debug + custom_components.comelit.hub: debug + custom_components.comelit.vedo: debug comelit: hub: @@ -22,3 +23,4 @@ comelit: port: 80 password: xxxxxx scan_interval: 30 + binary_sensors: disable diff --git a/configuration.yaml b/configuration.yaml index 366420f..b2b517d 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -13,4 +13,5 @@ comelit: host: X.X.X.X port: 80 password: xxxxxx - scan_interval: 30 \ No newline at end of file + scan_interval: 30 + binary_sensors: disable \ No newline at end of file diff --git a/custom_components/comelit/__init__.py b/custom_components/comelit/__init__.py index c0cf27e..d2ed493 100644 --- a/custom_components/comelit/__init__.py +++ b/custom_components/comelit/__init__.py @@ -3,7 +3,8 @@ import logging import voluptuous as vol import homeassistant.helpers.config_validation as cv -from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD, CONF_PORT, CONF_SCAN_INTERVAL) +from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD, CONF_PORT, CONF_SCAN_INTERVAL, + CONF_BINARY_SENSORS) from .hub import ComelitHub from .vedo import ComelitVedo from .const import DOMAIN, CONF_MQTT_USER, CONF_MQTT_PASSWORD, CONF_SERIAL, CONF_CLIENT @@ -29,7 +30,8 @@ vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_PORT, default=80): cv.port, vol.Required(CONF_PASSWORD): cv.string, - vol.Optional(CONF_SCAN_INTERVAL, default=1): cv.positive_int + vol.Optional(CONF_SCAN_INTERVAL, default=1): cv.positive_int, + vol.Optional(CONF_BINARY_SENSORS, default=False): cv.boolean } ) @@ -73,9 +75,10 @@ def setup(hass, config): vedo_port = schema[CONF_PORT] vedo_pwd = schema[CONF_PASSWORD] scan_interval = schema[CONF_SCAN_INTERVAL] - vedo = ComelitVedo(vedo_host, vedo_port, vedo_pwd, scan_interval) + expose_bin_sensors = schema[CONF_BINARY_SENSORS] + vedo = ComelitVedo(vedo_host, vedo_port, vedo_pwd, scan_interval, expose_bin_sensors) hass.data[DOMAIN]['vedo'] = vedo - # hass.helpers.discovery.load_platform('binary_sensor', DOMAIN, {}, config) + hass.helpers.discovery.load_platform('binary_sensor', DOMAIN, {}, config) hass.helpers.discovery.load_platform('alarm_control_panel', DOMAIN, {}, config) _LOGGER.info("Comelit Vedo integration started") diff --git a/custom_components/comelit/binary_sensor.py b/custom_components/comelit/binary_sensor.py index 760b240..87c203e 100644 --- a/custom_components/comelit/binary_sensor.py +++ b/custom_components/comelit/binary_sensor.py @@ -10,11 +10,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None): - if hass.data[DOMAIN]['hub'] is not None: - hass.data[DOMAIN]['hub'].binary_sensor_add_entities = add_entities - if hass.data[DOMAIN]['vedo'] is not None: + if 'vedo' in hass.data[DOMAIN] and hass.data[DOMAIN]['vedo'] is not None: hass.data[DOMAIN]['vedo'].binary_sensor_add_entities = add_entities - _LOGGER.info("Comelit Binary Sensor Integration started") + _LOGGER.info("Comelit Vedo Binary Sensor Integration started") class VedoSensor(ComelitDevice, BinarySensorEntity): diff --git a/custom_components/comelit/exception.py b/custom_components/comelit/exception.py new file mode 100644 index 0000000..a37c961 --- /dev/null +++ b/custom_components/comelit/exception.py @@ -0,0 +1,2 @@ +class CookieException(Exception): + pass diff --git a/custom_components/comelit/vedo.py b/custom_components/comelit/vedo.py index 6c3c08b..816b3b7 100644 --- a/custom_components/comelit/vedo.py +++ b/custom_components/comelit/vedo.py @@ -7,8 +7,9 @@ from threading import Thread from wrapt_timeout_decorator import timeout from homeassistant.const import STATE_ALARM_DISARMED, STATE_ALARM_ARMED_AWAY, STATE_ON, STATE_OFF -from .binary_sensor import VedoSensor +from custom_components.comelit.binary_sensor import VedoSensor from custom_components.comelit.alarm_control_panel import VedoAlarm +from custom_components.comelit.exception import CookieException _LOGGER = logging.getLogger(__name__) @@ -33,7 +34,7 @@ class VedoRequest: # Manage the Comelit Vedo Central. Fetches the alarm status and the motion status. class ComelitVedo: - def __init__(self, host, port, password, scan_interval): + def __init__(self, host, port, password, scan_interval, expose_bin_sensors): """Initialize the sensor.""" _LOGGER.info(f"Initialising ComelitVedo with host {host}, port {port}") self.sensors = {} @@ -41,7 +42,7 @@ def __init__(self, host, port, password, scan_interval): self.host = host self.port = port self.password = password - self._scan_interval = scan_interval + self.expose_bin_sensors = expose_bin_sensors thread1 = SensorUpdater("Thread#BS", scan_interval, self) thread1.start() @@ -63,7 +64,6 @@ def build_http(self, headers, uid, path): url = "http://{0}:{1}/{2}&_={3}".format(self.host, self.port, path, millis) else: url = "http://{0}:{1}/{2}?_={3}".format(self.host, self.port, path, millis) - _LOGGER.info(f"Build URL: {url}") return url, headers # Do the GET from the vedo IP @@ -97,13 +97,14 @@ def login(self): if response.status_code == 200: uid = response.headers.get('set-cookie') if uid is not None: - _LOGGER.info("Logged in, %s", response.text) + _LOGGER.debug("Logged in, %s", response.text) return uid else: _LOGGER.warning("Error doing the login %s", response.text) raise Exception("Unable to obtain the cookie") else: _LOGGER.error("Bad login response! - %s", response.text) + return None # Do the logout. Ignore errors def logout(self, uid): @@ -148,6 +149,8 @@ def disarm(self, id): # update the binary motion detection sensor def update_sensor(self, s): + if s is None: + return try: id = s["id"] name = s["name"] @@ -155,17 +158,19 @@ def update_sensor(self, s): state = STATE_ON else: state = STATE_OFF - sensor = VedoSensor(id, name, state) if id not in self.sensors: + # Add new sensor if hasattr(self, 'binary_sensor_add_entities'): + sensor = VedoSensor(id, name, state) self.binary_sensor_add_entities([sensor]) self.sensors[id] = sensor _LOGGER.info("added the binary sensor %s %s", name, sensor.entity_name) else: - _LOGGER.debug("updating the binary sensor %s %s", name, sensor.entity_name) + # update existing sensor self.sensors[id].update_state(state) + _LOGGER.debug("updated the binary sensor %s", name) except Exception as e: - _LOGGER.exception("Error updating sensor %s", e) + _LOGGER.exception("Error updating the sensor %s", e) # update the alarm area def update_area(self, area): @@ -178,18 +183,18 @@ def update_area(self, area): else: state = STATE_ALARM_DISARMED - alarm_area = VedoAlarm(id, name, state, self) if id not in self.areas: if hasattr(self, 'alarm_add_entities'): + alarm_area = VedoAlarm(id, name, state, self) self.alarm_add_entities([alarm_area]) self.areas[id] = alarm_area _LOGGER.info("added the alarm area %s %s", name, alarm_area.entity_name) else: self.areas[id].update_state(state) - _LOGGER.debug("updated the alarm area %s %s", name, alarm_area.entity_name) + _LOGGER.debug("updated the alarm area %s", name) except Exception as e: - _LOGGER.exception("Error updating alarm area %s", e) + _LOGGER.exception("Error updating the alarm area %s", e) # Update the binary sensors @@ -204,7 +209,8 @@ def __init__(self, name, scan_interval, vedo: ComelitVedo): # Invalidate the uid def logout(self): - self._vedo.logout(self._uid) + if self._vedo is not None: + self._vedo.logout(self._uid) self._uid = None # Polls the sensors @@ -238,7 +244,7 @@ def run(self): for i in range(len(in_area)): value = in_area[i] if value == 'Not logged': - raise Exception("cookie expired") + raise CookieException("cookie expired") if value > 1: sensor_dict = {"index": i, "id": i, "name": description[i], "status": zone_statuses[i]} @@ -246,8 +252,9 @@ def run(self): sensors.append(sensor_dict) if self._uid is not None: - # for sensor in sensors: - # self._vedo.update_sensor(sensor) + if self._vedo.expose_bin_sensors: + for sensor in sensors: + self._vedo.update_sensor(sensor) p1_pres = areas_desc["p1_pres"] p2_pres = areas_desc["p2_pres"] @@ -274,7 +281,8 @@ def run(self): "in_time": in_time[i], "out_time": out_time[i]} self._vedo.update_area(area) - + except CookieException: + self.logout() except Exception as e: _LOGGER.error("Error getting data! %s", e) self.logout()