Skip to content

Commit f317c94

Browse files
Wait for Max PIN length before generating credentials
This change fixes a bug where if the handler for `RequirePINforRemoteOperation` runs before the `maxCodeLength` attribute of the `lockCodes` capability is set, a default pin length of 4 would be used, which may be shorter than the minimum pin length of the device specified by the `MinPINCodeLength` attribute. Therefore, the read was removed from `init` and `added`, and was moved to the handler for `MaxPINCodeLength` to guarantee that the max pin length is known before attempting to generate the COTA credential.
1 parent d69565d commit f317c94

File tree

7 files changed

+48
-33
lines changed

7 files changed

+48
-33
lines changed

drivers/SmartThings/matter-lock/src/init.lua

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ end
143143

144144
local function max_pin_code_len_handler(driver, device, ib, response)
145145
device:emit_event(capabilities.lockCodes.maxCodeLength(ib.data.value, {visibility = {displayed = false}}))
146+
-- Device may require pin for remote operation if it supports COTA and PIN features.
147+
local eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.DoorLockFeature.CREDENTIALSOTA | DoorLock.types.DoorLockFeature.PIN_CREDENTIALS})
148+
if #eps == 0 then
149+
device.log.debug("Device will not require PIN for remote operation")
150+
device:set_field(lock_utils.COTA_CRED, false, {persist = true})
151+
else
152+
device:send(DoorLock.attributes.RequirePINforRemoteOperation:read(device, eps[1]))
153+
end
146154
end
147155

148156
local function min_pin_code_len_handler(driver, device, ib, response)
@@ -598,22 +606,9 @@ local function do_configure(driver, device)
598606
end
599607

600608
local function device_init(driver, device)
609+
lock_utils.check_field_name_updates(device)
601610
device:set_component_to_endpoint_fn(component_to_endpoint)
602611
device:subscribe()
603-
604-
-- check if we have a missing COTA credential. Only run this if it has not been run before (i.e. in device added),
605-
-- because there is a delay built into the COTA process and we do not want to start two COTA generations at the same time
606-
-- in the event this was triggered on add.
607-
if not device:get_field(lock_utils.COTA_READ_INITIALIZED) or not device:get_field(lock_utils.COTA_CRED) then
608-
local eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.DoorLockFeature.CREDENTIALSOTA | DoorLock.types.DoorLockFeature.PIN_CREDENTIALS})
609-
if #eps == 0 then
610-
device.log.debug("Device will not require PIN for remote operation")
611-
device:set_field(lock_utils.COTA_CRED, false, {persist = true})
612-
else
613-
device:send(DoorLock.attributes.RequirePINforRemoteOperation:read(device, eps[1]))
614-
device:set_field(lock_utils.COTA_READ_INITIALIZED, true, {persist = true})
615-
end
616-
end
617612
end
618613

619614
local function device_added(driver, device)
@@ -645,16 +640,6 @@ local function device_added(driver, device)
645640
command = capabilities.lockCodes.commands.reloadAllCodes.NAME,
646641
args = {}
647642
})
648-
649-
--Device may require pin for remote operation if it supports COTA and PIN features.
650-
eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.DoorLockFeature.CREDENTIALSOTA | DoorLock.types.DoorLockFeature.PIN_CREDENTIALS})
651-
if #eps == 0 then
652-
device.log.debug("Device will not require PIN for remote operation")
653-
device:set_field(lock_utils.COTA_CRED, false, {persist = true})
654-
else
655-
req:merge(DoorLock.attributes.RequirePINforRemoteOperation:read(device, eps[1]))
656-
device:set_field(lock_utils.COTA_READ_INITIALIZED, true, {persist = true})
657-
end
658643
device:send(req)
659644
end
660645
end

drivers/SmartThings/matter-lock/src/lock_utils.lua

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ local lock_utils = {
2525
COTA_CODE_NAME = "ST Remote Operation Code",
2626
COTA_CRED_INDEX = "cotaCredIndex",
2727
NONFUNCTIONAL = "nonFunctional",
28-
COTA_READ_INITIALIZED = "cotaReadInitialized",
2928
BUSY_STATE = "busyState",
3029
COMMAND_NAME = "commandName",
3130
USER_NAME = "userName",
@@ -99,6 +98,21 @@ function lock_utils.code_deleted(device, code_slot)
9998
return lock_codes
10099
end
101100

101+
local updated_fields = {
102+
{ current_field_name = "cotaReadInitialized", updated_field_name = nil }
103+
}
104+
105+
function lock_utils.check_field_name_updates(device)
106+
for _, field in ipairs(updated_fields) do
107+
if device:get_field(field.current_field_name) then
108+
if field.updated_field_name ~= nil then
109+
device:set_field(field.updated_field_name, device:get_field(field.current_field_name), {persist = true})
110+
end
111+
device:set_field(field.current_field_name, nil)
112+
end
113+
end
114+
end
115+
102116
--[[]]
103117
-- keys are the code slots that ST uses
104118
-- user_index and credential_index are used in the matter commands

drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ local subscribed_attributes = {
7070
[capabilities.lockCredentials.ID] = {
7171
DoorLock.attributes.NumberOfPINUsersSupported,
7272
DoorLock.attributes.MaxPINCodeLength,
73-
DoorLock.attributes.MinPINCodeLength,
74-
DoorLock.attributes.RequirePINforRemoteOperation
73+
DoorLock.attributes.MinPINCodeLength
7574
},
7675
[capabilities.lockSchedules.ID] = {
7776
DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser,
@@ -298,6 +297,14 @@ end
298297
-------------------------
299298
local function max_pin_code_len_handler(driver, device, ib, response)
300299
device:emit_event(capabilities.lockCredentials.maxPinCodeLen(ib.data.value, {visibility = {displayed = false}}))
300+
-- Device may require pin for remote operation if it supports COTA and PIN features.
301+
local eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.DoorLockFeature.CREDENTIALSOTA | DoorLock.types.DoorLockFeature.PIN_CREDENTIALS})
302+
if #eps == 0 then
303+
device.log.debug("Device will not require PIN for remote operation")
304+
device:set_field(lock_utils.COTA_CRED, false, {persist = true})
305+
else
306+
device:send(DoorLock.attributes.RequirePINforRemoteOperation:read(device, eps[1]))
307+
end
301308
end
302309

303310
--------------------------------------

drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ local function test_init()
5858
subscribe_request:merge(clusters.DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device))
5959
subscribe_request:merge(clusters.DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device))
6060
subscribe_request:merge(clusters.DoorLock.attributes.MinPINCodeLength:subscribe(mock_device))
61-
subscribe_request:merge(clusters.DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device))
6261
subscribe_request:merge(clusters.DoorLock.events.LockOperation:subscribe(mock_device))
6362
subscribe_request:merge(clusters.DoorLock.events.DoorLockAlarm:subscribe(mock_device))
6463
subscribe_request:merge(clusters.DoorLock.events.LockUserChange:subscribe(mock_device))

drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ local function test_init()
7070
subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device))
7171
subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device))
7272
test.socket["matter"]:__expect_send({mock_device.id, subscribe_request})
73-
test.socket.matter:__expect_send({mock_device.id, DoorLock.attributes.RequirePINforRemoteOperation:read(mock_device, 10)})
7473
test.mock_device.add_test_device(mock_device)
7574
end
7675

@@ -108,8 +107,8 @@ local function expect_kick_off_cota_process(device)
108107
local req = DoorLock.attributes.MaxPINCodeLength:read(device, 10)
109108
req:merge(DoorLock.attributes.MinPINCodeLength:read(device, 10))
110109
req:merge(DoorLock.attributes.NumberOfPINUsersSupported:read(device, 10))
111-
req:merge(DoorLock.attributes.RequirePINforRemoteOperation:read(device, 10))
112110
test.socket.matter:__expect_send({device.id, req})
111+
113112
expect_reload_all_codes_messages(device)
114113
test.wait_for_events()
115114

@@ -119,6 +118,19 @@ local function expect_kick_off_cota_process(device)
119118
DoorLock.attributes.NumberOfPINUsersSupported:build_test_report_data(device, 10, 16),
120119
})
121120

121+
test.wait_for_events()
122+
test.socket.matter:__queue_receive({
123+
device.id,
124+
DoorLock.attributes.MaxPINCodeLength:build_test_report_data(device, 10, 8),
125+
})
126+
test.socket.capability:__expect_send(
127+
device:generate_test_message(
128+
"main",
129+
capabilities.lockCodes.maxCodeLength(8, {visibility = {displayed = false}})
130+
)
131+
)
132+
test.socket.matter:__expect_send({device.id, DoorLock.attributes.RequirePINforRemoteOperation:read(device, 10)})
133+
122134
-- The creation of advance timers, advancing time, and waiting for events
123135
-- is done to ensure a correct order of operations and allow for all the
124136
-- `call_with_delay(0, ...)` calls to execute at the correct time.

drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ local function test_init()
6161
subscribe_request:merge(DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device))
6262
subscribe_request:merge(DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device))
6363
subscribe_request:merge(DoorLock.attributes.MinPINCodeLength:subscribe(mock_device))
64-
subscribe_request:merge(DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device))
6564
subscribe_request:merge(DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser:subscribe(mock_device))
6665
subscribe_request:merge(DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser:subscribe(mock_device))
6766
subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device))
@@ -232,6 +231,7 @@ test.register_coroutine_test(
232231
test.socket.capability:__expect_send(
233232
mock_device:generate_test_message("main", capabilities.lockCredentials.maxPinCodeLen(8, {visibility = {displayed = false}}))
234233
)
234+
test.socket.matter:__expect_send({mock_device.id, DoorLock.attributes.RequirePINforRemoteOperation:read(mock_device, 1)})
235235
end
236236
)
237237

drivers/SmartThings/matter-lock/src/test/test_new_matter_lock_battery.lua

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ local function test_init_user_pin()
198198
subscribe_request:merge(DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device_user_pin))
199199
subscribe_request:merge(DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device_user_pin))
200200
subscribe_request:merge(DoorLock.attributes.MinPINCodeLength:subscribe(mock_device_user_pin))
201-
subscribe_request:merge(DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device_user_pin))
202201
subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device_user_pin))
203202
subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device_user_pin))
204203
subscribe_request:merge(DoorLock.events.LockUserChange:subscribe(mock_device_user_pin))
@@ -213,7 +212,6 @@ local function test_init_user_pin_schedule_unlatch()
213212
subscribe_request:merge(DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device_user_pin_schedule_unlatch))
214213
subscribe_request:merge(DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device_user_pin_schedule_unlatch))
215214
subscribe_request:merge(DoorLock.attributes.MinPINCodeLength:subscribe(mock_device_user_pin_schedule_unlatch))
216-
subscribe_request:merge(DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device_user_pin_schedule_unlatch))
217215
subscribe_request:merge(DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser:subscribe(mock_device_user_pin_schedule_unlatch))
218216
subscribe_request:merge(DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser:subscribe(mock_device_user_pin_schedule_unlatch))
219217
subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device_user_pin_schedule_unlatch))

0 commit comments

Comments
 (0)