mirror of
https://github.com/Electric-Special/ha-core.git
synced 2026-03-21 07:05:48 +01:00
Support Shelly presencezone component (#152393)
Co-authored-by: Shay Levy <levyshay1@gmail.com> Co-authored-by: Simone Chemelli <simone.chemelli@gmail.com>
This commit is contained in:
@@ -37,7 +37,6 @@ from .utils import (
|
||||
async_remove_orphaned_entities,
|
||||
get_blu_trv_device_info,
|
||||
get_device_entry_gen,
|
||||
get_virtual_component_ids,
|
||||
is_block_momentary_input,
|
||||
is_rpc_momentary_input,
|
||||
is_view_for_platform,
|
||||
@@ -307,6 +306,13 @@ RPC_SENSORS: Final = {
|
||||
device_class=BinarySensorDeviceClass.OCCUPANCY,
|
||||
entity_class=RpcPresenceBinarySensor,
|
||||
),
|
||||
"presencezone_state": RpcBinarySensorDescription(
|
||||
key="presencezone",
|
||||
sub_key="state",
|
||||
name="Occupancy",
|
||||
device_class=BinarySensorDeviceClass.OCCUPANCY,
|
||||
entity_class=RpcPresenceBinarySensor,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -333,18 +339,12 @@ async def async_setup_entry(
|
||||
hass, config_entry, async_add_entities, RPC_SENSORS, RpcBinarySensor
|
||||
)
|
||||
|
||||
# the user can remove virtual components from the device configuration, so
|
||||
# we need to remove orphaned entities
|
||||
virtual_binary_sensor_ids = get_virtual_component_ids(
|
||||
coordinator.device.config, BINARY_SENSOR_PLATFORM
|
||||
)
|
||||
async_remove_orphaned_entities(
|
||||
hass,
|
||||
config_entry.entry_id,
|
||||
coordinator.mac,
|
||||
BINARY_SENSOR_PLATFORM,
|
||||
virtual_binary_sensor_ids,
|
||||
"boolean",
|
||||
coordinator.device.status,
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@@ -269,7 +269,15 @@ DEVICES_WITHOUT_FIRMWARE_CHANGELOG = (
|
||||
|
||||
CONF_GEN = "gen"
|
||||
|
||||
VIRTUAL_COMPONENTS = ("boolean", "button", "enum", "input", "number", "text")
|
||||
VIRTUAL_COMPONENTS = (
|
||||
"boolean",
|
||||
"button",
|
||||
"enum",
|
||||
"input",
|
||||
"number",
|
||||
"presencezone",
|
||||
"text",
|
||||
)
|
||||
VIRTUAL_COMPONENTS_MAP = {
|
||||
"binary_sensor": {"types": ["boolean"], "modes": ["label"]},
|
||||
"button": {"types": ["button"], "modes": ["button"]},
|
||||
|
||||
@@ -61,7 +61,6 @@ from .utils import (
|
||||
get_device_entry_gen,
|
||||
get_device_uptime,
|
||||
get_shelly_air_lamp_life,
|
||||
get_virtual_component_ids,
|
||||
get_virtual_component_unit,
|
||||
is_rpc_wifi_stations_disabled,
|
||||
is_view_for_platform,
|
||||
@@ -1459,6 +1458,14 @@ RPC_SENSORS: Final = {
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_class=RpcPresenceSensor,
|
||||
),
|
||||
"presencezone_num_objects": RpcSensorDescription(
|
||||
key="presencezone",
|
||||
sub_key="num_objects",
|
||||
translation_key="detected_objects",
|
||||
name="Detected objects",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_class=RpcPresenceSensor,
|
||||
),
|
||||
"object_water_consumption": RpcSensorDescription(
|
||||
key="object",
|
||||
sub_key="value",
|
||||
@@ -1570,21 +1577,6 @@ async def async_setup_entry(
|
||||
SENSOR_PLATFORM,
|
||||
coordinator.device.status,
|
||||
)
|
||||
|
||||
# the user can remove virtual components from the device configuration, so
|
||||
# we need to remove orphaned entities
|
||||
virtual_component_ids = get_virtual_component_ids(
|
||||
coordinator.device.config, SENSOR_PLATFORM
|
||||
)
|
||||
for component in ("enum", "number", "text"):
|
||||
async_remove_orphaned_entities(
|
||||
hass,
|
||||
config_entry.entry_id,
|
||||
coordinator.mac,
|
||||
SENSOR_PLATFORM,
|
||||
virtual_component_ids,
|
||||
component,
|
||||
)
|
||||
return
|
||||
|
||||
if config_entry.data[CONF_SLEEP_PERIOD]:
|
||||
|
||||
@@ -591,3 +591,46 @@ async def test_rpc_presence_component(
|
||||
|
||||
assert (state := hass.states.get(entity_id))
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
async def test_rpc_presencezone_component(
|
||||
hass: HomeAssistant,
|
||||
mock_rpc_device: Mock,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
entity_registry: EntityRegistry,
|
||||
) -> None:
|
||||
"""Test RPC binary sensor entity for presencezone component."""
|
||||
config = deepcopy(mock_rpc_device.config)
|
||||
config["presencezone:200"] = {"name": "Main zone", "enable": True}
|
||||
monkeypatch.setattr(mock_rpc_device, "config", config)
|
||||
|
||||
status = deepcopy(mock_rpc_device.status)
|
||||
status["presencezone:200"] = {"state": True, "num_objects": 3}
|
||||
monkeypatch.setattr(mock_rpc_device, "status", status)
|
||||
|
||||
mock_config_entry = await init_integration(hass, 4)
|
||||
|
||||
entity_id = f"{BINARY_SENSOR_DOMAIN}.test_name_main_zone_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-presencezone:200-presencezone_state"
|
||||
|
||||
mutate_rpc_device_status(
|
||||
monkeypatch, mock_rpc_device, "presencezone:200", "state", False
|
||||
)
|
||||
mock_rpc_device.mock_update()
|
||||
|
||||
assert (state := hass.states.get(entity_id))
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
config = deepcopy(mock_rpc_device.config)
|
||||
config["presencezone:200"] = {"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
|
||||
|
||||
@@ -1702,3 +1702,46 @@ async def test_rpc_presence_component(
|
||||
|
||||
assert (state := hass.states.get(entity_id))
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
async def test_rpc_presencezone_component(
|
||||
hass: HomeAssistant,
|
||||
mock_rpc_device: Mock,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
entity_registry: EntityRegistry,
|
||||
) -> None:
|
||||
"""Test RPC sensor entity for presencezone component."""
|
||||
config = deepcopy(mock_rpc_device.config)
|
||||
config["presencezone:201"] = {"name": "Other zone", "enable": True}
|
||||
monkeypatch.setattr(mock_rpc_device, "config", config)
|
||||
|
||||
status = deepcopy(mock_rpc_device.status)
|
||||
status["presencezone:201"] = {"state": True, "num_objects": 3}
|
||||
monkeypatch.setattr(mock_rpc_device, "status", status)
|
||||
|
||||
mock_config_entry = await init_integration(hass, 4)
|
||||
|
||||
entity_id = f"{SENSOR_DOMAIN}.test_name_other_zone_detected_objects"
|
||||
|
||||
assert (state := hass.states.get(entity_id))
|
||||
assert state.state == "3"
|
||||
|
||||
assert (entry := entity_registry.async_get(entity_id))
|
||||
assert entry.unique_id == "123456789ABC-presencezone:201-presencezone_num_objects"
|
||||
|
||||
mutate_rpc_device_status(
|
||||
monkeypatch, mock_rpc_device, "presencezone:201", "num_objects", 2
|
||||
)
|
||||
mock_rpc_device.mock_update()
|
||||
|
||||
assert (state := hass.states.get(entity_id))
|
||||
assert state.state == "2"
|
||||
|
||||
config = deepcopy(mock_rpc_device.config)
|
||||
config["presencezone:201"] = {"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