From 2e259892bf20d104a8bdc70441a6fa9c9b675a14 Mon Sep 17 00:00:00 2001 From: flavien Date: Sun, 27 Apr 2025 18:02:15 +0200 Subject: [PATCH] zha api --- bolt.svg | 3 +++ config_flow.py | 25 ++++++++++++------------- icon.png | Bin 1459 -> 0 bytes init.py | 48 +++++++++++++++++++++++++++--------------------- manifest.json | 2 +- 5 files changed, 43 insertions(+), 35 deletions(-) create mode 100644 bolt.svg delete mode 100644 icon.png diff --git a/bolt.svg b/bolt.svg new file mode 100644 index 0000000..f8ac91b --- /dev/null +++ b/bolt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/config_flow.py b/config_flow.py index 4253e5d..f1bb831 100644 --- a/config_flow.py +++ b/config_flow.py @@ -6,7 +6,6 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.core import callback -from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import device_registry as dr from .const import ( @@ -18,13 +17,18 @@ from .const import ( _LOGGER = logging.getLogger(__name__) -async def async_get_devices(hass): +async def async_get_zha_devices(hass): """Get ZHA devices.""" - device_registry = dr.async_get(hass) + if "zha" not in hass.data: + return [] + + zha_gateway = hass.data["zha"].get("zha_gateway") + if not zha_gateway: + return [] + return [ - entry - for entry in device_registry.devices.values() - if entry.via_device_id is not None and "zha" in entry.via_device_id + (str(device.ieee), f"{device.name} ({device.ieee})") + for device in zha_gateway.devices.values() ] class LinkyTariffConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): @@ -35,7 +39,7 @@ class LinkyTariffConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): async def async_step_user(self, user_input=None): """Handle the initial step.""" errors = {} - devices = await async_get_devices(self.hass) + devices = await async_get_zha_devices(self.hass) if not devices: return self.async_abort(reason="no_zha_devices") @@ -45,15 +49,10 @@ class LinkyTariffConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self._abort_if_unique_id_configured() return self.async_create_entry(title="Linky Tariff", data=user_input) - device_options = { - device.id: f"{device.name_by_user or device.name} ({device.id})" - for device in devices - } - return self.async_show_form( step_id="user", data_schema=vol.Schema({ - vol.Required(CONF_IEEE): vol.In(device_options), + vol.Required(CONF_IEEE): vol.In(dict(devices)), vol.Optional( CONF_POLL_INTERVAL, default=DEFAULT_POLL_INTERVAL diff --git a/icon.png b/icon.png deleted file mode 100644 index 4a2064f84f9428ee467c04cb85dc3ad3471209f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1459 zcmY*ZYfuwc6ux`il!Xw<0z!~i?BWA!b%7`jI3_|^4dqpJkg+YqR%5h7O|?Y?OgGR9 zVpKp;M$uvDR2{__kPdc4Ocl@}h)HoAwW-Dulq!!{VF*~Dd(&V2wda24+;hJ3?K$^g zM%r3|*IX|EfIzWMz8(OKGciCw?$axjMghPpP{`M8%#!+fGQ&OgcOm_0pna!)Xw zP}vfycxXL)m4En_p+7gCSG(+_`Cwzu%eRMezGaxnk%494NCa!m&Y6}@2qY1p-c#9} z{?(hqCK`%Qfd$*}P9d=3G6~jg{>%apc20#C_;DB=Pg$x#*#Z{oWm4qWNy9S)t43y* zCh$QC@+IqKdk|0_1#>+)--SEGe?{V^b1jv4M%DGYOq`}DS`RKp!&E}Ko>6*Z{wlm} zA)=B!J#P#{)l=>fqYDs{_p~%`K0D_c|4Ay~iF8`rNKnS3sMOq6pCLJr`^kcsIuA^k z3aazNpVWfPzNKnE%>N7giLa?xZ+eMm93|E3z?ac5+?VSjqspgaGl`69Qk{UVZ+Tj( zO$Uee1deho#lRe2)1=hVFNk7I$P1 z(dzDY|I^YoF-SXazb?k)G`vr+(&)7^5UDpMLi-gH$^Dz29p;rYNru-!6ON#=*dSQ|RU)5i=cLcdeAeY&(a?C`Je2iS{N$3OezhmgiH zU>o~8MGkCShb_mqv+2VHf+R7&!c5fG!~DXwlhVgFz870KJlOlfsU0c;9r>Wc5)yO6Y12@p84Qi23DKKh-*N;csq_eOUb(tAdJ5+d@*}dZ_4C{ z2r=izTLfVbXOx#-dB{O)(?8tl1o`OVD2D!}lO-! zpiB*2XpET)^k>=I4sKMQGUXiFD;Cuz4%qg(R@l zkQb8BI2ST?LM$Y4)-j{ZVaeEx3GazpMN_^72$|dB$|6c-;?u9#`Z=|bvKF7W;jIvaq zt5tg02Pmie@!=RO>L!ZPkr26z{UhY)ih<8iF(agm?qW$I-F}p-;WjZS2K7@u6`}2X T$5v}G_ZS03QkvY5pe+6u%RUjD diff --git a/init.py b/init.py index bcc0367..c28f28d 100644 --- a/init.py +++ b/init.py @@ -5,8 +5,9 @@ import logging from typing import Any from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_IEEE, CONF_SCAN_INTERVAL +from homeassistant.const import CONF_IEEE from homeassistant.core import HomeAssistant +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import ( @@ -63,31 +64,36 @@ class LinkyTariffCoordinator(DataUpdateCoordinator): update_interval=poll_interval, ) self.ieee = ieee - self._attr = None async def _async_update_data(self) -> dict[str, Any]: """Fetch data from ZHA device.""" try: - result = await self.hass.services.async_call( - "zha_toolkit", - "attr_read", - { - "ieee": self.ieee, - "endpoint_id": ENDPOINT_ID, - "cluster_id": CLUSTER_ID, - "attribute_id": ATTRIBUTE_ID, - "manufacturer": None, - }, - blocking=True, - return_response=True, - ) + if "zha" not in self.hass.data: + raise ValueError("ZHA integration not loaded") + + zha_gateway = self.hass.data["zha"].get("zha_gateway") + if not zha_gateway: + raise ValueError("ZHA gateway not available") + + zha_device = zha_gateway.devices.get(self.ieee) + if not zha_device: + raise ValueError(f"Device {self.ieee} not found in ZHA") + + endpoint = zha_device.endpoints.get(ENDPOINT_ID) + if not endpoint: + raise ValueError(f"Endpoint {ENDPOINT_ID} not found") + + cluster = endpoint.in_clusters.get(CLUSTER_ID) + if not cluster: + raise ValueError(f"Cluster {CLUSTER_ID} not found") + + result = await cluster.read_attributes([ATTRIBUTE_ID]) + value = result.get(ATTRIBUTE_ID, "unknown") - if result and "value" in result: - return { - "value": result["value"], - "last_update": self.hass.config.time_utc(), - } - return {"value": "unknown", "last_update": self.hass.config.time_utc()} + return { + "value": value, + "last_update": self.hass.config.time_utc(), + } except Exception as ex: _LOGGER.error("Error reading Linky tariff: %s", ex) diff --git a/manifest.json b/manifest.json index cbbff27..ffbc255 100644 --- a/manifest.json +++ b/manifest.json @@ -7,6 +7,6 @@ "codeowners": ["@flavien"], "requirements": [], "iot_class": "local_polling", - "loggers": ["zha_toolkit"], + "dependencies": ["zha"], "integration_type": "device" } \ No newline at end of file