From 3afcba2727c3bf11455c3d5156a9190d4b653c5d Mon Sep 17 00:00:00 2001 From: kikediazfernandez Date: Mon, 1 Apr 2024 20:10:42 +0200 Subject: [PATCH 1/8] Revert "repaired pase error" This reverts commit 6226f40a920350b653e0da4cd03f538d947ca3e6. --- custom_components/v2c_trydan/const.py | 6 +++- custom_components/v2c_trydan/manifest.json | 2 +- custom_components/v2c_trydan/number.py | 42 +++++++++++++++++++--- custom_components/v2c_trydan/switch.py | 23 ++++++++++-- 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/custom_components/v2c_trydan/const.py b/custom_components/v2c_trydan/const.py index 6880648..bafbf80 100644 --- a/custom_components/v2c_trydan/const.py +++ b/custom_components/v2c_trydan/const.py @@ -1,5 +1,9 @@ +from homeassistant.helpers.dispatcher import SignalType + DOMAIN = "v2c_trydan" CONF_IP_ADDRESS = "ip_address" CONF_KWH_PER_100KM = "kwh_per_100km" CONF_KM_TO_CHARGE = "km_to_charge" -CONF_PRECIO_LUZ = "precio_luz" \ No newline at end of file +CONF_PRECIO_LUZ = "precio_luz" + +DATA_UPDATED = f"{DOMAIN}_update" diff --git a/custom_components/v2c_trydan/manifest.json b/custom_components/v2c_trydan/manifest.json index b2dd84d..3116af2 100644 --- a/custom_components/v2c_trydan/manifest.json +++ b/custom_components/v2c_trydan/manifest.json @@ -11,6 +11,6 @@ "quality_scale": "internal", "requirements": ["aiohttp", "tenacity"], "ssdp": [], - "version": "2.9.8", + "version": "2.9.7", "zeroconf": [] } \ No newline at end of file diff --git a/custom_components/v2c_trydan/number.py b/custom_components/v2c_trydan/number.py index d6745fe..82082c3 100644 --- a/custom_components/v2c_trydan/number.py +++ b/custom_components/v2c_trydan/number.py @@ -1,8 +1,10 @@ -from homeassistant.components.number import NumberEntity +from homeassistant.components.number import NumberEntity, RestoreNumber from homeassistant.const import DEVICE_DEFAULT_NAME +from homeassistant.core import callback +from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers import config_validation as cv import logging -from . import DOMAIN +from .const import DOMAIN, DATA_UPDATED _LOGGER = logging.getLogger(__name__) @@ -138,7 +140,7 @@ async def async_set_native_value(self, value): else: _LOGGER.error("v2c_dynamic_power_mode must be between 0 and 7") -class KmToChargeNumber(NumberEntity): +class KmToChargeNumber(RestoreNumber): def __init__(self, hass): self._hass = hass self._state = 0 @@ -178,6 +180,21 @@ async def async_set_native_value(self, value): else: _LOGGER.error("v2c_km_to_charge must be between 0 and 1000") + async def async_added_to_hass(self) -> None: + await super().async_added_to_hass() + value = await self.async_get_last_number_data() + if not value: + return + self._state = value.native_value + + async_dispatcher_connect( + self._hass, DATA_UPDATED, self._schedule_immediate_update + ) + + @callback + def _schedule_immediate_update(self): + self.async_schedule_update_ha_state(True) + class IntensityNumber(NumberEntity): def __init__(self, hass): self._hass = hass @@ -219,7 +236,7 @@ async def async_set_native_value(self, value): else: _LOGGER.error("v2c_intensity must be between {} and {}".format(self.native_min_value, self.native_max_value)) -class MaxPrice(NumberEntity): +class MaxPrice(RestoreNumber): def __init__(self, hass): self._hass = hass self._state = 0 @@ -257,4 +274,19 @@ async def async_set_native_value(self, value): self._state = value self.async_write_ha_state() else: - _LOGGER.error("v2c_MaxPrice must be between 0 and 1") \ No newline at end of file + _LOGGER.error("v2c_MaxPrice must be between 0 and 1") + + async def async_added_to_hass(self) -> None: + await super().async_added_to_hass() + value = await self.async_get_last_number_data() + if not value: + return + self._state = value.native_value + + async_dispatcher_connect( + self._hass, DATA_UPDATED, self._schedule_immediate_update + ) + + @callback + def _schedule_immediate_update(self): + self.async_schedule_update_ha_state(True) diff --git a/custom_components/v2c_trydan/switch.py b/custom_components/v2c_trydan/switch.py index df1a541..118a13a 100644 --- a/custom_components/v2c_trydan/switch.py +++ b/custom_components/v2c_trydan/switch.py @@ -7,9 +7,11 @@ from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity from homeassistant.const import CONF_IP_ADDRESS -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import PlatformNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, @@ -17,7 +19,7 @@ ) from .coordinator import V2CtrydanDataUpdateCoordinator -from .const import DOMAIN, CONF_PRECIO_LUZ +from .const import DOMAIN, CONF_PRECIO_LUZ, DATA_UPDATED _LOGGER = logging.getLogger(__name__) @@ -82,7 +84,7 @@ async def async_turn_off(self, **kwargs): except Exception as e: _LOGGER.error(f"Error turning off switch: {e}") -class V2CCargaPVPCSwitch(SwitchEntity): +class V2CCargaPVPCSwitch(SwitchEntity, RestoreEntity): def __init__(self, precio_luz_entity): self._is_on = False self.precio_luz_entity = precio_luz_entity @@ -107,3 +109,18 @@ async def async_turn_on(self, **kwargs): async def async_turn_off(self, **kwargs): self._is_on = False + + async def async_added_to_hass(self) -> None: + await super().async_added_to_hass() + state = await self.async_get_last_state() + if not state: + return + self._is_on = state.state + + async_dispatcher_connect( + self.hass, DATA_UPDATED, self._schedule_immediate_update + ) + + @callback + def _schedule_immediate_update(self): + self.async_schedule_update_ha_state(True) From 062162566960054f70fca0ed6c4ae213493ffa9a Mon Sep 17 00:00:00 2001 From: kikediazfernandez Date: Mon, 1 Apr 2024 20:17:48 +0200 Subject: [PATCH 2/8] Restore state after reboot --- custom_components/v2c_trydan/const.py | 2 -- custom_components/v2c_trydan/manifest.json | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/custom_components/v2c_trydan/const.py b/custom_components/v2c_trydan/const.py index bafbf80..e167213 100644 --- a/custom_components/v2c_trydan/const.py +++ b/custom_components/v2c_trydan/const.py @@ -1,5 +1,3 @@ -from homeassistant.helpers.dispatcher import SignalType - DOMAIN = "v2c_trydan" CONF_IP_ADDRESS = "ip_address" CONF_KWH_PER_100KM = "kwh_per_100km" diff --git a/custom_components/v2c_trydan/manifest.json b/custom_components/v2c_trydan/manifest.json index 3116af2..b2dd84d 100644 --- a/custom_components/v2c_trydan/manifest.json +++ b/custom_components/v2c_trydan/manifest.json @@ -11,6 +11,6 @@ "quality_scale": "internal", "requirements": ["aiohttp", "tenacity"], "ssdp": [], - "version": "2.9.7", + "version": "2.9.8", "zeroconf": [] } \ No newline at end of file From 94702b07f9c3bc7d85d6662c9d172bedf0f262e3 Mon Sep 17 00:00:00 2001 From: kikediazfernandez Date: Mon, 1 Apr 2024 20:46:07 +0200 Subject: [PATCH 3/8] Correct TypeError in sensor ChargeKmSensor --- custom_components/v2c_trydan/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/v2c_trydan/sensor.py b/custom_components/v2c_trydan/sensor.py index 526f875..9a4b964 100644 --- a/custom_components/v2c_trydan/sensor.py +++ b/custom_components/v2c_trydan/sensor.py @@ -300,7 +300,7 @@ async def check_and_pause_charging(self, now): km_to_charge_float = 0.0 _LOGGER.info(f"Se recibió un valor no numérico para km_to_charge: {km_to_charge.state}") - if self.state >= km_to_charge and km_to_charge != 0: + if self.state >= km_to_charge_float and km_to_charge != 0: await self.hass.services.async_call("switch", "turn_on", {"entity_id": "switch.v2c_trydan_switch_paused"}) await self.hass.services.async_call("switch", "turn_on", {"entity_id": "switch.v2c_trydan_switch_locked"}) await self.async_set_km_to_charge(0) From 89b15b46309ca8990604e77e8eceac64e9165495 Mon Sep 17 00:00:00 2001 From: kikediazfernandez Date: Mon, 1 Apr 2024 20:55:47 +0200 Subject: [PATCH 4/8] Correct TypeError in sensor ChargeKmSensor --- custom_components/v2c_trydan/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/v2c_trydan/sensor.py b/custom_components/v2c_trydan/sensor.py index 9a4b964..2d7f9e3 100644 --- a/custom_components/v2c_trydan/sensor.py +++ b/custom_components/v2c_trydan/sensor.py @@ -300,7 +300,7 @@ async def check_and_pause_charging(self, now): km_to_charge_float = 0.0 _LOGGER.info(f"Se recibió un valor no numérico para km_to_charge: {km_to_charge.state}") - if self.state >= km_to_charge_float and km_to_charge != 0: + if self.state >= km_to_charge_float and km_to_charge_float != 0: await self.hass.services.async_call("switch", "turn_on", {"entity_id": "switch.v2c_trydan_switch_paused"}) await self.hass.services.async_call("switch", "turn_on", {"entity_id": "switch.v2c_trydan_switch_locked"}) await self.async_set_km_to_charge(0) From e97749d823a9885e47f456a868f78ffe5f688199 Mon Sep 17 00:00:00 2001 From: kikediazfernandez Date: Sun, 19 May 2024 14:13:07 +0200 Subject: [PATCH 5/8] Fix deprecated call to async_track_state_change --- custom_components/v2c_trydan/manifest.json | 2 +- custom_components/v2c_trydan/sensor.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/custom_components/v2c_trydan/manifest.json b/custom_components/v2c_trydan/manifest.json index 0794e80..5912e4d 100644 --- a/custom_components/v2c_trydan/manifest.json +++ b/custom_components/v2c_trydan/manifest.json @@ -11,6 +11,6 @@ "quality_scale": "internal", "requirements": ["aiohttp", "tenacity"], "ssdp": [], - "version": "2.9.9", + "version": "2.9.10", "zeroconf": [] } \ No newline at end of file diff --git a/custom_components/v2c_trydan/sensor.py b/custom_components/v2c_trydan/sensor.py index bf19a1e..f1df32f 100644 --- a/custom_components/v2c_trydan/sensor.py +++ b/custom_components/v2c_trydan/sensor.py @@ -12,7 +12,7 @@ STATE_UNKNOWN, CONF_IP_ADDRESS, ) -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback from homeassistant.components.sensor import ( PLATFORM_SCHEMA, SensorEntity, @@ -24,7 +24,7 @@ from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import ( async_track_time_interval, - async_track_state_change, + async_track_state_change_event, async_call_later, ) from homeassistant.helpers.update_coordinator import ( @@ -254,7 +254,9 @@ async def async_added_to_hass(self): await super().async_added_to_hass() async_track_time_interval(self.hass, self.check_and_pause_charging, timedelta(seconds=10)) - async def handle_paused_state_change(self, entity_id, old_state, new_state): + async def handle_paused_state_change(self, event: Event[EventStateChangedData]): + old_state = event.data["old_state"] + new_state = event.data["new_state"] if new_state is not None and old_state is not None: if new_state.state == "on" and old_state.state == "off": #_LOGGER.debug("Charging paused") @@ -282,7 +284,7 @@ async def async_set_km_to_charge(self, value): async def async_added_to_hass(self): await super().async_added_to_hass() async_track_time_interval(self.hass, self.check_and_pause_charging, timedelta(seconds=10)) - async_track_state_change(self.hass, ["switch.v2c_trydan_switch_paused"], self.handle_paused_state_change) + async_track_state_change_event(self.hass, ["switch.v2c_trydan_switch_paused"], self.handle_paused_state_change) self.hass.bus.async_listen("state_changed", self.handle_km_to_charge_state_change) From 5d9c66660984b62bea9014e641ac4e637fe4864a Mon Sep 17 00:00:00 2001 From: Enrique Diaz <123412679+kikediazfernandez@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:20:23 +0200 Subject: [PATCH 6/8] Resolves async_forward_entry_setup call deprecation resolves WARNING (MainThread) [homeassistant.helpers.frame] Detected that custom integration 'v2c_trydan' calls async_forward_entry_setup for integration, v2c_trydan with title: XXX.XXX.XXX.XXX and entry_id: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, which is deprecated and will stop working in Home Assistant 2025.6, await async_forward_entry_setups instead at custom_components/v2c_trydan/__init__.py, line 32: await hass.config_entries.async_forward_entry_setup(entry, platform), please create a bug report at https://github.com/Rain1971/V2C_trydant/issues --- custom_components/v2c_trydan/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/custom_components/v2c_trydan/__init__.py b/custom_components/v2c_trydan/__init__.py index 755ecbd..84ba8dc 100644 --- a/custom_components/v2c_trydan/__init__.py +++ b/custom_components/v2c_trydan/__init__.py @@ -28,8 +28,7 @@ async def async_setup(hass: HomeAssistant, config: dict): return True async def async_setup_entry(hass: HomeAssistant, entry): - for platform in PLATFORMS: - await hass.config_entries.async_forward_entry_setup(entry, platform) + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) hass.data[DOMAIN]["ip_address"] = entry.data[CONF_IP_ADDRESS] ip_address = entry.data[CONF_IP_ADDRESS] From d18c8f22d825709e147dd771b577e38589b546c6 Mon Sep 17 00:00:00 2001 From: Enrique Diaz <123412679+kikediazfernandez@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:55:48 +0200 Subject: [PATCH 7/8] async_forward_entry_setup fix --- custom_components/v2c_trydan/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom_components/v2c_trydan/__init__.py b/custom_components/v2c_trydan/__init__.py index 84ba8dc..415bfe9 100644 --- a/custom_components/v2c_trydan/__init__.py +++ b/custom_components/v2c_trydan/__init__.py @@ -1,7 +1,7 @@ """The v2c_trydan component.""" from homeassistant.config_entries import SOURCE_IMPORT from homeassistant.core import HomeAssistant, ServiceCall -from homeassistant.const import CONF_IP_ADDRESS +from homeassistant.const import CONF_IP_ADDRESS, Platform import logging import aiohttp from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -10,7 +10,7 @@ DOMAIN = "v2c_trydan" -PLATFORMS = ["sensor", "switch", "number"] +PLATFORMS = [Platform.SENSOR, Platform.SWITCH, Platform.NUMBER] async def async_setup(hass: HomeAssistant, config: dict): hass.data.setdefault(DOMAIN, {}) @@ -28,8 +28,6 @@ async def async_setup(hass: HomeAssistant, config: dict): return True async def async_setup_entry(hass: HomeAssistant, entry): - await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - hass.data[DOMAIN]["ip_address"] = entry.data[CONF_IP_ADDRESS] ip_address = entry.data[CONF_IP_ADDRESS] @@ -150,6 +148,8 @@ async def set_max_intensity_slider(call): hass.services.async_register(DOMAIN, "set_max_intensity_slider", set_max_intensity_slider) hass.services.async_register(DOMAIN, "set_dynamic_power_mode_slider", set_dynamic_power_mode_slider) + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + return True async def async_unload_entry(hass: HomeAssistant, entry): From a1606f044cf2c3481c6413937232be07ac95325e Mon Sep 17 00:00:00 2001 From: kikediazfernandez Date: Sun, 11 Aug 2024 19:45:55 +0200 Subject: [PATCH 8/8] Fix error restoring switch.v2c_carga_pvpc --- custom_components/v2c_trydan/sensor.py | 7 ++----- custom_components/v2c_trydan/switch.py | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/custom_components/v2c_trydan/sensor.py b/custom_components/v2c_trydan/sensor.py index f1df32f..84df9d0 100644 --- a/custom_components/v2c_trydan/sensor.py +++ b/custom_components/v2c_trydan/sensor.py @@ -9,6 +9,7 @@ from homeassistant.const import ( CONF_NAME, + STATE_UNAVAILABLE, STATE_UNKNOWN, CONF_IP_ADDRESS, ) @@ -250,10 +251,6 @@ def __init__(self, coordinator, ip_address, kwh_per_100km): self._kwh_per_100km = kwh_per_100km self._charging_paused = False - async def async_added_to_hass(self): - await super().async_added_to_hass() - async_track_time_interval(self.hass, self.check_and_pause_charging, timedelta(seconds=10)) - async def handle_paused_state_change(self, event: Event[EventStateChangedData]): old_state = event.data["old_state"] new_state = event.data["new_state"] @@ -454,7 +451,7 @@ async def extract_price_attrs(precio_luz_entity, max_price, current_hour): return valid_hours, valid_hours_next_day, total_hours async def pause_or_resume_charging(current_state, max_price, paused_switch, v2c_carga_pvpc_switch): - if v2c_carga_pvpc_switch.is_on: + if v2c_carga_pvpc_switch.is_on and current_state not in (STATE_UNKNOWN, STATE_UNAVAILABLE): if float(current_state) <= max_price: await paused_switch.async_turn_off() else: diff --git a/custom_components/v2c_trydan/switch.py b/custom_components/v2c_trydan/switch.py index 118a13a..17510fa 100644 --- a/custom_components/v2c_trydan/switch.py +++ b/custom_components/v2c_trydan/switch.py @@ -6,7 +6,7 @@ import voluptuous as vol from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity -from homeassistant.const import CONF_IP_ADDRESS +from homeassistant.const import CONF_IP_ADDRESS, STATE_ON from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import PlatformNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -115,7 +115,7 @@ async def async_added_to_hass(self) -> None: state = await self.async_get_last_state() if not state: return - self._is_on = state.state + self._is_on = state.state == STATE_ON async_dispatcher_connect( self.hass, DATA_UPDATED, self._schedule_immediate_update