Add missing sensors for Shelly Plus H&T (#76001)
* Add missing sensors for Shelly Plus H&T * Cleanup * Fix * Add voltage to battery sensor * Apply review comments
This commit is contained in:
parent
5bb5920697
commit
0738f08215
3 changed files with 53 additions and 7 deletions
|
@ -190,9 +190,9 @@ def async_setup_entry_rpc(
|
|||
] and not description.supported(wrapper.device.status[key]):
|
||||
continue
|
||||
|
||||
# Filter and remove entities that according to settings should not create an entity
|
||||
# Filter and remove entities that according to settings/status should not create an entity
|
||||
if description.removal_condition and description.removal_condition(
|
||||
wrapper.device.config, key
|
||||
wrapper.device.config, wrapper.device.status, key
|
||||
):
|
||||
domain = sensor_class.__module__.split(".")[-1]
|
||||
unique_id = f"{wrapper.mac}-{key}-{sensor_id}"
|
||||
|
@ -268,7 +268,7 @@ class RpcEntityDescription(EntityDescription, RpcEntityRequiredKeysMixin):
|
|||
|
||||
value: Callable[[Any, Any], Any] | None = None
|
||||
available: Callable[[dict], bool] | None = None
|
||||
removal_condition: Callable[[dict, str], bool] | None = None
|
||||
removal_condition: Callable[[dict, dict, str], bool] | None = None
|
||||
extra_state_attributes: Callable[[dict, dict], dict | None] | None = None
|
||||
use_polling_wrapper: bool = False
|
||||
supported: Callable = lambda _: False
|
||||
|
|
|
@ -46,7 +46,12 @@ from .entity import (
|
|||
async_setup_entry_rest,
|
||||
async_setup_entry_rpc,
|
||||
)
|
||||
from .utils import get_device_entry_gen, get_device_uptime, temperature_unit
|
||||
from .utils import (
|
||||
get_device_entry_gen,
|
||||
get_device_uptime,
|
||||
is_rpc_device_externally_powered,
|
||||
temperature_unit,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -352,6 +357,15 @@ RPC_SENSORS: Final = {
|
|||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
use_polling_wrapper=True,
|
||||
),
|
||||
"temperature_0": RpcSensorDescription(
|
||||
key="temperature:0",
|
||||
sub_key="tC",
|
||||
name="Temperature",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=True,
|
||||
),
|
||||
"rssi": RpcSensorDescription(
|
||||
key="wifi",
|
||||
sub_key="rssi",
|
||||
|
@ -373,6 +387,27 @@ RPC_SENSORS: Final = {
|
|||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
use_polling_wrapper=True,
|
||||
),
|
||||
"humidity_0": RpcSensorDescription(
|
||||
key="humidity:0",
|
||||
sub_key="rh",
|
||||
name="Humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=True,
|
||||
),
|
||||
"battery": RpcSensorDescription(
|
||||
key="devicepower:0",
|
||||
sub_key="battery",
|
||||
name="Battery",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value=lambda status, _: status["percent"],
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
removal_condition=is_rpc_device_externally_powered,
|
||||
entity_registry_enabled_default=True,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -271,7 +271,9 @@ def get_rpc_channel_name(device: RpcDevice, key: str) -> str:
|
|||
entity_name = device.config[key].get("name", device_name)
|
||||
|
||||
if entity_name is None:
|
||||
return f"{device_name} {key.replace(':', '_')}"
|
||||
if [k for k in key if k.startswith(("input", "switch"))]:
|
||||
return f"{device_name} {key.replace(':', '_')}"
|
||||
return device_name
|
||||
|
||||
return entity_name
|
||||
|
||||
|
@ -325,7 +327,9 @@ def get_rpc_key_ids(keys_dict: dict[str, Any], key: str) -> list[int]:
|
|||
return key_ids
|
||||
|
||||
|
||||
def is_rpc_momentary_input(config: dict[str, Any], key: str) -> bool:
|
||||
def is_rpc_momentary_input(
|
||||
config: dict[str, Any], status: dict[str, Any], key: str
|
||||
) -> bool:
|
||||
"""Return true if rpc input button settings is set to a momentary type."""
|
||||
return cast(bool, config[key]["type"] == "button")
|
||||
|
||||
|
@ -342,6 +346,13 @@ def is_rpc_channel_type_light(config: dict[str, Any], channel: int) -> bool:
|
|||
return con_types is not None and con_types[channel].lower().startswith("light")
|
||||
|
||||
|
||||
def is_rpc_device_externally_powered(
|
||||
config: dict[str, Any], status: dict[str, Any], key: str
|
||||
) -> bool:
|
||||
"""Return true if device has external power instead of battery."""
|
||||
return cast(bool, status[key]["external"]["present"])
|
||||
|
||||
|
||||
def get_rpc_input_triggers(device: RpcDevice) -> list[tuple[str, str]]:
|
||||
"""Return list of input triggers for RPC device."""
|
||||
triggers = []
|
||||
|
@ -350,7 +361,7 @@ def get_rpc_input_triggers(device: RpcDevice) -> list[tuple[str, str]]:
|
|||
|
||||
for id_ in key_ids:
|
||||
key = f"input:{id_}"
|
||||
if not is_rpc_momentary_input(device.config, key):
|
||||
if not is_rpc_momentary_input(device.config, device.status, key):
|
||||
continue
|
||||
|
||||
for trigger_type in RPC_INPUTS_EVENTS_TYPES:
|
||||
|
|
Loading…
Add table
Reference in a new issue