mirror of
https://github.com/home-assistant/core.git
synced 2025-11-05 00:49:37 +00:00
Add entities for Shelly presence component (#151816)
This commit is contained in:
@@ -73,6 +73,17 @@ class RpcBinarySensor(ShellyRpcAttributeEntity, BinarySensorEntity):
|
|||||||
return bool(self.attribute_value)
|
return bool(self.attribute_value)
|
||||||
|
|
||||||
|
|
||||||
|
class RpcPresenceBinarySensor(RpcBinarySensor):
|
||||||
|
"""Represent a RPC binary sensor entity for presence component."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Available."""
|
||||||
|
available = super().available
|
||||||
|
|
||||||
|
return available and self.coordinator.device.config[self.key]["enable"]
|
||||||
|
|
||||||
|
|
||||||
class RpcBluTrvBinarySensor(RpcBinarySensor):
|
class RpcBluTrvBinarySensor(RpcBinarySensor):
|
||||||
"""Represent a RPC BluTrv binary sensor."""
|
"""Represent a RPC BluTrv binary sensor."""
|
||||||
|
|
||||||
@@ -283,6 +294,14 @@ RPC_SENSORS: Final = {
|
|||||||
name="Mute",
|
name="Mute",
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
|
"presence_num_objects": RpcBinarySensorDescription(
|
||||||
|
key="presence",
|
||||||
|
sub_key="num_objects",
|
||||||
|
value=lambda status, _: bool(status),
|
||||||
|
name="Occupancy",
|
||||||
|
device_class=BinarySensorDeviceClass.OCCUPANCY,
|
||||||
|
entity_class=RpcPresenceBinarySensor,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
|
"detected_objects": {
|
||||||
|
"default": "mdi:account-group"
|
||||||
|
},
|
||||||
"gas_concentration": {
|
"gas_concentration": {
|
||||||
"default": "mdi:gauge"
|
"default": "mdi:gauge"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -124,6 +124,17 @@ class RpcSensor(ShellyRpcAttributeEntity, SensorEntity):
|
|||||||
return self.option_map[attribute_value]
|
return self.option_map[attribute_value]
|
||||||
|
|
||||||
|
|
||||||
|
class RpcPresenceSensor(RpcSensor):
|
||||||
|
"""Represent a RPC presence sensor."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Available."""
|
||||||
|
available = super().available
|
||||||
|
|
||||||
|
return available and self.coordinator.device.config[self.key]["enable"]
|
||||||
|
|
||||||
|
|
||||||
class RpcEmeterPhaseSensor(RpcSensor):
|
class RpcEmeterPhaseSensor(RpcSensor):
|
||||||
"""Represent a RPC energy meter phase sensor."""
|
"""Represent a RPC energy meter phase sensor."""
|
||||||
|
|
||||||
@@ -1428,6 +1439,14 @@ RPC_SENSORS: Final = {
|
|||||||
device_class=SensorDeviceClass.ENUM,
|
device_class=SensorDeviceClass.ENUM,
|
||||||
options=["dark", "twilight", "bright"],
|
options=["dark", "twilight", "bright"],
|
||||||
),
|
),
|
||||||
|
"presence_num_objects": RpcSensorDescription(
|
||||||
|
key="presence",
|
||||||
|
sub_key="num_objects",
|
||||||
|
translation_key="detected_objects",
|
||||||
|
name="Detected objects",
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
entity_class=RpcPresenceSensor,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
|
"detected_objects": {
|
||||||
|
"unit_of_measurement": "objects"
|
||||||
|
},
|
||||||
"gas_detected": {
|
"gas_detected": {
|
||||||
"state": {
|
"state": {
|
||||||
"none": "None",
|
"none": "None",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from syrupy.assertion import SnapshotAssertion
|
|||||||
|
|
||||||
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
||||||
from homeassistant.components.shelly.const import UPDATE_PERIOD_MULTIPLIER
|
from homeassistant.components.shelly.const import UPDATE_PERIOD_MULTIPLIER
|
||||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNKNOWN
|
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||||
from homeassistant.core import HomeAssistant, State
|
from homeassistant.core import HomeAssistant, State
|
||||||
from homeassistant.helpers.device_registry import DeviceRegistry
|
from homeassistant.helpers.device_registry import DeviceRegistry
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
@@ -527,3 +527,44 @@ async def test_rpc_flood_entities(
|
|||||||
|
|
||||||
entry = entity_registry.async_get(entity_id)
|
entry = entity_registry.async_get(entity_id)
|
||||||
assert entry == snapshot(name=f"{entity_id}-entry")
|
assert entry == snapshot(name=f"{entity_id}-entry")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_rpc_presence_component(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_rpc_device: Mock,
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
entity_registry: EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test RPC binary sensor entity for presence component."""
|
||||||
|
config = deepcopy(mock_rpc_device.config)
|
||||||
|
config["presence"] = {"enable": True}
|
||||||
|
monkeypatch.setattr(mock_rpc_device, "config", config)
|
||||||
|
|
||||||
|
status = deepcopy(mock_rpc_device.status)
|
||||||
|
status["presence"] = {"num_objects": 2}
|
||||||
|
monkeypatch.setattr(mock_rpc_device, "status", status)
|
||||||
|
|
||||||
|
mock_config_entry = await init_integration(hass, 4)
|
||||||
|
|
||||||
|
entity_id = f"{BINARY_SENSOR_DOMAIN}.test_name_occupancy"
|
||||||
|
|
||||||
|
assert (state := hass.states.get(entity_id))
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
|
||||||
|
assert (entry := entity_registry.async_get(entity_id))
|
||||||
|
assert entry.unique_id == "123456789ABC-presence-presence_num_objects"
|
||||||
|
|
||||||
|
mutate_rpc_device_status(monkeypatch, mock_rpc_device, "presence", "num_objects", 0)
|
||||||
|
mock_rpc_device.mock_update()
|
||||||
|
|
||||||
|
assert (state := hass.states.get(entity_id))
|
||||||
|
assert state.state == STATE_OFF
|
||||||
|
|
||||||
|
config = deepcopy(mock_rpc_device.config)
|
||||||
|
config["presence"] = {"enable": False}
|
||||||
|
monkeypatch.setattr(mock_rpc_device, "config", config)
|
||||||
|
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||||
|
mock_rpc_device.mock_update()
|
||||||
|
|
||||||
|
assert (state := hass.states.get(entity_id))
|
||||||
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|||||||
@@ -1630,3 +1630,44 @@ async def test_block_friendly_name_sleeping_sensor(
|
|||||||
|
|
||||||
assert (state := hass.states.get(entity.entity_id))
|
assert (state := hass.states.get(entity.entity_id))
|
||||||
assert state.attributes[ATTR_FRIENDLY_NAME] == "Test name Temperature"
|
assert state.attributes[ATTR_FRIENDLY_NAME] == "Test name Temperature"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_rpc_presence_component(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_rpc_device: Mock,
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
entity_registry: EntityRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Test RPC sensor entity for presence component."""
|
||||||
|
config = deepcopy(mock_rpc_device.config)
|
||||||
|
config["presence"] = {"enable": True}
|
||||||
|
monkeypatch.setattr(mock_rpc_device, "config", config)
|
||||||
|
|
||||||
|
status = deepcopy(mock_rpc_device.status)
|
||||||
|
status["presence"] = {"num_objects": 2}
|
||||||
|
monkeypatch.setattr(mock_rpc_device, "status", status)
|
||||||
|
|
||||||
|
mock_config_entry = await init_integration(hass, 4)
|
||||||
|
|
||||||
|
entity_id = f"{SENSOR_DOMAIN}.test_name_detected_objects"
|
||||||
|
|
||||||
|
assert (state := hass.states.get(entity_id))
|
||||||
|
assert state.state == "2"
|
||||||
|
|
||||||
|
assert (entry := entity_registry.async_get(entity_id))
|
||||||
|
assert entry.unique_id == "123456789ABC-presence-presence_num_objects"
|
||||||
|
|
||||||
|
mutate_rpc_device_status(monkeypatch, mock_rpc_device, "presence", "num_objects", 0)
|
||||||
|
mock_rpc_device.mock_update()
|
||||||
|
|
||||||
|
assert (state := hass.states.get(entity_id))
|
||||||
|
assert state.state == "0"
|
||||||
|
|
||||||
|
config = deepcopy(mock_rpc_device.config)
|
||||||
|
config["presence"] = {"enable": False}
|
||||||
|
monkeypatch.setattr(mock_rpc_device, "config", config)
|
||||||
|
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||||
|
mock_rpc_device.mock_update()
|
||||||
|
|
||||||
|
assert (state := hass.states.get(entity_id))
|
||||||
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|||||||
Reference in New Issue
Block a user