Add support for feature units (#843)

Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
This commit is contained in:
Teemu R 2024-04-22 11:25:30 +02:00 committed by GitHub
parent 651ad96144
commit 890900daf3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 27 additions and 25 deletions

View File

@ -598,9 +598,10 @@ async def state(ctx, dev: Device):
echo("\t[bold]== Children ==[/bold]") echo("\t[bold]== Children ==[/bold]")
for child in dev.children: for child in dev.children:
echo(f"\t* {child.alias} ({child.model}, {child.device_type})") echo(f"\t* {child.alias} ({child.model}, {child.device_type})")
for feat in child.features.values(): for id_, feat in child.features.items():
try: try:
echo(f"\t\t{feat.name}: {feat.value}") unit = f" {feat.unit}" if feat.unit else ""
echo(f"\t\t{feat.name} ({id_}): {feat.value}{unit}")
except Exception as ex: except Exception as ex:
echo(f"\t\t{feat.name}: got exception (%s)" % ex) echo(f"\t\t{feat.name}: got exception (%s)" % ex)
echo() echo()
@ -614,12 +615,8 @@ async def state(ctx, dev: Device):
echo("\n\t[bold]== Device-specific information == [/bold]") echo("\n\t[bold]== Device-specific information == [/bold]")
for id_, feature in dev.features.items(): for id_, feature in dev.features.items():
echo(f"\t{feature.name} ({id_}): {feature.value}") unit = f" {feature.unit}" if feature.unit else ""
echo(f"\t{feature.name} ({id_}): {feature.value}{unit}")
if dev.has_emeter:
echo("\n\t[bold]== Current State ==[/bold]")
emeter_status = dev.emeter_realtime
echo(f"\t{emeter_status}")
echo("\n\t[bold]== Modules ==[/bold]") echo("\n\t[bold]== Modules ==[/bold]")
for module in dev.modules.values(): for module in dev.modules.values():
@ -1177,7 +1174,8 @@ async def feature(dev: Device, child: str, name: str, value):
def _print_features(dev): def _print_features(dev):
for name, feat in dev.features.items(): for name, feat in dev.features.items():
try: try:
echo(f"\t{feat.name} ({name}): {feat.value}") unit = f" {feat.unit}" if feat.unit else ""
echo(f"\t{feat.name} ({name}): {feat.value}{unit}")
except Exception as ex: except Exception as ex:
echo(f"\t{feat.name} ({name}): [red]{ex}[/red]") echo(f"\t{feat.name} ({name}): [red]{ex}[/red]")
@ -1198,7 +1196,8 @@ async def feature(dev: Device, child: str, name: str, value):
feat = dev.features[name] feat = dev.features[name]
if value is None: if value is None:
echo(f"{feat.name} ({name}): {feat.value}") unit = f" {feat.unit}" if feat.unit else ""
echo(f"{feat.name} ({name}): {feat.value}{unit}")
return feat.value return feat.value
echo(f"Setting {name} to {value}") echo(f"Setting {name} to {value}")

View File

@ -36,6 +36,8 @@ class Feature:
container: Any = None container: Any = None
#: Icon suggestion #: Icon suggestion
icon: str | None = None icon: str | None = None
#: Unit, if applicable
unit: str | None = None
#: Type of the feature #: Type of the feature
type: FeatureType = FeatureType.Sensor type: FeatureType = FeatureType.Sensor

View File

@ -25,24 +25,27 @@ class EnergyModule(SmartModule):
name="Current consumption", name="Current consumption",
attribute_getter="current_power", attribute_getter="current_power",
container=self, container=self,
unit="W",
) )
) # W or mW? )
self._add_feature( self._add_feature(
Feature( Feature(
device, device,
name="Today's consumption", name="Today's consumption",
attribute_getter="emeter_today", attribute_getter="emeter_today",
container=self, container=self,
unit="Wh",
) )
) # Wh or kWh? )
self._add_feature( self._add_feature(
Feature( Feature(
device, device,
name="This month's consumption", name="This month's consumption",
attribute_getter="emeter_this_month", attribute_getter="emeter_this_month",
container=self, container=self,
unit="Wh",
) )
) # Wh or kWH? )
def query(self) -> dict: def query(self) -> dict:
"""Query to execute during the update cycle.""" """Query to execute during the update cycle."""
@ -54,9 +57,11 @@ class EnergyModule(SmartModule):
return req return req
@property @property
def current_power(self): def current_power(self) -> float | None:
"""Current power.""" """Current power in watts."""
return self.emeter_realtime.power if power := self.energy.get("current_power"):
return power / 1_000
return None
@property @property
def energy(self): def energy(self):
@ -72,22 +77,16 @@ class EnergyModule(SmartModule):
return EmeterStatus( return EmeterStatus(
{ {
"power_mw": self.energy.get("current_power"), "power_mw": self.energy.get("current_power"),
"total": self._convert_energy_data( "total": self.energy.get("today_energy") / 1_000,
self.energy.get("today_energy"), 1 / 1000
),
} }
) )
@property @property
def emeter_this_month(self) -> float | None: def emeter_this_month(self) -> float | None:
"""Get the emeter value for this month.""" """Get the emeter value for this month."""
return self._convert_energy_data(self.energy.get("month_energy"), 1 / 1000) return self.energy.get("month_energy")
@property @property
def emeter_today(self) -> float | None: def emeter_today(self) -> float | None:
"""Get the emeter value for today.""" """Get the emeter value for today."""
return self._convert_energy_data(self.energy.get("today_energy"), 1 / 1000) return self.energy.get("today_energy")
def _convert_energy_data(self, data, scale) -> float | None:
"""Return adjusted emeter information."""
return data if not data else data * scale

View File

@ -17,6 +17,7 @@ def dummy_feature() -> Feature:
container=None, container=None,
icon="mdi:dummy", icon="mdi:dummy",
type=FeatureType.BinarySensor, type=FeatureType.BinarySensor,
unit="dummyunit",
) )
return feat return feat
@ -30,6 +31,7 @@ def test_feature_api(dummy_feature: Feature):
assert dummy_feature.container is None assert dummy_feature.container is None
assert dummy_feature.icon == "mdi:dummy" assert dummy_feature.icon == "mdi:dummy"
assert dummy_feature.type == FeatureType.BinarySensor assert dummy_feature.type == FeatureType.BinarySensor
assert dummy_feature.unit == "dummyunit"
def test_feature_value(dummy_feature: Feature): def test_feature_value(dummy_feature: Feature):