From 9cc231dd51a7ddebc016aa0459a47227ac60a60d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christophe=20D=C3=A9sirant?= Date: Mon, 16 Nov 2020 10:47:04 +0100 Subject: [PATCH] Converting the sensor in a switch, and give the possibility to use the switch to activate/disactivate the presence simulation --- README.md | 19 +++++++---- __init__.py | 19 +++++------ const.py | 4 +-- sensor.py | 94 ----------------------------------------------------- 4 files changed, 23 insertions(+), 113 deletions(-) delete mode 100644 sensor.py diff --git a/README.md b/README.md index 47d6d2e..95a10bb 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,16 @@ You can edit these configurations afterwards by clicking on Options in the integ # Use it -The component will create an entity called `sensor.presence_simulation`. This entity will be set to `on` when the entity is running. `off` otherwise. +The component will create an entity called `switch.presence_simulation`. This entity will be set to `on` when the entity is running. `off` otherwise. +You have 2 ways of launching the simulation: +## With the switch +Toggling the `switch.presence_simulation` will toggle the presence simulation. + +## With the services Three services are available: -## Start the simulation -The service `presence_simulation.start` will start the simulation and set the `sensor.presence_simulation` entity to `on`. -## Stop the simulation -The service `presence_simulation.stop` will stop the simulation and set the `sensor.presence_simulation` entity to `off`. -## Toggle the simulation -The service `presence_simulation.toggle` will start or stop the simulation, depending on the current state of the `sensor.presence_simulation` entity. +### Start the simulation +The service `presence_simulation.start` will start the simulation and set the `switch.presence_simulation` entity to `on`. +### Stop the simulation +The service `presence_simulation.stop` will stop the simulation and set the `switch.presence_simulation` entity to `off`. +### Toggle the simulation +The service `presence_simulation.toggle` will start or stop the simulation, depending on the current state of the `switch.presence_simulation` entity. diff --git a/__init__.py b/__init__.py index afc685e..371845e 100644 --- a/__init__.py +++ b/__init__.py @@ -5,11 +5,10 @@ import asyncio from datetime import datetime,timedelta,timezone from homeassistant.components import history -from .sensor import PresenceSimulationSwitch from .const import ( DOMAIN, - SENSOR_PLATFORM, - SENSOR + SWITCH_PLATFORM, + SWITCH ) _LOGGER = logging.getLogger(__name__) @@ -19,7 +18,7 @@ async def async_setup_entry(hass, entry): unsub = entry.add_update_listener(update_listener) # Use `hass.async_create_task` to avoid a circular dependency between the platform and the component - hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, SENSOR_PLATFORM)) + hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, SWITCH_PLATFORM)) return await async_mysetup(hass, [entry.data["entities"]], entry.data["delta"]) async def async_setup(hass, config): @@ -37,8 +36,8 @@ async def async_mysetup(hass, entities, deltaStr): async def stop_presence_simulation(err=None): """Stop the presence simulation, raising a potential error""" - entity = hass.data[DOMAIN][SENSOR_PLATFORM][SENSOR] - entity.turn_off() + entity = hass.data[DOMAIN][SWITCH_PLATFORM][SWITCH] + entity.internal_turn_off() if err is not None: _LOGGER.debug("Error in presence simulation, exiting") raise e @@ -74,13 +73,13 @@ async def async_expand_entities(entities): async def handle_presence_simulation(call): """Start the presence simulation""" - entity = hass.data[DOMAIN][SENSOR_PLATFORM][SENSOR] + entity = hass.data[DOMAIN][SWITCH_PLATFORM][SWITCH] _LOGGER.debug("Is already running ? %s", entity.state) if is_running(): _LOGGER.warning("Presence simulation already running") return running = True - entity.turn_on() + entity.internal_turn_on() _LOGGER.debug("Started presence simulation") current_date = datetime.now(timezone.utc) @@ -124,7 +123,7 @@ async def simulate_single_entity(entity_id, hist): for state in hist: #hypothsis: states are ordered chronologically _LOGGER.debug("State %s", state.as_dict()) _LOGGER.debug("Switch of %s foreseen at %s", entity_id, state.last_changed+timedelta(delta)) - entity = hass.data[DOMAIN][SENSOR_PLATFORM][SENSOR] + entity = hass.data[DOMAIN][SWITCH_PLATFORM][SWITCH] await entity.async_add_next_event(state.last_changed+timedelta(delta), entity_id, state.state) while is_running(): @@ -154,7 +153,7 @@ async def update_entity(entity_id, state): def is_running(): """Returns true if the simulation is running""" - entity = hass.data[DOMAIN][SENSOR_PLATFORM][SENSOR] + entity = hass.data[DOMAIN][SWITCH_PLATFORM][SWITCH] return entity.is_on diff --git a/const.py b/const.py index b05aa68..bf09f8c 100644 --- a/const.py +++ b/const.py @@ -1,3 +1,3 @@ DOMAIN = "presence_simulation" -SENSOR_PLATFORM = "sensor" -SENSOR = "presence_simulation" +SWITCH_PLATFORM = "switch" +SWITCH = "presence_simulation" diff --git a/sensor.py b/sensor.py deleted file mode 100644 index 3938001..0000000 --- a/sensor.py +++ /dev/null @@ -1,94 +0,0 @@ -from homeassistant.helpers.entity import ToggleEntity -from datetime import datetime, timezone, timedelta -import math -import logging -from .const import ( - DOMAIN, - SENSOR_PLATFORM, - SENSOR -) -SCAN_INTERVAL = timedelta(seconds=5) -_LOGGER = logging.getLogger(__name__) - -async def async_setup_platform(hass, _, async_add_entities, discovery_info=None): - """Create presence simulation entity defined in YAML and add them to HA.""" - _LOGGER.debug("async_setup_platform") - if PresenceSimulationSwitch.instances == 0: - async_add_entities([PresenceSimulationSwitch(hass)], True) - - -async def async_setup_entry(hass, config_entry, async_add_devices): - _LOGGER.debug("async_setup_entry") - """Create presence simulation entities defined in config_flow and add them to HA.""" - if PresenceSimulationSwitch.instances == 0: - async_add_devices([PresenceSimulationSwitch(hass)], True) - -class PresenceSimulationSwitch(ToggleEntity): - instances = 0 - - def __init__(self, hass): - self.turn_off() - self.hass = hass - self.attr={} - self.attr["friendly_name"] = "Presence Simulation Toggle" - self._next_events = [] - PresenceSimulationSwitch.instances += 1 - pass - - @property - def name(self): - return "Presence Simulation" - - @property - def is_on(self): - return self._state == "on" - - @property - def state(self): - return self._state - - def turn_on(self, **kwargs): - self._state = "on" - - def turn_off(self, **kwargs): - self._state = "off" - self._next_events = [] - - async def async_update(self): - if len(self._next_events) > 0: - self.attr["next_event_datetime"], self.attr["next_entity_id"], self.attr["next_entity_state"] = sorted(self._next_events)[0] - else: - for prop in ("next_event_datetime", "next_entity_id", "next_entity_state"): - if prop in self.attr: - del self.attr[prop] - - def update(self): - if len(self._next_events) > 0: - self.attr["next_event_datetime"], self.attr["next_entity_id"], self.attr["next_entity_state"] = sorted(self._next_events)[0] - else: - for prop in ("next_event_datetime", "next_entity_id", "next_entity_state"): - if prop in self.attr: - del self.attr[prop] - - @property - def device_state_attributes(self): - return self.attr - - async def async_added_to_hass(self): - """When sensor is added to hassio.""" - await super().async_added_to_hass() - if DOMAIN not in self.hass.data: - self.hass.data[DOMAIN] = {} - if SENSOR_PLATFORM not in self.hass.data[DOMAIN]: - self.hass.data[DOMAIN][SENSOR_PLATFORM] = {} - self.hass.data[DOMAIN][SENSOR_PLATFORM][SENSOR] = self - - async def async_add_next_event(self, next_datetime, entity_id, state): - self._next_events.append((next_datetime, entity_id, state)) - - async def async_remove_event(self, entity_id): - i=0 - for e in self._next_events: - if e[1] == entity_id: - del self._next_events[i] - i += 1