Support Shelly wave shutter with firmware 14.2.0 in Z-Wave (#159750)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
blob810
2025-12-27 11:12:02 +01:00
committed by GitHub
parent cf9444dc64
commit c41d14fbe7
4 changed files with 2164 additions and 2 deletions

View File

@@ -374,7 +374,7 @@ DISCOVERY_SCHEMAS = [
platform=Platform.COVER,
hint="shutter_tilt",
manufacturer_id={0x0460},
product_id={0x0082},
product_id={0x0082, 0x0083},
product_type={0x0003},
primary_value=ZWaveValueDiscoverySchema(
command_class={CommandClass.SWITCH_MULTILEVEL},
@@ -412,7 +412,7 @@ DISCOVERY_SCHEMAS = [
platform=Platform.COVER,
hint="shutter",
manufacturer_id={0x0460},
product_id={0x0082},
product_id={0x0082, 0x0083},
product_type={0x0003},
primary_value=ZWaveValueDiscoverySchema(
command_class={CommandClass.SWITCH_MULTILEVEL},

View File

@@ -278,6 +278,14 @@ def qubino_shutter_state_fixture() -> dict[str, Any]:
return load_json_object_fixture("cover_qubino_shutter_state.json", DOMAIN)
@pytest.fixture(name="qubino_shutter_state_firmware_14_2_0", scope="package")
def qubino_shutter_state_firmware_14_2_0_fixture() -> dict[str, Any]:
"""Load the Qubino Shutter node state fixture data with firmware 14.2.0."""
return load_json_object_fixture(
"cover_qubino_shutter_state_firmware_14_2_0.json", DOMAIN
)
@pytest.fixture(name="aeotec_nano_shutter_state", scope="package")
def aeotec_nano_shutter_state_fixture() -> dict[str, Any]:
"""Load the Aeotec Nano Shutter node state fixture data."""
@@ -1049,6 +1057,16 @@ def qubino_shutter_cover_fixture(client, qubino_shutter_state) -> Node:
return node
@pytest.fixture(name="qubino_shutter_firmware_14_2_0")
def qubino_shutter_firmware_14_2_0_cover_fixture(
client, qubino_shutter_state_firmware_14_2_0
) -> Node:
"""Mock a Qubino flush shutter node with firmware 14.2.0."""
node = Node(client, copy.deepcopy(qubino_shutter_state_firmware_14_2_0))
client.driver.controller.nodes[node.node_id] = node
return node
@pytest.fixture(name="aeotec_nano_shutter")
def aeotec_nano_shutter_cover_fixture(client, aeotec_nano_shutter_state) -> Node:
"""Mock a Aeotec Nano Shutter node."""

View File

@@ -49,6 +49,7 @@ SHUTTER_COVER_ENTITY = "cover.flush_shutter"
AEOTEC_SHUTTER_COVER_ENTITY = "cover.nano_shutter_v_3"
FIBARO_FGR_222_SHUTTER_COVER_ENTITY = "cover.fgr_222_test_cover"
FIBARO_FGR_223_SHUTTER_COVER_ENTITY = "cover.fgr_223_test_cover"
SHELLY_WAVE_SHUTTER_COVER_ENTITY = "cover.shelly_fw_14_2_0_test_cover"
LOGGER.setLevel(logging.DEBUG)
@@ -436,6 +437,105 @@ async def test_fibaro_fgr223_shutter_cover(
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 100
async def test_shelly_wave_shutter_cover_with_tilt(
hass: HomeAssistant, client, qubino_shutter_firmware_14_2_0, integration
) -> None:
"""Test tilt function of the Shelly Wave Shutter with firmware 14.2.0.
When parameter 71 is set to 1 (Venetian mode), endpoint 2 controls the tilt.
"""
state = hass.states.get(SHELLY_WAVE_SHUTTER_COVER_ENTITY)
assert state
assert state.attributes[ATTR_DEVICE_CLASS] == CoverDeviceClass.SHUTTER
assert state.state == CoverState.CLOSED
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0
# Test opening tilts
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER_TILT,
{ATTR_ENTITY_ID: SHELLY_WAVE_SHUTTER_COVER_ENTITY},
blocking=True,
)
assert client.async_send_command.call_count == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 5
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(
COVER_DOMAIN,
SERVICE_CLOSE_COVER_TILT,
{ATTR_ENTITY_ID: SHELLY_WAVE_SHUTTER_COVER_ENTITY},
blocking=True,
)
assert client.async_send_command.call_count == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 5
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(
COVER_DOMAIN,
SERVICE_SET_COVER_TILT_POSITION,
{ATTR_ENTITY_ID: SHELLY_WAVE_SHUTTER_COVER_ENTITY, ATTR_TILT_POSITION: 12},
blocking=True,
)
assert client.async_send_command.call_count == 1
args = client.async_send_command.call_args[0][0]
assert args["command"] == "node.set_value"
assert args["nodeId"] == 5
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": 5,
"args": {
"commandClassName": "Multilevel Switch",
"commandClass": 38,
"endpoint": 2,
"property": "currentValue",
"newValue": 99,
"prevValue": 0,
"propertyName": "currentValue",
},
},
)
qubino_shutter_firmware_14_2_0.receive_event(event)
state = hass.states.get(SHELLY_WAVE_SHUTTER_COVER_ENTITY)
assert state
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 100
async def test_aeotec_nano_shutter_cover(
hass: HomeAssistant, client, aeotec_nano_shutter, integration
) -> None: