Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion test/fixtures/wallmote_central_scene_state.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@
"inclusion": "To add the ZP3111 to the Z-Wave network (inclusion), place the Z-Wave primary controller into inclusion mode. Press the Program Switch of ZP3111 for sending the NIF. After sending NIF, Z-Wave will send the auto inclusion, otherwise, ZP3111 will go to sleep after 20 seconds.",
"exclusion": "To remove the ZP3111 from the Z-Wave network (exclusion), place the Z-Wave primary controller into \u201cexclusion\u201d mode, and following its instruction to delete the ZP3111 to the controller. Press the Program Switch of ZP3111 once to be excluded.",
"reset": "Remove cover to trigged tamper switch, LED flash once & send out Alarm Report. Press Program Switch 10 times within 10 seconds, ZP3111 will send the \u201cDevice Reset Locally Notification\u201d command and reset to the factory default. (Remark: This is to be used only in the case of primary controller being inoperable or otherwise unavailable.)",
"manual": "https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/2479/ZP3111-5_R2_20170316.pdf"
"manual": "https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/2479/ZP3111-5_R2_20170316.pdf",
"comments": {
"level": "info",
"text": "test"
}
},
"isEmbedded": true
},
Expand Down
7 changes: 6 additions & 1 deletion test/model/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ async def test_highest_security_value(lock_schlage_be469, ring_keypad):
assert ring_keypad.highest_security_class is None


async def test_device_config(wallmote_central_scene):
async def test_device_config(
wallmote_central_scene, climate_radio_thermostat_ct100_plus
):
"""Test a device config."""
node: node_pkg.Node = wallmote_central_scene

Expand Down Expand Up @@ -143,10 +145,13 @@ async def test_device_config(wallmote_central_scene):
"https://products.z-wavealliance.org/ProductManual/File?folder=&filename=MarketCertificationFiles/2479/ZP3111-5_R2_20170316.pdf"
)
assert device_config.metadata.wakeup is None
assert device_config.metadata.comments == [{"level": "info", "text": "test"}]
assert device_config.associations == {}
assert device_config.param_information == {"_map": {}}
assert device_config.supports_zwave_plus is None

assert climate_radio_thermostat_ct100_plus.device_config.metadata.comments == []


async def test_unknown_values(cover_qubino_shutter):
"""Test that values that are unknown return as None."""
Expand Down
20 changes: 19 additions & 1 deletion zwave_js_server/model/device_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

https://zwave-js.github.io/node-zwave-js/#/api/node?id=deviceconfig
"""
from typing import Dict, List, Optional, TypedDict
from typing import Dict, List, Literal, Optional, TypedDict, Union


class DeviceDeviceDataType(TypedDict, total=False):
Expand Down Expand Up @@ -56,6 +56,15 @@ def max(self) -> Optional[str]:
return self.data.get("max")


class CommentDataType(TypedDict):
"""Represent a device config's comment data dict type."""

# See PR for suggested meanings of each level:
# https://github.com/zwave-js/node-zwave-js/pull/3947
level: Literal["info", "warning", "error"]
text: str


class DeviceMetadataDataType(TypedDict, total=False):
"""Represent a device metadata data dict type."""

Expand All @@ -64,6 +73,7 @@ class DeviceMetadataDataType(TypedDict, total=False):
exclusion: str
reset: str
manual: str
comments: Union[CommentDataType, List[CommentDataType]]


class DeviceMetadata:
Expand Down Expand Up @@ -98,6 +108,14 @@ def manual(self) -> Optional[str]:
"""Return manual instructions."""
return self.data.get("manual")

@property
def comments(self) -> List[CommentDataType]:
"""Return list of comments about device."""
comments = self.data.get("comments", [])
if isinstance(comments, dict):
return [comments]
return comments


class DeviceConfigDataType(TypedDict, total=False):
"""Represent a device config data dict type."""
Expand Down