Skip to content

Commit

Permalink
Update matter-lock driver for U-tec
Browse files Browse the repository at this point in the history
Signed-off-by: Hunsup Jung <[email protected]>
  • Loading branch information
HunsupJung committed Dec 10, 2024
1 parent 3a3295a commit e386b18
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 3 deletions.
6 changes: 6 additions & 0 deletions drivers/SmartThings/matter-lock/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ matterManufacturer:
vendorId: 0x135D
productId: 0x00A1
deviceProfileName: lock-nocodes-notamper
# U-tec
- id: "U-tec"
deviceLabel: U-tec
vendorId: 0x147F
productId: 0x0001
deviceProfileName: lock-user-pin-batteryLevel
matterGeneric:
- id: "matter/door-lock"
deviceLabel: Matter Door Lock
Expand Down
29 changes: 29 additions & 0 deletions drivers/SmartThings/matter-lock/profiles/lock-user-pin-battery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: lock-user-pin-battery
components:
- id: main
capabilities:
- id: lock
version: 1
config:
values:
- key: "lock.value"
enabledValues:
- locked
- unlocked
- not fully locked
- id: lockAlarm
version: 1
- id: remoteControlStatus
version: 1
- id: lockUsers
version: 1
- id: lockCredentials
version: 1
- id: battery
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: SmartLock
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: lock-user-pin-batteryLevel
components:
- id: main
capabilities:
- id: lock
version: 1
config:
values:
- key: "lock.value"
enabledValues:
- locked
- unlocked
- not fully locked
- id: lockAlarm
version: 1
- id: remoteControlStatus
version: 1
- id: lockUsers
version: 1
- id: lockCredentials
version: 1
- id: batteryLevel
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: SmartLock
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: lock-user-pin-schedule-battery
components:
- id: main
capabilities:
- id: lock
version: 1
config:
values:
- key: "lock.value"
enabledValues:
- locked
- unlocked
- not fully locked
- id: lockAlarm
version: 1
- id: remoteControlStatus
version: 1
- id: lockUsers
version: 1
- id: lockCredentials
version: 1
- id: lockSchedules
version: 1
- id: battery
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: SmartLock
76 changes: 73 additions & 3 deletions drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@ if version.api < 10 then
end

local DoorLock = clusters.DoorLock
local PowerSource = clusters.PowerSource
local INITIAL_COTA_INDEX = 1
local ALL_INDEX = 0xFFFE

local NEW_MATTER_LOCK_PRODUCTS = {
{0x115f, 0x2802}, -- AQARA, U200
{0x115f, 0x2801}, -- AQARA, U300
{0x147F, 0x0001}, -- U-tec
{0x10E1, 0x2002} -- VDA
}

local PROFILE_BASE_NAME = "__profile_base_name"

local subscribed_attributes = {
[capabilities.lock.ID] = {
DoorLock.attributes.LockState
Expand All @@ -53,6 +57,12 @@ local subscribed_attributes = {
[capabilities.lockSchedules.ID] = {
DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser,
DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser
},
[capabilities.battery.ID] = {
PowerSource.attributes.BatPercentRemaining
},
[capabilities.batteryLevel.ID] = {
PowerSource.attributes.BatChargeLevel
}
}

Expand Down Expand Up @@ -126,6 +136,7 @@ local function do_configure(driver, device)
local pin_eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.Feature.PIN_CREDENTIAL})
local week_schedule_eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.Feature.WEEK_DAY_ACCESS_SCHEDULES})
local year_schedule_eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.Feature.YEAR_DAY_ACCESS_SCHEDULES})
local battery_eps = device:get_endpoints(PowerSource.ID, {feature_bitmap = PowerSource.types.PowerSourceFeature.BATTERY})

local profile_name = "lock"
if #user_eps > 0 then
Expand All @@ -137,8 +148,16 @@ local function do_configure(driver, device)
profile_name = profile_name .. "-schedule"
end
end
device.log.info(string.format("Updating device profile to %s.", profile_name))
device:try_update_metadata({profile = profile_name})

if #battery_eps > 0 then
device:set_field(PROFILE_BASE_NAME, profile_name, {persist = true})
local req = im.InteractionRequest(im.InteractionRequest.RequestType.READ, {})
req:merge(clusters.PowerSource.attributes.AttributeList:read())
device:send(req)
else
device.log.info(string.format("Updating device profile to %s.", profile_name))
device:try_update_metadata({profile = profile_name})
end
end

local function info_changed(driver, device, event, args)
Expand Down Expand Up @@ -340,6 +359,49 @@ local function max_year_schedule_of_user_handler(driver, device, ib, response)
device:emit_event(capabilities.lockSchedules.yearDaySchedulesPerUser(ib.data.value, {visibility = {displayed = false}}))
end

---------------------------------
-- Power Source Attribute List --
---------------------------------
local function handle_power_source_attribute_list(driver, device, ib, response)
local support_battery_percentage = false
for _, attr in ipairs(ib.data.elements) do
-- Re-profile the device if BatPercentRemaining (Attribute ID 0x0C) is present.
if attr.value == 0x0C then
support_battery_percentage = true
end
end
local profile_name = device:get_field(PROFILE_BASE_NAME)
if support_battery_percentage then
profile_name = profile_name .. "-battery"
else
profile_name = profile_name .. "-batteryLevel"
end
device.log.info(string.format("Updating device profile to %s.", profile_name))
device:try_update_metadata({profile = profile_name})
end

-------------------------------
-- Battery Percent Remaining --
-------------------------------
local function handle_battery_percent_remaining(driver, device, ib, response)
if ib.data.value ~= nil then
device:emit_event(capabilities.battery.battery(math.floor(ib.data.value / 2.0 + 0.5)))
end
end

--------------------------
-- Battery Charge Level --
--------------------------
local function handle_battery_charge_level(driver, device, ib, response)
if ib.data.value == PowerSource.types.BatChargeLevelEnum.OK then
device:emit_event(capabilities.batteryLevel.battery.normal())
elseif ib.data.value == PowerSource.types.BatChargeLevelEnum.WARNING then
device:emit_event(capabilities.batteryLevel.battery.warning())
elseif ib.data.value == PowerSource.types.BatChargeLevelEnum.CRITICAL then
device:emit_event(capabilities.batteryLevel.battery.critical())
end
end

-- Capability Handler
-----------------
-- Lock/Unlock --
Expand Down Expand Up @@ -1634,6 +1696,11 @@ local new_matter_lock_handler = {
[DoorLock.attributes.RequirePINforRemoteOperation.ID] = require_remote_pin_handler,
[DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser.ID] = max_week_schedule_of_user_handler,
[DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser.ID] = max_year_schedule_of_user_handler,
},
[PowerSource.ID] = {
[PowerSource.attributes.AttributeList.ID] = handle_power_source_attribute_list,
[PowerSource.attributes.BatPercentRemaining.ID] = handle_battery_percent_remaining,
[PowerSource.attributes.BatChargeLevel.ID] = handle_battery_charge_level,
}
},
event = {
Expand Down Expand Up @@ -1685,7 +1752,10 @@ local new_matter_lock_handler = {
capabilities.lock,
capabilities.lockUsers,
capabilities.lockCredentials,
capabilities.lockSchedules
capabilities.lockSchedules,
capabilities.remoteControlStatus,
capabilities.battery,
capabilities.batteryLevel
},
can_handle = is_new_matter_lock_products
}
Expand Down

0 comments on commit e386b18

Please sign in to comment.