mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Add door opener button for HmIP-FDC (#179089)
This commit is contained in:
@@ -12,6 +12,8 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from .entity import HomematicipGenericEntity
|
||||
from .hap import HomematicIPConfigEntry, HomematicipHAP
|
||||
|
||||
DOOR_OPENER_MODELS = {"HmIP-FLC", "HmIP-FDC"}
|
||||
|
||||
|
||||
def _door_opener_authorization_channel(
|
||||
device: object,
|
||||
@@ -40,9 +42,9 @@ async def async_setup_entry(
|
||||
if isinstance(device, WallMountedGarageDoorController)
|
||||
]
|
||||
entities.extend(
|
||||
HomematicipFullFlushLockControllerButton(hap, device, auth_channel)
|
||||
HomematicipDoorOpenerButton(hap, device, auth_channel)
|
||||
for device in hap.home.devices
|
||||
if getattr(device, "modelType", None) == "HmIP-FLC"
|
||||
if getattr(device, "modelType", None) in DOOR_OPENER_MODELS
|
||||
and (auth_channel := _door_opener_authorization_channel(device)) is not None
|
||||
)
|
||||
async_add_entities(entities)
|
||||
@@ -62,8 +64,8 @@ class HomematicipGarageDoorControllerButton(HomematicipGenericEntity, ButtonEnti
|
||||
await self._device.send_start_impulse_async()
|
||||
|
||||
|
||||
class HomematicipFullFlushLockControllerButton(HomematicipGenericEntity, ButtonEntity):
|
||||
"""Representation of the HomematicIP full flush lock controller opener."""
|
||||
class HomematicipDoorOpenerButton(HomematicipGenericEntity, ButtonEntity):
|
||||
"""Representation of a HomematicIP door opener (HmIP-FLC, HmIP-FDC)."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -71,7 +73,7 @@ class HomematicipFullFlushLockControllerButton(HomematicipGenericEntity, ButtonE
|
||||
device,
|
||||
auth_channel: AccessAuthorizationChannel,
|
||||
) -> None:
|
||||
"""Initialize the full flush lock controller opener button."""
|
||||
"""Initialize the door opener button."""
|
||||
super().__init__(
|
||||
hap, device, post="Door opener", feature_id="lock_opener_button"
|
||||
)
|
||||
|
||||
@@ -199,6 +199,131 @@ def full_flush_lock_controller_device_data_fixture() -> dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(name="full_flush_door_controller_device_data")
|
||||
def full_flush_door_controller_device_data_fixture() -> dict[str, Any]:
|
||||
"""Return fixture data for an HmIP-FDC device."""
|
||||
return {
|
||||
"availableFirmwareVersion": "1.0.0",
|
||||
"connectionType": "HMIP_RF",
|
||||
"firmwareVersion": "1.0.0",
|
||||
"firmwareVersionInteger": 65536,
|
||||
"functionalChannels": {
|
||||
"0": {
|
||||
"configPending": False,
|
||||
"deviceId": "3014F711000000000000FDC1",
|
||||
"dutyCycle": False,
|
||||
"functionalChannelType": "DEVICE_BASE",
|
||||
"groupIndex": 0,
|
||||
"groups": [],
|
||||
"index": 0,
|
||||
"label": "",
|
||||
"lowBat": None,
|
||||
"multicastRoutingEnabled": False,
|
||||
"routerModuleEnabled": False,
|
||||
"routerModuleSupported": False,
|
||||
"rssiDeviceValue": -60,
|
||||
"rssiPeerValue": -60,
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureDeviceIdentify": True,
|
||||
"IFeatureRssiValue": True,
|
||||
"IOptionalFeatureDutyCycle": True,
|
||||
},
|
||||
"unreach": False,
|
||||
},
|
||||
"1": {
|
||||
"actionParameter": "NOT_CUSTOMISABLE",
|
||||
"binaryBehaviorType": "NORMALLY_CLOSE",
|
||||
"channelRole": None,
|
||||
"corrosionPreventionActive": False,
|
||||
"deviceId": "3014F711000000000000FDC1",
|
||||
"doorBellSensorEventTimestamp": None,
|
||||
"eventDelay": 0,
|
||||
"functionalChannelType": "MULTI_MODE_LOCK_INPUT_CHANNEL",
|
||||
"glassBroken": False,
|
||||
"groupIndex": 1,
|
||||
"groups": [],
|
||||
"index": 1,
|
||||
"label": "",
|
||||
"lockState": "UNLOCKED",
|
||||
"multiModeInputMode": "KEY_BEHAVIOR",
|
||||
"supportedOptionalFeatures": {
|
||||
"IOptionalFeatureLongPressSupported": True
|
||||
},
|
||||
"windowState": "CLOSED",
|
||||
},
|
||||
"2": {
|
||||
"actionParameter": "NOT_CUSTOMISABLE",
|
||||
"binaryBehaviorType": "NORMALLY_CLOSE",
|
||||
"channelRole": None,
|
||||
"corrosionPreventionActive": False,
|
||||
"deviceId": "3014F711000000000000FDC1",
|
||||
"doorBellSensorEventTimestamp": None,
|
||||
"eventDelay": 0,
|
||||
"functionalChannelType": "MULTI_MODE_LOCK_INPUT_CHANNEL",
|
||||
"glassBroken": False,
|
||||
"groupIndex": 2,
|
||||
"groups": [],
|
||||
"index": 2,
|
||||
"label": "",
|
||||
"lockState": "UNLOCKED",
|
||||
"multiModeInputMode": "KEY_BEHAVIOR",
|
||||
"supportedOptionalFeatures": {
|
||||
"IOptionalFeatureLongPressSupported": True
|
||||
},
|
||||
"windowState": "CLOSED",
|
||||
},
|
||||
"3": {
|
||||
"channelRole": "DOOR_OPENER_ACTUATOR",
|
||||
"deviceId": "3014F711000000000000FDC1",
|
||||
"doorLockActive": False,
|
||||
"functionalChannelType": "DOOR_SWITCH_CHANNEL",
|
||||
"groupIndex": 3,
|
||||
"groups": [],
|
||||
"impulseDuration": 3.0,
|
||||
"index": 3,
|
||||
"internalLinkConfiguration": None,
|
||||
"label": "",
|
||||
"multiModeInputMode": "KEY_BEHAVIOR",
|
||||
"processing": False,
|
||||
"profileMode": "AUTOMATIC",
|
||||
"supportedOptionalFeatures": {
|
||||
"IOptionalFeatureImpulseDuration": True,
|
||||
"IOptionalFeatureImpulseOutputState": True,
|
||||
},
|
||||
"userDesiredProfileMode": "AUTOMATIC",
|
||||
},
|
||||
"4": {
|
||||
"authorized": True,
|
||||
"channelRole": "DOOR_OPENER_ACTUATOR",
|
||||
"deviceId": "3014F711000000000000FDC1",
|
||||
"functionalChannelType": "ACCESS_AUTHORIZATION_CHANNEL",
|
||||
"groupIndex": 3,
|
||||
"groups": [],
|
||||
"index": 4,
|
||||
"label": "",
|
||||
"supportedOptionalFeatures": {
|
||||
"IFeatureAccessAuthorizationActuatorChannel": True
|
||||
},
|
||||
},
|
||||
},
|
||||
"homeId": "00000000-0000-0000-0000-000000000001",
|
||||
"id": "3014F711000000000000FDC1",
|
||||
"label": "Turoffner Haustuer",
|
||||
"lastStatusUpdate": 1778954102356,
|
||||
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
|
||||
"manuallyUpdateForced": True,
|
||||
"manufacturerCode": 1,
|
||||
"measuredAttributes": {},
|
||||
"modelId": 571,
|
||||
"modelType": "HmIP-FDC",
|
||||
"oem": "eQ-3",
|
||||
"permanentlyReachable": True,
|
||||
"serializedGlobalTradeItemNumber": "3014F711000000000000FDC1",
|
||||
"type": "FULL_FLUSH_DOOR_CONTROLLER",
|
||||
"updateState": "UP_TO_DATE",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(name="hmip_config")
|
||||
def hmip_config_fixture() -> ConfigType:
|
||||
"""Create a config for homematic ip cloud."""
|
||||
|
||||
@@ -124,3 +124,54 @@ async def test_hmip_full_flush_lock_controller_button_missing_channel(
|
||||
entity_id = "button.universal_motorschloss_controller_door_opener"
|
||||
assert hass.states.get(entity_id) is None
|
||||
assert entity_id not in mock_hap.hmip_device_by_entity_id
|
||||
|
||||
|
||||
async def test_hmip_full_flush_door_controller_button(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
default_mock_hap_factory: HomeFactory,
|
||||
full_flush_door_controller_device_data: dict[str, Any],
|
||||
) -> None:
|
||||
"""Test the door opener button on an HmIP-FDC (auth channel 4, not 9)."""
|
||||
entity_id = "button.turoffner_haustuer_door_opener"
|
||||
entity_name = "Turoffner Haustuer Door opener"
|
||||
device_model = "HmIP-FDC"
|
||||
mock_hap = await default_mock_hap_factory.async_get_mock_hap(
|
||||
test_devices=["Turoffner Haustuer"],
|
||||
extra_devices=[full_flush_door_controller_device_data],
|
||||
)
|
||||
|
||||
get_and_check_entity_basics(hass, mock_hap, entity_id, entity_name, device_model)
|
||||
|
||||
hmip_device = mock_hap.hmip_device_by_entity_id[entity_id]
|
||||
auth_channel = next(
|
||||
ch
|
||||
for ch in hmip_device.functionalChannels
|
||||
if ch.functionalChannelType.name == "ACCESS_AUTHORIZATION_CHANNEL"
|
||||
and ch.channelRole == "DOOR_OPENER_ACTUATOR"
|
||||
)
|
||||
assert auth_channel.index == 4
|
||||
|
||||
with (
|
||||
patch.object(
|
||||
auth_channel, "async_pull_latch", new_callable=AsyncMock
|
||||
) as mock_pull_latch,
|
||||
patch.object(
|
||||
hmip_device, "send_start_impulse_async", new_callable=AsyncMock
|
||||
) as mock_send_start_impulse,
|
||||
):
|
||||
now = dt_util.parse_datetime("2021-01-09 12:00:00+00:00")
|
||||
freezer.move_to(now)
|
||||
await hass.services.async_call(
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_pull_latch.assert_awaited_once_with()
|
||||
mock_send_start_impulse.assert_not_awaited()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == now.isoformat()
|
||||
|
||||
Reference in New Issue
Block a user