diff --git a/custom_components/airtub_udp/__init__.py b/custom_components/airtub_udp/__init__.py index 401eb3c..dc689e0 100755 --- a/custom_components/airtub_udp/__init__.py +++ b/custom_components/airtub_udp/__init__.py @@ -1,4 +1,4 @@ -"""UDP Multicast integration.""" +"""Airfit Airtub Partner integration.""" import asyncio import logging @@ -10,6 +10,7 @@ from itertools import cycle from homeassistant.core import HomeAssistant from homeassistant.helpers import discovery +from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv import voluptuous as vol from .const import DOMAIN, EVENT_NEW_DATA @@ -120,7 +121,7 @@ async def udp_listener( msg_received = True del data_dict["rec"] hass.states.async_set(f"{DOMAIN}.status", "ready") - # Ensure 'mod' and 'flt' and 'pwr' keys are present + # Ensure 'mod' and 'flt' keys are present if "mod" not in data_dict: data_dict["mod"] = 0 if "flt" not in data_dict: @@ -135,6 +136,38 @@ async def udp_listener( await asyncio.sleep(0) # Yield control to the event loop +class StatusEntity(Entity): + def __init__(self, hass, name, unique_id): + """Initialize the entity.""" + self.hass = hass + self._name = name + self._unique_id = unique_id + self._state = "ready" + + @property + def name(self): + """Return the name of the entity.""" + return self._name + + @property + def unique_id(self): + """Return the unique ID of the entity.""" + return self._unique_id + + @property + def state(self): + """Return the state of the entity.""" + return self._state + + +async def async_setup_entry(hass, config_entry, async_add_entities): + """Set up the sensor platform from a config entry.""" + name = f"{DOMAIN}.status" + unique_id = f"{config_entry.entry_id}_status" + status_entity = StatusEntity(hass, name, unique_id) + async_add_entities([status_entity], update_before_add=True) + + async def async_setup(hass: HomeAssistant, config: dict): """Set up the UDP Multicast component.""" if DOMAIN not in config: @@ -191,7 +224,17 @@ async def handle_json_service(call): _LOGGER.warning(f"AIRTUB: Error decoding JSON: {e}") hass.states.async_set(f"{DOMAIN}.status", "error") - await asyncio.sleep(8) + async def handle_data_received_event(event): + """Handle the event when data is received.""" + _LOGGER.debug("UDP data received, starting sensor and climate setup.") + hass.async_create_task( + discovery.async_load_platform(hass, "sensor", DOMAIN, {}, config) + ) + hass.async_create_task( + discovery.async_load_platform(hass, "climate", DOMAIN, {}, config) + ) + # Remove the listener after handling the event + hass.bus.async_remove_listener(EVENT_NEW_DATA, handle_data_received_event) try: hass.data[DOMAIN] = {"device": device, "data": {}, "ip": None} @@ -200,13 +243,8 @@ async def handle_json_service(call): udp_listener(hass, multicast_group, multicast_port, secret, device) ) - hass.async_create_task( - discovery.async_load_platform(hass, "sensor", DOMAIN, {}, config) - ) - - hass.async_create_task( - discovery.async_load_platform(hass, "climate", DOMAIN, {}, config) - ) + # Register the event listener + hass.bus.async_listen(EVENT_NEW_DATA, handle_data_received_event) hass.states.async_set(f"{DOMAIN}.status", "ready") hass.services.async_register( diff --git a/custom_components/airtub_udp/sensor.py b/custom_components/airtub_udp/sensor.py index 2c5f752..10bd1b6 100755 --- a/custom_components/airtub_udp/sensor.py +++ b/custom_components/airtub_udp/sensor.py @@ -95,7 +95,7 @@ def _setup_attributes(self, key): self._attr_icon = "mdi:meter-gas" self._attr_device_class = SensorDeviceClass.GAS self._attr_state_class = SensorStateClass.TOTAL - self._attr_precision = 6 # 小数点后6位 + self._attr_precision = 3 # 小数点后3位 else: self._attr_unit_of_measurement = None self._attr_icon = "mdi:numeric" @@ -122,6 +122,7 @@ def state(self, value): # 仅在 device_class 为 gas 并且值为 0 时触发 last_reset if self._attr_device_class == SensorDeviceClass.GAS and value < self._state: self._attr_last_reset = datetime.now() + _LOGGER.warning(f"Gas consumption was reset at {self._attr_last_reset}") self._state = value @property