Git Product home page Git Product logo

zwave-js-server-python's Introduction

zwave-js-server-python

Python library for communicating with zwave-js-server. Goal for this library is to replicate the structure and the events of Z-Wave JS 1:1. So it has a Driver, Controller and Node classes.

Setup development environment

To setup your development environment, run scripts/setup, which will install all requirements and set up pre-commit checks.

Trying it out

python3 -m zwave_js_server ws://localhost:3000

Or get the version of the server

python3 -m zwave_js_server ws://localhost:3000 --server-version

Or dump the state. Optionally add --event-timeout 5 if you want to listen 5 seconds extra for events.

python3 -m zwave_js_server ws://localhost:3000 --dump-state

Sending commands

try:
    result = await client.async_send_command({ "command": "start_listening" })
except zwave_js_server.client.FailedCommand as err:
    print("Command failed with", err.error_code)

zwave-js-server-python's People

Contributors

alcalzone avatar balloob avatar bramkragten avatar cdce8p avatar cgarwood avatar cgtobi avatar dependabot[bot] avatar dummy0815 avatar einstein- avatar firstof9 avatar kpine avatar marcelveldt avatar martinhjelmare avatar michsior14 avatar raman325 avatar reubenbijl avatar thecode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zwave-js-server-python's Issues

ISSUE - Using property key name in value ID means we are missing values in the node's value dictionary

While working on config parameter support, we noticed that all values that have a property key don't always have a property key name. This means that partial parameters are probably not working as expected:

{
    "commandClassName": "Configuration",
    "commandClass": 112,
    "endpoint": 0,
    "property": 101,
    "propertyKey": 1,
    "propertyName": "Group 1: Send battery reports",
    "metadata": {
        "type": "number",
        "readable": true,
        "writeable": true,
        "valueSize": 4,
        "min": 0,
        "max": 1,
        "default": 1,
        "format": 0,
        "allowManualEntry": true,
        "label": "Group 1: Send battery reports",
        "description": "Include battery information in periodic reports to Group 1",
        "isFromConfig": true
    },
    "value": 1
},
{
    "commandClassName": "Configuration",
    "commandClass": 112,
    "endpoint": 0,
    "property": 101,
    "propertyKey": 16,
    "propertyName": "Group 1: Send ultraviolet reports",
    "metadata": {
        "type": "number",
        "readable": true,
        "writeable": true,
        "valueSize": 4,
        "min": 0,
        "max": 1,
        "default": 1,
        "format": 0,
        "allowManualEntry": true,
        "label": "Group 1: Send ultraviolet reports",
        "description": "Include ultraviolet information in periodic reports to Group 1",
        "isFromConfig": true
    },
    "value": 1
},
{
    "commandClassName": "Configuration",
    "commandClass": 112,
    "endpoint": 0,
    "property": 101,
    "propertyKey": 32,
    "propertyName": "Group 1: Send temperature reports",
    "metadata": {
        "type": "number",
        "readable": true,
        "writeable": true,
        "valueSize": 4,
        "min": 0,
        "max": 1,
        "default": 1,
        "format": 0,
        "allowManualEntry": true,
        "label": "Group 1: Send temperature reports",
        "description": "Include temperature information in periodic reports to Group 1",
        "isFromConfig": true
    },
    "value": 1
},
{
    "commandClassName": "Configuration",
    "commandClass": 112,
    "endpoint": 0,
    "property": 101,
    "propertyKey": 64,
    "propertyName": "Group 1: Send humidity reports",
    "metadata": {
        "type": "number",
        "readable": true,
        "writeable": true,
        "valueSize": 4,
        "min": 0,
        "max": 1,
        "default": 1,
        "format": 0,
        "allowManualEntry": true,
        "label": "Group 1: Send humidity reports",
        "description": "Include humidity information in periodic reports to Group 1",
        "isFromConfig": true
    },
    "value": 1
},
{
    "commandClassName": "Configuration",
    "commandClass": 112,
    "endpoint": 0,
    "property": 101,
    "propertyKey": 128,
    "propertyName": "Group 1: Send luminance reports",
    "metadata": {
        "type": "number",
        "readable": true,
        "writeable": true,
        "valueSize": 4,
        "min": 0,
        "max": 1,
        "default": 1,
        "format": 0,
        "allowManualEntry": true,
        "label": "Group 1: Send luminance reports",
        "description": "Include luminance information in periodic reports to Group 1",
        "isFromConfig": true
    },
    "value": 1
}

