Skip to content

Conversation

HunsupJung
Copy link
Collaborator

@HunsupJung HunsupJung commented Aug 18, 2025

Type of Change

  • WWST Certification Request
    • If this is your first time contributing code:
      • I have reviewed the README.md file
      • I have reviewed the CODE_OF_CONDUCT.md file
      • I have signed the CLA
    • I plan on entering a WWST Certification Request or have entered a request through the WWST Certification console at developer.smartthings.com
  • Bug fix
  • New feature
  • Refactor

Checklist

  • I have performed a self-review of my code
  • I have commented my code in hard-to-understand areas
  • I have verified my changes by testing with a device or have communicated a plan for testing
  • I am adding new behavior, such as adding a sub-driver, and have added and run new unit tests to cover the new behavior

Description of Change

Summary of Completed Tests

This feature was tested with following TC at SVT.

https://smartthings.atlassian.net/wiki/spaces/STHK/pages/3890216961/REQ-22348+Matter+DoorLock+Aliro+Feature+Support+TC

Copy link

github-actions bot commented Aug 18, 2025

Duplicate profile check: Warning - duplicate profiles detected.
lock-modular-embedded-unlatch.yml == lock-modular.yml

Copy link

github-actions bot commented Aug 18, 2025

Channel deleted.

Copy link

github-actions bot commented Aug 18, 2025

Test Results

   70 files    451 suites   0s ⏱️
2 344 tests 2 344 ✅ 0 💤 0 ❌
3 949 runs  3 949 ✅ 0 💤 0 ❌

Results for commit f7324c8.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Aug 18, 2025

File Coverage
All files 71%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua 64%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-lock/src/init.lua 92%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-lock/src/lock_utils.lua 98%

Minimum allowed coverage is 90%

Generated by 🐒 cobertura-action against f7324c8

@@ -2078,6 +2647,385 @@ local function handle_refresh(driver, device, command)
device:set_field(lock_utils.BUSY_STATE, false, {persist = true})
end

local function handle_set_reader_config(driver, device, command)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the plan was to remove this command from the capability and generate the Matter command directly from the driver?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you know, Kwang-Hui wants to keep this command.

@HunsupJung HunsupJung force-pushed the feature/support-aliro branch 3 times, most recently from 3058d50 to 55368aa Compare August 26, 2025 12:41
@HunsupJung HunsupJung force-pushed the feature/support-aliro branch from 8057b10 to bc14176 Compare September 2, 2025 09:17
return octet_string
end

local function octet_string_to_hex_string(octet_string)
Copy link
Contributor

@hcarter-775 hcarter-775 Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use the utils function utils.bytes_to_hex_string here instead I think, you'll just need to do the nil check handling outside of this call (which you do already).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for letting me know the function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also delete this helper, since it's no longer being used?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes, I will delete this helper.

local function set_issuer_key_response_handler(driver, device, ib, response)
local cmdName = "setIssuerKey"
local userIdx = device:get_field(lock_utils.USER_INDEX)
local userType = DoorLock.types.UserTypeEnum.UNRESTRICTED_USER
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this an unrestricted_user?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The policy is that only unrestricted user can use digital key.

Comment on lines 1759 to 1761
local status = "success"
local elements = ib.info_block.data.elements
if elements.status.value == DoorLock.types.DlStatus.SUCCESS then
Copy link
Contributor

@hcarter-775 hcarter-775 Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
local status = "success"
local elements = ib.info_block.data.elements
if elements.status.value == DoorLock.types.DlStatus.SUCCESS then
local elements = ib.info_block.data.elements
status = RESPONSE_STATUS_MAP[elements.status.value]
if status == "success" then
...
end
-- In the case DlStatus returns Occupied, this means the current credential index is in use, so we must try the next one. If there is not a next index (i.e. it is nil), we should mark this as "resourceExhausted" and stop attempting to set the credentials.
if status == "occupied" and elements.next_credential_index.value == nil then
status = "resourceExhausted"
end
if status == "occupied" then
...
else
...
end
end

I believe we should lay all the functions that are formatted like this out like this ^
The current handling where there are many different "ways" to talk about the same thing (DlStatus in this case) is difficult to understand and hard to maintain

@hcarter-775
Copy link
Contributor

Hi @HunsupJung , I just made some initial comments not changing the handling of your code, but rather trying to maintain a more uniform code standard for readability and maintainability. I think it will be much easier to read and review once the above suggestions for writing have been implemented across the new code.

