From 3cd9f67f2a1020d6f9fbfc9a716cd0f1b25810eb Mon Sep 17 00:00:00 2001 From: Stephan Uhle Date: Mon, 20 Nov 2023 22:24:31 +0000 Subject: [PATCH] Updated dependency to new PyMyGekko lib. Added mygekko actions as scenes. --- custom_components/mygekko/climate.py | 34 ++++++------- custom_components/mygekko/const.py | 5 +- custom_components/mygekko/manifest.json | 2 +- custom_components/mygekko/scene.py | 35 +++++++++++++ custom_components/mygekko/sensor.py | 28 +++++----- custom_components/mygekko/switch.py | 26 ++++++---- .../mygekko/translations/en.json | 1 + .../mygekko/translations/fr.json | 1 + .../mygekko/translations/nb.json | 1 + custom_components/mygekko/water_heater.py | 51 ++++++++++--------- requirements_test.txt | 2 +- 11 files changed, 117 insertions(+), 69 deletions(-) create mode 100644 custom_components/mygekko/scene.py diff --git a/custom_components/mygekko/climate.py b/custom_components/mygekko/climate.py index ec5632c..8cc4ad5 100644 --- a/custom_components/mygekko/climate.py +++ b/custom_components/mygekko/climate.py @@ -5,9 +5,9 @@ from homeassistant.components.climate import HVACMode from homeassistant.const import UnitOfTemperature from homeassistant.core import callback -from PyMyGekko.resources.Thermostats import Thermostat -from PyMyGekko.resources.Thermostats import ThermostatFeature -from PyMyGekko.resources.Thermostats import ThermostatMode +from PyMyGekko.resources.RoomTemps import RoomTemp +from PyMyGekko.resources.RoomTemps import RoomTempsFeature +from PyMyGekko.resources.RoomTemps import RoomTempsMode from .const import CLIMATE from .const import DOMAIN @@ -17,10 +17,10 @@ async def async_setup_entry(hass, entry, async_add_devices): """Setup cover platform.""" coordinator = hass.data[DOMAIN][entry.entry_id] - thermostats = coordinator.api.get_thermostats() - if thermostats is not None: + room_temps = coordinator.api.get_room_temps() + if room_temps is not None: async_add_devices( - MyGekkoClimate(coordinator, thermostat) for thermostat in thermostats + MyGekkoClimate(coordinator, room_temp) for room_temp in room_temps ) @@ -30,14 +30,14 @@ class MyGekkoClimate(MyGekkoEntity, ClimateEntity): _attr_temperature_unit = UnitOfTemperature.CELSIUS _attr_preset_modes = ["Comfort", "Reduced", "Manual", "Standby"] - def __init__(self, coordinator, thermostat: Thermostat): - super().__init__(coordinator, thermostat, CLIMATE) - self._thermostat = thermostat - supported_features = self._thermostat.supported_features + def __init__(self, coordinator, room_temp: RoomTemp): + super().__init__(coordinator, room_temp, CLIMATE) + self._room_temp = room_temp + supported_features = self._room_temp.supported_features self._attr_supported_features = 0 self._attr_hvac_modes = [HVACMode.OFF, HVACMode.AUTO] - if ThermostatFeature.TARGET_TEMPERATURE in supported_features: + if RoomTempsFeature.TARGET_TEMPERATURE in supported_features: self._attr_supported_features |= ClimateEntityFeature.TARGET_TEMPERATURE @callback @@ -48,21 +48,21 @@ def _handle_coordinator_update(self) -> None: @property def current_temperature(self) -> float | None: """Return the current temperature.""" - return self._thermostat.current_temperature + return self._room_temp.current_temperature @property def target_temperature(self) -> float | None: """Return the temperature we try to reach.""" - return self._thermostat.target_temperature + return self._room_temp.target_temperature async def async_set_temperature(self, **kwargs) -> None: """Set new target temperature.""" - await self._thermostat.set_target_temperature(float(kwargs[ATTR_TEMPERATURE])) + await self._room_temp.set_target_temperature(float(kwargs[ATTR_TEMPERATURE])) @property def hvac_mode(self) -> HVACMode | str | None: """Return hvac operation ie. heat, cool mode.""" - if self._thermostat.mode == ThermostatMode.Off: + if self._room_temp.working_mode == RoomTempsMode.Off: return HVACMode.OFF else: return HVACMode.AUTO @@ -70,6 +70,6 @@ def hvac_mode(self) -> HVACMode | str | None: async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: """Set new target hvac mode.""" if hvac_mode == HVACMode.OFF: - await self._thermostat.set_mode(ThermostatMode.Off) + await self._room_temp.set_working_mode(RoomTempsMode.Off) else: - await self._thermostat.set_mode(ThermostatMode.Comfort) + await self._room_temp.set_working_mode(RoomTempsMode.Comfort) diff --git a/custom_components/mygekko/const.py b/custom_components/mygekko/const.py index 59fe867..dfdb44b 100644 --- a/custom_components/mygekko/const.py +++ b/custom_components/mygekko/const.py @@ -3,7 +3,7 @@ NAME = "MyGekko" DOMAIN = "mygekko" DOMAIN_DATA = f"{DOMAIN}_data" -VERSION = "0.0.32" +VERSION = "0.0.33" ATTRIBUTION = "Data provided by http://jsonplaceholder.typicode.com/" ISSUE_URL = "https://github.com/stephanu/mygekko/issues" @@ -18,8 +18,9 @@ LIGHT = "light" CLIMATE = "climate" SWITCH = "switch" +SCENE = "scene" WATER_HEATER = "water_heater" -PLATFORMS = [COVER, LIGHT, CLIMATE, SWITCH, WATER_HEATER] +PLATFORMS = [COVER, LIGHT, CLIMATE, SWITCH, SCENE, WATER_HEATER] # Configuration and options diff --git a/custom_components/mygekko/manifest.json b/custom_components/mygekko/manifest.json index bcc0e27..edd0423 100644 --- a/custom_components/mygekko/manifest.json +++ b/custom_components/mygekko/manifest.json @@ -8,6 +8,6 @@ "iot_class": "cloud_polling", "issue_tracker": "https://github.com/stephanu/mygekko/issues", "logger": ["PyMyGekko"], - "requirements": ["pymygekko==0.0.5rc4"], + "requirements": ["pymygekko==0.0.5rc5"], "version": "1.0.0" } diff --git a/custom_components/mygekko/scene.py b/custom_components/mygekko/scene.py new file mode 100644 index 0000000..bf87169 --- /dev/null +++ b/custom_components/mygekko/scene.py @@ -0,0 +1,35 @@ +"""Scene platform for MyGekko.""" +from typing import Any + +from homeassistant.components.scene import Scene +from homeassistant.core import callback +from PyMyGekko.resources.Actions import Action +from PyMyGekko.resources.Actions import ActionState + +from .const import DOMAIN +from .const import SCENE +from .entity import MyGekkoEntity + + +async def async_setup_entry(hass, entry, async_add_devices): + """Setup scene platform.""" + coordinator = hass.data[DOMAIN][entry.entry_id] + actions = coordinator.api.get_actions() + if actions is not None: + async_add_devices(MyGekkoScene(coordinator, action) for action in actions) + + +class MyGekkoScene(MyGekkoEntity, Scene): + """mygekko Scene class.""" + + def __init__(self, coordinator, action: Action): + super().__init__(coordinator, action, SCENE) + self._action = action + + @callback + def _handle_coordinator_update(self) -> None: + """Handle updated data from the coordinator.""" + self.async_write_ha_state() + + async def activate(self, **kwargs: Any) -> None: + await self._action.set_state(ActionState.ON) diff --git a/custom_components/mygekko/sensor.py b/custom_components/mygekko/sensor.py index 6c9b870..2bbef10 100644 --- a/custom_components/mygekko/sensor.py +++ b/custom_components/mygekko/sensor.py @@ -3,9 +3,8 @@ from homeassistant.components.sensor import SensorEntity from homeassistant.components.sensor import SensorEntityDescription from homeassistant.components.sensor import SensorStateClass -from PyMyGekko.resources.EnergyMeters import EnergyMeter +from PyMyGekko.resources.EnergyCosts import EnergyCost -from .const import DEFAULT_NAME from .const import DOMAIN from .const import ICON from .const import SENSOR @@ -30,32 +29,35 @@ async def async_setup_entry(hass, entry, async_add_devices): """Setup sensor platform.""" coordinator = hass.data[DOMAIN][entry.entry_id] - energy_meters: list[EnergyMeter] = coordinator.api.get_energy_meters() - if energy_meters is not None: - for energy_meter in energy_meters: - if energy_meter.sensor_data and "values" in energy_meter.sensor_data: - for sensor in energy_meter.sensor_data["values"]: - async_add_devices(MyGekkoSensor(coordinator, sensor)) + energy_costs: list[EnergyCost] = coordinator.api.get_energy_costs() + if energy_costs is not None: + for energy_cost in energy_costs: + if energy_cost.sensor_data and "values" in energy_cost.sensor_data: + async_add_devices( + MyGekkoSensor(coordinator, energy_cost, sensor) + for sensor in energy_cost.sensor_data["values"] + ) class MyGekkoSensor(MyGekkoEntity, SensorEntity): """mygekko Sensor class.""" - def __init__(self, coordinator, energy_meter: EnergyMeter): - super().__init__(coordinator, energy_meter, SENSOR) - self._energy_meter = energy_meter + def __init__(self, coordinator, energy_cost: EnergyCost, sensor_data): + super().__init__(coordinator, energy_cost, SENSOR) + self._energy_cost = energy_cost + self._sensor_data = sensor_data # supported_features = self._blind.supported_features self._attr_supported_features = 0 @property def name(self): """Return the name of the sensor.""" - return f"{DEFAULT_NAME}_{SENSOR}" + return self._sensor_data["name"] @property def state(self): """Return the state of the sensor.""" - return self.coordinator.data.get("body") + return self._sensor_data["value"] @property def icon(self): diff --git a/custom_components/mygekko/switch.py b/custom_components/mygekko/switch.py index 5105e07..3d4e34b 100644 --- a/custom_components/mygekko/switch.py +++ b/custom_components/mygekko/switch.py @@ -1,8 +1,8 @@ """Switch platform for MyGekko.""" from homeassistant.components.switch import SwitchEntity from homeassistant.core import callback -from PyMyGekko.resources.Switches import Switch -from PyMyGekko.resources.Switches import SwitchState +from PyMyGekko.resources.Loads import Load +from PyMyGekko.resources.Loads import LoadState from .const import DOMAIN from .const import SWITCH @@ -12,28 +12,32 @@ async def async_setup_entry(hass, entry, async_add_devices): """Setup switch platform.""" coordinator = hass.data[DOMAIN][entry.entry_id] - switches = coordinator.api.get_switches() - if switches is not None: - async_add_devices(MyGekkoSwitch(coordinator, switch) for switch in switches) + loads = coordinator.api.get_loads() + if loads is not None: + async_add_devices(MyGekkoSwitch(coordinator, load) for load in loads) class MyGekkoSwitch(MyGekkoEntity, SwitchEntity): """mygekko Switch class.""" - def __init__(self, coordinator, switch: Switch): - super().__init__(coordinator, switch, SWITCH) - self._switch = switch + def __init__(self, coordinator, load: Load): + super().__init__(coordinator, load, SWITCH) + self._load = load @callback def _handle_coordinator_update(self) -> None: """Handle updated data from the coordinator.""" self.async_write_ha_state() + @property def is_on(self) -> bool | None: - return self._switch.state == SwitchState.ON_PERMANENT + return ( + self._load.state == LoadState.ON_PERMANENT + or self._load.state == LoadState.ON_IMPULSE + ) async def async_turn_off(self, **kwargs): - await self._switch.set_state(SwitchState.OFF) + await self._load.set_state(LoadState.OFF) async def async_turn_on(self, **kwargs): - await self._switch.set_state(SwitchState.ON_PERMANENT) + await self._load.set_state(LoadState.ON_PERMANENT) diff --git a/custom_components/mygekko/translations/en.json b/custom_components/mygekko/translations/en.json index a6bd8f3..0d74bbe 100644 --- a/custom_components/mygekko/translations/en.json +++ b/custom_components/mygekko/translations/en.json @@ -27,6 +27,7 @@ "light": "Light enabled", "climate": "Climate enabled", "switch": "Switch enabled", + "scene": "Scene enabled", "water_heater": "Water Heater enabled", "demo_mode": "Demo Mode" } diff --git a/custom_components/mygekko/translations/fr.json b/custom_components/mygekko/translations/fr.json index 03b83b6..ddfa5d1 100644 --- a/custom_components/mygekko/translations/fr.json +++ b/custom_components/mygekko/translations/fr.json @@ -27,6 +27,7 @@ "light": "Lumière activée", "climate": "Climat activé", "switch": "Interrupteur activé", + "scene": "Scène activée", "water_heater": "Chauffe-eau activé", "demo_mode": "Mode démo" }, diff --git a/custom_components/mygekko/translations/nb.json b/custom_components/mygekko/translations/nb.json index ce71511..cd002e8 100644 --- a/custom_components/mygekko/translations/nb.json +++ b/custom_components/mygekko/translations/nb.json @@ -27,6 +27,7 @@ "light": "Licht aktivert", "climate": "Klimaat aktivert", "switch": "Bryter aktivert", + "scene": "Scène aktivert", "water_heater": "Waterverwarming aktivert", "demo_mode": "Demomodus" }, diff --git a/custom_components/mygekko/water_heater.py b/custom_components/mygekko/water_heater.py index 83454ab..8bd9f67 100644 --- a/custom_components/mygekko/water_heater.py +++ b/custom_components/mygekko/water_heater.py @@ -9,9 +9,9 @@ from homeassistant.const import STATE_ON from homeassistant.const import UnitOfTemperature from homeassistant.core import callback -from PyMyGekko.resources.WaterHeaters import WaterHeater -from PyMyGekko.resources.WaterHeaters import WaterHeaterFeature -from PyMyGekko.resources.WaterHeaters import WaterHeaterState +from PyMyGekko.resources.HotWaterSystems import HotWaterSystem +from PyMyGekko.resources.HotWaterSystems import HotWaterSystemFeature +from PyMyGekko.resources.HotWaterSystems import HotWaterSystemState from .const import DOMAIN from .const import WATER_HEATER @@ -24,10 +24,11 @@ async def async_setup_entry(hass, entry, async_add_devices): """Setup light platform.""" coordinator = hass.data[DOMAIN][entry.entry_id] - waterHeaters = coordinator.api.get_water_heaters() - if waterHeaters is not None: + hotwater_systems = coordinator.api.get_hot_water_systems() + if hotwater_systems is not None: async_add_devices( - MyGekkoWaterHeater(coordinator, waterHeater) for waterHeater in waterHeaters + MyGekkoWaterHeater(coordinator, hotwater_system) + for hotwater_system in hotwater_systems ) @@ -36,17 +37,17 @@ class MyGekkoWaterHeater(MyGekkoEntity, WaterHeaterEntity): _attr_temperature_unit = UnitOfTemperature.CELSIUS - def __init__(self, coordinator, water_heater: WaterHeater): - super().__init__(coordinator, water_heater, WATER_HEATER) - self._water_heater = water_heater + def __init__(self, coordinator, hotwater_system: HotWaterSystem): + super().__init__(coordinator, hotwater_system, WATER_HEATER) + self._hotwater_system = hotwater_system - supported_features = self._water_heater.supported_features + supported_features = self._hotwater_system.supported_features self._attr_supported_features = 0 - if WaterHeaterFeature.ON_OFF in supported_features: + if HotWaterSystemFeature.ON_OFF in supported_features: self._attr_supported_features |= WaterHeaterEntityFeature.ON_OFF - if WaterHeaterFeature.TARGET_TEMPERATURE in supported_features: + if HotWaterSystemFeature.TARGET_TEMPERATURE in supported_features: self._attr_supported_features |= WaterHeaterEntityFeature.TARGET_TEMPERATURE @callback @@ -55,43 +56,45 @@ def _handle_coordinator_update(self) -> None: self.async_write_ha_state() async def async_turn_off(self, **kwargs): - _LOGGER.debug("Switch off water heater %s", self._water_heater.name) - await self._water_heater.set_state(WaterHeaterState.OFF) + _LOGGER.debug("Switch off water heater %s", self._hotwater_system.name) + await self._hotwater_system.set_state(HotWaterSystemState.OFF) async def async_turn_on(self, **kwargs): - _LOGGER.debug("Switch on water heater %s", self._water_heater.name) - await self._water_heater.set_state(WaterHeaterState.ON) + _LOGGER.debug("Switch on water heater %s", self._hotwater_system.name) + await self._hotwater_system.set_state(HotWaterSystemState.ON) @property def target_temperature(self) -> float | None: """Return the target temperature of the water heater.""" _LOGGER.debug( "The water heaters %s current target temperature is %s", - self._water_heater.name, - self._water_heater.target_temperature, + self._hotwater_system.name, + self._hotwater_system.target_temperature, ) - return self._water_heater.target_temperature + return self._hotwater_system.target_temperature async def async_set_temperature(self, **kwargs: Any) -> None: """Set new target temperature.""" - await self._water_heater.set_target_temperature(float(kwargs[ATTR_TEMPERATURE])) + await self._hotwater_system.set_target_temperature( + float(kwargs[ATTR_TEMPERATURE]) + ) @property def current_temperature(self) -> float | None: """Return the top temperature of the water heater.""" _LOGGER.debug( "The water heaters %s current top temperature is %s", - self._water_heater.name, - self._water_heater.current_temperature_top, + self._hotwater_system.name, + self._hotwater_system.current_temperature_top, ) - return self._water_heater.current_temperature_top + return self._hotwater_system.current_temperature_top @property def current_operation(self) -> str | None: """Return current operation ie. eco, electric, performance, ...""" - if self._water_heater.state == WaterHeaterState.OFF: + if self._hotwater_system.state == HotWaterSystemState.OFF: return STATE_OFF else: return STATE_ON diff --git a/requirements_test.txt b/requirements_test.txt index 3a97e5a..98fab15 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,4 @@ -r requirements_dev.txt pytest-asyncio pytest-homeassistant-custom-component==0.13.76 -PyMyGekko==0.0.5rc4 +PyMyGekko==0.0.5rc5