Skip to content

Commit

Permalink
Add zwave_js Protection CC select entities (#54717)
Browse files Browse the repository at this point in the history
* Add Protection CC select entities

comment

* Disable entity by default

* use class attribute

* Enable protection entity by default

* add guard for none
  • Loading branch information
raman325 authored Aug 17, 2021
1 parent 35f563e commit cff6883
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 0 deletions.
10 changes: 10 additions & 0 deletions homeassistant/components/zwave_js/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,16 @@ def get_config_parameter_discovery_schema(
),
required_values=[SIREN_TONE_SCHEMA],
),
# select
# protection CC
ZWaveDiscoverySchema(
platform="select",
primary_value=ZWaveValueDiscoverySchema(
command_class={CommandClass.PROTECTION},
property={"local", "rf"},
type={"number"},
),
),
]


Expand Down
36 changes: 36 additions & 0 deletions homeassistant/components/zwave_js/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def async_add_select(info: ZwaveDiscoveryInfo) -> None:
entities: list[ZWaveBaseEntity] = []
if info.platform_hint == "Default tone":
entities.append(ZwaveDefaultToneSelectEntity(config_entry, client, info))
else:
entities.append(ZwaveSelectEntity(config_entry, client, info))
async_add_entities(entities)

config_entry.async_on_unload(
Expand All @@ -40,6 +42,40 @@ def async_add_select(info: ZwaveDiscoveryInfo) -> None:
)


class ZwaveSelectEntity(ZWaveBaseEntity, SelectEntity):
"""Representation of a Z-Wave select entity."""

def __init__(
self, config_entry: ConfigEntry, client: ZwaveClient, info: ZwaveDiscoveryInfo
) -> None:
"""Initialize a ZwaveSelectEntity entity."""
super().__init__(config_entry, client, info)

# Entity class attributes
self._attr_name = self.generate_name(include_value_name=True)
self._attr_options = list(self.info.primary_value.metadata.states.values())

@property
def current_option(self) -> str | None:
"""Return the selected entity option to represent the entity state."""
if self.info.primary_value.value is None:
return None
return str(
self.info.primary_value.metadata.states.get(
str(self.info.primary_value.value), self.info.primary_value.value
)
)

async def async_select_option(self, option: str | int) -> None:
"""Change the selected option."""
key = next(
key
for key, val in self.info.primary_value.metadata.states.items()
if val == option
)
await self.info.node.async_set_value(self.info.primary_value, int(key))


class ZwaveDefaultToneSelectEntity(ZWaveBaseEntity, SelectEntity):
"""Representation of a Z-Wave default tone select entity."""

Expand Down
100 changes: 100 additions & 0 deletions tests/components/zwave_js/test_select.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
"""Test the Z-Wave JS number platform."""
from zwave_js_server.event import Event

from homeassistant.const import STATE_UNKNOWN

DEFAULT_TONE_SELECT_ENTITY = "select.indoor_siren_6_default_tone_2"
PROTECTION_SELECT_ENTITY = "select.family_room_combo_local_protection_state"


async def test_default_tone_select(hass, client, aeotec_zw164_siren, integration):
Expand Down Expand Up @@ -99,3 +102,100 @@ async def test_default_tone_select(hass, client, aeotec_zw164_siren, integration

state = hass.states.get(DEFAULT_TONE_SELECT_ENTITY)
assert state.state == "30DOOR~1 (27 sec)"


async def test_protection_select(hass, client, inovelli_lzw36, integration):
"""Test the default tone select entity."""
node = inovelli_lzw36
state = hass.states.get(PROTECTION_SELECT_ENTITY)

assert state
assert state.state == "Unprotected"
attr = state.attributes
assert attr["options"] == [
"Unprotected",
"ProtectedBySequence",
"NoOperationPossible",
]

# Test select option with string value
await hass.services.async_call(
"select",
"select_option",
{"entity_id": PROTECTION_SELECT_ENTITY, "option": "ProtectedBySequence"},
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.node_id
assert args["valueId"] == {
"endpoint": 0,
"commandClass": 117,
"commandClassName": "Protection",
"property": "local",
"propertyName": "local",
"ccVersion": 2,
"metadata": {
"type": "number",
"readable": True,
"writeable": True,
"label": "Local protection state",
"states": {
"0": "Unprotected",
"1": "ProtectedBySequence",
"2": "NoOperationPossible",
},
},
"value": 0,
}
assert args["value"] == 1

client.async_send_command.reset_mock()

# Test value update from value updated event
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": node.node_id,
"args": {
"commandClassName": "Protection",
"commandClass": 117,
"endpoint": 0,
"property": "local",
"newValue": 1,
"prevValue": 0,
"propertyName": "local",
},
},
)
node.receive_event(event)

state = hass.states.get(PROTECTION_SELECT_ENTITY)
assert state.state == "ProtectedBySequence"

# Test null value
event = Event(
type="value updated",
data={
"source": "node",
"event": "value updated",
"nodeId": node.node_id,
"args": {
"commandClassName": "Protection",
"commandClass": 117,
"endpoint": 0,
"property": "local",
"newValue": None,
"prevValue": 1,
"propertyName": "local",
},
},
)
node.receive_event(event)

state = hass.states.get(PROTECTION_SELECT_ENTITY)
assert state.state == STATE_UNKNOWN

0 comments on commit cff6883

Please sign in to comment.