Copy link
Contributor

@hcarter-775 hcarter-775 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some more comments about general handling, with a couple concerns for how the credential handling works

@@ -1598,12 +2102,14 @@ local function clear_credential_response_handler(driver, device, ib, response)
status = "invalidCommand"
end

-- Delete User in table
-- Delete Pin in table
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this handler, in the event we have a failed status, why would we update the commandResult with a 0 userIndex? Wouldn't it be more accurate not to send the capability any data on this index?

Further, per the capability def:

           userIndex:
              type: integer
              minimum: 1

so this should not be allowed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, in the case that the credIdx is ALL_INDEX, aren't we returning a nil index to userIndex?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is good checking point. Actually, now there is no case for using ALL_INDEX, so I will modify it to returning a nil index to user Index for it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I believe this makes sense 👍

Comment on lines 2224 to 2233
local function clear_credential_response_handler(driver, device, ib, response)
local cmdName = device:get_field(lock_utils.COMMAND_NAME)
if cmdName == "deleteCredential" then
delete_pin_response_handler(driver, device, ib, response)
elseif cmdName == "clearIssuerKey" then
clear_issuer_key_response_handler(driver, device, ib, response)
elseif cmdName == "clearEndpointKey" then
clear_endpoint_key_response_handler(driver, device, ib, response)
end
end
Copy link
Contributor

@hcarter-775 hcarter-775 Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
local function clear_credential_response_handler(driver, device, ib, response)
local cmdName = device:get_field(lock_utils.COMMAND_NAME)
if cmdName == "deleteCredential" then
delete_pin_response_handler(driver, device, ib, response)
elseif cmdName == "clearIssuerKey" then
clear_issuer_key_response_handler(driver, device, ib, response)
elseif cmdName == "clearEndpointKey" then
clear_endpoint_key_response_handler(driver, device, ib, response)
end
end
local function clear_credential_response_handler(driver, device, ib, response)
local cmdName = device:get_field(lock_utils.COMMAND_NAME)
if cmdName ~= "deleteCredential" and cmdName ~= "clearEndpointKey" and cmdName ~= "clearIssuerKey" then
return
end
local status = RESPONSE_STATUS_MAP[ib.status]
if status ~= "failure" and status ~= "invalidCommand" then
status = "success" -- treat all non-failure and non-invalid statuses as a success
end
local command_result_info = { commandName = cmdName, statusCode = status } -- default command result
local userIdx = device:get_field(lock_utils.USER_INDEX)
local credentials_successfully_removed = false
if cmdName == "deleteCredential" and status == "success" then
-- Get result from data saved in relevant, associated fields
local credIdx = device:get_field(lock_utils.CRED_INDEX)
-- find userIdx associated with credIdx, don't use lock utils field in this case
userIdx = 0
userIdx = delete_credential_from_table(device, credIdx)
if userIdx ~= 0 then
credentials_successfully_removed = not has_credentials(device, userIdx)
end
-- set unique command result fields
command_result_info.userIndex = userIdx
command_result_info.credentialIndex = credIdx
elseif cmdName == "clearIssuerKey" and status == "success" then
-- Get result from data saved in relevant, associated fields
local reqId = device:get_field(lock_utils.COMMAND_REQUEST_ID)
delete_aliro_from_table(device, userIdx, "issuerKey", nil)
credentials_successfully_removed = not has_credentials(device, userIdx)
-- set unique command result fields
command_result_info.userIndex = userIdx
command_result_info.requestId = reqId
elseif cmdName == "clearEndpointKey" and status == "success" then
-- Get result from data saved in relevant, associated fields
local deviceKeyId = device:get_field(lock_utils.DEVICE_KEY_ID)
local keyType = device:get_field(lock_utils.ENDPOINT_KEY_TYPE)
local reqId = device:get_field(lock_utils.COMMAND_REQUEST_ID)
delete_aliro_from_table(device, userIdx, keyType, deviceKeyId)
credentials_successfully_removed = not has_credentials(device, userIdx)
-- set unique command result fields
command_result_info.userIndex = userIdx
command_result_info.keyId = deviceKeyId
command_result_info.requestId = reqId
end
-- user data if credentials were removed
if credentials_successfully_removed then
delete_user_from_table(device, userIdx)
delete_week_schedule_from_table_as_user(device, userIdx)
delete_year_schedule_from_table_as_user(device, userIdx)
end
-- Update commandResult
if cmdName == "deleteCredential" then
device:emit_event(capabilities.lockCredentials.commandResult(
command_result_info,
{ state_change = true, visibility = {displayed = false} }
))
else
device:emit_event(capabilities.lockAliro.commandResult(
command_result_info,
{ state_change = true, visibility = {displayed = false} }
))
end
device:set_field(lock_utils.BUSY_STATE, false, {persist = true})
end

