mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Huawei LTE sensor improvements (#84019)
* Use `None` for unknown states consistently * Use huawei_lte_api NetworkModeEnum instead of magic strings * Recognize some new sensor items * Exclude current day duration sensor * Fix current month upload/download types * Add current day transfer * Extract lambdas used in multiple spots to named functions * Formatter naming consistency improvements
This commit is contained in:
parent
7953c4a6d5
commit
a5a079fb06
@ -2,11 +2,14 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from bisect import bisect
|
from bisect import bisect
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable, Sequence
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from huawei_lte_api.enums.net import NetworkModeEnum
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
DOMAIN as SENSOR_DOMAIN,
|
DOMAIN as SENSOR_DOMAIN,
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
@ -17,7 +20,6 @@ from homeassistant.components.sensor import (
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
STATE_UNKNOWN,
|
|
||||||
UnitOfDataRate,
|
UnitOfDataRate,
|
||||||
UnitOfFrequency,
|
UnitOfFrequency,
|
||||||
UnitOfInformation,
|
UnitOfInformation,
|
||||||
@ -62,6 +64,45 @@ def format_default(value: StateType) -> tuple[StateType, str | None]:
|
|||||||
return value, unit
|
return value, unit
|
||||||
|
|
||||||
|
|
||||||
|
def format_freq_mhz(value: StateType) -> tuple[StateType, UnitOfFrequency]:
|
||||||
|
"""Format a frequency value for which source is in tens of MHz."""
|
||||||
|
return (
|
||||||
|
round(int(value) / 10) if value is not None else None,
|
||||||
|
UnitOfFrequency.MEGAHERTZ,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def format_last_reset_elapsed_seconds(value: str | None) -> datetime | None:
|
||||||
|
"""Convert elapsed seconds to last reset datetime."""
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
last_reset = datetime.now() - timedelta(seconds=int(value))
|
||||||
|
last_reset.replace(microsecond=0)
|
||||||
|
return last_reset
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def signal_icon(limits: Sequence[int], value: StateType) -> str:
|
||||||
|
"""Get signal icon."""
|
||||||
|
return (
|
||||||
|
"mdi:signal-cellular-outline",
|
||||||
|
"mdi:signal-cellular-1",
|
||||||
|
"mdi:signal-cellular-2",
|
||||||
|
"mdi:signal-cellular-3",
|
||||||
|
)[bisect(limits, value if value is not None else -1000)]
|
||||||
|
|
||||||
|
|
||||||
|
def bandwidth_icon(limits: Sequence[int], value: StateType) -> str:
|
||||||
|
"""Get bandwidth icon."""
|
||||||
|
return (
|
||||||
|
"mdi:speedometer-slow",
|
||||||
|
"mdi:speedometer-medium",
|
||||||
|
"mdi:speedometer",
|
||||||
|
)[bisect(limits, value if value is not None else -1000)]
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class HuaweiSensorGroup:
|
class HuaweiSensorGroup:
|
||||||
"""Class describing Huawei LTE sensor groups."""
|
"""Class describing Huawei LTE sensor groups."""
|
||||||
@ -75,8 +116,10 @@ class HuaweiSensorGroup:
|
|||||||
class HuaweiSensorEntityDescription(SensorEntityDescription):
|
class HuaweiSensorEntityDescription(SensorEntityDescription):
|
||||||
"""Class describing Huawei LTE sensor entities."""
|
"""Class describing Huawei LTE sensor entities."""
|
||||||
|
|
||||||
formatter: Callable[[str], tuple[StateType, str | None]] = format_default
|
format_fn: Callable[[str], tuple[StateType, str | None]] = format_default
|
||||||
icon_fn: Callable[[StateType], str] | None = None
|
icon_fn: Callable[[StateType], str] | None = None
|
||||||
|
last_reset_item: str | None = None
|
||||||
|
last_reset_format_fn: Callable[[str | None], datetime | None] | None = None
|
||||||
|
|
||||||
|
|
||||||
SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
||||||
@ -114,11 +157,21 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
#
|
#
|
||||||
KEY_DEVICE_SIGNAL: HuaweiSensorGroup(
|
KEY_DEVICE_SIGNAL: HuaweiSensorGroup(
|
||||||
descriptions={
|
descriptions={
|
||||||
|
"arfcn": HuaweiSensorEntityDescription(
|
||||||
|
key="arfcn",
|
||||||
|
name="ARFCN",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
"band": HuaweiSensorEntityDescription(
|
"band": HuaweiSensorEntityDescription(
|
||||||
key="band",
|
key="band",
|
||||||
name="Band",
|
name="Band",
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
|
"bsic": HuaweiSensorEntityDescription(
|
||||||
|
key="bsic",
|
||||||
|
name="Base station identity code",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
"cell_id": HuaweiSensorEntityDescription(
|
"cell_id": HuaweiSensorEntityDescription(
|
||||||
key="cell_id",
|
key="cell_id",
|
||||||
name="Cell ID",
|
name="Cell ID",
|
||||||
@ -144,11 +197,13 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
"dlbandwidth": HuaweiSensorEntityDescription(
|
"dlbandwidth": HuaweiSensorEntityDescription(
|
||||||
key="dlbandwidth",
|
key="dlbandwidth",
|
||||||
name="Downlink bandwidth",
|
name="Downlink bandwidth",
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: bandwidth_icon((8, 15), x),
|
||||||
"mdi:speedometer-slow",
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
"mdi:speedometer-medium",
|
),
|
||||||
"mdi:speedometer",
|
"dlfrequency": HuaweiSensorEntityDescription(
|
||||||
)[bisect((8, 15), x if x is not None else -1000)],
|
key="dlfrequency",
|
||||||
|
name="Downlink frequency",
|
||||||
|
device_class=SensorDeviceClass.FREQUENCY,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
"earfcn": HuaweiSensorEntityDescription(
|
"earfcn": HuaweiSensorEntityDescription(
|
||||||
@ -161,12 +216,7 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
name="EC/IO",
|
name="EC/IO",
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
# https://wiki.teltonika.lt/view/EC/IO
|
# https://wiki.teltonika.lt/view/EC/IO
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: signal_icon((-20, -10, -6), x),
|
||||||
"mdi:signal-cellular-outline",
|
|
||||||
"mdi:signal-cellular-1",
|
|
||||||
"mdi:signal-cellular-2",
|
|
||||||
"mdi:signal-cellular-3",
|
|
||||||
)[bisect((-20, -10, -6), x if x is not None else -1000)],
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
@ -183,29 +233,23 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
),
|
),
|
||||||
"ltedlfreq": HuaweiSensorEntityDescription(
|
"ltedlfreq": HuaweiSensorEntityDescription(
|
||||||
key="ltedlfreq",
|
key="ltedlfreq",
|
||||||
name="Downlink frequency",
|
name="LTE downlink frequency",
|
||||||
formatter=lambda x: (
|
format_fn=format_freq_mhz,
|
||||||
round(int(x) / 10) if x is not None else None,
|
|
||||||
UnitOfFrequency.MEGAHERTZ,
|
|
||||||
),
|
|
||||||
device_class=SensorDeviceClass.FREQUENCY,
|
device_class=SensorDeviceClass.FREQUENCY,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
"lteulfreq": HuaweiSensorEntityDescription(
|
"lteulfreq": HuaweiSensorEntityDescription(
|
||||||
key="lteulfreq",
|
key="lteulfreq",
|
||||||
name="Uplink frequency",
|
name="LTE uplink frequency",
|
||||||
formatter=lambda x: (
|
format_fn=format_freq_mhz,
|
||||||
round(int(x) / 10) if x is not None else None,
|
|
||||||
UnitOfFrequency.MEGAHERTZ,
|
|
||||||
),
|
|
||||||
device_class=SensorDeviceClass.FREQUENCY,
|
device_class=SensorDeviceClass.FREQUENCY,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
"mode": HuaweiSensorEntityDescription(
|
"mode": HuaweiSensorEntityDescription(
|
||||||
key="mode",
|
key="mode",
|
||||||
name="Mode",
|
name="Mode",
|
||||||
formatter=lambda x: (
|
format_fn=lambda x: (
|
||||||
{"0": "2G", "2": "3G", "7": "4G"}.get(x, "Unknown"),
|
{"0": "2G", "2": "3G", "7": "4G"}.get(x),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: (
|
||||||
@ -244,12 +288,7 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
name="RSCP",
|
name="RSCP",
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
# https://wiki.teltonika.lt/view/RSCP
|
# https://wiki.teltonika.lt/view/RSCP
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: signal_icon((-95, -85, -75), x),
|
||||||
"mdi:signal-cellular-outline",
|
|
||||||
"mdi:signal-cellular-1",
|
|
||||||
"mdi:signal-cellular-2",
|
|
||||||
"mdi:signal-cellular-3",
|
|
||||||
)[bisect((-95, -85, -75), x if x is not None else -1000)],
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
@ -258,12 +297,7 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
name="RSRP",
|
name="RSRP",
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
# http://www.lte-anbieter.info/technik/rsrp.php
|
# http://www.lte-anbieter.info/technik/rsrp.php
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: signal_icon((-110, -95, -80), x),
|
||||||
"mdi:signal-cellular-outline",
|
|
||||||
"mdi:signal-cellular-1",
|
|
||||||
"mdi:signal-cellular-2",
|
|
||||||
"mdi:signal-cellular-3",
|
|
||||||
)[bisect((-110, -95, -80), x if x is not None else -1000)],
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
entity_registry_enabled_default=True,
|
entity_registry_enabled_default=True,
|
||||||
@ -273,12 +307,7 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
name="RSRQ",
|
name="RSRQ",
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
# http://www.lte-anbieter.info/technik/rsrq.php
|
# http://www.lte-anbieter.info/technik/rsrq.php
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: signal_icon((-11, -8, -5), x),
|
||||||
"mdi:signal-cellular-outline",
|
|
||||||
"mdi:signal-cellular-1",
|
|
||||||
"mdi:signal-cellular-2",
|
|
||||||
"mdi:signal-cellular-3",
|
|
||||||
)[bisect((-11, -8, -5), x if x is not None else -1000)],
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
entity_registry_enabled_default=True,
|
entity_registry_enabled_default=True,
|
||||||
@ -288,12 +317,7 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
name="RSSI",
|
name="RSSI",
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
# https://eyesaas.com/wi-fi-signal-strength/
|
# https://eyesaas.com/wi-fi-signal-strength/
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: signal_icon((-80, -70, -60), x),
|
||||||
"mdi:signal-cellular-outline",
|
|
||||||
"mdi:signal-cellular-1",
|
|
||||||
"mdi:signal-cellular-2",
|
|
||||||
"mdi:signal-cellular-3",
|
|
||||||
)[bisect((-80, -70, -60), x if x is not None else -1000)],
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
entity_registry_enabled_default=True,
|
entity_registry_enabled_default=True,
|
||||||
@ -303,12 +327,7 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
name="SINR",
|
name="SINR",
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
# http://www.lte-anbieter.info/technik/sinr.php
|
# http://www.lte-anbieter.info/technik/sinr.php
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: signal_icon((0, 5, 10), x),
|
||||||
"mdi:signal-cellular-outline",
|
|
||||||
"mdi:signal-cellular-1",
|
|
||||||
"mdi:signal-cellular-2",
|
|
||||||
"mdi:signal-cellular-3",
|
|
||||||
)[bisect((0, 5, 10), x if x is not None else -1000)],
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
entity_registry_enabled_default=True,
|
entity_registry_enabled_default=True,
|
||||||
@ -343,11 +362,13 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
"ulbandwidth": HuaweiSensorEntityDescription(
|
"ulbandwidth": HuaweiSensorEntityDescription(
|
||||||
key="ulbandwidth",
|
key="ulbandwidth",
|
||||||
name="Uplink bandwidth",
|
name="Uplink bandwidth",
|
||||||
icon_fn=lambda x: (
|
icon_fn=lambda x: bandwidth_icon((8, 15), x),
|
||||||
"mdi:speedometer-slow",
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
"mdi:speedometer-medium",
|
),
|
||||||
"mdi:speedometer",
|
"ulfrequency": HuaweiSensorEntityDescription(
|
||||||
)[bisect((8, 15), x if x is not None else -1000)],
|
key="ulfrequency",
|
||||||
|
name="Uplink frequency",
|
||||||
|
device_class=SensorDeviceClass.FREQUENCY,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -367,15 +388,29 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
KEY_MONITORING_MONTH_STATISTICS: HuaweiSensorGroup(
|
KEY_MONITORING_MONTH_STATISTICS: HuaweiSensorGroup(
|
||||||
exclude=re.compile(r"^month(duration|lastcleartime)$", re.IGNORECASE),
|
exclude=re.compile(
|
||||||
|
r"^(currentday|month)(duration|lastcleartime)$", re.IGNORECASE
|
||||||
|
),
|
||||||
descriptions={
|
descriptions={
|
||||||
|
"CurrentDayUsed": HuaweiSensorEntityDescription(
|
||||||
|
key="CurrentDayUsed",
|
||||||
|
name="Current day transfer",
|
||||||
|
native_unit_of_measurement=UnitOfInformation.BYTES,
|
||||||
|
device_class=SensorDeviceClass.DATA_SIZE,
|
||||||
|
icon="mdi:arrow-up-down-bold",
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
last_reset_item="CurrentDayDuration",
|
||||||
|
last_reset_format_fn=format_last_reset_elapsed_seconds,
|
||||||
|
),
|
||||||
"CurrentMonthDownload": HuaweiSensorEntityDescription(
|
"CurrentMonthDownload": HuaweiSensorEntityDescription(
|
||||||
key="CurrentMonthDownload",
|
key="CurrentMonthDownload",
|
||||||
name="Current month download",
|
name="Current month download",
|
||||||
native_unit_of_measurement=UnitOfInformation.BYTES,
|
native_unit_of_measurement=UnitOfInformation.BYTES,
|
||||||
device_class=SensorDeviceClass.DATA_SIZE,
|
device_class=SensorDeviceClass.DATA_SIZE,
|
||||||
icon="mdi:download",
|
icon="mdi:download",
|
||||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
last_reset_item="MonthDuration",
|
||||||
|
last_reset_format_fn=format_last_reset_elapsed_seconds,
|
||||||
),
|
),
|
||||||
"CurrentMonthUpload": HuaweiSensorEntityDescription(
|
"CurrentMonthUpload": HuaweiSensorEntityDescription(
|
||||||
key="CurrentMonthUpload",
|
key="CurrentMonthUpload",
|
||||||
@ -383,7 +418,9 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
native_unit_of_measurement=UnitOfInformation.BYTES,
|
native_unit_of_measurement=UnitOfInformation.BYTES,
|
||||||
device_class=SensorDeviceClass.DATA_SIZE,
|
device_class=SensorDeviceClass.DATA_SIZE,
|
||||||
icon="mdi:upload",
|
icon="mdi:upload",
|
||||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
last_reset_item="MonthDuration",
|
||||||
|
last_reset_format_fn=format_last_reset_elapsed_seconds,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -521,8 +558,8 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
"State": HuaweiSensorEntityDescription(
|
"State": HuaweiSensorEntityDescription(
|
||||||
key="State",
|
key="State",
|
||||||
name="Operator search mode",
|
name="Operator search mode",
|
||||||
formatter=lambda x: (
|
format_fn=lambda x: (
|
||||||
{"0": "Auto", "1": "Manual"}.get(x, "Unknown"),
|
{"0": "Auto", "1": "Manual"}.get(x),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
entity_category=EntityCategory.CONFIG,
|
entity_category=EntityCategory.CONFIG,
|
||||||
@ -535,16 +572,16 @@ SENSOR_META: dict[str, HuaweiSensorGroup] = {
|
|||||||
"NetworkMode": HuaweiSensorEntityDescription(
|
"NetworkMode": HuaweiSensorEntityDescription(
|
||||||
key="NetworkMode",
|
key="NetworkMode",
|
||||||
name="Preferred mode",
|
name="Preferred mode",
|
||||||
formatter=lambda x: (
|
format_fn=lambda x: (
|
||||||
{
|
{
|
||||||
"00": "4G/3G/2G",
|
NetworkModeEnum.MODE_AUTO.value: "4G/3G/2G",
|
||||||
"01": "2G",
|
NetworkModeEnum.MODE_4G_3G_AUTO.value: "4G/3G",
|
||||||
"02": "3G",
|
NetworkModeEnum.MODE_4G_2G_AUTO.value: "4G/2G",
|
||||||
"03": "4G",
|
NetworkModeEnum.MODE_4G_ONLY.value: "4G",
|
||||||
"0301": "4G/2G",
|
NetworkModeEnum.MODE_3G_2G_AUTO.value: "3G/2G",
|
||||||
"0302": "4G/3G",
|
NetworkModeEnum.MODE_3G_ONLY.value: "3G",
|
||||||
"0201": "3G/2G",
|
NetworkModeEnum.MODE_2G_ONLY.value: "2G",
|
||||||
}.get(x, "Unknown"),
|
}.get(x),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
entity_category=EntityCategory.CONFIG,
|
entity_category=EntityCategory.CONFIG,
|
||||||
@ -660,8 +697,9 @@ class HuaweiLteSensor(HuaweiLteBaseEntityWithDevice, SensorEntity):
|
|||||||
item: str
|
item: str
|
||||||
entity_description: HuaweiSensorEntityDescription
|
entity_description: HuaweiSensorEntityDescription
|
||||||
|
|
||||||
_state: StateType = field(default=STATE_UNKNOWN, init=False)
|
_state: StateType = field(default=None, init=False)
|
||||||
_unit: str | None = field(default=None, init=False)
|
_unit: str | None = field(default=None, init=False)
|
||||||
|
_last_reset: datetime | None = field(default=None, init=False)
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
"""Initialize remaining attributes."""
|
"""Initialize remaining attributes."""
|
||||||
@ -671,11 +709,19 @@ class HuaweiLteSensor(HuaweiLteBaseEntityWithDevice, SensorEntity):
|
|||||||
"""Subscribe to needed data on add."""
|
"""Subscribe to needed data on add."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
self.router.subscriptions[self.key].add(f"{SENSOR_DOMAIN}/{self.item}")
|
self.router.subscriptions[self.key].add(f"{SENSOR_DOMAIN}/{self.item}")
|
||||||
|
if self.entity_description.last_reset_item:
|
||||||
|
self.router.subscriptions[self.key].add(
|
||||||
|
f"{SENSOR_DOMAIN}/{self.entity_description.last_reset_item}"
|
||||||
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Unsubscribe from needed data on remove."""
|
"""Unsubscribe from needed data on remove."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
self.router.subscriptions[self.key].remove(f"{SENSOR_DOMAIN}/{self.item}")
|
self.router.subscriptions[self.key].remove(f"{SENSOR_DOMAIN}/{self.item}")
|
||||||
|
if self.entity_description.last_reset_item:
|
||||||
|
self.router.subscriptions[self.key].remove(
|
||||||
|
f"{SENSOR_DOMAIN}/{self.entity_description.last_reset_item}"
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _device_unique_id(self) -> str:
|
def _device_unique_id(self) -> str:
|
||||||
@ -698,6 +744,11 @@ class HuaweiLteSensor(HuaweiLteBaseEntityWithDevice, SensorEntity):
|
|||||||
return self.entity_description.icon_fn(self.state)
|
return self.entity_description.icon_fn(self.state)
|
||||||
return self.entity_description.icon
|
return self.entity_description.icon
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last_reset(self) -> datetime | None:
|
||||||
|
"""Return the time when the sensor was last reset, if any."""
|
||||||
|
return self._last_reset
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update state."""
|
"""Update state."""
|
||||||
try:
|
try:
|
||||||
@ -706,7 +757,26 @@ class HuaweiLteSensor(HuaweiLteBaseEntityWithDevice, SensorEntity):
|
|||||||
_LOGGER.debug("%s[%s] not in data", self.key, self.item)
|
_LOGGER.debug("%s[%s] not in data", self.key, self.item)
|
||||||
value = None
|
value = None
|
||||||
|
|
||||||
formatter = self.entity_description.formatter
|
last_reset = None
|
||||||
|
if (
|
||||||
|
self.entity_description.last_reset_item
|
||||||
|
and self.entity_description.last_reset_format_fn
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
last_reset_value = self.router.data[self.key][
|
||||||
|
self.entity_description.last_reset_item
|
||||||
|
]
|
||||||
|
except KeyError:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s[%s] not in data",
|
||||||
|
self.key,
|
||||||
|
self.entity_description.last_reset_item,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
last_reset = self.entity_description.last_reset_format_fn(
|
||||||
|
last_reset_value
|
||||||
|
)
|
||||||
|
|
||||||
self._state, self._unit = formatter(value)
|
self._state, self._unit = self.entity_description.format_fn(value)
|
||||||
|
self._last_reset = last_reset
|
||||||
self._available = value is not None
|
self._available = value is not None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user