Each of these values would have the same value_id of <node_id>-112-0-101-00 which means they overwrite each other during initialization.

What's the best way to approach this problem? I originally thought using property key instead of property key name in the value ID will solve the problem, but that eliminates the user friendliness of using names for platforms like climate, where we can use setpoint names.

Fibaro FGRGBWM441 RGB controller no color wheel

I dunno if this is the right place but apparently this controller is only partially supported. Instead of getting a color whel I get a light switch for each color. What do you need to debug or where do I have to raise this issue?

Handle exceptions raised in integration in message handler

Behavior

  • We raise some exceptions in Home Assistant when we encounter an impossible request, eg missing value ValueError("Value requested is not available") in the climate platform.
  • These exceptions will bubble up in the message handler callback inside this library and cause the client to disconnect.
  • The listener task will remain in a broken state due to the exception and we don't recover unless Home Assistant is restarted.

home-assistant/core#46357

TODO: Support Configuration Parameters on alternate endpoints

config parameters can be on endpoints other than 0. To address this:

Add node_ready event

Once #3 is merged we should add a "node_ready" event.

This event fires:

  1. At startup, when the node is interviewed (or restored from cache) and it's ready to handle commands.
  2. When a new node is added and the first interview is ready.

Now we only have node added to handle 2 which is not good as we might not have all values.
And we have "all nodes ready" to handle 1 but this is also not god because it means that a node can only be used if all nodes are ready (like now in ozw integration).

TODO: Add tests for all events

We are missing at least one event from tests (validate dsk and enter pin). We need to do a sweep and ensure all events have a test for them to make sure that all of the proper plumbing is in place.

Validation for `async_multicast_set_value` is too strict

The value validation implemented in async_multicast_set_value (here) seems to be a bit too strict and results in the rejection of commands that are supported by the underlying zwave-js API.

This causes usability issues with devices which do not have their root endpoint exposed by default (such as the Fibaro FGD212). For example, when targeting an area which contains a device like this one with a multicast command, an error will be returned that the node does not have that value (example).

My understanding is that the capabilities of the root endpoint, at minimum, should always mirror mirror endpoint 1. Given this, would it be appropriate to either relax this validation to allow for it for it to be explicitly skipped?

Initialize repo

  • Setup base structure for python development with VS Code.
  • GH Action: dependabot.
  • GH Action: linting and tests.

Sending a broadcast with `async_multicast_set_value` fails

Using the following service call (device is specified because I have two networks) in HA:

service: zwave_js.multicast_set_value
data:
  command_class: "64"
  property: mode
  value: 2
  broadcast: true
target:
  device_id: 31e237d264f3cedaa2301e57c740746d

Results in:

