mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 03:33:35 +00:00
Add support for feature units (#843)
Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
This commit is contained in:
parent
651ad96144
commit
890900daf3
19
kasa/cli.py
19
kasa/cli.py
@ -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}")
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user