Correct Z-Wave Lock API Command

It’s not clear to me if the lock itself is storing the lockCodes or if they are attributes of the lock that are part of the ST Cloud/API platform. It’s clear the event is returning a codeName that doesn’t match what is stored in lockCodes, but whether there is a mapping function in either the platform or an accessible method for the drivers to do that mapping is available or not. @philh30 might be able to provide some insight on this.

I don’t think philh30 can shed any more light on this. His driver is just the stock driver with the ability to set the stock parameters with in the driver itself.

1 Like

I haven’t taken the time to fully digest what the default handlers are doing with code names. They’re definitely storing those names in a field within the driver, and there’s logic to name it “Code 1” if the driver doesn’t already know the code name. I’m guessing what’s missing is logic for the driver to pull names from the lockCodes capability, which is where SLGA is populating names.

3 Likes

This is the line of code that sets the local variable code_name:

code_name = LockCodesDefaults.get_code_name(device, code_id)

There is special handling for code_id of 0 to map code_name “Master”.
Once code_name is set, it is passed to the event message here:

event.data = {codeName = code_name}

LockCodesDefaults mentions lockCodes which could be the same structure where the codeId to codeName mappings are stored, but I’d have to find that code to do some more digging.

LockCodesDefaults = require “st.zwave.defaults.lockCodes”

A little more digging and it looks like st.zwave.defaults.lockCodes is a default capability handler for the proposed capability lockCodes. I presume that ST supplies that handler and if so, there is likely some issue in that capability handler. I haven’t been able to find code for that handler and this is the only documentation of the capability that I can find Proposed Capabilities | SmartThings Developers which doesn’t even mention the capability commands that are being used in the driver.

Default handlers are in the lua_libs tar shown under assets on the page below

Ok, so here’s the code for getting the codeName:

local function get_code_name(device, code_id)
  if (device:get_field(constants.CODE_STATE) ~= nil and device:get_field(constants.CODE_STATE)["setName"..code_id] ~= nil) then
    -- this means a code set operation succeeded
    return device:get_field(constants.CODE_STATE)["setName"..code_id]
  elseif tonumber(code_id) == MASTER_CODE_INDEX then
    return "Master Code"
  elseif (get_lock_codes(device)[code_id] ~= nil) then
    return get_lock_codes(device)[code_id]
  else
    return "Code " .. code_id
  end
end
lock_code_defaults.get_code_name = get_code_name

And the routine it calls:

local function get_lock_codes(device)
  local lock_codes = device:get_field(constants.LOCK_CODES)
  if (lock_codes == nil) then
    return {}
  end
  return utils.deep_copy(lock_codes)
end
lock_code_defaults.get_lock_codes = get_lock_codes

Not sure how to read all the conditions in the If/Then, but it looks like it’s falling all the way to the last else where it returns “Code” concatenated with the code_id. @nayelyz Since we can see the codeName in the set event and we can retrieve the codeName array with code/name pairs present, there is clearly something messed up in the logic of the default handler’s name retrieval methodology since it falls all the way to the final behavior of the logic. What’s the best way to report this bug?

2 Likes

Not really my thing, but I find myself more intrigued by this code in the lock notification report …

st/zwave/defaults/lock.lua

          local lock_codes = device:get_field(constants.LOCK_CODES)

>8 – Snip a bit – >8

          local code_name = lock_codes[code_id] == nil and lock_codes[code_id] or "Code " .. code_id
          event["data"] = { codeId = code_id, codeName = code_name, method = event["data"].method}

I can’t get my head around how that code could be right. I want it to say ~= nil.

As it stands I see:

If the slot doesn’t have a name then use the name which it doesn’t have, but as it doesn’t have one use ‘Code x’.
If the slot does have a name then use ‘Code x’.

1 Like

Just as a contrast, here is the corresponding code for Zigbee.

st/zigbee/defaults/lock_defaults.lua

      local code_name = "Code "..code_id
      local lock_codes = device:get_field("lockCodes")
      if (lock_codes ~= nil and
          lock_codes[code_id] ~= nil) then
        code_name = lock_codes[code_id]
      end
      event.data = {method = METHOD[0], codeId = code_id .. "", codeName = code_name}

In contrast to the Z-Wave version, this makes sense. It sets the name to ‘Code x’ and then replaces it with the slot name if there is one defined.

2 Likes

Brilliant!

And you said this wasn’t really your thing. :smile:

1 Like

Think you could be on to something. I’m not really good with GitHub or I’d do a PR to get the change added. @philh30 could you do a PR on the library repository to make this change?

I’m not sure that PRs from the community are productive (and the Lua libraries aren’t posted in a format conducive to them). Grabbing the attention of developer support on the forum has been the best way to get these sorts of issues corrected.

Yeah, I just figured out the libraries aren’t in a public repository anyway :frowning:

Well let’s call in reinforcements in the form of @nayelyz and @andresg

Hello, I am somewhat dubious about the file st/zwave/defaults/lock.lua in the v3 Lua libs, specifically line 78 which reads:

local code_name = lock_codes[code_id] == nil and lock_codes[code_id] or "Code " .. code_id

That is supposed to extract the name of slot code_id, falling back to to ‘Code code_id’ if there isn’t a name. I would suggest that what it actually does is evaluate to ‘Code code_id’ regardless and it probably should be ‘~=’ in the first comparison.

That code is part of the default lock notification routine and it would explain why the code name isn’t making it to the event data for Z-Wave locks, which seems to have been exercising a number of users in this thread. The similar routine for Zigbee locks is expressed differently and correctly and I assume it works fine.

Would you mind running your eyes over it and reporting it if necessary?

2 Likes

To follow up here, @philh30 has addressed the issues I raised above, specifically the codeName clearing issue on the BE469, and the lock/unlock events returning a dummy codeName (i.e., “Code 5” instead of “John Doe”) in a beta driver I’ve been testing the last few days. See his post below for info.