Skip to content

Commit 21d06fd

Browse files
jcisiojoostlek
andauthored
Fix unit when plant power is above 1000W in Hypontech (#165959)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
1 parent c8cf13b commit 21d06fd

File tree

4 files changed

+225
-8
lines changed

4 files changed

+225
-8
lines changed

homeassistant/components/hypontech/sensor.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,34 @@
2121
from .entity import HypontechEntity, HypontechPlantEntity
2222

2323

24+
def _power_unit(data: OverviewData | PlantData) -> str:
25+
"""Return the unit of measurement for power based on the API unit."""
26+
return UnitOfPower.KILO_WATT if data.company.upper() == "KW" else UnitOfPower.WATT
27+
28+
2429
@dataclass(frozen=True, kw_only=True)
2530
class HypontechSensorDescription(SensorEntityDescription):
2631
"""Describes Hypontech overview sensor entity."""
2732

2833
value_fn: Callable[[OverviewData], float | None]
34+
unit_fn: Callable[[OverviewData], str] | None = None
2935

3036

3137
@dataclass(frozen=True, kw_only=True)
3238
class HypontechPlantSensorDescription(SensorEntityDescription):
3339
"""Describes Hypontech plant sensor entity."""
3440

3541
value_fn: Callable[[PlantData], float | None]
42+
unit_fn: Callable[[PlantData], str] | None = None
3643

3744

3845
OVERVIEW_SENSORS: tuple[HypontechSensorDescription, ...] = (
3946
HypontechSensorDescription(
4047
key="pv_power",
41-
native_unit_of_measurement=UnitOfPower.WATT,
4248
device_class=SensorDeviceClass.POWER,
4349
state_class=SensorStateClass.MEASUREMENT,
4450
value_fn=lambda c: c.power,
51+
unit_fn=_power_unit,
4552
),
4653
HypontechSensorDescription(
4754
key="lifetime_energy",
@@ -64,10 +71,10 @@ class HypontechPlantSensorDescription(SensorEntityDescription):
6471
PLANT_SENSORS: tuple[HypontechPlantSensorDescription, ...] = (
6572
HypontechPlantSensorDescription(
6673
key="pv_power",
67-
native_unit_of_measurement=UnitOfPower.WATT,
6874
device_class=SensorDeviceClass.POWER,
6975
state_class=SensorStateClass.MEASUREMENT,
7076
value_fn=lambda c: c.power,
77+
unit_fn=_power_unit,
7178
),
7279
HypontechPlantSensorDescription(
7380
key="lifetime_energy",
@@ -124,6 +131,13 @@ def __init__(
124131
self.entity_description = description
125132
self._attr_unique_id = f"{coordinator.account_id}_{description.key}"
126133

134+
@property
135+
def native_unit_of_measurement(self) -> str | None:
136+
"""Return the unit of measurement."""
137+
if self.entity_description.unit_fn is not None:
138+
return self.entity_description.unit_fn(self.coordinator.data.overview)
139+
return super().native_unit_of_measurement
140+
127141
@property
128142
def native_value(self) -> float | None:
129143
"""Return the state of the sensor."""
@@ -146,6 +160,13 @@ def __init__(
146160
self.entity_description = description
147161
self._attr_unique_id = f"{plant_id}_{description.key}"
148162

163+
@property
164+
def native_unit_of_measurement(self) -> str | None:
165+
"""Return the unit of measurement."""
166+
if self.entity_description.unit_fn is not None:
167+
return self.entity_description.unit_fn(self.plant)
168+
return super().native_unit_of_measurement
169+
149170
@property
150171
def native_value(self) -> float | None:
151172
"""Return the state of the sensor."""

tests/components/hypontech/fixtures/overview.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"e_today": 1.54,
77
"total_co2": 0.03,
88
"total_tree": 1.73,
9-
"power": 0,
9+
"power": 1223,
1010
"normal_dev_num": 0,
1111
"offline_dev_num": 1,
1212
"fault_dev_num": 0,

tests/components/hypontech/fixtures/plant_list.json

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,41 @@
1111
"city": "New York",
1212
"e_today": 1.54,
1313
"e_total": 48,
14-
"power": 0,
14+
"power": 123,
1515
"owner_id": "2123456789123456789",
1616
"plant_id": "1123456789123456789",
1717
"eid": 0,
1818
"top": 0,
1919
"micro": 1,
2020
"property": 1,
21-
"kwhimp": 0
21+
"kwhimp": 0,
22+
"company": "W"
23+
},
24+
{
25+
"status": "online",
26+
"time": "2026-02-16T18:04:50+01:00",
27+
"plant_name": "Rooftop",
28+
"plant_type": "PvGrid",
29+
"photo": "",
30+
"owner_name": "admin@example.com",
31+
"country": "United States",
32+
"city": "New York",
33+
"e_today": 2.5,
34+
"e_total": 100,
35+
"power": 1.1,
36+
"owner_id": "2123456789123456789",
37+
"plant_id": "3123456789123456789",
38+
"eid": 0,
39+
"top": 0,
40+
"micro": 1,
41+
"property": 1,
42+
"kwhimp": 0,
43+
"company": "KW"
2244
}
2345
],
2446
"message": "ok",
2547
"time": 1771277551,
2648
"totalPage": 1,
27-
"totalCount": 1,
49+
"totalCount": 2,
2850
"code": 20000
2951
}

tests/components/hypontech/snapshots/test_sensor.ambr

Lines changed: 176 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
'last_changed': <ANY>,
113113
'last_reported': <ANY>,
114114
'last_updated': <ANY>,
115-
'state': '0',
115+
'state': '123',
116116
})
117117
# ---
118118
# name: test_sensors[sensor.balcon_today_energy-entry]
@@ -286,7 +286,7 @@
286286
'last_changed': <ANY>,
287287
'last_reported': <ANY>,
288288
'last_updated': <ANY>,
289-
'state': '0',
289+
'state': '1223',
290290
})
291291
# ---
292292
# name: test_sensors[sensor.overview_today_energy-entry]
@@ -347,3 +347,177 @@
347347
'state': '1.54',
348348
})
349349
# ---
350+
# name: test_sensors[sensor.rooftop_lifetime_energy-entry]
351+
EntityRegistryEntrySnapshot({
352+
'aliases': list([
353+
None,
354+
]),
355+
'area_id': None,
356+
'capabilities': dict({
357+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
358+
}),
359+
'config_entry_id': <ANY>,
360+
'config_subentry_id': <ANY>,
361+
'device_class': None,
362+
'device_id': <ANY>,
363+
'disabled_by': None,
364+
'domain': 'sensor',
365+
'entity_category': None,
366+
'entity_id': 'sensor.rooftop_lifetime_energy',
367+
'has_entity_name': True,
368+
'hidden_by': None,
369+
'icon': None,
370+
'id': <ANY>,
371+
'labels': set({
372+
}),
373+
'name': None,
374+
'object_id_base': 'Lifetime energy',
375+
'options': dict({
376+
'sensor': dict({
377+
'suggested_display_precision': 2,
378+
}),
379+
}),
380+
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
381+
'original_icon': None,
382+
'original_name': 'Lifetime energy',
383+
'platform': 'hypontech',
384+
'previous_unique_id': None,
385+
'suggested_object_id': None,
386+
'supported_features': 0,
387+
'translation_key': 'lifetime_energy',
388+
'unique_id': '3123456789123456789_lifetime_energy',
389+
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
390+
})
391+
# ---
392+
# name: test_sensors[sensor.rooftop_lifetime_energy-state]
393+
StateSnapshot({
394+
'attributes': ReadOnlyDict({
395+
'device_class': 'energy',
396+
'friendly_name': 'Rooftop Lifetime energy',
397+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
398+
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
399+
}),
400+
'context': <ANY>,
401+
'entity_id': 'sensor.rooftop_lifetime_energy',
402+
'last_changed': <ANY>,
403+
'last_reported': <ANY>,
404+
'last_updated': <ANY>,
405+
'state': '100.0',
406+
})
407+
# ---
408+
# name: test_sensors[sensor.rooftop_power-entry]
409+
EntityRegistryEntrySnapshot({
410+
'aliases': list([
411+
None,
412+
]),
413+
'area_id': None,
414+
'capabilities': dict({
415+
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
416+
}),
417+
'config_entry_id': <ANY>,
418+
'config_subentry_id': <ANY>,
419+
'device_class': None,
420+
'device_id': <ANY>,
421+
'disabled_by': None,
422+
'domain': 'sensor',
423+
'entity_category': None,
424+
'entity_id': 'sensor.rooftop_power',
425+
'has_entity_name': True,
426+
'hidden_by': None,
427+
'icon': None,
428+
'id': <ANY>,
429+
'labels': set({
430+
}),
431+
'name': None,
432+
'object_id_base': 'Power',
433+
'options': dict({
434+
'sensor': dict({
435+
'suggested_display_precision': 2,
436+
}),
437+
}),
438+
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
439+
'original_icon': None,
440+
'original_name': 'Power',
441+
'platform': 'hypontech',
442+
'previous_unique_id': None,
443+
'suggested_object_id': None,
444+
'supported_features': 0,
445+
'translation_key': None,
446+
'unique_id': '3123456789123456789_pv_power',
447+
'unit_of_measurement': <UnitOfPower.KILO_WATT: 'kW'>,
448+
})
449+
# ---
450+
# name: test_sensors[sensor.rooftop_power-state]
451+
StateSnapshot({
452+
'attributes': ReadOnlyDict({
453+
'device_class': 'power',
454+
'friendly_name': 'Rooftop Power',
455+
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
456+
'unit_of_measurement': <UnitOfPower.KILO_WATT: 'kW'>,
457+
}),
458+
'context': <ANY>,
459+
'entity_id': 'sensor.rooftop_power',
460+
'last_changed': <ANY>,
461+
'last_reported': <ANY>,
462+
'last_updated': <ANY>,
463+
'state': '1',
464+
})
465+
# ---
466+
# name: test_sensors[sensor.rooftop_today_energy-entry]
467+
EntityRegistryEntrySnapshot({
468+
'aliases': list([
469+
None,
470+
]),
471+
'area_id': None,
472+
'capabilities': dict({
473+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
474+
}),
475+
'config_entry_id': <ANY>,
476+
'config_subentry_id': <ANY>,
477+
'device_class': None,
478+
'device_id': <ANY>,
479+
'disabled_by': None,
480+
'domain': 'sensor',
481+
'entity_category': None,
482+
'entity_id': 'sensor.rooftop_today_energy',
483+
'has_entity_name': True,
484+
'hidden_by': None,
485+
'icon': None,
486+
'id': <ANY>,
487+
'labels': set({
488+
}),
489+
'name': None,
490+
'object_id_base': 'Today energy',
491+
'options': dict({
492+
'sensor': dict({
493+
'suggested_display_precision': 2,
494+
}),
495+
}),
496+
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
497+
'original_icon': None,
498+
'original_name': 'Today energy',
499+
'platform': 'hypontech',
500+
'previous_unique_id': None,
501+
'suggested_object_id': None,
502+
'supported_features': 0,
503+
'translation_key': 'today_energy',
504+
'unique_id': '3123456789123456789_today_energy',
505+
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
506+
})
507+
# ---
508+
# name: test_sensors[sensor.rooftop_today_energy-state]
509+
StateSnapshot({
510+
'attributes': ReadOnlyDict({
511+
'device_class': 'energy',
512+
'friendly_name': 'Rooftop Today energy',
513+
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
514+
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
515+
}),
516+
'context': <ANY>,
517+
'entity_id': 'sensor.rooftop_today_energy',
518+
'last_changed': <ANY>,
519+
'last_reported': <ANY>,
520+
'last_updated': <ANY>,
521+
'state': '2.5',
522+
})
523+
# ---

0 commit comments

Comments
 (0)