Based on all the related logic across the sub-functions, I almost think this formatting would make more sense.

Copy link
Contributor

@hcarter-775 hcarter-775 Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wonder about this gate that occurs in all 3 cases: if has_credentials(device, userIdx) == false then ... end. I'm wondering what will happen when has_credentials evaluates to true? It looks like the data would have been removed on the device (considering we are getting a success response) but in this case we haven't removed this data on our end?

Since this is how the credential removal will work moving forward, I wonder what this check is actually for?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is this deleteCredential command how we will handle deletion for all cases moving forward? Since before, we were using deleteUser, I wonder how this might change our handling.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know I understand what you said perfectly.
Plugin team will use deleteCredential instead of deleteUser in R4.

Copy link
Collaborator Author

@HunsupJung HunsupJung Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering what will happen when has_credentials evaluates to true?

We need to keep the user and schedule data, so if has_credentials is true, we do nothing.

Copy link
Contributor

@hcarter-775 hcarter-775 Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know I understand what you said perfectly.
Plugin team will use deleteCredential instead of deleteUser in R4.

OK, that's fine. Thanks for confirming.

We need to keep the user and schedule data, so if has_credentials is true, we do nothing.

Oh ok, I understand now. We're doing this since there are multiple ways for data to be stored for a user. So even a successful credential deletion doesn't mean all credentials are removed.

Given this new understanding, I would change my suggested variable name in the refactor from credentials_successfully_removed to all_user_credentials_removed

HunsupJung and others added 3 commits September 11, 2025 15:40
Signed-off-by: Hunsup Jung <[email protected]>
 - Replace new function to existing function
 - Rename check_busy_state to is_busy_state_set
 - Rename some variables clearly
 - Remove unnecessary logic

Signed-off-by: Hunsup Jung <[email protected]>
@HunsupJung HunsupJung force-pushed the feature/support-aliro branch from 63e6f9f to 7b65e7f Compare September 11, 2025 09:39
@hcarter-775
Copy link
Contributor

@HunsupJung Sure you are aware, but the CI needs to be passing before we can merge this PR 👍

@HunsupJung HunsupJung merged commit df2fc59 into main Sep 17, 2025
12 checks passed
@HunsupJung HunsupJung deleted the feature/support-aliro branch September 17, 2025 12:31
hcarter-775 added a commit that referenced this pull request Sep 17, 2025
hcarter-775 added a commit that referenced this pull request Sep 17, 2025
* Updating matter rvc ux (#2343)

Signed-off-by: HunsupJung <[email protected]>

* Update matter-rvc driver (#2400)

- Replace Embedded device configuration with Device presentation to support translation
 - If selected_area is empty, selecting all areas

Signed-off-by: HunsupJung <[email protected]>

* Update new-matter-lock driver to support Aliro feature (#2344)

Signed-off-by: Hunsup Jung <[email protected]>
Co-authored-by: Harrison Carter <[email protected]>

---------

Signed-off-by: HunsupJung <[email protected]>
Signed-off-by: Hunsup Jung <[email protected]>
Co-authored-by: HunsupJung <[email protected]>
hcarter-775 added a commit that referenced this pull request Sep 17, 2025
hcarter-775 added a commit that referenced this pull request Sep 17, 2025
…pport (#2406)

* Updating matter rvc ux (#2343)

Signed-off-by: HunsupJung <[email protected]>

* Update matter-rvc driver (#2400)

- Replace Embedded device configuration with Device presentation to support translation
 - If selected_area is empty, selecting all areas

Signed-off-by: HunsupJung <[email protected]>

* Update new-matter-lock driver to support Aliro feature (#2344)

Signed-off-by: Hunsup Jung <[email protected]>
Co-authored-by: Harrison Carter <[email protected]>

---------

Signed-off-by: HunsupJung <[email protected]>
Signed-off-by: Hunsup Jung <[email protected]>
Co-authored-by: HunsupJung <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants