Retrieving values/parameters from a Z-Wave node

I am able to retrieve values from a Z-Wave Node through the Z-Wave JS UI. I am at a loss however on how to retrieve them programmatically in some way. zwave-js has methods to set parameters but not get it seems. What am I missing? Is the only way to do this is to retrieve the diagnostic file and file the parameter with JavaScript? In particular I want to retrieve a user lock_usercode for a particular slot. Thank you for your comments.

You can use something like Keymaster (custom component) or one of the alternatives (can be found in these forums) to access and manage the user codes. They are not available via the integration.

Alternatively you could:

  1. Enable MQTT and create an MQTT sensor from whatever usercode topics it exposes
  2. Use the zwave_js.invoke_cc_api to Get usercodes, and use a trigger-based template entity or automation to handle the value updated platform trigger.
1 Like
1 Like

Thank you for your reply, I do appreciate it! Keymaster is, as one user put it, “too sprawly”. I have a very unusual use case. This is for an instance to manage many locks in a mixed use commercial building. Right now it is using, wait for it, …Wink. I had started going down the route you label at 2. I am not adverse to writing scripts. I am very new to HA and the languages/markup that it uses but not new to software development or even hardware development (degrees in both). I do have a “day job” and manage said building so I don’t have a lot of extra time. I will post follow on messages here on this effort. I posted the question to make sure I was not missing some basic concept, being new to HA. Thanks again for your reply.

I am not the only one that has reasons not to use Keymaster I guess. Release 0.2.1 is a little too new for my tastes. I think going the route mention as number 2 by you is a great learning exercise if nothing else. Thank you for your reply!

For invoke_cc_api you would use the UserCode.get API.

service: zwave_js.invoke_cc_api
data:
  command_class: "99"
  method_name: get
  parameters:
    - 8

Where "99" is UserCode Command Class ID, and 8 is the user ID to request. (add your entity / device id).

You only need to run this command once on HA startup. It ensures that you have the correct user code values in case they were set while HA was offline. If that’s not a possibility, you could potentially skip it. When user codes are set during runtime, HA will see the value update events. The value update triggers below do not trigger on startup.

You haven’t said what you want to do with the user codes, so there are two options really, 1) write a sensor template to trigger on Z-Wave value updates and capture the result into a sensor state, or 2) write an automation to trigger on Z-Wave value updates and perform some actions.

In either case, the trigger is the same. The easiest way to create this trigger is in the automation editor. I don’t have a lock, so using a light dimmer level as an example.

And resulting YAML is:

platform: device
device_id: 08a3216a6eb9f54870e14e8c5b0f7f9d
domain: zwave_js
type: zwave_js.value_updated.value
command_class: 38
property: currentValue

UserCode CC again is 99 and the property is userCode. property_key would be set if you want to trigger on a specific user id.

Or you can write it in YAML manually to take advantage of being able to use an entity ID (beware of device automations):

trigger:
  platform: zwave_js.value_updated
  entity_id:
    - lock.front_lock
  command_class: 99
  property: userCode
  # `property_key` is the user code, if you want to trigger on a specific one
  # property_key: 8

You can plug either trigger into a trigger-based sensor, or use strictly as an automation trigger.

1 Like

Thank you for your reply. This is very helpful. I do have some questions though.
I can evoke the api call through “services” under “developer tools”. When I call the service by pressing the “Call Service” button I get a green check but where is the value? How do these calls work with respect to the response? How do I capture/reference the response? Doing this in a sandbox is all well and good but how do I make use of this? Part of a larger script somewhere?

What I want to do with the user code is to display it on a special dashboard that has all the door locks. I currently have 17 of these door locks (maybe a couple more in the future in this one building) Periodically I have to give out the code to a door lock to a new tenant. This is a good as place as any for me to reference the codes, especially if they come from the single source of truth, the lock itself instead of a spreadsheet. Most often the dashboard will be used to remotely open the door or open the door when I am on site. These locks are in a building about 100 miles from where I live.

It is technically possible for a tenant to change the door lock code if they already have access to the interior of the door. They would have to have the necessary instructions but they could do it, why I am not sure. Normally if they have a security issue they ask me to change a code. Change the code while my HA instance is down? that probability is much smaller. But retrieving the codes on startup is a good call and I will likely implement that down the road here. Thanks for that call out.

As for the “sensor template”, is this like a virtual sensor the reflects the value of the door code? And then reference the sensor value in the dashboard? Can you point me to some good example/instruction on how to make such a thing?

Thanks again, I truly do appreciate your help!

The green check means the service call was successful.

Z-Wave services don’t return values, they were written prior to HA supporting such a thing, and haven’t been updated. If they did, you could process the response in an automation.

Instead the Get causes a “value updated” event to be sent by the driver, which contains the result of the service call, which in this case is the usercode. If you turn on the integration debug logging you can see the events coming from the z-wave server in realtime in the HA logs.

The trigger is what handles the “value updated” event. It’s the only way to “read” values in HA that aren’t supported by the built-in entities. You can see essentially the same data in the device diagnostic file (Device page → ... → Download diagnostics). Here’s an example:

    {
      "endpoint": 0,
      "commandClass": 99,
      "commandClassName": "User Code",
      "property": "userCode",
      "propertyKey": 1,
      "propertyName": "userCode",
      "propertyKeyName": "1",
      "ccVersion": 1,
      "metadata": {
        "type": "string",
        "readable": true,
        "writeable": true,
        "label": "User Code (1)",
        "minLength": 4,
        "maxLength": 10
      },
      "value": "5555"
    },

