Add zwave_js speed config for additional GE/Jasco fan controllers (#92371)

* Add zwave_js speed config for additional GE/Jasco fan controllers

Add speed info for Honeywell(GE/Jasco) 39358 In-Wall Fan Speed Control and Enbrighten(GE/Jasco) 55258 In-Wall Fan Speed Control.

* Add test for Honeywell 39358 In-Wall Fan Speed Control
This commit is contained in:
Jeff Grieger 2023-05-31 18:09:35 -04:00 committed by GitHub
parent cd330a2740
commit 47a2d5b472
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 10600 additions and 2 deletions

View file

@ -256,11 +256,15 @@ DISCOVERY_SCHEMAS = [
# Honeywell 39358 In-Wall Fan Control using switch multilevel CC
ZWaveDiscoverySchema(
platform=Platform.FAN,
hint="has_fan_value_mapping",
manufacturer_id={0x0039},
product_id={0x3131},
product_type={0x4944},
primary_value=SWITCH_MULTILEVEL_CURRENT_VALUE_SCHEMA,
required_values=[SWITCH_MULTILEVEL_TARGET_VALUE_SCHEMA],
data_template=FixedFanValueMappingDataTemplate(
FanValueMapping(speeds=[(1, 32), (33, 66), (67, 99)]),
),
),
# GE/Jasco - In-Wall Smart Fan Control - 12730 / ZW4002
ZWaveDiscoverySchema(
@ -274,12 +278,12 @@ DISCOVERY_SCHEMAS = [
FanValueMapping(speeds=[(1, 33), (34, 67), (68, 99)]),
),
),
# GE/Jasco - In-Wall Smart Fan Control - 14287 / ZW4002
# GE/Jasco - In-Wall Smart Fan Control - 14287 / 55258 / ZW4002
ZWaveDiscoverySchema(
platform=Platform.FAN,
hint="has_fan_value_mapping",
manufacturer_id={0x0063},
product_id={0x3131},
product_id={0x3131, 0x3337},
product_type={0x4944},
primary_value=SWITCH_MULTILEVEL_CURRENT_VALUE_SCHEMA,
data_template=FixedFanValueMappingDataTemplate(

View file

@ -433,6 +433,12 @@ def leviton_zw4sf_state_fixture():
return json.loads(load_fixture("zwave_js/leviton_zw4sf_state.json"))
@pytest.fixture(name="fan_honeywell_39358_state", scope="session")
def fan_honeywell_39358_state_fixture():
"""Load the fan node state fixture data."""
return json.loads(load_fixture("zwave_js/fan_honeywell_39358_state.json"))
@pytest.fixture(name="gdc_zw062_state", scope="session")
def motorized_barrier_cover_state_fixture():
"""Load the motorized barrier cover node state fixture data."""
@ -943,6 +949,14 @@ def leviton_zw4sf_fixture(client, leviton_zw4sf_state):
return node
@pytest.fixture(name="fan_honeywell_39358")
def fan_honeywell_39358_fixture(client, fan_honeywell_39358_state):
"""Mock a fan node."""
node = Node(client, copy.deepcopy(fan_honeywell_39358_state))
client.driver.controller.nodes[node.node_id] = node
return node
@pytest.fixture(name="null_name_check")
def null_name_check_fixture(client, null_name_check_state):
"""Mock a node with no name."""

File diff suppressed because it is too large Load diff

View file

@ -938,3 +938,72 @@ async def test_thermostat_fan_without_preset_modes(
assert not state.attributes.get(ATTR_PRESET_MODE)
assert not state.attributes.get(ATTR_PRESET_MODES)
async def test_honeywell_39358_fan(
hass: HomeAssistant, client, fan_honeywell_39358, integration
) -> None:
"""Test a Honeywell 39358 fan with 3 fixed speeds."""
node = fan_honeywell_39358
node_id = 61
entity_id = "fan.honeywell_in_wall_smart_fan_control"
async def get_zwave_speed_from_percentage(percentage):
"""Set the fan to a particular percentage and get the resulting Zwave speed."""
client.async_send_command.reset_mock()
await hass.services.async_call(
"fan",
"turn_on",
{"entity_id": entity_id, "percentage": percentage},
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"] == node_id
return args["value"]
async def get_percentage_from_zwave_speed(zwave_speed):
"""Set the underlying device speed and get the resulting percentage."""
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": node_id,
"args": {
"commandClassName": "Multilevel Switch",
"commandClass": 38,
"endpoint": 0,
"property": "currentValue",
"newValue": zwave_speed,
"prevValue": 0,
"propertyName": "currentValue",
},
},
)
node.receive_event(event)
state = hass.states.get(entity_id)
return state.attributes[ATTR_PERCENTAGE]
# This device has the speeds:
# low = 1-32, med = 33-66, high = 67-99
percentages_to_zwave_speeds = [
[[0], [0]],
[range(1, 34), range(1, 33)],
[range(34, 68), range(33, 67)],
[range(68, 101), range(67, 100)],
]
for percentages, zwave_speeds in percentages_to_zwave_speeds:
for percentage in percentages:
actual_zwave_speed = await get_zwave_speed_from_percentage(percentage)
assert actual_zwave_speed in zwave_speeds
for zwave_speed in zwave_speeds:
actual_percentage = await get_percentage_from_zwave_speed(zwave_speed)
assert actual_percentage in percentages
state = hass.states.get(entity_id)
assert state.attributes[ATTR_PERCENTAGE_STEP] == pytest.approx(33.3333, rel=1e-3)
assert state.attributes[ATTR_PRESET_MODES] == []