2022-11-15 23:52:12.434 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: Node Node(node_id=1) doesn't have value 1-64-0-mode
Traceback (most recent call last):
  File "/home/keith/src/hass-core/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/home/keith/src/hass-core/homeassistant/helpers/script.py", line 684, in _async_call_service_step
    await service_task
  File "/home/keith/src/hass-core/homeassistant/core.py", line 1744, in async_call
    task.result()
  File "/home/keith/src/hass-core/homeassistant/core.py", line 1781, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/home/keith/src/hass-core/homeassistant/components/zwave_js/services.py", line 604, in async_multicast_set_value
    success = await async_multicast_set_value(
  File "/home/keith/src/hass-core/venv/lib/python3.10/site-packages/zwave_js_server/util/multicast.py", line 51, in async_multicast_set_value
    raise NotFoundError(f"Node {node} doesn't have value {value_id}")
zwave_js_server.exceptions.NotFoundError: Node Node(node_id=1) doesn't have value 1-64-0-mode

HA invokes async_multicast_set_value with an empty nodes argument when a broadcast is specified. However, async_multicast_set_value ignores the empty node list and attempts to validate the specified value ID for every node in the network.

async def async_multicast_set_value(
client: Client,
new_value: Any,
value_data: ValueDataType,
nodes: Optional[List[Node]] = None,
options: Optional[dict] = None,
) -> bool:
"""Send a multicast set_value command."""
assert client.driver
# Iterate through nodes specified or all nodes if not specified
for node in nodes or client.driver.controller.nodes.values():
# If the value to set is for Basic CC and targetValue property, skip validation
if (
value_data["commandClass"] == CommandClass.BASIC
and value_data["property"] == TARGET_VALUE_PROPERTY
):
break
value_id = _get_value_id_str_from_dict(node, value_data)
# Check that the value exists on the node
if value_id not in node.values:
raise NotFoundError(f"Node {node} doesn't have value {value_id}")

Add integration discovery schema tests

  • Collect network dumps from all devices that have custom schemas. See the issues reported in the core repo.
  • Add tests for the discovery.py module in the integration and use the dumps to check that the schemas work.

PEP 655: Improve TypedDict typing

TypedDict's have a Required and NotRequired type that can be used to explicitly mark fields as optional versus not. This is standard in python 3.11 but must be imported via typing_extensions in python 3.10. All TypedDict's should use these new types which will require a review of zwave-js-server and node-zwave-js because I believe we have commented that more fields are optional than there actually are

https://peps.python.org/pep-0655/

Needs pydantic/pydantic#5584

Feature Wishlist

If you have a feature request that's not on the roadmap, add a comment here!

Caveats:

  • This is open to all but not a support avenue, and support requests will be hidden as off topic
  • If you like an existing idea, add a +1 to that comment and do not add another one.

async_stop_inclusion KeyError

If an inclusion is running, firing async_stop_inclusion gives the following error:

Traceback (most recent call last):
  File "/home/cgarwood/home-assistant/core/homeassistant/components/websocket_api/decorators.py", line 18, in _handle_async_response
    await func(hass, connection, msg)
  File "/home/cgarwood/home-assistant/core/homeassistant/components/zwave_js/websocket_api.py", line 91, in websocket_stop_inclusion
    result = await controller.async_stop_inclusion()
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/model/controller.py", line 152, in async_stop_inclusion
    return cast(bool, data["success"])
KeyError: 'success'

If an inclusion is not running, it returns False as expected.

cc @Michsior14

Provide some minimum documentation

Hi,

this project looks great. After having played around with zwavejs2mqtt I'm really excited about this. However, as a newbie I am not sure how to use this at all.

The minimum example at the bottom of the readme file leaves me confused.

It would be great if there was a minium end-to-end example. I searched for start_listening in node-zwave-js but without any code occurrences. And there is nothing on stackoverflow on zwave-js-server-python.

Much appreciated
Dan

connection state

the connection state is set only after the "disconnected" event is fired, this causes a race condition in the integration to set the availability state when client connection state changes.
the event should be fired when the connection state is already been set

Protect against value type mismatches

In some cases, a value ID with a specific type will have a value that does not match the type. For example:

                        {
                            "endpoint": 0,
                            "commandClass": 38,
                            "commandClassName": "Multilevel Switch",
                            "property": "currentValue",
                            "propertyName": "currentValue",
                            "ccVersion": 3,
                            "metadata": {
                                "type": "number",
                                "readable": true,
                                "writeable": false,
                                "min": 0,
                                "max": 99,
                                "label": "Current value"
                            },
                            "value": "unknown"
                        },

This is a "number" type, but Instead of a valid value in the range 0 to 99, the value is the string "unknown". Unknown is a valid value reported by devices, so node-zwave-js just sets it as a string.

It might make more sense for this value to be converted to None in the library, so the HA components don't need to anything special besides check for None (which most do already).

I don't know if there are any other strings besides "unknown" that could be returned for a number, or if this is it.

See these HA issues for examples and dump files related to this problem:

Add (major) version check for Zwave JS

New versions of upstream Zwave JS can possibly contain breaking changes in the API/definitions.
If the zwave server is hosted by the user itself (or in another application like zwave2mqtt) we have no control if the python lib is 100% compatible with the Zwave jS version.

Suggestion is that we add a major-version check in the code of the library and halt (or log) if the major version is not compatible.

This depends on a PR for Zwave JS to include the version.

Hang when shutting down while a server is offline

Using the zwave_js integration in HA, I have two servers configured. Sometimes one of my servers is offline. In this state, the library will attempt to reconnect. If I shutdown HA in this condition, the shutdown will timeout. If all the servers are online, the HA shutdown is nearly instantaneous.

Same result with 0.14.1 and 0.14.2.

2021-01-31 22:52:54 DEBUG (MainThread) [zwave_js_server] Trying to connect
2021-01-31 22:52:54 WARNING (MainThread) [zwave_js_server] Unable to connect: Cannot connect to host rpi1:3000 ssl:default [Connect call failed ('192.168.1.20', 3000)]
2021-01-31 22:52:54 INFO (MainThread) [zwave_js_server] Connection closed
2021-01-31 23:01:47 DEBUG (MainThread) [zwave_js_server] Trying to connect
2021-01-31 23:01:47 WARNING (MainThread) [zwave_js_server] Unable to connect: Cannot connect to host rpi1:3000 ssl:default [Connect call failed ('192.168.1.20', 3000)]
2021-01-31 23:01:47 INFO (MainThread) [zwave_js_server] Connection closed
2021-01-31 23:10:53 DEBUG (MainThread) [zwave_js_server] Trying to connect
2021-01-31 23:10:53 WARNING (MainThread) [zwave_js_server] Unable to connect: Cannot connect to host rpi1:3000 ssl:default [Connect call failed ('192.168.1.20', 3000)]
2021-01-31 23:10:53 INFO (MainThread) [zwave_js_server] Connection closed
2021-01-31 23:19:34 DEBUG (MainThread) [zwave_js_server] Trying to connect
2021-01-31 23:19:34 WARNING (MainThread) [zwave_js_server] Unable to connect: Cannot connect to host rpi1:3000 ssl:default [Connect call failed ('192.168.1.20', 3000)]
2021-01-31 23:19:34 INFO (MainThread) [zwave_js_server] Connection closed
^C2021-01-31 23:21:14 INFO (MainThread) [zwave_js_server] Connection closed
2021-01-31 23:21:14 INFO (MainThread) [homeassistant.components.zwave_js] Disconnected from Zwave JS Server
2021-01-31 23:23:14 WARNING (MainThread) [homeassistant.core] Timed out waiting for shutdown stage 1 to complete, the shutdown will continue

Handle reconnect to Z-Wave JS server

The client holds a driver object based on the initial received state. This object has listeners attached from Home Assistant.

When we reconnect, the client now holds a driver object that no longer represents the latest state. We don't deal with this case.

I can think of two options:

  1. We throw away the driver object. Consumers of this lib will just have to re-initialize their stack + attach listeners. In the case of HA we would reload the config entry.
  2. We teach each model to update based on the latest state and add new events to indicate the consumer that they have to re-scan each model for latest data/values.

Migrate to zwave-js 7.0.0

This issue lists changes that are required to support zwave-js 7.0.0.

  • The changes require a new schema version, so we can't release any of these changes unless we bump the schema version.
  • Of course, we need to coordinate the changes between server and client libraries. Most changes require a change in both libraries.

Rename controller method

Rework node properties

Rework node notification event

Change (check) log level return type

  • Numeric loglevels are converted to the corresponding string loglevel internally. driver.getLogConfig always returns the string loglevel regardless. Check if we need to update the enum in the client.
    class LogLevel(IntEnum):
    """Enum for log levels used by node-zwave-js."""
    # https://github.com/zwave-js/node-zwave-js/blob/master/packages/core/src/log/shared.ts#L12
    # https://github.com/winstonjs/triple-beam/blame/master/config/npm.js#L14
    ERROR = 0
    WARN = 1
    INFO = 2
    HTTP = 3
    VERBOSE = 4
    DEBUG = 5
    SILLY = 6

consistent class and instance names

We already had a few cases where the name "value" was confusing.

Proposal:

rename Node class to ZwaveNode and when referring to an instance of it, use zwave_node

rename Value class to ZwaveValue and when referring to an instance of it, use zwave_value

How to ease migration to Z-Wave JS

Scope

Issue to track ideas and problems for helping users migrate to Z-Wave JS from the other two older Z-Wave integrations in Home Assistant.

  • Please add your input in a new comment and we'll update the top post with important information.

Known facts

  • Value id:s used in the integration entity unique_id are different between the 3 integrations, so we won't be able to use those. Entities can be matched using command class and endpoint/index values.
  • Battery nodes won't be picked up by z-wave js until they wake up for the first time after the migration (ozw would have had the same issue moving from zwave)
  • Command class support is different between the 3 integrations so some entities may not port over, or new entities will be discovered

Reconnection issue, zwave_js_server not ready?

I'm having a hard time tracking down the actual cause of this issue but I figured I would post my logs as it may be obvious to someone else.

I can reproduce this by restarting my zwavejs2mqtt container or rebooting my system. If HA attempts to connect to the zwavejs websocket before it's fully ready I will get this error and HA will refuse to attempt a reconnection.

2021-02-05 10:07:06 WARNING (MainThread) [homeassistant.config_entries] Config entry 'Z-Wave JS' for zwave_js integration not ready yet. Retrying in 5 seconds
2021-02-05 10:07:11 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry Z-Wave JS for zwave_js
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 239, in async_setup
    result = await component.async_setup_entry(hass, self)  # type: ignore
  File "/usr/src/homeassistant/homeassistant/components/zwave_js/__init__.py", line 182, in async_setup_entry
    await client.connect()
  File "/usr/local/lib/python3.8/site-packages/zwave_js_server/client.py", line 81, in connect
    await self._client.receive_json()
  File "/usr/local/lib/python3.8/site-packages/aiohttp/client_ws.py", line 291, in receive_json
    data = await self.receive_str(timeout=timeout)
  File "/usr/local/lib/python3.8/site-packages/aiohttp/client_ws.py", line 276, in receive_str
    raise TypeError(f"Received message {msg.type}:{msg.data!r} is not str")
TypeError: Received message 257:None is not str

Perhaps we just need to backoff and retry if we don't receive the expected json (what I think is happening here)?

Reach 100 % test coverage

  • This library needs more tests.

Current status (updated 2021-02-05):

(zwave-js-server-python) x$ pytest --durations 10 --cov-report term-missing --cov=zwave_js_server
...
----------- coverage: platform linux, python 3.8.5-final-0 -----------
Name                                     Stmts   Miss  Cover   Missing
----------------------------------------------------------------------
zwave_js_server/__init__.py                  0      0   100%
zwave_js_server/__main__.py                 63     63     0%   2-131
zwave_js_server/client.py                  135      6    96%   71, 99, 165, 180, 224-225
zwave_js_server/const.py                   198      0   100%
zwave_js_server/dump.py                     24     24     0%   2-40
zwave_js_server/event.py                    33      2    94%   58-59
zwave_js_server/exceptions.py               25      1    96%   36
zwave_js_server/model/__init__.py            0      0   100%
zwave_js_server/model/association.py        14      0   100%
zwave_js_server/model/controller.py        159      9    94%   12, 327-336, 358-359, 363
zwave_js_server/model/device_class.py       25      0   100%
zwave_js_server/model/device_config.py      49      3    94%   71, 76, 86
zwave_js_server/model/driver.py             17      3    82%   8, 26-28
zwave_js_server/model/endpoint.py           21      3    86%   29, 39, 44
zwave_js_server/model/node.py              208     24    88%   19, 90, 95, 165, 170, 175, 180, 185, 190, 215, 220, 225, 230, 285, 350-351, 359, 366, 371-374, 379, 383
zwave_js_server/model/notification.py       22      6    73%   10, 28-29, 34, 39, 44
zwave_js_server/model/value.py             111      9    92%   7, 81, 86, 91, 96, 101, 120, 145, 175
zwave_js_server/model/version.py             9      0   100%
zwave_js_server/util/__init__.py             0      0   100%
zwave_js_server/util/lock.py                38      0   100%
zwave_js_server/version.py                   7      0   100%
----------------------------------------------------------------------
TOTAL                                     1158    153    87%

Add support for MultilevelSwitchCommandClass

Using node-z-wave-js beta, when receiving a multilevelSwitchCC an error is generated.

See change with Z-Wave-js - zwave-js/node-zwave-js#4282

ZwaveJS and jwaveJSMQTT logs
19:47:35.664 DRIVER « [Node 030] [REQ] [ApplicationCommand]
└─[MultilevelSwitchCCStopLevelChange]
19:47:35.664 CNTRLR [Node 030] treating MultilevelSwitchCC::StopLevelChange as a notification
2022-03-29 19:47:35.664 INFO ZWAVE: Node 30 CC Multilevel Switch { eventType: 5 }
2022-03-29 19:47:35.969 INFO ZWAVE-SERVER: Client disconnected

Home Assistant Logs
[homeassistant.components.zwave_js] Failed to listen: Notification received with unsupported command class SWITCH_MULTILEVEL: {'source': 'node', 'event': 'notification', 'nodeId': 30, 'ccId': 38, 'args': {'eventType': 5}}

Integration Roadmap

Roadmap for the Z-Wave JS integration.
Note: for a list of all that is already supported see here.

Open Tasks

General

  • Complete certification requirements [Board]

Maintenance

  • #590
  • Refactor discovery so that discovery logic for each platform lives in each platform - use Matter as a reference
  • Explore using stateful metadata parameter for value notification discovery in device triggers

Platform support/features

  • set date/time entity (when support for this entity type is added)
  • add is_opening and is_closing support for covers [PR]
  • Ensure that when secure inclusion fails, the reason is passed back to the user in the UI
  • Handle inclusion initiated outside of HA
  • Add a lastSeen sensor

Service calls

None

Z-Wave control panel (UI)

WS API Ready, awaiting frontend changes

  • Refresh Node (re-interview, refresh values, refresh CC values)
  • Replace Failed Node
  • Show node metadata on the device page (exclusion, inclusion, reset, wakeup, manual, device database URL)
  • UI for managing node associations
  • Add support for changing wakeup time to config panel (separate CC from normal configuration)
  • add rfRegion to device info for controller node

Lib ready, WS API support missing

  • NVM backup and restore
  • Let users view, add, delete, and update provisioning entries
  • Node diagnostics (checking route health, testing power level, etc.)
  • Record events and commands, see options (in either case we can have a stop button to stop recording because we can see whether recording is enabled or not):
    • reload config entry after setting a parameter that tells the config entry to start recording when initializing the client during setup
    • Update the parameter live, downside is we miss past events
  • Controller hard reset

Z-Wave JS ready, lib support missing

None

zwave-js support missing

None

Unclear yet on what's needed

  • Some form of network health check, make it easier to point out dead nodes or nodes that are slow to respond or having communication failures.
  • Network visualization of the mesh (like ZHA)

Note: Full configuration of the options are already available in the zwavejs2mqtt control panel.

Other

  • Better documentation! (this will likely never be checked off unless and until the zwave-js project stops maturing)
  • Improve the Core config flow for add-on config options. Provide a list of USB devices to select device, and validate that security keys have the correct format.

Finished

Services

  • Set configuration parameter service.
  • Poll node/value service.
  • Bulk set partial configuration parameter service.
  • Multicast support
  • Reset meters

UI

  • UI for updating node configuration settings
  • Adjust logging level of zwave-js server from UI
  • Subscribe to logs in the frontend
  • Node specific page
  • Log config update handling
  • Heal network
  • Show parameter number on node config page (most device manuals refer to parameter numbers instead of descriptions)
  • Heal node
  • Remove failed node
  • metadata comments (e.g. known issues with the device)
  • QR code (SmartStart) inclusion [2021.12]
  • Controller statistics [2022.6]
  • Node tx/rx statistics [2022.7]
  • Node Firmware Updates [2022.7]
  • Controller firmware updates [2023.3]
  • DSK only QR code support [2023.3]

General

  • Add sensor for node status (awake/asleep/dead/etc)
  • SoundSwitch (siren) support [2021.8]
    • Support setting default tone and volume [2021.9]
  • Device conditions (config parameter state, any value state, node status) [2021.8]
  • Device triggers for value notifications, notifications, and node status [2021.8]
  • Protection Command Class (select entity) [2021.9]
  • Automation triggers (non-device) for any value update [2021.9]
  • Device triggers for any value update [2021.9]
  • Device actions [2021.10]
  • Migration wizard from (deprecated) zwave integration [2021.10]
  • S2 support [2021.10]
  • Automatic firmware updates [2022.9]
  • Manual idling buttons for notification CC values [2023.5]
  • perform optimistic state updates for multilevel switch entities [2023.6]
  • improve Indicator CC support [2023.6]
  • Controller and node statistics sensors [2023.6]
  • config parameter entities [2023.6]
  • Add support for window covering CC [[2023.6]]
  • add support for Energy Production CC [[2023.6]]
  • Add "identify" event handler to generate a persistent notification in HA

Obsolete

  • Some sort of UI for configuring complex device settings, like notifications for Inovelli switches: https://nathanfiscus.github.io/inovelli-notification-calc/ or aeotec energy monitor reporting configs. (solved by partial parameter service)
  • Migration wizard from ozw integration (based on current analytics and the low usage of the ozw component, we feel a migration wizard is significantly more effort than its worth)

Add controller and node methods that match available commands

We should add methods to the Controller and Node classes that match the available commands from Z-Wave JS Server and set correct types.

  • Controller commands
    • controller.begin_inclusion #39
    • controller.stop_inclusion #39
    • controller.begin_exclusion #39
    • controller.stop_exclusion #39
    • controller.remove_failed_node #39
    • controller.replace_failed_node #39
    • controller.heal_node #39
    • controller.begin_healing_network #39
    • controller.stop_healing_network #39
    • controller.is_failed_node #39
    • controller.get_association_groups #39
    • controller.get_associations #39
    • controller.is_association_allowed #39
    • controller.add_associations #39
    • controller.remove_associations #39
    • controller.remove_node_from_all_assocations #39
  • Node commands
    • node.set_value #38
    • node.refresh_info #38
    • node.get_defined_value_ids #38
    • node.get_value_metadata #38
    • node.abort_firmware_update #38

Node metadata not always available

I've run into a few issues while testing inclusion/exclusion where I receive the following error during inclusion:

2021-01-15 21:28:37 ERROR (MainThread) [zwave_js_server] Unexpected error handling {'type': 'event', 'event': {'source': 'node', 'event': 'ready', 'nodeId': 60, 'node': Node(node_id=60)}}
Traceback (most recent call last):
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/client.py", line 292, in _handle_connection
    self.async_handle_message(msg_)
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/client.py", line 110, in async_handle_message
    self.driver.receive_event(event)
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/model/driver.py", line 23, in receive_event
    self.controller.receive_event(event)
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/model/controller.py", line 324, in receive_event
    node.receive_event(event)
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/model/node.py", line 227, in receive_event
    self.emit(event.type, event.data)
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/event.py", line 52, in emit
    listener(data)
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/event.py", line 43, in event_listener
    callback(data)
  File "/home/cgarwood/home-assistant/core/homeassistant/components/zwave_js/__init__.py", line 105, in <lambda>
    "ready", lambda event: async_on_node_ready(event["node"]),
  File "/home/cgarwood/home-assistant/core/homeassistant/components/zwave_js/__init__.py", line 90, in async_on_node_ready
    for disc_info in async_discover_values(node):
  File "/home/cgarwood/home-assistant/core/homeassistant/components/zwave_js/discovery.py", line 134, in async_discover_values
    disc_val = async_discover_value(value)
  File "/home/cgarwood/home-assistant/core/homeassistant/components/zwave_js/discovery.py", line 174, in async_discover_value
    if schema.type is not None and value.metadata.type not in schema.type:
  File "/home/cgarwood/home-assistant/core/venv/lib/python3.8/site-packages/zwave_js_server/model/value.py", line 122, in metadata
    return ValueMetadata(self.data["metadata"])
KeyError: 'metadata'

However, it doesn't happen all the time. Might be an upstream issue with zwave-js? Seems like that should exist if the node is firing the ready event.

Make all method names consistent

There are some method names on the client that are prefixed with async_.

  • Remove the async_ prefix that some library methods have.

`"inclusion aborted"` controller event is not handled

This can be easily reproduced by including an S2 device with classic inclusion and submitting a blank or incorrect PIN code. This event is not in the official docs for controller events. It's actually a zwave-js-server generated event.

2022-05-19 11:25:55 DEBUG (MainThread) [zwave_js_server] Received message:
WSMessage(type=<WSMsgType.TEXT: 1>, data='{"type":"event","event":{"source":"controller","event":"inclusion aborted"}}', extra='')

2022-05-19 11:25:55 DEBUG (MainThread) [zwave_js_server] Listen completed. Cleaning up
2022-05-19 11:25:55 ERROR (MainThread) [homeassistant.components.zwave_js] Unexpected exception: 'inclusion aborted'
Traceback (most recent call last):
  File "/home/foo/src/hass-core/homeassistant/components/zwave_js/__init__.py", line 615, in client_listen
    await client.listen(driver_ready)
  File "/home/foo/src/hass-core/venv/lib/python3.9/site-packages/zwave_js_server/client.py", line 244, in listen
    self._handle_incoming_message(data)
  File "/home/foo/src/hass-core/venv/lib/python3.9/site-packages/zwave_js_server/client.py", line 386, in _handle_incoming_message
    self.driver.receive_event(event)  # type: ignore
  File "/home/foo/src/hass-core/venv/lib/python3.9/site-packages/zwave_js_server/model/driver.py", line 80, in receive_event
    self.controller.receive_event(event)
  File "/home/foo/src/hass-core/venv/lib/python3.9/site-packages/zwave_js_server/model/controller/__init__.py", line 707, in receive_event
    CONTROLLER_EVENT_MODEL_MAP[event.type](**event.data)
KeyError: 'inclusion aborted'
2022-05-19 11:25:55 INFO (MainThread) [homeassistant.components.zwave_js] Disconnected from server. Reloading integration

LogMessageContextDataType validation

Looks like we need to adjust the validation in LogMessageContextDataType.

Logger: homeassistant.components.zwave_js
Source: components/zwave_js/__init__.py:602
Integration: Z-Wave JS (documentation, issues)
First occurred: 11:41:17 AM (1 occurrences)
Last logged: 11:41:17 AM

Unexpected exception: 1 validation error for LogMessageDataType context -> type unexpected value; permitted: 'value', 'node' (type=value_error.const; given=controller; permitted=('value', 'node'))
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/zwave_js/__init__.py", line 602, in client_listen
    await client.listen(driver_ready)
  File "/usr/local/lib/python3.9/site-packages/zwave_js_server/client.py", line 244, in listen
    self._handle_incoming_message(data)
  File "/usr/local/lib/python3.9/site-packages/zwave_js_server/client.py", line 386, in _handle_incoming_message
    self.driver.receive_event(event)  # type: ignore
  File "/usr/local/lib/python3.9/site-packages/zwave_js_server/model/driver.py", line 83, in receive_event
    DRIVER_EVENT_MODEL_MAP[event.type](**event.data)
  File "/usr/local/lib/python3.9/site-packages/pydantic/main.py", line 331, in __init__
    raise validation_error
pydantic.error_wrappers.ValidationError: 1 validation error for LogMessageDataType
context -> type
  unexpected value; permitted: 'value', 'node' (type=value_error.const; given=controller; permitted=('value', 'node'))

We probably need to add "controller" to the allowed items here:

type: Literal["value", "node"]

`Controller.async_begin_inclusion` method incorrectly sets inclusion strategy

data = await self.client.async_send_command(
{
"command": "controller.begin_inclusion",
"options": {"inclusionStrategy": inclusion_strategy},
},
require_schema=8,
)

async_begin_inclusion is naming the strategy field as "inclusionStrategy", instead of "strategy" (see API docs). When it reaches node-zwave-js, the options.strategy value is undefined, causing unexpected behavior.

This is a problem in HA 2021.9 but not 2021.8. I believe it forces all inclusions to be done insecurely (due to conditionals in the driver), or doesn't allows skipping of S2 bootstrapping for devices that are buggy. 2021.8 is OK because it uses the previous inclusion message schema (v7), and the server properly creates the options object with the strategy field.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.