The event data will be a subset of that. You can either use the trigger in an automation to do something, or you can use the trigger in the definition of a template sensor. The template allows you to capture the event data and store it as the state of the entity, which it sounds like you want. So for your use case, you probably want a duplicate sensor for each user id. The trigger would match what I showed above and the only difference would be the property_key, one for each userid.

There’s an example in the docs I linked to above, but I think it looks something like this (I don’t have a lock to test):

template:
  - trigger:
      entity_id: lock.front_lock
      command_class: 99   # UserCode CC
      property: userCode
      property_key: 2     # userId
    sensor:
      - name: "Front Lock User Code 2"
        state: '{{ trigger.current_value }}'
  - trigger:
      entity_id: lock.front_lock
      command_class: 99   # UserCode CC
      property: userCode
      property_key: 3     # userId
    sensor:
      - name: "Front Lock User Code 3"
        state: '{{ trigger.current_value }}'
  # etc.

The result would be two entities, sensor.front_lock_user_code_2 and sensor.front_lock_user_code_3 and the states would be the user code. Repeat for the number of codes you want to manage. You can then add these sensors to your dashboard in whichever way you prefer.

If you also want to determine if a user code is actually in use, you’d need to create yet more template sensors for this value:

    {
      "endpoint": 0,
      "commandClass": 99,
      "commandClassName": "User Code",
      "property": "userIdStatus",
      "propertyKey": 1,
      "propertyName": "userIdStatus",
      "propertyKeyName": "1",
      "ccVersion": 1,
      "metadata": {
        "type": "number",
        "readable": true,
        "writeable": true,
        "label": "User ID status (1)",
        "states": {
          "0": "Available",
          "1": "Enabled",
          "2": "Disabled"
        }
      },
      "value": 1
    },

Maybe you can see why Keymaster is pretty popular. It and the one I linked above do all this for you with code.

Obviously, all the above is done to just read the usercodes. It doesn’t provide any interface to manage the user codes.

Here’s another thread with different approaches:

Instead of using the templates I posted above that show the actual state of the user codes, these just store the codes you set into input text helpers. So as long as the setting of the user codes is succesfull, you might not need to track the actual state. They also provide a UI management aspect.

BTW, doesn’t Z-Wave JS UI have a built-in usercode management UI? I haven’t seen it because I don’t have a lock, but I thought it did. If your needs are simple, that might be good enough.

1 Like

@freshcoast A belated thank you for this post. My HA time got re-directed to automating and installing some new “plantation” shutters that had finally arrived after a 2 month wait. I also replaced my z-wave stick after having basic connectivity issues. In reading your reply I am going to have to do a lot more HA general learning before tackling any extension of the basic lock control currently provide by the standard Z-wave integration. Now that the shutters are in the wife is requesting a way to control them that is not an app on her phone so I am off to tackle that before coming back to this. Thanks again for your post and I will be coming back to it in the not too distant future.

1 Like

I’m sorry for jumping in at the bottom of this post but it’s been incredibly helpful for what I’m trying to do but I’m one step short of getting it all to work. I really appreciate the info provided above. There is no way I’d have gotten this far without it.

I have the invoke_cc_api working just fine and I can see the results in my zwave_js_ui Events log which includes the pin code I’m looking for. What I’m trying to do is to use a template sensor to store the pin code so I can confirm that the desired slot actually has the correct pin code in it. I’ve got all of the logic working but can’t seem to get the template sensor working.

The trigger seems to be working fine:

- trigger:
  - platform: event
    event_type: "zwave_js.value_updated.value"
    event_data:
      command_class: 99
      property: userCode
      propertyKeyName: 1
          
  sensor:
    - name: "Test Pin Code"
      state: "{{trigger.current_value}}"

I’ve tried that template with lots of different options i.e. newValue, data.newValue, etc, etc.

This is what is in the zwave_js_ui Events log:

4/21/2024, 8:28:35 AM - VALUE UPDATED
Arg 0:
└─commandClassName: User Code
└─commandClass: 99
└─property: userCode
└─propertyKey: 1
└─endpoint: 0
└─newValue: 0917
└─prevValue: 0917
└─propertyName: userCode
└─propertyKeyName: 1

I’ve watched every YouTube video guide and read as much as I can find on template sensors but still no luck. Any help would be greatly appreciated.
TIA

You’re very close, but your propertyKeyName trigger field is wrong. The trigger uses “snake case” not “camel case” naming. The docs show the valid trigger field names:

https://www.home-assistant.io/integrations/zwave_js/#example-automation-trigger-configuration

It should be:

- trigger:
  - platform: event
    event_type: "zwave_js.value_updated.value"
    event_data:
      command_class: 99
      property: userCode
      property_key_name: 1
          
  sensor:
    - name: "Test Pin Code"
      state: "{{trigger.current_value}}"

I would use property_key: 1 here, but it’s the same thing in this particular case.

The trigger is also not scoped by node (needs device id or entity). Not a problem if you only have a single device with user codes, but something to keep in mind if you add another lock.