From 9cd6597332704183ec6b8123a259cf30d2f110e2 Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Thu, 29 Aug 2024 13:54:24 -0500 Subject: [PATCH 1/6] init: add support for batteryLevel in matter lock --- .../profiles/base-lock-batteryLevel.yml | 25 +++++++++++++++++++ .../profiles/lock-lockalarm-batteryLevel.yml | 23 +++++++++++++++++ .../lock-nocodes-notamper-batterylevel.yml | 21 ++++++++++++++++ .../lock-without-codes-batteryLevel.yml | 23 +++++++++++++++++ .../nonfunctional-lock-batteryLevel.yml | 16 ++++++++++++ drivers/SmartThings/matter-lock/src/init.lua | 13 ++++++++++ 6 files changed, 121 insertions(+) create mode 100755 drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml create mode 100755 drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml create mode 100644 drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml create mode 100755 drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml create mode 100644 drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml diff --git a/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml new file mode 100755 index 0000000000..865b172357 --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml @@ -0,0 +1,25 @@ +name: base-lock +components: +- id: main + capabilities: + - id: lock + version: 1 + config: + values: + - key: "lock.value" + enabledValues: + - locked + - unlocked + - unknown + - id: lockCodes + version: 1 + - id: tamperAlert + version: 1 + - id: batteryLevel + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml new file mode 100755 index 0000000000..46c81c036a --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml @@ -0,0 +1,23 @@ +name: lock-lockalarm +components: +- id: main + capabilities: + - id: lock + version: 1 + config: + values: + - key: "lock.value" + enabledValues: + - locked + - unlocked + - unknown + - id: lockAlarm + version: 1 + - id: batteryLevel + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml new file mode 100644 index 0000000000..df8cdd2332 --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml @@ -0,0 +1,21 @@ +name: lock-nocodes-notamper +components: +- id: main + capabilities: + - id: lock + version: 1 + config: + values: + - key: "lock.value" + enabledValues: + - locked + - unlocked + - unknown + - id: batteryLevel + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml new file mode 100755 index 0000000000..812263cfce --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml @@ -0,0 +1,23 @@ +name: lock-without-codes +components: +- id: main + capabilities: + - id: lock + version: 1 + config: + values: + - key: "lock.value" + enabledValues: + - locked + - unlocked + - unknown + - id: batteryLevel + version: 1 + - id: tamperAlert + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml new file mode 100644 index 0000000000..3608430a65 --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml @@ -0,0 +1,16 @@ +name: nonfunctional-lock +components: +- id: main + capabilities: + - id: lockCodes + version: 1 + - id: tamperAlert + version: 1 + - id: batteryLevel + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/src/init.lua b/drivers/SmartThings/matter-lock/src/init.lua index a8eabfea3a..53f75a14c1 100755 --- a/drivers/SmartThings/matter-lock/src/init.lua +++ b/drivers/SmartThings/matter-lock/src/init.lua @@ -97,6 +97,16 @@ local function handle_battery_percent_remaining(driver, device, ib, response) end end +local function handle_battery_charge_level(driver, device, ib, response) + if ib.data.value == clusters.PowerSource.types.BatChargeLevelEnum.OK then + device:emit_event(capabilities.batteryLevel.battery.normal()) + elseif ib.data.value == clusters.PowerSource.types.BatChargeLevelEnum.WARNING then + device:emit_event(capabilities.batteryLevel.battery.warning()) + elseif ib.data.value == clusters.PowerSource.types.BatChargeLevelEnum.CRITICAL then + device:emit_event(capabilities.batteryLevel.battery.critical()) + end +end + local function max_pin_code_len_handler(driver, device, ib, response) device:emit_event(capabilities.lockCodes.maxCodeLength(ib.data.value, {visibility = {displayed = false}})) end @@ -573,6 +583,7 @@ local matter_lock_driver = { }, [PowerSource.ID] = { [PowerSource.attributes.BatPercentRemaining.ID] = handle_battery_percent_remaining, + [PowerSource.attributes.BatChargeLevel.ID] = handle_battery_charge_level, }, }, event = { @@ -593,6 +604,7 @@ local matter_lock_driver = { subscribed_attributes = { [capabilities.lock.ID] = {DoorLock.attributes.LockState}, [capabilities.battery.ID] = {PowerSource.attributes.BatPercentRemaining}, + [capabilities.batteryLevel.ID] = {PowerSource.attributes.BatChargeLevel}, }, subscribed_events = { [capabilities.tamperAlert.ID] = {DoorLock.events.DoorLockAlarm, DoorLock.events.LockOperation}, @@ -618,6 +630,7 @@ local matter_lock_driver = { capabilities.lockCodes, capabilities.tamperAlert, capabilities.battery, + capabilities.batteryLevel, }, sub_drivers = { require("aqara-lock"), From 3ac8cede56f51f9cd2b7a0249ce7f86644df3f26 Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Thu, 29 Aug 2024 15:52:20 -0500 Subject: [PATCH 2/6] add: wwst cert fingerprint --- drivers/SmartThings/matter-lock/fingerprints.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/SmartThings/matter-lock/fingerprints.yml b/drivers/SmartThings/matter-lock/fingerprints.yml index 9b6431b0b8..d2acaad9e2 100755 --- a/drivers/SmartThings/matter-lock/fingerprints.yml +++ b/drivers/SmartThings/matter-lock/fingerprints.yml @@ -1,4 +1,10 @@ matterManufacturer: +#Level + - id: "4767/1" + deviceLabel: Level Lock Plus (Matter) + vendorId: 0x129F + productId: 0x0001 + deviceProfileName: lock-nocodes-notamper-batteryLevel #Nuki - id: "Nuki Smart Lock Pro" deviceLabel: Nuki Smart Lock Pro From 5e95a545ae048484d71eb82343bdea42be22d29f Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Thu, 29 Aug 2024 17:02:01 -0500 Subject: [PATCH 3/6] edit: re-name 'name:' field in new profiles --- .../SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml | 2 +- .../matter-lock/profiles/lock-lockalarm-batteryLevel.yml | 2 +- .../matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml | 2 +- .../matter-lock/profiles/lock-without-codes-batteryLevel.yml | 2 +- .../matter-lock/profiles/nonfunctional-lock-batteryLevel.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml index 865b172357..8f938723e8 100755 --- a/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml @@ -1,4 +1,4 @@ -name: base-lock +name: base-lock-batteryLevel components: - id: main capabilities: diff --git a/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml index 46c81c036a..b429dcb017 100755 --- a/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml @@ -1,4 +1,4 @@ -name: lock-lockalarm +name: lock-lockalarm-batteryLevel components: - id: main capabilities: diff --git a/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml index df8cdd2332..2b81c5ca38 100644 --- a/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml @@ -1,4 +1,4 @@ -name: lock-nocodes-notamper +name: lock-nocodes-notamper-batteryLevel components: - id: main capabilities: diff --git a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml index 812263cfce..1d172bd23e 100755 --- a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml @@ -1,4 +1,4 @@ -name: lock-without-codes +name: lock-without-codes-batteryLevel components: - id: main capabilities: diff --git a/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml index 3608430a65..fc3371b31c 100644 --- a/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/nonfunctional-lock-batteryLevel.yml @@ -1,4 +1,4 @@ -name: nonfunctional-lock +name: nonfunctional-lock-batteryLevel components: - id: main capabilities: From 3611baf79b3d4f70e0424c3facf37002cfed908a Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Fri, 30 Aug 2024 09:18:08 -0500 Subject: [PATCH 4/6] remove: wwst cert info --- drivers/SmartThings/matter-lock/fingerprints.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/SmartThings/matter-lock/fingerprints.yml b/drivers/SmartThings/matter-lock/fingerprints.yml index d2acaad9e2..9b6431b0b8 100755 --- a/drivers/SmartThings/matter-lock/fingerprints.yml +++ b/drivers/SmartThings/matter-lock/fingerprints.yml @@ -1,10 +1,4 @@ matterManufacturer: -#Level - - id: "4767/1" - deviceLabel: Level Lock Plus (Matter) - vendorId: 0x129F - productId: 0x0001 - deviceProfileName: lock-nocodes-notamper-batteryLevel #Nuki - id: "Nuki Smart Lock Pro" deviceLabel: Nuki Smart Lock Pro From f035ceba7c492d90036d0ac6d9ac1a5673dea754 Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Wed, 4 Sep 2024 10:05:37 -0500 Subject: [PATCH 5/6] add: a unit test, embedded config change unknowne -> not fully locked --- .../profiles/base-lock-batteryLevel.yml | 2 +- .../profiles/lock-lockalarm-batteryLevel.yml | 2 +- ...=> lock-nocodes-notamper-batteryLevel.yml} | 2 +- .../lock-without-codes-batteryLevel.yml | 2 +- .../test/test_matter_lock_batteryLevel.lua | 89 +++++++++++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) rename drivers/SmartThings/matter-lock/profiles/{lock-nocodes-notamper-batterylevel.yml => lock-nocodes-notamper-batteryLevel.yml} (92%) create mode 100644 drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua diff --git a/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml index 8f938723e8..257a3c6e3f 100755 --- a/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/base-lock-batteryLevel.yml @@ -10,7 +10,7 @@ components: enabledValues: - locked - unlocked - - unknown + - not fully locked - id: lockCodes version: 1 - id: tamperAlert diff --git a/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml index b429dcb017..f946fd27cc 100755 --- a/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-lockalarm-batteryLevel.yml @@ -10,7 +10,7 @@ components: enabledValues: - locked - unlocked - - unknown + - not fully locked - id: lockAlarm version: 1 - id: batteryLevel diff --git a/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batteryLevel.yml similarity index 92% rename from drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml rename to drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batteryLevel.yml index 2b81c5ca38..f55fbe012c 100644 --- a/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batterylevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-nocodes-notamper-batteryLevel.yml @@ -10,7 +10,7 @@ components: enabledValues: - locked - unlocked - - unknown + - not fully locked - id: batteryLevel version: 1 - id: firmwareUpdate diff --git a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml index 1d172bd23e..3901d503d7 100755 --- a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml @@ -10,7 +10,7 @@ components: enabledValues: - locked - unlocked - - unknown + - not fully locked - id: batteryLevel version: 1 - id: tamperAlert diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua new file mode 100644 index 0000000000..38940caee8 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua @@ -0,0 +1,89 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local test = require "integration_test" +local capabilities = require "st.capabilities" +test.add_package_capability("lockAlarm.yml") +local t_utils = require "integration_test.utils" +local clusters = require "st.matter.clusters" + +local mock_device_record = { + profile = t_utils.get_profile_definition("lock-nocodes-notamper-batteryLevel.yml"), + manufacturer_info = {vendor_id = 0x101D, product_id = 0x1}, + endpoints = { + { + endpoint_id = 2, + clusters = { + {cluster_id = clusters.Basic.ID, cluster_type = "SERVER"}, + }, + device_types = { + device_type_id = 0x0016, device_type_revision = 1, -- RootNode + } + }, + { + endpoint_id = 10, + clusters = { + {cluster_id = clusters.DoorLock.ID, cluster_type = "SERVER", feature_map = 0x0000}, + {cluster_id = clusters.PowerSource.ID, cluster_type = "SERVER"}, + }, + }, + }, +} +local mock_device = test.mock_device.build_test_matter_device(mock_device_record) + + +local function test_init() + local subscribe_request = clusters.DoorLock.attributes.LockState:subscribe(mock_device) + subscribe_request:merge(clusters.PowerSource.attributes.BatChargeLevel:subscribe(mock_device)) + test.socket["matter"]:__expect_send({mock_device.id, subscribe_request}) + test.mock_device.add_test_device(mock_device) +end +test.set_test_init_function(test_init) + +test.register_message_test( + "Handle BatChargeLevel capability handling with batteryLevel.", { + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.PowerSource.attributes.BatChargeLevel:build_test_report_data( + mock_device, 10, clusters.PowerSource.types.BatChargeLevelEnum.CRITICAL + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.batteryLevel.battery.critical()), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.PowerSource.attributes.BatChargeLevel:build_test_report_data( + mock_device, 10, clusters.PowerSource.types.BatChargeLevelEnum.OK + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.batteryLevel.battery.normal()), + }, + } +) + +test.run_registered_tests() From fce33335c033ab33ff1ae6e7d4874dab71479c4b Mon Sep 17 00:00:00 2001 From: Harrison Carter Date: Wed, 4 Sep 2024 17:22:51 -0500 Subject: [PATCH 6/6] edit: move batteryLevel capabability, edit new test file --- .../lock-without-codes-batteryLevel.yml | 4 ++-- .../test/test_matter_lock_batteryLevel.lua | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml index 3901d503d7..15ce853cfd 100755 --- a/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml +++ b/drivers/SmartThings/matter-lock/profiles/lock-without-codes-batteryLevel.yml @@ -11,10 +11,10 @@ components: - locked - unlocked - not fully locked - - id: batteryLevel - version: 1 - id: tamperAlert version: 1 + - id: batteryLevel + version: 1 - id: firmwareUpdate version: 1 - id: refresh diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua index 38940caee8..22f9ccd29a 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_batteryLevel.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2024 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ local mock_device_record = { endpoint_id = 10, clusters = { {cluster_id = clusters.DoorLock.ID, cluster_type = "SERVER", feature_map = 0x0000}, - {cluster_id = clusters.PowerSource.ID, cluster_type = "SERVER"}, + {cluster_id = clusters.PowerSource.ID, cluster_type = "SERVER", feature_map = 0x0002}, }, }, }, @@ -68,6 +68,21 @@ test.register_message_test( direction = "send", message = mock_device:generate_test_message("main", capabilities.batteryLevel.battery.critical()), }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + clusters.PowerSource.attributes.BatChargeLevel:build_test_report_data( + mock_device, 10, clusters.PowerSource.types.BatChargeLevelEnum.WARNING + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.batteryLevel.battery.warning()), + }, { channel = "matter", direction = "receive",