This commit is contained in:
Flavien Haas 2025-04-27 18:02:15 +02:00
parent 9203a0562a
commit 2e259892bf
5 changed files with 43 additions and 35 deletions

3
bolt.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M7 2v11h3v9l7-12h-4l4-8z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 119 B

View File

@ -6,7 +6,6 @@ import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
from .const import ( from .const import (
@ -18,13 +17,18 @@ from .const import (
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
async def async_get_devices(hass): async def async_get_zha_devices(hass):
"""Get ZHA devices.""" """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 [ return [
entry (str(device.ieee), f"{device.name} ({device.ieee})")
for entry in device_registry.devices.values() for device in zha_gateway.devices.values()
if entry.via_device_id is not None and "zha" in entry.via_device_id
] ]
class LinkyTariffConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): 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): async def async_step_user(self, user_input=None):
"""Handle the initial step.""" """Handle the initial step."""
errors = {} errors = {}
devices = await async_get_devices(self.hass) devices = await async_get_zha_devices(self.hass)
if not devices: if not devices:
return self.async_abort(reason="no_zha_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() self._abort_if_unique_id_configured()
return self.async_create_entry(title="Linky Tariff", data=user_input) 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( return self.async_show_form(
step_id="user", step_id="user",
data_schema=vol.Schema({ data_schema=vol.Schema({
vol.Required(CONF_IEEE): vol.In(device_options), vol.Required(CONF_IEEE): vol.In(dict(devices)),
vol.Optional( vol.Optional(
CONF_POLL_INTERVAL, CONF_POLL_INTERVAL,
default=DEFAULT_POLL_INTERVAL default=DEFAULT_POLL_INTERVAL

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

48
init.py
View File

@ -5,8 +5,9 @@ import logging
from typing import Any from typing import Any
from homeassistant.config_entries import ConfigEntry 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.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import ( from .const import (
@ -63,31 +64,36 @@ class LinkyTariffCoordinator(DataUpdateCoordinator):
update_interval=poll_interval, update_interval=poll_interval,
) )
self.ieee = ieee self.ieee = ieee
self._attr = None
async def _async_update_data(self) -> dict[str, Any]: async def _async_update_data(self) -> dict[str, Any]:
"""Fetch data from ZHA device.""" """Fetch data from ZHA device."""
try: try:
result = await self.hass.services.async_call( if "zha" not in self.hass.data:
"zha_toolkit", raise ValueError("ZHA integration not loaded")
"attr_read",
{ zha_gateway = self.hass.data["zha"].get("zha_gateway")
"ieee": self.ieee, if not zha_gateway:
"endpoint_id": ENDPOINT_ID, raise ValueError("ZHA gateway not available")
"cluster_id": CLUSTER_ID,
"attribute_id": ATTRIBUTE_ID, zha_device = zha_gateway.devices.get(self.ieee)
"manufacturer": None, if not zha_device:
}, raise ValueError(f"Device {self.ieee} not found in ZHA")
blocking=True,
return_response=True, 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 {
return { "value": value,
"value": result["value"], "last_update": self.hass.config.time_utc(),
"last_update": self.hass.config.time_utc(), }
}
return {"value": "unknown", "last_update": self.hass.config.time_utc()}
except Exception as ex: except Exception as ex:
_LOGGER.error("Error reading Linky tariff: %s", ex) _LOGGER.error("Error reading Linky tariff: %s", ex)

View File

@ -7,6 +7,6 @@
"codeowners": ["@flavien"], "codeowners": ["@flavien"],
"requirements": [], "requirements": [],
"iot_class": "local_polling", "iot_class": "local_polling",
"loggers": ["zha_toolkit"], "dependencies": ["zha"],
"integration_type": "device" "integration_type": "device"
} }