From 15a46225ad35b30b5d13e7ef5f960d5bff6507e7 Mon Sep 17 00:00:00 2001 From: Konstantin Deev Date: Tue, 25 Jun 2024 16:39:20 -0500 Subject: [PATCH] add code for the uuid normalization (#108) * add code for the uuid normalization * add code for the uuid normalization * add code for the uuid normalization * do not load historical data * yet another attempt * normalize everything * remove test code * stop reading historical data on start * Revert "stop reading historical data on start" This reverts commit e60c598c8a7f5da8d92e933837a9cdcb3fc42f03. --- custom_components/eyeonwater/__init__.py | 7 ---- custom_components/eyeonwater/binary_sensor.py | 9 ++-- custom_components/eyeonwater/sensor.py | 41 +++++++++++++------ .../eyeonwater/statistic_helper.py | 11 ++++- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/custom_components/eyeonwater/__init__.py b/custom_components/eyeonwater/__init__.py index 9323eda..69d55fd 100644 --- a/custom_components/eyeonwater/__init__.py +++ b/custom_components/eyeonwater/__init__.py @@ -47,13 +47,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: _LOGGER.exception("Fetching meters failed") raise - # Fetch actual meter_info for all meters - try: - await eye_on_water_data.read_meters(days_to_load=30) - except Exception: - _LOGGER.exception("Reading meters failed") - raise - async def async_update_data(): _LOGGER.debug("Fetching latest data") await eye_on_water_data.read_meters(days_to_load=3) diff --git a/custom_components/eyeonwater/binary_sensor.py b/custom_components/eyeonwater/binary_sensor.py index 4e12f86..ec3e78c 100644 --- a/custom_components/eyeonwater/binary_sensor.py +++ b/custom_components/eyeonwater/binary_sensor.py @@ -16,6 +16,7 @@ from pyonwater import Meter from .const import DATA_COORDINATOR, DATA_SMART_METER, DOMAIN, WATER_METER_NAME +from .statistic_helper import normalize_id @dataclass @@ -98,13 +99,15 @@ def __init__( translation_key=description.translation_key, ) self.meter = meter + self._uuid = normalize_id(meter.meter_uuid) + self._id = normalize_id(meter.meter_id) self._state = False self._available = False - self._attr_unique_id = f"{description.key}_{self.meter.meter_uuid}" + self._attr_unique_id = f"{description.key}_{self._uuid}" self._attr_is_on = self._state self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, self.meter.meter_uuid)}, - name=f"{WATER_METER_NAME} {self.meter.meter_id}", + identifiers={(DOMAIN, self._uuid)}, + name=f"{WATER_METER_NAME} {self._id}", model=self.meter.meter_info.reading.model, manufacturer=self.meter.meter_info.reading.customer_name, hw_version=self.meter.meter_info.reading.hardware_version, diff --git a/custom_components/eyeonwater/sensor.py b/custom_components/eyeonwater/sensor.py index 3beaf2f..d541d75 100644 --- a/custom_components/eyeonwater/sensor.py +++ b/custom_components/eyeonwater/sensor.py @@ -28,6 +28,7 @@ get_ha_native_unit_of_measurement, get_last_imported_time, get_statistic_metadata, + normalize_id, ) if TYPE_CHECKING: @@ -58,7 +59,8 @@ async def async_setup_entry( ), ) sensors.append(EyeOnWaterSensor(meter, coordinator)) - sensors.append(EyeOnWaterTempSensor(meter, coordinator)) + if meter.meter_info.sensors and meter.meter_info.sensors.endpoint_temperature: + sensors.append(EyeOnWaterTempSensor(meter, coordinator)) async_add_entities(sensors, update_before_add=False) @@ -79,20 +81,23 @@ def __init__( """Initialize the sensor.""" super().__init__(coordinator) self.meter = meter + self._uuid = normalize_id(meter.meter_uuid) + self._id = normalize_id(meter.meter_id) + self._state: pyonwater.DataPoint | None = None self._available = False self._historical_sensor = True - self._attr_name = f"{WATER_METER_NAME} {self.meter.meter_id} Statistic" + self._attr_name = f"{WATER_METER_NAME} {self._id} Statistic" self._attr_device_class = SensorDeviceClass.WATER - self._attr_unique_id = f"{self.meter.meter_uuid}_statistic" + self._attr_unique_id = f"{self._uuid}_statistic" self._attr_native_unit_of_measurement = get_ha_native_unit_of_measurement( meter.native_unit_of_measurement, ) self._attr_suggested_display_precision = 0 self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, self.meter.meter_uuid)}, - name=f"{WATER_METER_NAME} {self.meter.meter_id}", + identifiers={(DOMAIN, self._uuid)}, + name=f"{WATER_METER_NAME} {self._id}", model=self.meter.meter_info.reading.model, manufacturer=self.meter.meter_info.reading.customer_name, hw_version=self.meter.meter_info.reading.hardware_version, @@ -172,10 +177,13 @@ def __init__( """Initialize the sensor.""" super().__init__(coordinator) self.meter = meter - self._attr_unique_id = f"{self.meter.meter_uuid}_temperature" + self._uuid = normalize_id(meter.meter_uuid) + self._id = normalize_id(meter.meter_id) + + self._attr_unique_id = f"{self._uuid}_temperature" self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, self.meter.meter_uuid)}, - name=f"{WATER_METER_NAME} {self.meter.meter_id}", + identifiers={(DOMAIN, self._uuid)}, + name=f"{WATER_METER_NAME} {self._id}", model=self.meter.meter_info.reading.model, manufacturer=self.meter.meter_info.reading.customer_name, hw_version=self.meter.meter_info.reading.hardware_version, @@ -185,7 +193,13 @@ def __init__( @property def native_value(self) -> float | None: """Get native value.""" - return self.meter.meter_info.sensors.endpoint_temperature.seven_day_min + if ( + self.meter.meter_info.sensors + and self.meter.meter_info.sensors.endpoint_temperature + ): + return self.meter.meter_info.sensors.endpoint_temperature.seven_day_min + + return None class EyeOnWaterSensor(CoordinatorEntity, SensorEntity): @@ -204,17 +218,20 @@ def __init__( """Initialize the sensor.""" super().__init__(coordinator) self.meter = meter + self._uuid = normalize_id(meter.meter_uuid) + self._id = normalize_id(meter.meter_id) + self._state: pyonwater.DataPoint | None = None self._available = False - self._attr_unique_id = meter.meter_uuid + self._attr_unique_id = self._uuid self._attr_native_unit_of_measurement = get_ha_native_unit_of_measurement( meter.native_unit_of_measurement, ) self._attr_suggested_display_precision = 0 self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, self.meter.meter_uuid)}, - name=f"{WATER_METER_NAME} {self.meter.meter_id}", + identifiers={(DOMAIN, self._uuid)}, + name=f"{WATER_METER_NAME} {self._id}", model=self.meter.meter_info.reading.model, manufacturer=self.meter.meter_info.reading.customer_name, hw_version=self.meter.meter_info.reading.hardware_version, diff --git a/custom_components/eyeonwater/statistic_helper.py b/custom_components/eyeonwater/statistic_helper.py index 8124687..a22cb4b 100644 --- a/custom_components/eyeonwater/statistic_helper.py +++ b/custom_components/eyeonwater/statistic_helper.py @@ -40,12 +40,21 @@ def get_ha_native_unit_of_measurement(unit: pyonwater.NativeUnits): def get_statistic_name(meter_id: str) -> str: """Generate statistic name for a meter.""" + meter_id = normalize_id(meter_id) return f"{WATER_METER_NAME} {meter_id} Statistic" +def normalize_id(uuid: str) -> str: + """Normalize ID.""" + chars = [c if c.isalnum() or c == "_" else "_" for c in uuid] + uuid = "".join(chars) + return uuid.lower() + + def get_statistics_id(meter_id: str) -> str: """Generate statistic ID for a meter.""" - return f"sensor.water_meter_{meter_id.lower()}_statistic" + meter_id = normalize_id(meter_id) + return f"sensor.water_meter_{meter_id}_statistic" def get_statistic_metadata(meter: Meter) -> StatisticMetaData: