diff --git a/custom_components/dirigera_platform/__init__.py b/custom_components/dirigera_platform/__init__.py index dc7ddb3..0985920 100644 --- a/custom_components/dirigera_platform/__init__.py +++ b/custom_components/dirigera_platform/__init__.py @@ -71,11 +71,12 @@ async def async_setup_entry(hass: core.HomeAssistant, entry: config_entries.Conf hass.data[DOMAIN][entry.entry_id] = hass_data # Setup the entities - hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "light")) - hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "switch")) - hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")) - hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "sensor")) - hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "cover")) + #hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "light")) + #hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "switch")) + #hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "binary_sensor")) + #hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "sensor")) + #hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "cover")) + hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "fan")) logger.debug("Complete async_setup_entry...") @@ -97,7 +98,8 @@ async def async_unload_entry(hass: core.HomeAssistant, entry: config_entries.Con hass.config_entries.async_forward_entry_unload(entry, "switch"), hass.config_entries.async_forward_entry_unload(entry, "binary_sensor"), hass.config_entries.async_forward_entry_unload(entry, "sensor"), - hass.config_entries.async_forward_entry_unload(entry, "cover") + hass.config_entries.async_forward_entry_unload(entry, "cover"), + hass.config_entries.async_forward_entry_unload(entry, "fan") ] )] ) diff --git a/custom_components/dirigera_platform/binary_sensor.py b/custom_components/dirigera_platform/binary_sensor.py index 54443dd..cb5d695 100644 --- a/custom_components/dirigera_platform/binary_sensor.py +++ b/custom_components/dirigera_platform/binary_sensor.py @@ -32,13 +32,13 @@ async def async_setup_entry( # If mock then start with mocks if config[CONF_IP_ADDRESS] == "mock": logger.warning("Setting up mock motion sensors") - mock_motion_sensor1 = ikea_motion_sensor_mock(hub,"mock_motion_sensor1") - mock_motion_sensor2 = ikea_motion_sensor_mock(hub,"mock_motion_sensor2") + mock_motion_sensor1 = ikea_motion_sensor_mock() + mock_motion_sensor2 = ikea_motion_sensor_mock() motion_sensors = [mock_motion_sensor1,mock_motion_sensor2] logger.warning("Setting up mock open/close sensors") - mock_open_close_sensor1 = ikea_open_close_mock(hub,"mock_open_close_sensor1") - mock_open_close_sensor2 = ikea_open_close_mock(hub,"mock_open_close_sensor2") + mock_open_close_sensor1 = ikea_open_close_mock() + mock_open_close_sensor2 = ikea_open_close_mock() open_close_sensors = [mock_open_close_sensor1,mock_open_close_sensor2] else: diff --git a/custom_components/dirigera_platform/cover.py b/custom_components/dirigera_platform/cover.py index 0f14945..773bacb 100644 --- a/custom_components/dirigera_platform/cover.py +++ b/custom_components/dirigera_platform/cover.py @@ -122,7 +122,7 @@ def set_cover_position(self, **kwargs): self._json_data.set_target_position(position) def update(self): - logger.debug("outlet update...") + logger.debug("cover update...") try: self._json_data = self._hub.get_blinds_by_id(self._json_data.id) except Exception as ex: diff --git a/custom_components/dirigera_platform/dirigera_lib_patch.py b/custom_components/dirigera_platform/dirigera_lib_patch.py index 7d15b77..c2b1957 100644 --- a/custom_components/dirigera_platform/dirigera_lib_patch.py +++ b/custom_components/dirigera_platform/dirigera_lib_patch.py @@ -3,6 +3,7 @@ from dirigera.devices.motion_sensor import MotionSensor from dirigera.devices.open_close_sensor import OpenCloseSensor, dict_to_open_close_sensor from dirigera.devices.environment_sensor import EnvironmentSensor, dict_to_environment_sensor +from dirigera.devices.air_purifier import AirPurifier, dict_to_air_purifier from dirigera.hub.abstract_smart_home_hub import AbstractSmartHomeHub from typing import Any, Dict, List @@ -50,4 +51,10 @@ def get_blinds_by_id(self, id_: str) -> OpenCloseSensor: blind_sensor = self._get_device_data_by_id(id_) if blind_sensor["deviceType"] != "blinds": raise ValueError("Device is not a Blind") - return dict_to_environment_sensor(blind_sensor, self) \ No newline at end of file + return dict_to_environment_sensor(blind_sensor, self) + + def get_air_purifier_by_id(self, id_: str) -> AirPurifier: + air_purifier_device = self._get_device_data_by_id(id_) + if air_purifier_device["deviceType"] != "airPurifier": + raise ValueError("Device is not an Air Purifier") + return dict_to_air_purifier(air_purifier_device, self) \ No newline at end of file diff --git a/custom_components/dirigera_platform/fan.py b/custom_components/dirigera_platform/fan.py new file mode 100644 index 0000000..e690148 --- /dev/null +++ b/custom_components/dirigera_platform/fan.py @@ -0,0 +1,442 @@ +from homeassistant import config_entries, core +from homeassistant.const import CONF_IP_ADDRESS, CONF_TOKEN +from homeassistant.core import HomeAssistantError +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.components.sensor import SensorDeviceClass +from homeassistant.components.sensor import SensorEntity +from homeassistant.components.binary_sensor import BinarySensorEntity, BinarySensorDeviceClass +from homeassistant.components.switch import SwitchEntity, SwitchDeviceClass + +from homeassistant.components.fan import FanEntity, FanEntityFeature + +from .dirigera_lib_patch import HubX +from dirigera.devices.air_purifier import FanModeEnum + +from .const import DOMAIN +from .mocks.ikea_air_purifier_mock import ikea_starkvind_air_purifier_mock_device +import datetime +import logging +import math + +logger = logging.getLogger("custom_components.dirigera_platform") + +async def async_setup_entry( + hass: core.HomeAssistant, + config_entry: config_entries.ConfigEntry, + async_add_entities, +): + logger.debug("FAN/AirPurifier Starting async_setup_entry") + """Setup sensors from a config entry created in the integrations UI.""" + config = hass.data[DOMAIN][config_entry.entry_id] + logger.debug(config) + + hub = HubX(config[CONF_TOKEN], config[CONF_IP_ADDRESS]) + + air_purifiers = [] + + # If mock then start with mocks + if config[CONF_IP_ADDRESS] == "mock": + logger.warning("Setting up mock air purifier") + mock_air_purifier1 = ikea_starkvind_air_purifier_mock_device() + air_purifiers = [mock_air_purifier1] + #ikea_vindstyrka_temperature.async_will_remove_from_hass = ikea_vindstyrka_device_mock.async_will_remove_from_hass + + else: + hub_air_purifiers = await hass.async_add_executor_job(hub.get_air_purifiers) + air_purifiers = [ikea_starkvind_air_purifier_device(hub, air_purifier) for air_purifier in hub_air_purifiers] + + sensor_to_add = [] + logger.debug("Found {} air_purifier devices to setup...".format(len(air_purifiers))) + + for air_purifier_device in air_purifiers: + # Fan Entity + sensor_to_add.append(ikea_starkvind_air_purifier_fan(air_purifier_device)) + + # Separate BinarySensor Entitiy is created for the following + # 1. filterAlarmStatus - BinarySensor + sensor_to_add.append(ikea_starkvind_air_purifier_binary_sensor(air_purifier_device, BinarySensorDeviceClass.PROBLEM,"Filter Alarm Status","filter_alarm_status","mdi:alarm-light-outline")) + + # Seperate SwitchEnity are created for the folllwing + # 1. childLock - BinarySensor + # 2. statusLight - BinarySensor + sensor_to_add.append(ikea_starkvind_air_purifier_switch_sensor(air_purifier_device,"Child Lock","child_lock","set_child_lock","mdi:account-lock-outline")) + sensor_to_add.append(ikea_starkvind_air_purifier_switch_sensor(air_purifier_device,"Status Light","status_light","set_status_light","mdi:lightbulb")) + + # Seperate SensorEntity are created for the folllwing + # 1. filterLifeTime - Sensor + # 2. filterElapsedtime - Sensor + # 3. CurrentPM25 - Sensor + # 4. MotorRunTime - Sensor + sensor_to_add.append(ikea_starkvind_air_purifier_sensor(air_purifier_device,"Filter Lifetime",SensorDeviceClass.DURATION,"filter_lifetime","min","mdi:clock-time-eleven-outline")) + sensor_to_add.append(ikea_starkvind_air_purifier_sensor(air_purifier_device,"Filter Elapsed Time",SensorDeviceClass.DURATION,"filter_elapsed_time","min","mdi:timelapse")) + sensor_to_add.append(ikea_starkvind_air_purifier_sensor(air_purifier_device,"Current pm25",SensorDeviceClass.PM25,"current_p_m25","µg/m³","mdi:molecule")) + sensor_to_add.append(ikea_starkvind_air_purifier_sensor(air_purifier_device,"Motor Runtime",SensorDeviceClass.DURATION,"motor_runtime","min","mdi:run-fast")) + + async_add_entities(sensor_to_add) + logger.debug("FAN/AirPurifier Complete async_setup_entry") + +class ikea_starkvind_air_purifier_device: + def __init__(self, hub, json_data) -> None: + self._json_data = json_data + self._updated_at = None + self._hub = hub + self._updated_at = None + logger.debug("Air purifer Fan Entity ctor complete...") + + def update(self): + if self._updated_at is None or \ + (datetime.datetime.now() - self._updated_at).total_seconds() > 30: + try: + self._json_data = self._hub.get_air_purifier_by_id(self._json_data.id) + self._updated_at = datetime.datetime.now() + except Exception as ex: + logger.error("error encountered running update on : {}".format(self.name)) + logger.error(ex) + raise HomeAssistantError(ex,DOMAIN,"hub_exception") + + @property + def available(self): + return self._json_data.is_reachable + + @property + def device_info(self) -> DeviceInfo: + return DeviceInfo( + identifiers={("dirigera_platform",self._json_data.id)}, + name = self._json_data.attributes.custom_name, + manufacturer = self._json_data.attributes.manufacturer, + model=self._json_data.attributes.model , + sw_version=self._json_data.attributes.firmware_version + ) + + @property + def name(self) -> str: + return self._json_data.attributes.custom_name + + @property + def unique_id(self): + return self._json_data.id + + @property + def supported_features(self): + return FanEntityFeature.PRESET_MODE | FanEntityFeature.SET_SPEED + + @property + def motor_state(self) -> int: + return self._json_data.motor_state + + @property + def percentage(self) -> int: + # Scale the 1-50 into + return math.ceil(self.motor_state * 100/50) + + @property + def fan_mode_sequence(self) -> str: + return self._json_data.fan_mode_sequence + + @property + def preset_modes(self): + return [ e.value for e in FanModeEnum] + + @property + def preset_mode(self) -> str: + return self._json_data.fan_mode + + @property + def speed_count(self): + return 50 + + @property + def motor_runtime(self): + return self._json_data.motor_runtime + + @property + def filter_alarm_status(self) -> bool: + return self._json_data.fan_alarm_status + + @property + def filter_elapsed_time(self) -> int: + return self._json_data.filter_elapsed_time + + @property + def filter_lifetime(self) -> int: + return self._json_data.filter_lifetime + + @property + def current_p_m25(self) -> int: + return self._json_data.current_p_m25 + + @property + def status_light(self) -> bool: + return self._json_data.status_light + + @property + def child_lock(self) -> bool: + return self._json_data.child_lock + + @property + def is_on(self): + if self.available and self.motor_state > 0: + return True + return False + + def set_percentage(self, percentage: int) -> None: + # Convert percent to speed + desired_speed = math.ceil(percentage * 50 / 100) + logger.debug("set_percentage got : {}, scaled to : {}".format(percentage, desired_speed)) + self.json_data.set_motor_state(desired_speed) + + def set_status_light(self, status:bool) -> None: + logger.debug("set_status_light : {}".format(status)) + self._json_data.set_status_light(status) + + def set_child_lock(self, status: bool) -> None: + logger.debug("set_child_lock : {}".format(status)) + self._json_data.set_child_lock(status) + + def set_fan_mode(self, preset_mode: FanModeEnum) -> None: + logger.debug("set_fan_mode : {}".format(preset_mode.value)) + self.json_data.set_fan_mode(preset_mode) + + def set_preset_mode(self, preset_mode: str): + logger.debug("set_preset_mode : {}".format(preset_mode)) + mode_to_set = None + if preset_mode == FanModeEnum.AUTO: + mode_to_set = FanModeEnum.AUTO + elif preset_mode == FanModeEnum.HIGH: + mode_to_set = FanModeEnum.HIGH + elif preset_mode == FanModeEnum.MEDIUM: + mode_to_set = FanModeEnum.MEDIUM + elif preset_mode == FanModeEnum.LOW: + mode_to_set = FanModeEnum.LOW + + if mode_to_set is None: + logger.error("Non defined preset used to set : {}".format(preset_mode)) + return + + logger.debug("set_preset_mode equated to : {}".format(mode_to_set.value)) + self.set_fan_mode(mode_to_set) + + def turn_on(self, percentage = None, preset_mode = None) -> None: + logger.debug("Airpurifier call to turn_on with percentage: {}, preset_mode: {}".format(percentage, preset_mode)) + if preset_mode is not None: + self.set_preset_mode(preset_mode) + elif percentage is not None: + self.set_percentage(percentage) + else: + logger.debug("We were asked to be turned on but percentage and preset were not set, using last known") + if self.preset_mode is not None: + self.set_preset_mode(self.preset_mode) + elif self.percentage is not None: + self.set_percentage(self.percentage) + else: + logger.debug("No last known value, setting to auto") + self.set_preset_mode("auto") + + def turn_off(self, **kwargs) -> None: + self.set_percentage(0) + +class ikea_starkvind_air_purifier_fan(FanEntity): + def __init__(self, device:ikea_starkvind_air_purifier_device) -> None: + self._device = device + + @property + def available(self): + return self._device.available + + @property + def device_info(self) -> DeviceInfo: + return self._device.device_info + + @property + def name(self): + return self._device.name + + @property + def preset_mode(self): + return self._device.preset_mode + + @property + def speed_count(self): + return self._device.speed_count + + @property + def unique_id(self) -> str: + return self._device.unique_id + + @property + def supported_features(self): + return self._device.supported_features + + @property + def is_on(self): + return self._device.is_on + + @property + def percentage(self): + return self._device.percentage + + @property + def preset_mode(self): + return self._device.preset_mode + + @property + def preset_modes(self): + return self._device.preset_modes + + @property + def speed_count(self): + return self._device.speed_count + + def update(self): + self._device.update() + + def set_percentage(self, percentage: int) -> None: + self._device.set_percentage(percentage) + + def set_preset_mode(self, preset_mode: str): + self._device.set_preset_mode(preset_mode) + + def turn_on(self, percentage = None, preset_mode = None) -> None: + self._device.turn_on(percentage, preset_mode) + + def turn_off(self, **kwargs) -> None: + self._device.turn_off() + +class ikea_starkvind_air_purifier_sensor(SensorEntity): + def __init__(self, device:ikea_starkvind_air_purifier_device, prefix: str, device_class: SensorDeviceClass, native_value_prop: str, native_uom: str, icon_name: str): + self._device = device + self._prefix = prefix + self._native_value_prop = native_value_prop + self._device_class = device_class + self._native_unit_of_measurement = native_uom + self._icon = icon_name + + def update(self): + self._device.update() + + @property + def icon(self): + return "mdi:air-filter" + + @property + def name(self): + return self._device.name + " " + self._prefix.replace("_"," ") + + @property + def unique_id(self) -> str: + return self._device.unique_id + self._prefix + + @property + def available(self): + return self._device.available + + @property + def device_info(self) -> DeviceInfo: + return self._device.device_info + + @property + def device_class(self): + return self._device_class + + @property + def native_unit_of_measurement(self) -> str: + return self._native_unit_of_measurement + + @property + def native_value(self): + return getattr(self._device, self._native_value_prop) + +class ikea_starkvind_air_purifier_binary_sensor(BinarySensorEntity): + def __init__(self, device:ikea_starkvind_air_purifier_device, device_class: BinarySensorDeviceClass, prefix: str, native_value_prop: str, icon_name: str): + self._device = device + self._prefix = prefix + self._device_class = device_class + self._native_value_prop = native_value_prop + self._icon = icon_name + + def update(self): + self._device.update() + + @property + def name(self): + return self._device.name + " " + self._prefix.replace("_"," ") + + @property + def unique_id(self) -> str: + return self._device.unique_id + self._prefix + + @property + def available(self): + return self._device.available + + @property + def device_info(self) -> DeviceInfo: + return self._device.device_info + + @property + def device_class(self): + return self._device_class + + @property + def is_on(self): + return getattr(self._device, self._native_value_prop) + + def async_turn_off(self): + pass + + def async_handle_turn_on_service(self): + pass + +class ikea_starkvind_air_purifier_switch_sensor(SwitchEntity): + def __init__(self, device:ikea_starkvind_air_purifier_device, prefix: str, is_on_prop: str, turn_on_off_fx: str, icon_name: str): + self._device = device + self._prefix = prefix + self._is_on_prop = is_on_prop + self._turn_on_off = getattr(self._device, turn_on_off_fx) + self._icon = icon_name + + def update(self): + self._device.update() + + @property + def name(self): + return self._device.name + " " + self._prefix.replace("_"," ") + + @property + def unique_id(self) -> str: + return self._device.unique_id + self._prefix + + @property + def available(self): + return self._device.available + + @property + def device_info(self) -> DeviceInfo: + return self._device.device_info + + @property + def device_class(self): + return SwitchDeviceClass.OUTLET + + @property + def is_on(self): + logger.debug("ikea_starkvind_air_purifier_switch_sensor is_on call..") + return getattr(self._device, self._is_on_prop) + + def async_handle_turn_on_service(self): + logger.debug("{} turn_on".format(self.name)) + try: + self._turn_on_off(True) + except Exception as ex: + logger.error("error encountered turning on : {}".format(self.name)) + logger.error(ex) + raise HomeAssistantError(ex,DOMAIN,"hub_exception") + + def turn_off(self): + logger.debug("{} turn_off".format(self.name)) + try: + self._turn_on_off(False) + except Exception as ex: + logger.error("error encountered turning off : {}".format(self.name)) + logger.error(ex) + raise HomeAssistantError(ex,DOMAIN,"hub_exception") \ No newline at end of file diff --git a/custom_components/dirigera_platform/light.py b/custom_components/dirigera_platform/light.py index 3c229f4..d2a3b0b 100644 --- a/custom_components/dirigera_platform/light.py +++ b/custom_components/dirigera_platform/light.py @@ -38,8 +38,8 @@ async def async_setup_entry( # If mock then start with mocks if config[CONF_IP_ADDRESS] == "mock": logger.warning("Setting up mock bulbs") - mock_bulb1 = ikea_bulb_mock(hub,"mock_bulb1") - mock_bulb2 = ikea_bulb_mock(hub,"mock_bulb2") + mock_bulb1 = ikea_bulb_mock() + mock_bulb2 = ikea_bulb_mock() lights = [mock_bulb1,mock_bulb2] else: hub_lights = await hass.async_add_executor_job(hub.get_lights) @@ -50,6 +50,8 @@ async def async_setup_entry( logger.debug("LIGHT Complete async_setup_entry") class ikea_bulb(LightEntity): + _attr_has_entity_name = True + def __init__(self, hub, json_data) -> None: logger.debug("ikea_bulb ctor...") self._hub = hub diff --git a/custom_components/dirigera_platform/manifest.json b/custom_components/dirigera_platform/manifest.json index 3b5d670..840a96e 100755 --- a/custom_components/dirigera_platform/manifest.json +++ b/custom_components/dirigera_platform/manifest.json @@ -8,6 +8,6 @@ "iot_class": "local_polling", "issue_tracker": "https://github.com/sanjoyg/dirigera_platform", "loggers": ["custom_components.dirigera_platform"], - "requirements": ["dirigera==1.0.6"], + "requirements": ["dirigera==1.0.10"], "version": "0.0.1" } diff --git a/custom_components/dirigera_platform/mocks/ikea_air_purifier_mock.py b/custom_components/dirigera_platform/mocks/ikea_air_purifier_mock.py new file mode 100644 index 0000000..58499d9 --- /dev/null +++ b/custom_components/dirigera_platform/mocks/ikea_air_purifier_mock.py @@ -0,0 +1,200 @@ +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.core import HomeAssistantError +from homeassistant.components.fan import FanEntity, FanEntityFeature + +import logging +import datetime +import math +from dirigera.devices.air_purifier import FanModeEnum +from ..sensor import ikea_vindstyrka_device +from ..const import DOMAIN + +logger = logging.getLogger("custom_components.dirigera_platform") + +class ikea_starkvind_air_purifier_mock_device: + counter = 0 + + def __init__(self) -> None: + ikea_starkvind_air_purifier_mock_device.counter = ikea_starkvind_air_purifier_mock_device.counter + 1 + self._name = "MOCK Air Purifier " + str(ikea_starkvind_air_purifier_mock_device.counter) + self._unique_id = "AP1907151129080101_" + str(ikea_starkvind_air_purifier_mock_device.counter) + self._updated_at = None + self._motor_state = 20 + self._status_light = True + self._child_lock = True + self._fan_mode = "auto" + logger.debug("Air purifer Mock Device ctor complete...") + + def update(self): + if self._updated_at is None or \ + (datetime.datetime.now() - self._updated_at).total_seconds() > 10: + try: + logger.info("AirPurifier Mock Update called...") + self._updated_at = datetime.datetime.now() + except Exception as ex: + logger.error("error encountered running update on : {}".format(self.name)) + logger.error(ex) + raise HomeAssistantError(ex,DOMAIN,"hub_exception") + + @property + def available(self): + return True + + @property + def is_on(self): + logger.debug("ikea_starkvind_air_purifier_mock_device is_on called...") + if self.available and self.motor_state > 0: + return True + return False + + @property + def device_info(self) -> DeviceInfo: + logger.info("Got device_info call on airpurifier mock...") + return DeviceInfo( + identifiers={("dirigera_platform",self._unique_id)}, + name = self._name, + manufacturer = "MOCK", + model="Mock 1.0" , + sw_version="Mock SW 1.0" + ) + + @property + def name(self) -> str: + logger.info("Returning name as {} airpurifier mock...".format(self._name)) + return self._name + + @property + def unique_id(self): + logger.info("Returning unique_id as {} airpurifier mock...".format(self._unique_id)) + return self._unique_id + + @property + def supported_features(self): + logger.debug("AirPurifier supported features called...") + return FanEntityFeature.PRESET_MODE | FanEntityFeature.SET_SPEED + + @property + def motor_state(self) -> int: + return self._motor_state + + @property + def percentage(self) -> int: + # Scale the 1-50 into + return math.ceil(self.motor_state * 100/50) + + @property + def fan_mode_sequence(self) -> str: + return "lowMediumHighAuto" + + @property + def preset_modes(self): + return [ e.value for e in FanModeEnum] + + @property + def preset_mode(self) -> str: + return self._fan_mode + + @property + def speed_count(self): + return 50 + + @property + def motor_runtime(self): + return 30 + + @property + def filter_alarm_status(self) -> bool: + return False + + @property + def filter_elapsed_time(self) -> int: + return 60 + + @property + def filter_lifetime(self) -> int: + return 90 + + @property + def current_p_m25(self) -> int: + return 241 + + @property + def status_light(self) -> bool: + logger.debug("air purifier mock status_light : {}".format(self._status_light)) + return self._status_light + + @property + def child_lock(self) -> bool: + logger.debug("air purifier mock child_lock : {}".format(self._child_lock)) + return self._child_lock + + def set_percentage(self, percentage: int) -> None: + # Convert percent to speed + desired_speed = math.ceil(percentage * 50 / 100) + logger.debug("set_percentage got : {}, scaled to : {}".format(percentage, desired_speed)) + self._motor_state = desired_speed + + def set_status_light(self, status:bool) -> None: + logger.debug("set_status_light : {}".format(status)) + self._status_light = status + + def set_child_lock(self, status: bool) -> None: + logger.debug("set_child_lock : {}".format(status)) + self._child_lock = status + + def set_fan_mode(self, preset_mode: FanModeEnum) -> None: + logger.debug("set_fan_mode : {}".format(preset_mode.value)) + self._fan_mode = str(preset_mode.value) + if preset_mode == FanModeEnum.AUTO: + self._motor_state =1 + elif preset_mode == FanModeEnum.HIGH: + self._motor_state = 50 + elif preset_mode == FanModeEnum.MEDIUM: + self._motor_state = 25 + elif preset_mode == FanModeEnum.LOW: + self._motor_state = 10 + else: + logger.debug("Unknown fan_mode called...") + + def set_preset_mode(self, preset_mode: str): + logger.debug("set_preset_mode : {}".format(preset_mode)) + mode_to_set = None + if preset_mode == FanModeEnum.AUTO.value: + mode_to_set = FanModeEnum.AUTO + elif preset_mode == FanModeEnum.HIGH.value: + mode_to_set = FanModeEnum.HIGH + elif preset_mode == FanModeEnum.MEDIUM.value: + mode_to_set = FanModeEnum.MEDIUM + elif preset_mode == FanModeEnum.LOW.value: + mode_to_set = FanModeEnum.LOW + + if mode_to_set is None: + logger.error("Non defined preset used to set : {}".format(preset_mode)) + return + + logger.debug("set_preset_mode equated to : {}".format(mode_to_set.value)) + self.set_fan_mode(mode_to_set) + + def turn_on(self, percentage = None, preset_mode = None, **kwargs) -> None: + + logger.debug("Airpurifier call to turn_on with percentage: {}, preset_mode: {}".format(percentage, preset_mode)) + if preset_mode is not None: + self.set_preset_mode(preset_mode) + elif percentage is not None: + self.set_percentage(percentage) + else: + logger.debug("We were asked to be turned on but percentage and preset were not set, using last know") + if self.preset_mode is not None: + self.set_preset_mode(self.preset_mode) + elif self.percentage is not None: + self.set_percentage(self.percentage) + else: + logger.debug("No last known value, setting to auto") + self.set_preset_mode("auto") + + + def turn_off(self, **kwargs) -> None: + self.set_percentage(0) + + async def async_will_remove_from_hass(self) -> None: + ikea_starkvind_air_purifier_mock_device.counter = ikea_starkvind_air_purifier_mock_device.counter - 1 \ No newline at end of file diff --git a/custom_components/dirigera_platform/mocks/ikea_bulb_mock.py b/custom_components/dirigera_platform/mocks/ikea_bulb_mock.py index ad0db49..058a74b 100644 --- a/custom_components/dirigera_platform/mocks/ikea_bulb_mock.py +++ b/custom_components/dirigera_platform/mocks/ikea_bulb_mock.py @@ -13,9 +13,8 @@ class ikea_bulb_mock(LightEntity): counter = 0 - def __init__(self, hub, hub_light) -> None: + def __init__(self) -> None: logger.debug("ikea_bulb mock ctor...") - self._hub = hub ikea_bulb_mock.counter = ikea_bulb_mock.counter + 1 self._manufacturer = "IKEA of Sweden" diff --git a/custom_components/dirigera_platform/mocks/ikea_motion_sensor_mock.py b/custom_components/dirigera_platform/mocks/ikea_motion_sensor_mock.py index e01b261..751c227 100644 --- a/custom_components/dirigera_platform/mocks/ikea_motion_sensor_mock.py +++ b/custom_components/dirigera_platform/mocks/ikea_motion_sensor_mock.py @@ -7,9 +7,7 @@ class ikea_motion_sensor_mock(BinarySensorEntity): counter = 0 - def __init__(self, hub, hub_outlet): - self._hub = hub - self._hub_outlet = hub_outlet + def __init__(self): ikea_motion_sensor_mock.counter = ikea_motion_sensor_mock.counter + 1 self._manufacturer = "IKEA of Sweden" diff --git a/custom_components/dirigera_platform/mocks/ikea_open_close_mock.py b/custom_components/dirigera_platform/mocks/ikea_open_close_mock.py index eec8104..87bd98a 100644 --- a/custom_components/dirigera_platform/mocks/ikea_open_close_mock.py +++ b/custom_components/dirigera_platform/mocks/ikea_open_close_mock.py @@ -7,9 +7,7 @@ class ikea_open_close_mock(BinarySensorEntity): counter = 0 - def __init__(self, hub, hub_outlet): - self._hub = hub - self._hub_outlet = hub_outlet + def __init__(self): ikea_open_close_mock.counter = ikea_open_close_mock.counter + 1 self._manufacturer = "IKEA of Sweden" diff --git a/custom_components/dirigera_platform/mocks/ikea_vindstyrka_mock.py b/custom_components/dirigera_platform/mocks/ikea_vindstyrka_mock.py index c5d95b3..962f4a8 100644 --- a/custom_components/dirigera_platform/mocks/ikea_vindstyrka_mock.py +++ b/custom_components/dirigera_platform/mocks/ikea_vindstyrka_mock.py @@ -66,9 +66,11 @@ def device_info(self) -> DeviceInfo: sw_version="mock sw" ) + @property def name(self) -> str: return self._name + @property def unique_id(self): return self._unique_id diff --git a/custom_components/dirigera_platform/requirements.txt b/custom_components/dirigera_platform/requirements.txt index 613a509..3841dbb 100644 --- a/custom_components/dirigera_platform/requirements.txt +++ b/custom_components/dirigera_platform/requirements.txt @@ -1 +1 @@ -dirigera==1.0.4 +dirigera==1.0.10 diff --git a/custom_components/dirigera_platform/sensor.py b/custom_components/dirigera_platform/sensor.py index 19d3aa4..851c9dc 100644 --- a/custom_components/dirigera_platform/sensor.py +++ b/custom_components/dirigera_platform/sensor.py @@ -128,8 +128,8 @@ class ikea_env_base_entity(SensorEntity): def __init__(self, ikea_env_device: ikea_vindstyrka_device, id_suffix : str, name_suffix: str): logger.debug("ikea_env_base_entity ctor...") self._ikea_env_device = ikea_env_device - self._unique_id = self._ikea_env_device.unique_id() + id_suffix - self._name = self._ikea_env_device.name() + " " + name_suffix + self._unique_id = self._ikea_env_device.unique_id + id_suffix + self._name = self._ikea_env_device.name + " " + name_suffix @property def available(self): @@ -164,7 +164,7 @@ def device_class(self): return SensorDeviceClass.TEMPERATURE; @property - def native_value(self) -> int: + def native_value(self) -> float: return self._ikea_env_device.get_current_temperature() @property