Add shutter_tilt support for Fibaro FGR 223 (#96283)
* add support for shutter_tilt for Fibaro FGR 223 add tests for fgr 223 * Adjust comments and docstring --------- Co-authored-by: Lennart <18117505+Ced4@users.noreply.github.com> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/101386/head
parent
b02f64196b
commit
9ab340047d
|
@ -160,6 +160,8 @@ class ZWaveValueDiscoverySchema(DataclassMustHaveAtLeastOne):
|
|||
writeable: bool | None = None
|
||||
# [optional] the value's states map must include ANY of these key/value pairs
|
||||
any_available_states: set[tuple[int, str]] | None = None
|
||||
# [optional] the value's value must match this value
|
||||
value: Any | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -378,6 +380,61 @@ DISCOVERY_SCHEMAS = [
|
|||
)
|
||||
],
|
||||
),
|
||||
# Fibaro Shutter Fibaro FGR223
|
||||
# Combine both switch_multilevel endpoints into shutter_tilt
|
||||
# if operating mode (151) is set to venetian blind (2)
|
||||
ZWaveDiscoverySchema(
|
||||
platform=Platform.COVER,
|
||||
hint="shutter_tilt",
|
||||
manufacturer_id={0x010F},
|
||||
product_id={0x1000, 0x1001},
|
||||
product_type={0x0303},
|
||||
primary_value=ZWaveValueDiscoverySchema(
|
||||
command_class={CommandClass.SWITCH_MULTILEVEL},
|
||||
property={CURRENT_VALUE_PROPERTY},
|
||||
endpoint={1},
|
||||
type={ValueType.NUMBER},
|
||||
),
|
||||
data_template=CoverTiltDataTemplate(
|
||||
current_tilt_value_id=ZwaveValueID(
|
||||
property_=CURRENT_VALUE_PROPERTY,
|
||||
command_class=CommandClass.SWITCH_MULTILEVEL,
|
||||
endpoint=2,
|
||||
),
|
||||
target_tilt_value_id=ZwaveValueID(
|
||||
property_=TARGET_VALUE_PROPERTY,
|
||||
command_class=CommandClass.SWITCH_MULTILEVEL,
|
||||
endpoint=2,
|
||||
),
|
||||
),
|
||||
required_values=[
|
||||
ZWaveValueDiscoverySchema(
|
||||
command_class={CommandClass.CONFIGURATION},
|
||||
property={151},
|
||||
endpoint={0},
|
||||
value={2},
|
||||
)
|
||||
],
|
||||
),
|
||||
# Fibaro Shutter Fibaro FGR223
|
||||
# Disable endpoint 2 (slat),
|
||||
# as these are either combined with endpoint one as shutter_tilt
|
||||
# or it has no practical function.
|
||||
# CC: Switch_Multilevel
|
||||
ZWaveDiscoverySchema(
|
||||
platform=Platform.COVER,
|
||||
hint="shutter",
|
||||
manufacturer_id={0x010F},
|
||||
product_id={0x1000, 0x1001},
|
||||
product_type={0x0303},
|
||||
primary_value=ZWaveValueDiscoverySchema(
|
||||
command_class={CommandClass.SWITCH_MULTILEVEL},
|
||||
property={CURRENT_VALUE_PROPERTY},
|
||||
endpoint={2},
|
||||
type={ValueType.NUMBER},
|
||||
),
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
# Fibaro Nice BiDi-ZWave (IBT4ZWAVE)
|
||||
ZWaveDiscoverySchema(
|
||||
platform=Platform.COVER,
|
||||
|
@ -1236,6 +1293,9 @@ def check_value(value: ZwaveValue, schema: ZWaveValueDiscoverySchema) -> bool:
|
|||
)
|
||||
):
|
||||
return False
|
||||
# check value
|
||||
if schema.value is not None and value.value not in schema.value:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
|
|
@ -483,6 +483,12 @@ def fibaro_fgr222_shutter_state_fixture():
|
|||
return json.loads(load_fixture("zwave_js/cover_fibaro_fgr222_state.json"))
|
||||
|
||||
|
||||
@pytest.fixture(name="fibaro_fgr223_shutter_state", scope="session")
|
||||
def fibaro_fgr223_shutter_state_fixture():
|
||||
"""Load the Fibaro FGR223 node state fixture data."""
|
||||
return json.loads(load_fixture("zwave_js/cover_fibaro_fgr223_state.json"))
|
||||
|
||||
|
||||
@pytest.fixture(name="merten_507801_state", scope="session")
|
||||
def merten_507801_state_fixture():
|
||||
"""Load the Merten 507801 Shutter node state fixture data."""
|
||||
|
@ -1054,6 +1060,14 @@ def fibaro_fgr222_shutter_cover_fixture(client, fibaro_fgr222_shutter_state):
|
|||
return node
|
||||
|
||||
|
||||
@pytest.fixture(name="fibaro_fgr223_shutter")
|
||||
def fibaro_fgr223_shutter_cover_fixture(client, fibaro_fgr223_shutter_state):
|
||||
"""Mock a Fibaro FGR223 Shutter node."""
|
||||
node = Node(client, copy.deepcopy(fibaro_fgr223_shutter_state))
|
||||
client.driver.controller.nodes[node.node_id] = node
|
||||
return node
|
||||
|
||||
|
||||
@pytest.fixture(name="merten_507801")
|
||||
def merten_507801_cover_fixture(client, merten_507801_state):
|
||||
"""Mock a Merten 507801 Shutter node."""
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,7 +47,8 @@ GDC_COVER_ENTITY = "cover.aeon_labs_garage_door_controller_gen5"
|
|||
BLIND_COVER_ENTITY = "cover.window_blind_controller"
|
||||
SHUTTER_COVER_ENTITY = "cover.flush_shutter"
|
||||
AEOTEC_SHUTTER_COVER_ENTITY = "cover.nano_shutter_v_3"
|
||||
FIBARO_SHUTTER_COVER_ENTITY = "cover.fgr_222_test_cover"
|
||||
FIBARO_FGR_222_SHUTTER_COVER_ENTITY = "cover.fgr_222_test_cover"
|
||||
FIBARO_FGR_223_SHUTTER_COVER_ENTITY = "cover.fgr_223_test_cover"
|
||||
LOGGER.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
|
@ -238,7 +239,7 @@ async def test_fibaro_fgr222_shutter_cover(
|
|||
hass: HomeAssistant, client, fibaro_fgr222_shutter, integration
|
||||
) -> None:
|
||||
"""Test tilt function of the Fibaro Shutter devices."""
|
||||
state = hass.states.get(FIBARO_SHUTTER_COVER_ENTITY)
|
||||
state = hass.states.get(FIBARO_FGR_222_SHUTTER_COVER_ENTITY)
|
||||
assert state
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == CoverDeviceClass.SHUTTER
|
||||
|
||||
|
@ -249,7 +250,7 @@ async def test_fibaro_fgr222_shutter_cover(
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: FIBARO_SHUTTER_COVER_ENTITY},
|
||||
{ATTR_ENTITY_ID: FIBARO_FGR_222_SHUTTER_COVER_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -271,7 +272,7 @@ async def test_fibaro_fgr222_shutter_cover(
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: FIBARO_SHUTTER_COVER_ENTITY},
|
||||
{ATTR_ENTITY_ID: FIBARO_FGR_222_SHUTTER_COVER_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -293,7 +294,7 @@ async def test_fibaro_fgr222_shutter_cover(
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: FIBARO_SHUTTER_COVER_ENTITY, ATTR_TILT_POSITION: 12},
|
||||
{ATTR_ENTITY_ID: FIBARO_FGR_222_SHUTTER_COVER_ENTITY, ATTR_TILT_POSITION: 12},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
@ -330,7 +331,101 @@ async def test_fibaro_fgr222_shutter_cover(
|
|||
},
|
||||
)
|
||||
fibaro_fgr222_shutter.receive_event(event)
|
||||
state = hass.states.get(FIBARO_SHUTTER_COVER_ENTITY)
|
||||
state = hass.states.get(FIBARO_FGR_222_SHUTTER_COVER_ENTITY)
|
||||
assert state
|
||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 100
|
||||
|
||||
|
||||
async def test_fibaro_fgr223_shutter_cover(
|
||||
hass: HomeAssistant, client, fibaro_fgr223_shutter, integration
|
||||
) -> None:
|
||||
"""Test tilt function of the Fibaro Shutter devices."""
|
||||
state = hass.states.get(FIBARO_FGR_223_SHUTTER_COVER_ENTITY)
|
||||
assert state
|
||||
assert state.attributes[ATTR_DEVICE_CLASS] == CoverDeviceClass.SHUTTER
|
||||
|
||||
assert state.state == STATE_OPEN
|
||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0
|
||||
|
||||
# Test opening tilts
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: FIBARO_FGR_223_SHUTTER_COVER_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args[0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == 10
|
||||
assert args["valueId"] == {
|
||||
"endpoint": 2,
|
||||
"commandClass": 38,
|
||||
"property": "targetValue",
|
||||
}
|
||||
assert args["value"] == 99
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
# Test closing tilts
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: FIBARO_FGR_223_SHUTTER_COVER_ENTITY},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args[0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == 10
|
||||
assert args["valueId"] == {
|
||||
"endpoint": 2,
|
||||
"commandClass": 38,
|
||||
"property": "targetValue",
|
||||
}
|
||||
assert args["value"] == 0
|
||||
|
||||
client.async_send_command.reset_mock()
|
||||
# Test setting tilt position
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: FIBARO_FGR_223_SHUTTER_COVER_ENTITY, ATTR_TILT_POSITION: 12},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(client.async_send_command.call_args_list) == 1
|
||||
args = client.async_send_command.call_args[0][0]
|
||||
assert args["command"] == "node.set_value"
|
||||
assert args["nodeId"] == 10
|
||||
assert args["valueId"] == {
|
||||
"endpoint": 2,
|
||||
"commandClass": 38,
|
||||
"property": "targetValue",
|
||||
}
|
||||
assert args["value"] == 12
|
||||
|
||||
# Test some tilt
|
||||
event = Event(
|
||||
type="value updated",
|
||||
data={
|
||||
"source": "node",
|
||||
"event": "value updated",
|
||||
"nodeId": 10,
|
||||
"args": {
|
||||
"commandClassName": "Multilevel Switch",
|
||||
"commandClass": 38,
|
||||
"endpoint": 2,
|
||||
"property": "currentValue",
|
||||
"newValue": 99,
|
||||
"prevValue": 0,
|
||||
"propertyName": "currentValue",
|
||||
},
|
||||
},
|
||||
)
|
||||
fibaro_fgr223_shutter.receive_event(event)
|
||||
state = hass.states.get(FIBARO_FGR_223_SHUTTER_COVER_ENTITY)
|
||||
assert state
|
||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 100
|
||||
|
||||
|
@ -694,13 +789,42 @@ async def test_fibaro_fgr222_shutter_cover_no_tilt(
|
|||
client.driver.controller.emit("node added", {"node": node})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FIBARO_SHUTTER_COVER_ENTITY)
|
||||
state = hass.states.get(FIBARO_FGR_222_SHUTTER_COVER_ENTITY)
|
||||
assert state
|
||||
assert state.state == STATE_UNKNOWN
|
||||
assert ATTR_CURRENT_POSITION not in state.attributes
|
||||
assert ATTR_CURRENT_TILT_POSITION not in state.attributes
|
||||
|
||||
|
||||
async def test_fibaro_fgr223_shutter_cover_no_tilt(
|
||||
hass: HomeAssistant, client, fibaro_fgr223_shutter_state, integration
|
||||
) -> None:
|
||||
"""Test absence of tilt function for Fibaro Shutter roller blind.
|
||||
|
||||
Fibaro Shutter devices can have operating mode set to roller blind (1).
|
||||
"""
|
||||
node_state = replace_value_of_zwave_value(
|
||||
fibaro_fgr223_shutter_state,
|
||||
[
|
||||
ZwaveValueMatcher(
|
||||
property_=151,
|
||||
command_class=CommandClass.CONFIGURATION,
|
||||
endpoint=0,
|
||||
),
|
||||
],
|
||||
1,
|
||||
)
|
||||
node = Node(client, node_state)
|
||||
client.driver.controller.emit("node added", {"node": node})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(FIBARO_FGR_223_SHUTTER_COVER_ENTITY)
|
||||
assert state
|
||||
assert state.state == STATE_OPEN
|
||||
assert ATTR_CURRENT_POSITION in state.attributes
|
||||
assert ATTR_CURRENT_TILT_POSITION not in state.attributes
|
||||
|
||||
|
||||
async def test_iblinds_v3_cover(
|
||||
hass: HomeAssistant, client, iblinds_v3, integration
|
||||
) -> None:
|
||||
|
|
Loading…
Reference in New Issue