Handling Duplicate CodePins in the SmartThings Lock Codes API

Hi SmartThings Community,

I’m encountering an issue while setting lock codes using the SmartThings CLI and API. Here’s the situation:

I use the following command to set a code for a specific slot:

const command = {
  component: 'main',
  capability: 'lockCodes',
  command: 'setCode',
  arguments: [slot, code, name],
};

await client.devices.executeCommand(stDeviceUuid, command);

If the codePin I’m trying to set is already in use for another slot, the API response returns a 200 status with the message “ACCEPTED.” However, when I check the SmartThings account, I see that the lock code appears in another slot, but with a status of “failed,” indicating the operation wasn’t successful.

Here’s the webhook event I receive in response:

{
  "event": {
    "eventTime": "2024-12-02T13:08:55Z",
    "eventType": "DEVICE_EVENT",
    "deviceEvent": {
      "eventId": "95e14029-b0ae-11ef-a59b-73b611cd0233",
      "locationId": "b8061385-4f6c-4597-bfd4-084e6ec6a1a5",
      "ownerId": "b8061385-4f6c-4597-bfd4-084e6ec6a1a5",
      "ownerType": "LOCATION",
      "deviceId": "127cf400-e486-4889-a8a5-31caa15b1cbd",
      "componentId": "main",
      "capability": "lockCodes",
      "attribute": "codeChanged",
      "value": "1 failed",
      "valueType": "string",
      "stateChange": true,
      "data": {},
      "subscriptionName": "deviceCodeChanged"
    }
  }
}

My Questions:

  1. Is there a way to pass custom metadata when using the setCode command so I can track additional context in the webhook event?
  2. Can I fetch more details about the failure using the eventId provided in the webhook event?
  3. What is the best way to handle duplicate codePin errors programmatically, given the current API behavior?

Thanks in advance for any insights!

Hi, @Yaroslav_Mudryi
Have you verified the format of the commant you sent using the function executeCommand is correct?

The API’s response will always be 200 if no obvious errors are detected with the request but it won’t wait until it’s completed to give you a response on the execution.

No, the webhook event is generated with pre-defined attributes about the event that changed the attribute’s status, but what kind of “custom metadata” did you want to add?

No, that ID is only for internal use, we could use it to find the event logs in case there’s an issue

Do you mean to know that the exact reason it failed was due to the codePin being duplicated? I would need to ask the engineering team.

Thank you for your response and insights! Let me provide additional context about my scenario to clarify the challenges I’m facing:
Our app creates codes for devices and stores them in a database with attributes such as code, slot, and stDeviceUuid. We use this information to control and monitor the state of codes we’ve created.

Here’s the issue I’m running into:
When I already have a code stored on my SmartThings account with slot 1 and codePin 1234, and I attempt to create a new code with the same codePin but for slot 2, the executeCommand response is 200 ACCEPTED. However, after execution completes on the SmartThings platform, I receive a webhook with a message indicating that the code in slot 1 failed.

The challenge is that in my database, I don’t have any record of a code in slot 1, so I can’t directly correlate this failure to the code I just attempted to set in slot 2. This creates a gap in handling the failure programmatically.

My Questions:

  1. How can I identify that the code I recently attempted to set (in this case, for slot 2) failed?
    Is there any metadata or additional status tracking method that I can use to correlate the webhook event with the code I recently set?
  2. Is there a method or API I can use to fetch all the current codes and their statuses for a device?
    This would allow me to compare the SmartThings account state with my database and handle discrepancies or errors accordingly.

Let me know if there’s anything you’d like to adjust or clarify further!

Thank you for the details, this provides a better insight.

I’ll check this with the engineering team now that you provided more context, but I think the option below can help with your case.

The lockCodes capability has the following commands available, which you could use to get the configuration of those slots:

  • reloadAllCodes is intended to go through every index on the lock and re-build our understanding of which codes are set on the lock.
  • requestCode is meant to go ask the lock for what is set at a specific index.

Please let me know if you get a good response from those commands since it could depend on what is controlling the device.

You can also look at the capability status for the lockCodes which will include an array of the current codeSlots and corresponding codeNames that the lock driver has available. By using the commands @nayelyz suggested to refresh the lockCodes capability and then using the capability status, you will have a complete picture of all the codes that a lock believes are set and the slotName currently assigned in the driver.

bep@debian12:~$ smartthings devices:capability-status 72
───────────────────
 #  Id             
───────────────────
 1  main (default) 
 2  settings       
───────────────────
? Select a component. 1
────────────────────────────────────────
 #  Id                                  
────────────────────────────────────────
 1  battery                             
 2  lock                                
 3  lockCodes                           
 4  platinummassive43262.unlockCodeName 
 5  refresh                             
────────────────────────────────────────
 6  tamperAlert                         
────────────────────────────────────────
? Select a capability. 3
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Attribute      Value                                                                                                                                                         
 codeLength     6                                                                                                                                                             
 maxCodes       30                                                                                                                                                            
 maxCodeLength                                                                                                                                                                
 codeChanged    "1 changed"                                                                                                                                                   
 lock                                                                                                                                                                         
 minCodeLength  8                                                                                                                                                             
 codeReport                                                                                                                                                                   
 scanCodes      "Complete"                                                                                                                                                    
 lockCodes      "{\"1\":\"Bruce and Teri\",\"2\":\"Gladys\",\"3\":\"Sean\",\"4\":\"Studio Guest\",\"5\":\"Jeremy\",\"6\":\"Maddie Davis\",\"7\":\"Lyss\",\"8\":\"Michelle\"}" 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 Like

We’ve seen performing a reloadAllCodes clears the known names in ST and results in all slots being named things like “Code 1”, “Code 2”, etc. This is the case even when setting and viewing these codes using Smart Lock Guest Access, once you run that command the names are gone.

So I don’t think that’s a viable solution, even without running the reloadAllCodes command, knowing the name of slot 1 or slot 2 does not help in this situation. I agree with Yaroslav that the error he receives should be a failure to set slot 2, not slot 1.

@nayelyz Hello. Any news ?)

Hi, @gjanes
I remember this issue was reported a while ago and was solved, this is the post where this was discussed: Correct Z-Wave Lock API Command - #12 by Jake_Mohl

So, I’m curious, do you have access to the device that has this behavior? It would be interesting how that command it’s handled by its driver.
That can be done by opening the listener for driver logs using the CLI’s command smartthings edge:drivers:logcat

@Yaroslav_Mudryi did you test any of the suggestions?

  1. Mine: use the commands “reloadAllCodes” and “requestCode”
  2. From @h0ckeysk8er: Look at the capability status for the lockCodes which will include an array of the current codeSlots

I’ve never really worked with locks, except that I once contributed to debugging the Lua library by identifying an incorrect complex conditional.

From the outside looking in it seems that if there is only one ID in the notification then telling you something you already know (which is that you just tried to set a new code on slot 2) is less useful than telling you something you didn’t know, which was that there was already a duplicate code in slot 1. So due to an issue with slot 1 the request to add a new code in slot 2 failed due to a duplicate code (which is what failed means).