diff --git a/drivers/SmartThings/matter-lock/fingerprints.yml b/drivers/SmartThings/matter-lock/fingerprints.yml index e8e5f86be1..30ca4a4352 100755 --- a/drivers/SmartThings/matter-lock/fingerprints.yml +++ b/drivers/SmartThings/matter-lock/fingerprints.yml @@ -4,12 +4,12 @@ matterManufacturer: deviceLabel: Aqara Smart Lock U200 vendorId: 0x115F productId: 0x2802 - deviceProfileName: lock-lockalarm-nobattery + deviceProfileName: lock-user-pin - id: "4447/10241" deviceLabel: Aqara Smart Lock U300 vendorId: 0x115F productId: 0x2801 - deviceProfileName: lock-lockalarm-nobattery + deviceProfileName: lock-user-pin #Level - id: "4767/1" deviceLabel: Level Lock Plus (Matter) diff --git a/drivers/SmartThings/matter-lock/profiles/lock-user-pin-schedule.yml b/drivers/SmartThings/matter-lock/profiles/lock-user-pin-schedule.yml new file mode 100644 index 0000000000..d27423f2b8 --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-user-pin-schedule.yml @@ -0,0 +1,29 @@ +name: lock-user-pin-schedule +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: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock-user-pin.yml b/drivers/SmartThings/matter-lock/profiles/lock-user-pin.yml new file mode 100644 index 0000000000..8a48917392 --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-user-pin.yml @@ -0,0 +1,27 @@ +name: lock-user-pin +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: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock-user-schedule.yml b/drivers/SmartThings/matter-lock/profiles/lock-user-schedule.yml new file mode 100644 index 0000000000..e4e9daf65a --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-user-schedule.yml @@ -0,0 +1,27 @@ +name: lock-user-schedule +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: lockSchedules + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock-user.yml b/drivers/SmartThings/matter-lock/profiles/lock-user.yml new file mode 100644 index 0000000000..07ca0dd74e --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock-user.yml @@ -0,0 +1,25 @@ +name: lock-user +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: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/profiles/lock.yml b/drivers/SmartThings/matter-lock/profiles/lock.yml new file mode 100644 index 0000000000..9f0bf30a43 --- /dev/null +++ b/drivers/SmartThings/matter-lock/profiles/lock.yml @@ -0,0 +1,23 @@ +name: lock +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: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: SmartLock diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetCredentialStatusResponse.lua b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetCredentialStatusResponse.lua new file mode 100644 index 0000000000..70d0a6eff1 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetCredentialStatusResponse.lua @@ -0,0 +1,129 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetCredentialStatusResponse = {} + +GetCredentialStatusResponse.NAME = "GetCredentialStatusResponse" +GetCredentialStatusResponse.ID = 0x0025 +GetCredentialStatusResponse.field_defs = { + { + name = "credential_exists", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Boolean", + }, + { + name = "user_index", + field_id = 1, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "creator_fabric_index", + field_id = 2, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "last_modified_fabric_index", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "next_credential_index", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function GetCredentialStatusResponse:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetCredentialStatusResponse:build_test_command_response(device, endpoint_id, credential_exists, user_index, creator_fabric_index, last_modified_fabric_index, next_credential_index, interaction_status) + local function init(self, device, endpoint_id, credential_exists, user_index, creator_fabric_index, last_modified_fabric_index, next_credential_index) + local out = {} + local args = {credential_exists, user_index, creator_fabric_index, last_modified_fabric_index, next_credential_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetCredentialStatusResponse, + __tostring = GetCredentialStatusResponse.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) + end + local self_request = init(self, device, endpoint_id, credential_exists, user_index, creator_fabric_index, last_modified_fabric_index, next_credential_index) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + self_request.info_blocks[1].tlv, + interaction_status + ) +end + +function GetCredentialStatusResponse:init() + return nil +end + +function GetCredentialStatusResponse:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetCredentialStatusResponse:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetCredentialStatusResponse, {__call = GetCredentialStatusResponse.init}) + +return GetCredentialStatusResponse diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetUserResponse.lua b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetUserResponse.lua new file mode 100644 index 0000000000..6ee0bd8792 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetUserResponse.lua @@ -0,0 +1,165 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetUserResponse = {} + +GetUserResponse.NAME = "GetUserResponse" +GetUserResponse.ID = 0x001C +GetUserResponse.field_defs = { + { + name = "user_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "user_name", + field_id = 1, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.UTF8String1", + }, + { + name = "user_uniqueid", + field_id = 2, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint32", + }, + { + name = "user_status", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.UserStatusEnum", + }, + { + name = "user_type", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.UserTypeEnum", + }, + { + name = "credential_rule", + field_id = 5, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.CredentialRuleEnum", + }, + { + name = "credentials", + field_id = 6, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Array", + element_type = require "DoorLock.types.CredentialStruct", + }, + { + name = "creator_fabric_index", + field_id = 7, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "last_modified_fabric_index", + field_id = 8, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "next_user_index", + field_id = 9, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function GetUserResponse:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetUserResponse:build_test_command_response(device, endpoint_id, user_index, user_name, user_uniqueid, user_status, user_type, credential_rule, credentials, creator_fabric_index, last_modified_fabric_index, next_user_index, interaction_status) + local function init(self, device, endpoint_id, user_index, user_name, user_uniqueid, user_status, user_type, credential_rule, credentials, creator_fabric_index, last_modified_fabric_index, next_user_index) + local out = {} + local args = {user_index, user_name, user_uniqueid, user_status, user_type, credential_rule, credentials, creator_fabric_index, last_modified_fabric_index, next_user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetUserResponse, + __tostring = GetUserResponse.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) + end + local self_request = init(self, device, endpoint_id, user_index, user_name, user_uniqueid, user_status, user_type, credential_rule, credentials, creator_fabric_index, last_modified_fabric_index, next_user_index) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + self_request.info_blocks[1].tlv, + interaction_status + ) +end + +function GetUserResponse:init() + return nil +end + +function GetUserResponse:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetUserResponse:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetUserResponse, {__call = GetUserResponse.init}) + +return GetUserResponse diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetWeekDayScheduleResponse.lua b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetWeekDayScheduleResponse.lua new file mode 100644 index 0000000000..86b53a686e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetWeekDayScheduleResponse.lua @@ -0,0 +1,150 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetWeekDayScheduleResponse = {} + +GetWeekDayScheduleResponse.NAME = "GetWeekDayScheduleResponse" +GetWeekDayScheduleResponse.ID = 0x000C +GetWeekDayScheduleResponse.field_defs = { + { + name = "week_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "status", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DlStatus", + }, + { + name = "days_mask", + field_id = 3, + is_nullable = false, + is_optional = true, + data_type = require "DoorLock.types.DaysMaskMap", + }, + { + name = "start_hour", + field_id = 4, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "start_minute", + field_id = 5, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "end_hour", + field_id = 6, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "end_minute", + field_id = 7, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.Uint8", + }, +} + +function GetWeekDayScheduleResponse:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetWeekDayScheduleResponse:build_test_command_response(device, endpoint_id, week_day_index, user_index, status, days_mask, start_hour, start_minute, end_hour, end_minute, interaction_status) + local function init(self, device, endpoint_id, week_day_index, user_index, status, days_mask, start_hour, start_minute, end_hour, end_minute) + local out = {} + local args = {week_day_index, user_index, status, days_mask, start_hour, start_minute, end_hour, end_minute} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetWeekDayScheduleResponse, + __tostring = GetWeekDayScheduleResponse.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) + end + local self_request = init(self, device, endpoint_id, week_day_index, user_index, status, days_mask, start_hour, start_minute, end_hour, end_minute) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + self_request.info_blocks[1].tlv, + interaction_status + ) +end + +function GetWeekDayScheduleResponse:init() + return nil +end + +function GetWeekDayScheduleResponse:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetWeekDayScheduleResponse:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetWeekDayScheduleResponse, {__call = GetWeekDayScheduleResponse.init}) + +return GetWeekDayScheduleResponse diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetYearDayScheduleResponse.lua b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetYearDayScheduleResponse.lua new file mode 100644 index 0000000000..ecb591477e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/GetYearDayScheduleResponse.lua @@ -0,0 +1,129 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetYearDayScheduleResponse = {} + +GetYearDayScheduleResponse.NAME = "GetYearDayScheduleResponse" +GetYearDayScheduleResponse.ID = 0x000F +GetYearDayScheduleResponse.field_defs = { + { + name = "year_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "status", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DlStatus", + }, + { + name = "local_start_time", + field_id = 3, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.Uint32", + }, + { + name = "local_end_time", + field_id = 4, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.Uint32", + }, +} + +function GetYearDayScheduleResponse:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetYearDayScheduleResponse:build_test_command_response(device, endpoint_id, year_day_index, user_index, status, local_start_time, local_end_time, interaction_status) + local function init(self, device, endpoint_id, year_day_index, user_index, status, local_start_time, local_end_time) + local out = {} + local args = {year_day_index, user_index, status, local_start_time, local_end_time} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetYearDayScheduleResponse, + __tostring = GetYearDayScheduleResponse.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) + end + local self_request = init(self, device, endpoint_id, year_day_index, user_index, status, local_start_time, local_end_time) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + self_request.info_blocks[1].tlv, + interaction_status + ) +end + +function GetYearDayScheduleResponse:init() + return nil +end + +function GetYearDayScheduleResponse:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetYearDayScheduleResponse:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetYearDayScheduleResponse, {__call = GetYearDayScheduleResponse.init}) + +return GetYearDayScheduleResponse diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/SetCredentialResponse.lua b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/SetCredentialResponse.lua new file mode 100644 index 0000000000..eaf1658d14 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/SetCredentialResponse.lua @@ -0,0 +1,115 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SetCredentialResponse = {} + +SetCredentialResponse.NAME = "SetCredentialResponse" +SetCredentialResponse.ID = 0x0023 +SetCredentialResponse.field_defs = { + { + name = "status", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DlStatus", + }, + { + name = "user_index", + field_id = 1, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "next_credential_index", + field_id = 2, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function SetCredentialResponse:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function SetCredentialResponse:build_test_command_response(device, endpoint_id, status, user_index, next_credential_index, interaction_status) + local function init(self, device, endpoint_id, status, user_index, next_credential_index) + local out = {} + local args = {status, user_index, next_credential_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = SetCredentialResponse, + __tostring = SetCredentialResponse.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) + end + local self_request = init(self, device, endpoint_id, status, user_index, next_credential_index) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + self_request.info_blocks[1].tlv, + interaction_status + ) +end + +function SetCredentialResponse:init() + return nil +end + +function SetCredentialResponse:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SetCredentialResponse:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SetCredentialResponse, {__call = SetCredentialResponse.init}) + +return SetCredentialResponse diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/init.lua b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/init.lua new file mode 100644 index 0000000000..9148db5f96 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/client/commands/init.lua @@ -0,0 +1,23 @@ +local command_mt = {} +command_mt.__command_cache = {} +command_mt.__index = function(self, key) + if command_mt.__command_cache[key] == nil then + local req_loc = string.format("DoorLock.client.commands.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + command_mt.__command_cache[key] = raw_def:set_parent_cluster(cluster) + end + return command_mt.__command_cache[key] +end + +local DoorLockClientCommands = {} + +function DoorLockClientCommands:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(DoorLockClientCommands, command_mt) + +return DoorLockClientCommands + diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/init.lua b/drivers/SmartThings/matter-lock/src/DoorLock/init.lua new file mode 100644 index 0000000000..b9675ebf77 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/init.lua @@ -0,0 +1,258 @@ +local cluster_base = require "st.matter.cluster_base" +local DoorLockServerAttributes = require "DoorLock.server.attributes" +local DoorLockServerCommands = require "DoorLock.server.commands" +local DoorLockClientCommands = require "DoorLock.client.commands" +local DoorLockEvents = require "DoorLock.server.events" +local DoorLockTypes = require "DoorLock.types" + +local DoorLock = {} + +DoorLock.ID = 0x0101 +DoorLock.NAME = "DoorLock" +DoorLock.server = {} +DoorLock.client = {} +DoorLock.server.attributes = DoorLockServerAttributes:set_parent_cluster(DoorLock) +DoorLock.server.commands = DoorLockServerCommands:set_parent_cluster(DoorLock) +DoorLock.client.commands = DoorLockClientCommands:set_parent_cluster(DoorLock) +DoorLock.server.events = DoorLockEvents:set_parent_cluster(DoorLock) +DoorLock.types = DoorLockTypes + +function DoorLock:get_attribute_by_id(attr_id) + local attr_id_map = { + [0x0000] = "LockState", + [0x0001] = "LockType", + [0x0002] = "ActuatorEnabled", + [0x0003] = "DoorState", + [0x0004] = "DoorOpenEvents", + [0x0005] = "DoorClosedEvents", + [0x0006] = "OpenPeriod", + [0x0011] = "NumberOfTotalUsersSupported", + [0x0012] = "NumberOfPINUsersSupported", + [0x0013] = "NumberOfRFIDUsersSupported", + [0x0014] = "NumberOfWeekDaySchedulesSupportedPerUser", + [0x0015] = "NumberOfYearDaySchedulesSupportedPerUser", + [0x0016] = "NumberOfHolidaySchedulesSupported", + [0x0017] = "MaxPINCodeLength", + [0x0018] = "MinPINCodeLength", + [0x0019] = "MaxRFIDCodeLength", + [0x001A] = "MinRFIDCodeLength", + [0x001B] = "CredentialRulesSupport", + [0x001C] = "NumberOfCredentialsSupportedPerUser", + [0x0021] = "Language", + [0x0022] = "LEDSettings", + [0x0023] = "AutoRelockTime", + [0x0024] = "SoundVolume", + [0x0025] = "OperatingMode", + [0x0026] = "SupportedOperatingModes", + [0x0027] = "DefaultConfigurationRegister", + [0x0028] = "EnableLocalProgramming", + [0x0029] = "EnableOneTouchLocking", + [0x002A] = "EnableInsideStatusLED", + [0x002B] = "EnablePrivacyModeButton", + [0x002C] = "LocalProgrammingFeatures", + [0x0030] = "WrongCodeEntryLimit", + [0x0031] = "UserCodeTemporaryDisableTime", + [0x0032] = "SendPINOverTheAir", + [0x0033] = "RequirePINforRemoteOperation", + [0x0035] = "ExpiringUserTimeout", + [0x0080] = "AliroReaderVerificationKey", + [0x0081] = "AliroReaderGroupIdentifier", + [0x0082] = "AliroReaderGroupSubIdentifier", + [0x0083] = "AliroExpeditedTransactionSupportedProtocolVersions", + [0x0084] = "AliroGroupResolvingKey", + [0x0085] = "AliroSupportedBLEUWBProtocolVersions", + [0x0086] = "AliroBLEAdvertisingVersion", + [0x0087] = "NumberOfAliroCredentialIssuerKeysSupported", + [0x0088] = "NumberOfAliroEndpointKeysSupported", + [0xFFF9] = "AcceptedCommandList", + [0xFFFA] = "EventList", + [0xFFFB] = "AttributeList", + } + local attr_name = attr_id_map[attr_id] + if attr_name ~= nil then + return self.attributes[attr_name] + end + return nil +end + +function DoorLock:get_server_command_by_id(command_id) + local server_id_map = { + [0x0000] = "LockDoor", + [0x0001] = "UnlockDoor", + [0x0003] = "UnlockWithTimeout", + [0x000B] = "SetWeekDaySchedule", + [0x000C] = "GetWeekDaySchedule", + [0x000D] = "ClearWeekDaySchedule", + [0x000E] = "SetYearDaySchedule", + [0x000F] = "GetYearDaySchedule", + [0x0010] = "ClearYearDaySchedule", + [0x0011] = "SetHolidaySchedule", + [0x0012] = "GetHolidaySchedule", + [0x0013] = "ClearHolidaySchedule", + [0x001A] = "SetUser", + [0x001B] = "GetUser", + [0x001D] = "ClearUser", + [0x0022] = "SetCredential", + [0x0024] = "GetCredentialStatus", + [0x0026] = "ClearCredential", + [0x0027] = "UnboltDoor", + [0x0028] = "SetAliroReaderConfig", + [0x0029] = "ClearAliroReaderConfig", + } + if server_id_map[command_id] ~= nil then + return self.server.commands[server_id_map[command_id]] + end + return nil +end + +function DoorLock:get_client_command_by_id(command_id) + local client_id_map = { + [0x000C] = "GetWeekDayScheduleResponse", + [0x000F] = "GetYearDayScheduleResponse", + [0x0012] = "GetHolidayScheduleResponse", + [0x001C] = "GetUserResponse", + [0x0023] = "SetCredentialResponse", + [0x0025] = "GetCredentialStatusResponse", + } + if client_id_map[command_id] ~= nil then + return self.client.commands[client_id_map[command_id]] + end + return nil +end + +function DoorLock:get_event_by_id(event_id) + local event_id_map = { + [0x0000] = "DoorLockAlarm", + [0x0001] = "DoorStateChange", + [0x0002] = "LockOperation", + [0x0003] = "LockOperationError", + [0x0004] = "LockUserChange", + } + if event_id_map[event_id] ~= nil then + return self.server.events[event_id_map[event_id]] + end + return nil +end + +DoorLock.attribute_direction_map = { + ["LockState"] = "server", + ["LockType"] = "server", + ["ActuatorEnabled"] = "server", + ["DoorState"] = "server", + ["DoorOpenEvents"] = "server", + ["DoorClosedEvents"] = "server", + ["OpenPeriod"] = "server", + ["NumberOfTotalUsersSupported"] = "server", + ["NumberOfPINUsersSupported"] = "server", + ["NumberOfRFIDUsersSupported"] = "server", + ["NumberOfWeekDaySchedulesSupportedPerUser"] = "server", + ["NumberOfYearDaySchedulesSupportedPerUser"] = "server", + ["NumberOfHolidaySchedulesSupported"] = "server", + ["MaxPINCodeLength"] = "server", + ["MinPINCodeLength"] = "server", + ["MaxRFIDCodeLength"] = "server", + ["MinRFIDCodeLength"] = "server", + ["CredentialRulesSupport"] = "server", + ["NumberOfCredentialsSupportedPerUser"] = "server", + ["Language"] = "server", + ["LEDSettings"] = "server", + ["AutoRelockTime"] = "server", + ["SoundVolume"] = "server", + ["OperatingMode"] = "server", + ["SupportedOperatingModes"] = "server", + ["DefaultConfigurationRegister"] = "server", + ["EnableLocalProgramming"] = "server", + ["EnableOneTouchLocking"] = "server", + ["EnableInsideStatusLED"] = "server", + ["EnablePrivacyModeButton"] = "server", + ["LocalProgrammingFeatures"] = "server", + ["WrongCodeEntryLimit"] = "server", + ["UserCodeTemporaryDisableTime"] = "server", + ["SendPINOverTheAir"] = "server", + ["RequirePINforRemoteOperation"] = "server", + ["ExpiringUserTimeout"] = "server", + ["AliroReaderVerificationKey"] = "server", + ["AliroReaderGroupIdentifier"] = "server", + ["AliroReaderGroupSubIdentifier"] = "server", + ["AliroExpeditedTransactionSupportedProtocolVersions"] = "server", + ["AliroGroupResolvingKey"] = "server", + ["AliroSupportedBLEUWBProtocolVersions"] = "server", + ["AliroBLEAdvertisingVersion"] = "server", + ["NumberOfAliroCredentialIssuerKeysSupported"] = "server", + ["NumberOfAliroEndpointKeysSupported"] = "server", + ["AcceptedCommandList"] = "server", + ["EventList"] = "server", + ["AttributeList"] = "server", +} + +DoorLock.command_direction_map = { + ["LockDoor"] = "server", + ["UnlockDoor"] = "server", + ["UnlockWithTimeout"] = "server", + ["SetWeekDaySchedule"] = "server", + ["GetWeekDaySchedule"] = "server", + ["ClearWeekDaySchedule"] = "server", + ["SetYearDaySchedule"] = "server", + ["GetYearDaySchedule"] = "server", + ["ClearYearDaySchedule"] = "server", + ["SetHolidaySchedule"] = "server", + ["GetHolidaySchedule"] = "server", + ["ClearHolidaySchedule"] = "server", + ["SetUser"] = "server", + ["GetUser"] = "server", + ["ClearUser"] = "server", + ["SetCredential"] = "server", + ["GetCredentialStatus"] = "server", + ["ClearCredential"] = "server", + ["UnboltDoor"] = "server", + ["SetAliroReaderConfig"] = "server", + ["ClearAliroReaderConfig"] = "server", + ["GetWeekDayScheduleResponse"] = "client", + ["GetYearDayScheduleResponse"] = "client", + ["GetHolidayScheduleResponse"] = "client", + ["GetUserResponse"] = "client", + ["SetCredentialResponse"] = "client", + ["GetCredentialStatusResponse"] = "client", +} + +DoorLock.FeatureMap = DoorLock.types.Feature + +function DoorLock.are_features_supported(feature, feature_map) + if (DoorLock.FeatureMap.bits_are_valid(feature)) then + return (feature & feature_map) == feature + end + return false +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = DoorLock.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, DoorLock.NAME)) + end + return DoorLock[direction].attributes[key] +end +DoorLock.attributes = {} +setmetatable(DoorLock.attributes, attribute_helper_mt) + +local command_helper_mt = {} +command_helper_mt.__index = function(self, key) + local direction = DoorLock.command_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown command %s on cluster %s", key, DoorLock.NAME)) + end + return DoorLock[direction].commands[key] +end +DoorLock.commands = {} +setmetatable(DoorLock.commands, command_helper_mt) + +local event_helper_mt = {} +event_helper_mt.__index = function(self, key) + return DoorLock.server.events[key] +end +DoorLock.events = {} +setmetatable(DoorLock.events, event_helper_mt) + +setmetatable(DoorLock, {__index = cluster_base}) + +return DoorLock \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AcceptedCommandList.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AcceptedCommandList.lua new file mode 100644 index 0000000000..fe8e273558 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AcceptedCommandList.lua @@ -0,0 +1,74 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AcceptedCommandList = { + ID = 0xFFF9, + NAME = "AcceptedCommandList", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.Uint32", +} + +function AcceptedCommandList:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, AcceptedCommandList.element_type) + end +end + +function AcceptedCommandList:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AcceptedCommandList:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AcceptedCommandList:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AcceptedCommandList:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AcceptedCommandList:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AcceptedCommandList:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AcceptedCommandList, {__call = AcceptedCommandList.new_value, __index = AcceptedCommandList.base_type}) +return AcceptedCommandList \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/ActuatorEnabled.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/ActuatorEnabled.lua new file mode 100644 index 0000000000..359261a551 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/ActuatorEnabled.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local ActuatorEnabled = { + ID = 0x0002, + NAME = "ActuatorEnabled", + base_type = require "st.matter.data_types.Boolean", +} + +function ActuatorEnabled:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function ActuatorEnabled:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function ActuatorEnabled:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil --event_id + ) +end + +function ActuatorEnabled:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function ActuatorEnabled:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function ActuatorEnabled:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(ActuatorEnabled, {__call = ActuatorEnabled.new_value, __index = ActuatorEnabled.base_type}) +return ActuatorEnabled \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroBLEAdvertisingVersion.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroBLEAdvertisingVersion.lua new file mode 100644 index 0000000000..582babc3cb --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroBLEAdvertisingVersion.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AliroBLEAdvertisingVersion = { + ID = 0x0086, + NAME = "AliroBLEAdvertisingVersion", + base_type = require "st.matter.data_types.Uint8", +} + +function AliroBLEAdvertisingVersion:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AliroBLEAdvertisingVersion:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroBLEAdvertisingVersion:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroBLEAdvertisingVersion:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AliroBLEAdvertisingVersion:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AliroBLEAdvertisingVersion:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AliroBLEAdvertisingVersion, {__call = AliroBLEAdvertisingVersion.new_value, __index = AliroBLEAdvertisingVersion.base_type}) +return AliroBLEAdvertisingVersion \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroExpeditedTransactionSupportedProtocolVersions.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroExpeditedTransactionSupportedProtocolVersions.lua new file mode 100644 index 0000000000..1e5ed5f7f5 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroExpeditedTransactionSupportedProtocolVersions.lua @@ -0,0 +1,74 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AliroExpeditedTransactionSupportedProtocolVersions = { + ID = 0x0083, + NAME = "AliroExpeditedTransactionSupportedProtocolVersions", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.OctetString1", +} + +function AliroExpeditedTransactionSupportedProtocolVersions:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, AliroExpeditedTransactionSupportedProtocolVersions.element_type) + end +end + +function AliroExpeditedTransactionSupportedProtocolVersions:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AliroExpeditedTransactionSupportedProtocolVersions:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroExpeditedTransactionSupportedProtocolVersions:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroExpeditedTransactionSupportedProtocolVersions:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AliroExpeditedTransactionSupportedProtocolVersions:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AliroExpeditedTransactionSupportedProtocolVersions:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AliroExpeditedTransactionSupportedProtocolVersions, {__call = AliroExpeditedTransactionSupportedProtocolVersions.new_value, __index = AliroExpeditedTransactionSupportedProtocolVersions.base_type}) +return AliroExpeditedTransactionSupportedProtocolVersions \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroGroupResolvingKey.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroGroupResolvingKey.lua new file mode 100644 index 0000000000..517cc25aeb --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroGroupResolvingKey.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AliroGroupResolvingKey = { + ID = 0x0084, + NAME = "AliroGroupResolvingKey", + base_type = require "st.matter.data_types.OctetString1", +} + +function AliroGroupResolvingKey:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AliroGroupResolvingKey:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroGroupResolvingKey:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroGroupResolvingKey:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AliroGroupResolvingKey:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AliroGroupResolvingKey:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AliroGroupResolvingKey, {__call = AliroGroupResolvingKey.new_value, __index = AliroGroupResolvingKey.base_type}) +return AliroGroupResolvingKey \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderGroupIdentifier.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderGroupIdentifier.lua new file mode 100644 index 0000000000..bce6f2c049 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderGroupIdentifier.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AliroReaderGroupIdentifier = { + ID = 0x0081, + NAME = "AliroReaderGroupIdentifier", + base_type = require "st.matter.data_types.OctetString1", +} + +function AliroReaderGroupIdentifier:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AliroReaderGroupIdentifier:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroReaderGroupIdentifier:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroReaderGroupIdentifier:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AliroReaderGroupIdentifier:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AliroReaderGroupIdentifier:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AliroReaderGroupIdentifier, {__call = AliroReaderGroupIdentifier.new_value, __index = AliroReaderGroupIdentifier.base_type}) +return AliroReaderGroupIdentifier \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderGroupSubIdentifier.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderGroupSubIdentifier.lua new file mode 100644 index 0000000000..867dbcce93 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderGroupSubIdentifier.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AliroReaderGroupSubIdentifier = { + ID = 0x0082, + NAME = "AliroReaderGroupSubIdentifier", + base_type = require "st.matter.data_types.OctetString1", +} + +function AliroReaderGroupSubIdentifier:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AliroReaderGroupSubIdentifier:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroReaderGroupSubIdentifier:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroReaderGroupSubIdentifier:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AliroReaderGroupSubIdentifier:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AliroReaderGroupSubIdentifier:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AliroReaderGroupSubIdentifier, {__call = AliroReaderGroupSubIdentifier.new_value, __index = AliroReaderGroupSubIdentifier.base_type}) +return AliroReaderGroupSubIdentifier \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderVerificationKey.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderVerificationKey.lua new file mode 100644 index 0000000000..ccf8ac37a0 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AliroReaderVerificationKey.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AliroReaderVerificationKey = { + ID = 0x0080, + NAME = "AliroReaderVerificationKey", + base_type = require "st.matter.data_types.OctetString1", +} + +function AliroReaderVerificationKey:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AliroReaderVerificationKey:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroReaderVerificationKey:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AliroReaderVerificationKey:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AliroReaderVerificationKey:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AliroReaderVerificationKey:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AliroReaderVerificationKey, {__call = AliroReaderVerificationKey.new_value, __index = AliroReaderVerificationKey.base_type}) +return AliroReaderVerificationKey \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AttributeList.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AttributeList.lua new file mode 100644 index 0000000000..c191ec3d5a --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/AttributeList.lua @@ -0,0 +1,74 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AttributeList = { + ID = 0xFFFB, + NAME = "AttributeList", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.Uint32", +} + +function AttributeList:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, AttributeList.element_type) + end +end + +function AttributeList:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AttributeList:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AttributeList:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AttributeList:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AttributeList:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AttributeList:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AttributeList, {__call = AttributeList.new_value, __index = AttributeList.base_type}) +return AttributeList \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/DoorState.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/DoorState.lua new file mode 100644 index 0000000000..59fd6cbe79 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/DoorState.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local DoorState = { + ID = 0x0003, + NAME = "DoorState", + base_type = require "DoorLock.types.DoorStateEnum", +} + +function DoorState:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function DoorState:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function DoorState:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil --event_id + ) +end + +function DoorState:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function DoorState:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function DoorState:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(DoorState, {__call = DoorState.new_value, __index = DoorState.base_type}) +return DoorState \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/EventList.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/EventList.lua new file mode 100644 index 0000000000..616bbf92bc --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/EventList.lua @@ -0,0 +1,74 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local EventList = { + ID = 0xFFFA, + NAME = "EventList", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.Uint32", +} + +function EventList:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, EventList.element_type) + end +end + +function EventList:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function EventList:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function EventList:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function EventList:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function EventList:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function EventList:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(EventList, {__call = EventList.new_value, __index = EventList.base_type}) +return EventList \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/LockState.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/LockState.lua new file mode 100644 index 0000000000..5d7615e2c6 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/LockState.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local LockState = { + ID = 0x0000, + NAME = "LockState", + base_type = require "DoorLock.types.DlLockState", +} + +function LockState:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function LockState:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function LockState:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function LockState:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LockState:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function LockState:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(LockState, {__call = LockState.new_value, __index = LockState.base_type}) +return LockState \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/MaxPINCodeLength.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/MaxPINCodeLength.lua new file mode 100644 index 0000000000..efdef6065c --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/MaxPINCodeLength.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local MaxPINCodeLength = { + ID = 0x0017, + NAME = "MaxPINCodeLength", + base_type = require "st.matter.data_types.Uint8", +} + +function MaxPINCodeLength:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function MaxPINCodeLength:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function MaxPINCodeLength:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function MaxPINCodeLength:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MaxPINCodeLength:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MaxPINCodeLength:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MaxPINCodeLength, {__call = MaxPINCodeLength.new_value, __index = MaxPINCodeLength.base_type}) +return MaxPINCodeLength \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/MinPINCodeLength.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/MinPINCodeLength.lua new file mode 100644 index 0000000000..f94a777a64 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/MinPINCodeLength.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local MinPINCodeLength = { + ID = 0x0018, + NAME = "MinPINCodeLength", + base_type = require "st.matter.data_types.Uint8", +} + +function MinPINCodeLength:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function MinPINCodeLength:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function MinPINCodeLength:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function MinPINCodeLength:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MinPINCodeLength:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MinPINCodeLength:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MinPINCodeLength, {__call = MinPINCodeLength.new_value, __index = MinPINCodeLength.base_type}) +return MinPINCodeLength \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfAliroCredentialIssuerKeysSupported.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfAliroCredentialIssuerKeysSupported.lua new file mode 100644 index 0000000000..f28e356e3c --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfAliroCredentialIssuerKeysSupported.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfAliroCredentialIssuerKeysSupported = { + ID = 0x0087, + NAME = "NumberOfAliroCredentialIssuerKeysSupported", + base_type = require "st.matter.data_types.Uint16", +} + +function NumberOfAliroCredentialIssuerKeysSupported:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfAliroCredentialIssuerKeysSupported:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfAliroCredentialIssuerKeysSupported:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfAliroCredentialIssuerKeysSupported:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfAliroCredentialIssuerKeysSupported:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfAliroCredentialIssuerKeysSupported:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfAliroCredentialIssuerKeysSupported, {__call = NumberOfAliroCredentialIssuerKeysSupported.new_value, __index = NumberOfAliroCredentialIssuerKeysSupported.base_type}) +return NumberOfAliroCredentialIssuerKeysSupported \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfAliroEndpointKeysSupported.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfAliroEndpointKeysSupported.lua new file mode 100644 index 0000000000..b40d6c7df4 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfAliroEndpointKeysSupported.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfAliroEndpointKeysSupported = { + ID = 0x0088, + NAME = "NumberOfAliroEndpointKeysSupported", + base_type = require "st.matter.data_types.Uint16", +} + +function NumberOfAliroEndpointKeysSupported:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfAliroEndpointKeysSupported:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfAliroEndpointKeysSupported:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfAliroEndpointKeysSupported:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfAliroEndpointKeysSupported:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfAliroEndpointKeysSupported:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfAliroEndpointKeysSupported, {__call = NumberOfAliroEndpointKeysSupported.new_value, __index = NumberOfAliroEndpointKeysSupported.base_type}) +return NumberOfAliroEndpointKeysSupported \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfCredentialsSupportedPerUser.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfCredentialsSupportedPerUser.lua new file mode 100644 index 0000000000..48f08cf19c --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfCredentialsSupportedPerUser.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfCredentialsSupportedPerUser = { + ID = 0x001C, + NAME = "NumberOfCredentialsSupportedPerUser", + base_type = require "st.matter.data_types.Uint8", +} + +function NumberOfCredentialsSupportedPerUser:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfCredentialsSupportedPerUser:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfCredentialsSupportedPerUser:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfCredentialsSupportedPerUser:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfCredentialsSupportedPerUser:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfCredentialsSupportedPerUser:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfCredentialsSupportedPerUser, {__call = NumberOfCredentialsSupportedPerUser.new_value, __index = NumberOfCredentialsSupportedPerUser.base_type}) +return NumberOfCredentialsSupportedPerUser \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfPINUsersSupported.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfPINUsersSupported.lua new file mode 100644 index 0000000000..c9a2da141d --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfPINUsersSupported.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfPINUsersSupported = { + ID = 0x0012, + NAME = "NumberOfPINUsersSupported", + base_type = require "st.matter.data_types.Uint16", +} + +function NumberOfPINUsersSupported:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfPINUsersSupported:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfPINUsersSupported:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfPINUsersSupported:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfPINUsersSupported:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfPINUsersSupported:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfPINUsersSupported, {__call = NumberOfPINUsersSupported.new_value, __index = NumberOfPINUsersSupported.base_type}) +return NumberOfPINUsersSupported \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfTotalUsersSupported.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfTotalUsersSupported.lua new file mode 100644 index 0000000000..ff0cd93791 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfTotalUsersSupported.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfTotalUsersSupported = { + ID = 0x0011, + NAME = "NumberOfTotalUsersSupported", + base_type = require "st.matter.data_types.Uint16", +} + +function NumberOfTotalUsersSupported:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfTotalUsersSupported:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfTotalUsersSupported:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfTotalUsersSupported:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfTotalUsersSupported:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfTotalUsersSupported:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfTotalUsersSupported, {__call = NumberOfTotalUsersSupported.new_value, __index = NumberOfTotalUsersSupported.base_type}) +return NumberOfTotalUsersSupported \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfWeekDaySchedulesSupportedPerUser.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfWeekDaySchedulesSupportedPerUser.lua new file mode 100644 index 0000000000..f5878babee --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfWeekDaySchedulesSupportedPerUser.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfWeekDaySchedulesSupportedPerUser = { + ID = 0x0014, + NAME = "NumberOfWeekDaySchedulesSupportedPerUser", + base_type = require "st.matter.data_types.Uint8", +} + +function NumberOfWeekDaySchedulesSupportedPerUser:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfWeekDaySchedulesSupportedPerUser:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfWeekDaySchedulesSupportedPerUser:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfWeekDaySchedulesSupportedPerUser:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfWeekDaySchedulesSupportedPerUser:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfWeekDaySchedulesSupportedPerUser:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfWeekDaySchedulesSupportedPerUser, {__call = NumberOfWeekDaySchedulesSupportedPerUser.new_value, __index = NumberOfWeekDaySchedulesSupportedPerUser.base_type}) +return NumberOfWeekDaySchedulesSupportedPerUser \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfYearDaySchedulesSupportedPerUser.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfYearDaySchedulesSupportedPerUser.lua new file mode 100644 index 0000000000..4039dab170 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/NumberOfYearDaySchedulesSupportedPerUser.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local NumberOfYearDaySchedulesSupportedPerUser = { + ID = 0x0015, + NAME = "NumberOfYearDaySchedulesSupportedPerUser", + base_type = require "st.matter.data_types.Uint8", +} + +function NumberOfYearDaySchedulesSupportedPerUser:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function NumberOfYearDaySchedulesSupportedPerUser:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfYearDaySchedulesSupportedPerUser:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function NumberOfYearDaySchedulesSupportedPerUser:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function NumberOfYearDaySchedulesSupportedPerUser:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function NumberOfYearDaySchedulesSupportedPerUser:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(NumberOfYearDaySchedulesSupportedPerUser, {__call = NumberOfYearDaySchedulesSupportedPerUser.new_value, __index = NumberOfYearDaySchedulesSupportedPerUser.base_type}) +return NumberOfYearDaySchedulesSupportedPerUser \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/OperatingMode.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/OperatingMode.lua new file mode 100644 index 0000000000..79823fb0e4 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/OperatingMode.lua @@ -0,0 +1,80 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local OperatingMode = { + ID = 0x0025, + NAME = "OperatingMode", + base_type = require "DoorLock.types.OperatingModeEnum", +} + +function OperatingMode:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function OperatingMode:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function OperatingMode:write(device, endpoint_id, value) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.write( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + data + ) +end + +function OperatingMode:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function OperatingMode:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function OperatingMode:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function OperatingMode:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(OperatingMode, {__call = OperatingMode.new_value, __index = OperatingMode.base_type}) +return OperatingMode \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/RequirePINforRemoteOperation.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/RequirePINforRemoteOperation.lua new file mode 100644 index 0000000000..6512d9e530 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/RequirePINforRemoteOperation.lua @@ -0,0 +1,80 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local RequirePINforRemoteOperation = { + ID = 0x0033, + NAME = "RequirePINforRemoteOperation", + base_type = require "st.matter.data_types.Boolean", +} + +function RequirePINforRemoteOperation:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function RequirePINforRemoteOperation:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function RequirePINforRemoteOperation:write(device, endpoint_id, value) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.write( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + data + ) +end + +function RequirePINforRemoteOperation:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function RequirePINforRemoteOperation:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function RequirePINforRemoteOperation:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function RequirePINforRemoteOperation:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(RequirePINforRemoteOperation, {__call = RequirePINforRemoteOperation.new_value, __index = RequirePINforRemoteOperation.base_type}) +return RequirePINforRemoteOperation \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/SendPINOverTheAir.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/SendPINOverTheAir.lua new file mode 100644 index 0000000000..5b52a9b583 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/SendPINOverTheAir.lua @@ -0,0 +1,80 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SendPINOverTheAir = { + ID = 0x0032, + NAME = "SendPINOverTheAir", + base_type = require "st.matter.data_types.Boolean", +} + +function SendPINOverTheAir:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function SendPINOverTheAir:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function SendPINOverTheAir:write(device, endpoint_id, value) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.write( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + data + ) +end + +function SendPINOverTheAir:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function SendPINOverTheAir:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SendPINOverTheAir:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function SendPINOverTheAir:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(SendPINOverTheAir, {__call = SendPINOverTheAir.new_value, __index = SendPINOverTheAir.base_type}) +return SendPINOverTheAir \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/SupportedOperatingModes.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/SupportedOperatingModes.lua new file mode 100644 index 0000000000..7859d8346e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/SupportedOperatingModes.lua @@ -0,0 +1,67 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SupportedOperatingModes = { + ID = 0x0026, + NAME = "SupportedOperatingModes", + base_type = require "DoorLock.types.DlSupportedOperatingModes", +} + +function SupportedOperatingModes:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function SupportedOperatingModes:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function SupportedOperatingModes:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function SupportedOperatingModes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SupportedOperatingModes:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function SupportedOperatingModes:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SupportedOperatingModes, {__call = SupportedOperatingModes.new_value, __index = SupportedOperatingModes.base_type}) +return SupportedOperatingModes \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/UserCodeTemporaryDisableTime.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/UserCodeTemporaryDisableTime.lua new file mode 100644 index 0000000000..26226e667c --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/UserCodeTemporaryDisableTime.lua @@ -0,0 +1,80 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local UserCodeTemporaryDisableTime = { + ID = 0x0031, + NAME = "UserCodeTemporaryDisableTime", + base_type = require "st.matter.data_types.Uint8", +} + +function UserCodeTemporaryDisableTime:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function UserCodeTemporaryDisableTime:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function UserCodeTemporaryDisableTime:write(device, endpoint_id, value) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.write( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + data + ) +end + +function UserCodeTemporaryDisableTime:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function UserCodeTemporaryDisableTime:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function UserCodeTemporaryDisableTime:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function UserCodeTemporaryDisableTime:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(UserCodeTemporaryDisableTime, {__call = UserCodeTemporaryDisableTime.new_value, __index = UserCodeTemporaryDisableTime.base_type}) +return UserCodeTemporaryDisableTime \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/WrongCodeEntryLimit.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/WrongCodeEntryLimit.lua new file mode 100644 index 0000000000..2109ef3945 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/WrongCodeEntryLimit.lua @@ -0,0 +1,80 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local WrongCodeEntryLimit = { + ID = 0x0030, + NAME = "WrongCodeEntryLimit", + base_type = require "st.matter.data_types.Uint8", +} + +function WrongCodeEntryLimit:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function WrongCodeEntryLimit:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function WrongCodeEntryLimit:write(device, endpoint_id, value) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.write( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + data + ) +end + +function WrongCodeEntryLimit:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function WrongCodeEntryLimit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function WrongCodeEntryLimit:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function WrongCodeEntryLimit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(WrongCodeEntryLimit, {__call = WrongCodeEntryLimit.new_value, __index = WrongCodeEntryLimit.base_type}) +return WrongCodeEntryLimit \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/init.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/init.lua new file mode 100644 index 0000000000..9e35b63132 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/attributes/init.lua @@ -0,0 +1,23 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("DoorLock.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local DoorLockServerAttributes = {} + +function DoorLockServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(DoorLockServerAttributes, attr_mt) + +return DoorLockServerAttributes \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearAliroReaderConfig.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearAliroReaderConfig.lua new file mode 100644 index 0000000000..007104e3ec --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearAliroReaderConfig.lua @@ -0,0 +1,91 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local ClearAliroReaderConfig = {} + +ClearAliroReaderConfig.NAME = "ClearAliroReaderConfig" +ClearAliroReaderConfig.ID = 0x0029 +ClearAliroReaderConfig.field_defs = { +} + +function ClearAliroReaderConfig:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function ClearAliroReaderConfig:init(device, endpoint_id) + local out = {} + local args = {} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = ClearAliroReaderConfig, + __tostring = ClearAliroReaderConfig.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function ClearAliroReaderConfig:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function ClearAliroReaderConfig:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function ClearAliroReaderConfig:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(ClearAliroReaderConfig, {__call = ClearAliroReaderConfig.init}) + +return ClearAliroReaderConfig \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearCredential.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearCredential.lua new file mode 100644 index 0000000000..07244d15a5 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearCredential.lua @@ -0,0 +1,98 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local ClearCredential = {} + +ClearCredential.NAME = "ClearCredential" +ClearCredential.ID = 0x0026 +ClearCredential.field_defs = { + { + name = "credential", + field_id = 0, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.CredentialStruct", + }, +} + +function ClearCredential:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function ClearCredential:init(device, endpoint_id, credential) + local out = {} + local args = {credential} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = ClearCredential, + __tostring = ClearCredential.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function ClearCredential:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function ClearCredential:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function ClearCredential:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(ClearCredential, {__call = ClearCredential.init}) + +return ClearCredential \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearUser.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearUser.lua new file mode 100644 index 0000000000..2e5b7ba51b --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearUser.lua @@ -0,0 +1,98 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local ClearUser = {} + +ClearUser.NAME = "ClearUser" +ClearUser.ID = 0x001D +ClearUser.field_defs = { + { + name = "user_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function ClearUser:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function ClearUser:init(device, endpoint_id, user_index) + local out = {} + local args = {user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = ClearUser, + __tostring = ClearUser.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function ClearUser:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function ClearUser:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function ClearUser:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(ClearUser, {__call = ClearUser.init}) + +return ClearUser \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearWeekDaySchedule.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearWeekDaySchedule.lua new file mode 100644 index 0000000000..30ddd45933 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearWeekDaySchedule.lua @@ -0,0 +1,104 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local ClearWeekDaySchedule = {} + +ClearWeekDaySchedule.NAME = "ClearWeekDaySchedule" +ClearWeekDaySchedule.ID = 0x000D +ClearWeekDaySchedule.field_defs = { + { + name = "week_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function ClearWeekDaySchedule:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function ClearWeekDaySchedule:init(device, endpoint_id, week_day_index, user_index) + local out = {} + local args = {week_day_index, user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = ClearWeekDaySchedule, + __tostring = ClearWeekDaySchedule.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function ClearWeekDaySchedule:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function ClearWeekDaySchedule:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function ClearWeekDaySchedule:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(ClearWeekDaySchedule, {__call = ClearWeekDaySchedule.init}) + +return ClearWeekDaySchedule \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearYearDaySchedule.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearYearDaySchedule.lua new file mode 100644 index 0000000000..ba9380b114 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/ClearYearDaySchedule.lua @@ -0,0 +1,104 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local ClearYearDaySchedule = {} + +ClearYearDaySchedule.NAME = "ClearYearDaySchedule" +ClearYearDaySchedule.ID = 0x0010 +ClearYearDaySchedule.field_defs = { + { + name = "year_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function ClearYearDaySchedule:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function ClearYearDaySchedule:init(device, endpoint_id, year_day_index, user_index) + local out = {} + local args = {year_day_index, user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = ClearYearDaySchedule, + __tostring = ClearYearDaySchedule.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function ClearYearDaySchedule:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function ClearYearDaySchedule:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function ClearYearDaySchedule:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(ClearYearDaySchedule, {__call = ClearYearDaySchedule.init}) + +return ClearYearDaySchedule \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetCredentialStatus.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetCredentialStatus.lua new file mode 100644 index 0000000000..9b1d37355e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetCredentialStatus.lua @@ -0,0 +1,86 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetCredentialStatus = {} + +GetCredentialStatus.NAME = "GetCredentialStatus" +GetCredentialStatus.ID = 0x0024 +GetCredentialStatus.field_defs = { + { + name = "credential", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.CredentialStruct", + }, +} + +function GetCredentialStatus:init(device, endpoint_id, credential) + local out = {} + local args = {credential} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetCredentialStatus, + __tostring = GetCredentialStatus.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function GetCredentialStatus:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetCredentialStatus:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetCredentialStatus:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetCredentialStatus, {__call = GetCredentialStatus.init}) + +return GetCredentialStatus \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetUser.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetUser.lua new file mode 100644 index 0000000000..ecdf60bdcd --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetUser.lua @@ -0,0 +1,86 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetUser = {} + +GetUser.NAME = "GetUser" +GetUser.ID = 0x001B +GetUser.field_defs = { + { + name = "user_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function GetUser:init(device, endpoint_id, user_index) + local out = {} + local args = {user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetUser, + __tostring = GetUser.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function GetUser:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetUser:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetUser:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetUser, {__call = GetUser.init}) + +return GetUser \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetWeekDaySchedule.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetWeekDaySchedule.lua new file mode 100644 index 0000000000..817c57cda4 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetWeekDaySchedule.lua @@ -0,0 +1,93 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetWeekDaySchedule = {} + +GetWeekDaySchedule.NAME = "GetWeekDaySchedule" +GetWeekDaySchedule.ID = 0x000C +GetWeekDaySchedule.field_defs = { + { + name = "week_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function GetWeekDaySchedule:init(device, endpoint_id, week_day_index, user_index) + local out = {} + local args = {week_day_index, user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetWeekDaySchedule, + __tostring = GetWeekDaySchedule.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function GetWeekDaySchedule:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetWeekDaySchedule:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetWeekDaySchedule:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetWeekDaySchedule, {__call = GetWeekDaySchedule.init}) + +return GetWeekDaySchedule \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetYearDaySchedule.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetYearDaySchedule.lua new file mode 100644 index 0000000000..35ea38a3f8 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/GetYearDaySchedule.lua @@ -0,0 +1,93 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local GetYearDaySchedule = {} + +GetYearDaySchedule.NAME = "GetYearDaySchedule" +GetYearDaySchedule.ID = 0x000F +GetYearDaySchedule.field_defs = { + { + name = "year_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function GetYearDaySchedule:init(device, endpoint_id, year_day_index, user_index) + local out = {} + local args = {year_day_index, user_index} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = GetYearDaySchedule, + __tostring = GetYearDaySchedule.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function GetYearDaySchedule:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function GetYearDaySchedule:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function GetYearDaySchedule:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(GetYearDaySchedule, {__call = GetYearDaySchedule.init}) + +return GetYearDaySchedule \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/LockDoor.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/LockDoor.lua new file mode 100644 index 0000000000..9440546cab --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/LockDoor.lua @@ -0,0 +1,98 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local LockDoor = {} + +LockDoor.NAME = "LockDoor" +LockDoor.ID = 0x0000 +LockDoor.field_defs = { + { + name = "pin_code", + field_id = 0, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.OctetString1", + }, +} + +function LockDoor:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function LockDoor:init(device, endpoint_id, pin_code) + local out = {} + local args = {pin_code} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = LockDoor, + __tostring = LockDoor.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function LockDoor:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LockDoor:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function LockDoor:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(LockDoor, {__call = LockDoor.init}) + +return LockDoor \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetAliroReaderConfig.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetAliroReaderConfig.lua new file mode 100644 index 0000000000..8317db64b7 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetAliroReaderConfig.lua @@ -0,0 +1,119 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SetAliroReaderConfig = {} + +SetAliroReaderConfig.NAME = "SetAliroReaderConfig" +SetAliroReaderConfig.ID = 0x0028 +SetAliroReaderConfig.field_defs = { + { + name = "signing_key", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.OctetString1", + }, + { + name = "verification_key", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.OctetString1", + }, + { + name = "group_identifier", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.OctetString1", + }, + { + name = "group_resolving_key", + field_id = 3, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.OctetString1", + }, +} + +function SetAliroReaderConfig:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function SetAliroReaderConfig:init(device, endpoint_id, signing_key, verification_key, group_identifier, group_resolving_key) + local out = {} + local args = {signing_key, verification_key, group_identifier, group_resolving_key} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = SetAliroReaderConfig, + __tostring = SetAliroReaderConfig.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function SetAliroReaderConfig:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SetAliroReaderConfig:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function SetAliroReaderConfig:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SetAliroReaderConfig, {__call = SetAliroReaderConfig.init}) + +return SetAliroReaderConfig \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetCredential.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetCredential.lua new file mode 100644 index 0000000000..ad024b9619 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetCredential.lua @@ -0,0 +1,122 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SetCredential = {} + +SetCredential.NAME = "SetCredential" +SetCredential.ID = 0x0022 +SetCredential.field_defs = { + { + name = "operation_type", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DataOperationTypeEnum", + }, + { + name = "credential", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.CredentialStruct", + }, + { + name = "credential_data", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.OctetString2", + }, + { + name = "user_index", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "user_status", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.UserStatusEnum", + }, + { + name = "user_type", + field_id = 5, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.UserTypeEnum", + }, +} + +function SetCredential:init(device, endpoint_id, operation_type, credential, credential_data, user_index, user_status, user_type) + local out = {} + local args = {operation_type, credential, credential_data, user_index, user_status, user_type} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = SetCredential, + __tostring = SetCredential.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function SetCredential:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SetCredential:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function SetCredential:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SetCredential, {__call = SetCredential.init}) + +return SetCredential \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetUser.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetUser.lua new file mode 100644 index 0000000000..a115db2b57 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetUser.lua @@ -0,0 +1,140 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SetUser = {} + +SetUser.NAME = "SetUser" +SetUser.ID = 0x001A +SetUser.field_defs = { + { + name = "operation_type", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DataOperationTypeEnum", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "user_name", + field_id = 2, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.UTF8String1", + }, + { + name = "user_uniqueid", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint32", + }, + { + name = "user_status", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.UserStatusEnum", + }, + { + name = "user_type", + field_id = 5, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.UserTypeEnum", + }, + { + name = "credential_rule", + field_id = 6, + is_nullable = true, + is_optional = false, + data_type = require "DoorLock.types.CredentialRuleEnum", + }, +} + +function SetUser:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function SetUser:init(device, endpoint_id, operation_type, user_index, user_name, user_uniqueid, user_status, user_type, credential_rule) + local out = {} + local args = {operation_type, user_index, user_name, user_uniqueid, user_status, user_type, credential_rule} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = SetUser, + __tostring = SetUser.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function SetUser:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SetUser:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function SetUser:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SetUser, {__call = SetUser.init}) + +return SetUser \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetWeekDaySchedule.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetWeekDaySchedule.lua new file mode 100644 index 0000000000..c13f677303 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetWeekDaySchedule.lua @@ -0,0 +1,139 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SetWeekDaySchedule = {} + +SetWeekDaySchedule.NAME = "SetWeekDaySchedule" +SetWeekDaySchedule.ID = 0x000B +SetWeekDaySchedule.field_defs = { + { + name = "week_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "days_mask", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DaysMaskMap", + }, + { + name = "start_hour", + field_id = 3, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "start_minute", + field_id = 4, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "end_hour", + field_id = 5, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "end_minute", + field_id = 6, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, +} + +function SetWeekDaySchedule:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function SetWeekDaySchedule:init(device, endpoint_id, week_day_index, user_index, days_mask, start_hour, start_minute, end_hour, end_minute) + local out = {} + local args = {week_day_index, user_index, days_mask, start_hour, start_minute, end_hour, end_minute} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = SetWeekDaySchedule, + __tostring = SetWeekDaySchedule.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function SetWeekDaySchedule:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SetWeekDaySchedule:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function SetWeekDaySchedule:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SetWeekDaySchedule, {__call = SetWeekDaySchedule.init}) + +return SetWeekDaySchedule \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetYearDaySchedule.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetYearDaySchedule.lua new file mode 100644 index 0000000000..0e65d0027e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/SetYearDaySchedule.lua @@ -0,0 +1,118 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local SetYearDaySchedule = {} + +SetYearDaySchedule.NAME = "SetYearDaySchedule" +SetYearDaySchedule.ID = 0x000E +SetYearDaySchedule.field_defs = { + { + name = "year_day_index", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "user_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "local_start_time", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint32", + }, + { + name = "local_end_time", + field_id = 3, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint32", + }, +} + +function SetYearDaySchedule:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, + status + ) +end + +function SetYearDaySchedule:init(device, endpoint_id, year_day_index, user_index, local_start_time, local_end_time) + local out = {} + local args = {year_day_index, user_index, local_start_time, local_end_time} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = SetYearDaySchedule, + __tostring = SetYearDaySchedule.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID + ) +end + +function SetYearDaySchedule:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function SetYearDaySchedule:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function SetYearDaySchedule:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(SetYearDaySchedule, {__call = SetYearDaySchedule.init}) + +return SetYearDaySchedule \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/UnlockDoor.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/UnlockDoor.lua new file mode 100644 index 0000000000..32bfd9fb3d --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/UnlockDoor.lua @@ -0,0 +1,98 @@ +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local UnlockDoor = {} + +UnlockDoor.NAME = "UnlockDoor" +UnlockDoor.ID = 0x0001 +UnlockDoor.field_defs = { + { + name = "pin_code", + field_id = 0, + is_nullable = false, + is_optional = true, + data_type = require "st.matter.data_types.OctetString1", + }, +} + +function UnlockDoor:build_test_command_response(device, endpoint_id, status) + return self._cluster:build_test_command_response( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil, --tlv + status + ) +end + +function UnlockDoor:init(device, endpoint_id, pin_code) + local out = {} + local args = {pin_code} + if #args > #self.field_defs then + error(self.NAME .. " received too many arguments") + end + for i,v in ipairs(self.field_defs) do + if v.is_optional and args[i] == nil then + out[v.name] = nil + elseif v.is_nullable and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(args[i], data_types.Null, v.name) + out[v.name].field_id = v.field_id + elseif not v.is_optional and args[i] == nil then + out[v.name] = data_types.validate_or_build_type(v.default, v.data_type, v.name) + out[v.name].field_id = v.field_id + else + out[v.name] = data_types.validate_or_build_type(args[i], v.data_type, v.name) + out[v.name].field_id = v.field_id + end + end + setmetatable(out, { + __index = UnlockDoor, + __tostring = UnlockDoor.pretty_print + }) + return self._cluster:build_cluster_command( + device, + out, + endpoint_id, + self._cluster.ID, + self.ID, + true + ) +end + +function UnlockDoor:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function UnlockDoor:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function UnlockDoor:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(UnlockDoor, {__call = UnlockDoor.init}) + +return UnlockDoor \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/init.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/init.lua new file mode 100644 index 0000000000..ee8db4a85f --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/commands/init.lua @@ -0,0 +1,22 @@ +local command_mt = {} +command_mt.__command_cache = {} +command_mt.__index = function(self, key) + if command_mt.__command_cache[key] == nil then + local req_loc = string.format("DoorLock.server.commands.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + command_mt.__command_cache[key] = raw_def:set_parent_cluster(cluster) + end + return command_mt.__command_cache[key] +end + +local DoorLockServerCommands = {} + +function DoorLockServerCommands:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(DoorLockServerCommands, command_mt) + +return DoorLockServerCommands \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/events/DoorLockAlarm.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/DoorLockAlarm.lua new file mode 100644 index 0000000000..da5f1ed0d1 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/DoorLockAlarm.lua @@ -0,0 +1,100 @@ +local data_types = require "st.matter.data_types" +local cluster_base = require "st.matter.cluster_base" +local TLVParser = require "st.matter.TLV.TLVParser" +local StructureABC = require "st.matter.data_types.base_defs.StructureABC" + +local DoorLockAlarm = { + ID = 0x0000, + NAME = "DoorLockAlarm", + base_type = data_types.Structure, +} + +DoorLockAlarm.field_defs = { + { + name = "alarm_code", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.AlarmCodeEnum", + }, +} + +function DoorLockAlarm:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and not + ((field_def.is_nullable or field_def.is_optional) and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function DoorLockAlarm:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function DoorLockAlarm:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function DoorLockAlarm:build_test_event_report( + device, + endpoint_id, + fields, + status +) + local data = {} + data.elements = {} + data.num_elements = 0 + setmetatable(data, StructureABC.new_mt({NAME = "DoorLockAlarmEventData", ID = 0x15})) + for idx, field_def in ipairs(self.field_defs) do --Note: idx is 1 when field_id is 0 + if (not field_def.is_optional and not field_def.is_nullable) and not fields[field_def.name] then + error("Missing non optional or non_nullable field: " .. field_def.name) + elseif fields[field_def.name] then + data.elements[field_def.name] = data_types.validate_or_build_type(fields[field_def.name], field_def.data_type, field_def.name) + data.elements[field_def.name].field_id = field_def.field_id + data.num_elements = data.num_elements + 1 + end + end + return cluster_base.build_test_event_report( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function DoorLockAlarm:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +function DoorLockAlarm:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +return DoorLockAlarm \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/events/DoorStateChange.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/DoorStateChange.lua new file mode 100644 index 0000000000..da106194be --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/DoorStateChange.lua @@ -0,0 +1,100 @@ +local data_types = require "st.matter.data_types" +local cluster_base = require "st.matter.cluster_base" +local TLVParser = require "st.matter.TLV.TLVParser" +local StructureABC = require "st.matter.data_types.base_defs.StructureABC" + +local DoorStateChange = { + ID = 0x0001, + NAME = "DoorStateChange", + base_type = data_types.Structure, +} + +DoorStateChange.field_defs = { + { + name = "door_state", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DoorStateEnum", + }, +} + +function DoorStateChange:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and not + ((field_def.is_nullable or field_def.is_optional) and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function DoorStateChange:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function DoorStateChange:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function DoorStateChange:build_test_event_report( + device, + endpoint_id, + fields, + status +) + local data = {} + data.elements = {} + data.num_elements = 0 + setmetatable(data, StructureABC.new_mt({NAME = "DoorStateChangeEventData", ID = 0x15})) + for idx, field_def in ipairs(self.field_defs) do --Note: idx is 1 when field_id is 0 + if (not field_def.is_optional and not field_def.is_nullable) and not fields[field_def.name] then + error("Missing non optional or non_nullable field: " .. field_def.name) + elseif fields[field_def.name] then + data.elements[field_def.name] = data_types.validate_or_build_type(fields[field_def.name], field_def.data_type, field_def.name) + data.elements[field_def.name].field_id = field_def.field_id + data.num_elements = data.num_elements + 1 + end + end + return cluster_base.build_test_event_report( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function DoorStateChange:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +function DoorStateChange:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +return DoorStateChange \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockOperation.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockOperation.lua new file mode 100644 index 0000000000..8171c09c2e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockOperation.lua @@ -0,0 +1,136 @@ +local data_types = require "st.matter.data_types" +local cluster_base = require "st.matter.cluster_base" +local TLVParser = require "st.matter.TLV.TLVParser" +local StructureABC = require "st.matter.data_types.base_defs.StructureABC" + +local LockOperation = { + ID = 0x0002, + NAME = "LockOperation", + base_type = data_types.Structure, +} + +LockOperation.field_defs = { + { + name = "lock_operation_type", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.LockOperationTypeEnum", + }, + { + name = "operation_source", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.OperationSourceEnum", + }, + { + name = "user_index", + field_id = 2, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "fabric_index", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "source_node", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint64", + }, + { + name = "credentials", + field_id = 5, + is_nullable = true, + is_optional = true, + data_type = require "st.matter.data_types.Array", + element_type = require "DoorLock.types.CredentialStruct", + }, +} + +function LockOperation:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and not + ((field_def.is_nullable or field_def.is_optional) and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function LockOperation:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function LockOperation:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function LockOperation:build_test_event_report( + device, + endpoint_id, + fields, + status +) + local data = {} + data.elements = {} + data.num_elements = 0 + setmetatable(data, StructureABC.new_mt({NAME = "LockOperationEventData", ID = 0x15})) + for idx, field_def in ipairs(self.field_defs) do + if (not field_def.is_optional and not field_def.is_nullable) and not fields[field_def.name] then + error("Missing non optional or non_nullable field: " .. field_def.name) + elseif fields[field_def.name] then + data.elements[field_def.name] = data_types.validate_or_build_type(fields[field_def.name], field_def.data_type, field_def.name) + data.elements[field_def.name].field_id = field_def.field_id + data.num_elements = data.num_elements + 1 + end + end + return cluster_base.build_test_event_report( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function LockOperation:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +function LockOperation:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +return LockOperation \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockOperationError.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockOperationError.lua new file mode 100644 index 0000000000..a5363437e4 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockOperationError.lua @@ -0,0 +1,143 @@ +local data_types = require "st.matter.data_types" +local cluster_base = require "st.matter.cluster_base" +local TLVParser = require "st.matter.TLV.TLVParser" +local StructureABC = require "st.matter.data_types.base_defs.StructureABC" + +local LockOperationError = { + ID = 0x0003, + NAME = "LockOperationError", + base_type = data_types.Structure, +} + +LockOperationError.field_defs = { + { + name = "lock_operation_type", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.LockOperationTypeEnum", + }, + { + name = "operation_source", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.OperationSourceEnum", + }, + { + name = "operation_error", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.OperationErrorEnum", + }, + { + name = "user_index", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "fabric_index", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "source_node", + field_id = 5, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint64", + }, + { + name = "credentials", + field_id = 6, + is_nullable = true, + is_optional = true, + data_type = require "st.matter.data_types.Array", + element_type = require "DoorLock.types.CredentialStruct", + }, +} + +function LockOperationError:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and not + ((field_def.is_nullable or field_def.is_optional) and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function LockOperationError:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function LockOperationError:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function LockOperationError:build_test_event_report( + device, + endpoint_id, + fields, + status +) + local data = {} + data.elements = {} + data.num_elements = 0 + setmetatable(data, StructureABC.new_mt({NAME = "LockOperationErrorEventData", ID = 0x15})) + for idx, field_def in ipairs(self.field_defs) do + if (not field_def.is_optional and not field_def.is_nullable) and not fields[field_def.name] then + error("Missing non optional or non_nullable field: " .. field_def.name) + elseif fields[field_def.name] then + data.elements[field_def.name] = data_types.validate_or_build_type(fields[field_def.name], field_def.data_type, field_def.name) + data.elements[field_def.name].field_id = field_def.field_id + data.num_elements = data.num_elements + 1 + end + end + return cluster_base.build_test_event_report( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function LockOperationError:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +function LockOperationError:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +return LockOperationError \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockUserChange.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockUserChange.lua new file mode 100644 index 0000000000..2566f27c06 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/LockUserChange.lua @@ -0,0 +1,142 @@ +local data_types = require "st.matter.data_types" +local cluster_base = require "st.matter.cluster_base" +local TLVParser = require "st.matter.TLV.TLVParser" +local StructureABC = require "st.matter.data_types.base_defs.StructureABC" + +local LockUserChange = { + ID = 0x0004, + NAME = "LockUserChange", + base_type = data_types.Structure, +} + +LockUserChange.field_defs = { + { + name = "lock_data_type", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.LockDataTypeEnum", + }, + { + name = "data_operation_type", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.DataOperationTypeEnum", + }, + { + name = "operation_source", + field_id = 2, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.OperationSourceEnum", + }, + { + name = "user_index", + field_id = 3, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, + { + name = "fabric_index", + field_id = 4, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint8", + }, + { + name = "source_node", + field_id = 5, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint64", + }, + { + name = "data_index", + field_id = 6, + is_nullable = true, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +function LockUserChange:augment_type(base_type_obj) + local elems = {} + for _, v in ipairs(base_type_obj.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and not + ((field_def.is_nullable or field_def.is_optional) and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + base_type_obj.elements = elems +end + +function LockUserChange:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function LockUserChange:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + nil, + self.ID + ) +end + +function LockUserChange:build_test_event_report( + device, + endpoint_id, + fields, + status +) + local data = {} + data.elements = {} + data.num_elements = 0 + setmetatable(data, StructureABC.new_mt({NAME = "LockUserChangeEventData", ID = 0x15})) + for idx, field_def in ipairs(self.field_defs) do + if (not field_def.is_optional and not field_def.is_nullable) and not fields[field_def.name] then + error("Missing non optional or non_nullable field: " .. field_def.name) + elseif fields[field_def.name] then + data.elements[field_def.name] = data_types.validate_or_build_type(fields[field_def.name], field_def.data_type, field_def.name) + data.elements[field_def.name].field_id = field_def.field_id + data.num_elements = data.num_elements + 1 + end + end + return cluster_base.build_test_event_report( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function LockUserChange:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +function LockUserChange:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +return LockUserChange \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/server/events/init.lua b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/init.lua new file mode 100644 index 0000000000..0079543a93 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/server/events/init.lua @@ -0,0 +1,23 @@ +local event_mt = {} +event_mt.__event_cache = {} +event_mt.__index = function(self, key) + if event_mt.__event_cache[key] == nil then + local req_loc = string.format("DoorLock.server.events.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + event_mt.__event_cache[key] = raw_def + end + return event_mt.__event_cache[key] +end + +local DoorLockEvents = {} + +function DoorLockEvents:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(DoorLockEvents, event_mt) + +return DoorLockEvents \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/AlarmCodeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/AlarmCodeEnum.lua new file mode 100644 index 0000000000..06460249f2 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/AlarmCodeEnum.lua @@ -0,0 +1,45 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local AlarmCodeEnum = {} +local new_mt = UintABC.new_mt({NAME = "AlarmCodeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.LOCK_JAMMED] = "LOCK_JAMMED", + [self.LOCK_FACTORY_RESET] = "LOCK_FACTORY_RESET", + [self.LOCK_RADIO_POWER_CYCLED] = "LOCK_RADIO_POWER_CYCLED", + [self.WRONG_CODE_ENTRY_LIMIT] = "WRONG_CODE_ENTRY_LIMIT", + [self.FRONT_ESCEUTCHEON_REMOVED] = "FRONT_ESCEUTCHEON_REMOVED", + [self.DOOR_FORCED_OPEN] = "DOOR_FORCED_OPEN", + [self.DOOR_AJAR] = "DOOR_AJAR", + [self.FORCED_USER] = "FORCED_USER", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.LOCK_JAMMED = 0x00 +new_mt.__index.LOCK_FACTORY_RESET = 0x01 +new_mt.__index.LOCK_RADIO_POWER_CYCLED = 0x03 +new_mt.__index.WRONG_CODE_ENTRY_LIMIT = 0x04 +new_mt.__index.FRONT_ESCEUTCHEON_REMOVED = 0x05 +new_mt.__index.DOOR_FORCED_OPEN = 0x06 +new_mt.__index.DOOR_AJAR = 0x07 +new_mt.__index.FORCED_USER = 0x08 + +AlarmCodeEnum.LOCK_JAMMED = 0x00 +AlarmCodeEnum.LOCK_FACTORY_RESET = 0x01 +AlarmCodeEnum.LOCK_RADIO_POWER_CYCLED = 0x03 +AlarmCodeEnum.WRONG_CODE_ENTRY_LIMIT = 0x04 +AlarmCodeEnum.FRONT_ESCEUTCHEON_REMOVED = 0x05 +AlarmCodeEnum.DOOR_FORCED_OPEN = 0x06 +AlarmCodeEnum.DOOR_AJAR = 0x07 +AlarmCodeEnum.FORCED_USER = 0x08 + +AlarmCodeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(AlarmCodeEnum, new_mt) + +return AlarmCodeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialRuleEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialRuleEnum.lua new file mode 100644 index 0000000000..ead4d559b7 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialRuleEnum.lua @@ -0,0 +1,31 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local CredentialRuleEnum = {} +local new_mt = UintABC.new_mt({NAME = "CredentialRuleEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.SINGLE] = "SINGLE", + [self.DUAL] = "DUAL", + [self.TRI] = "TRI", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.SINGLE = 0x00 +new_mt.__index.DUAL = 0x01 +new_mt.__index.TRI = 0x02 + +CredentialRuleEnum.SINGLE = 0x00 +CredentialRuleEnum.DUAL = 0x01 +CredentialRuleEnum.TRI = 0x02 + +CredentialRuleEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(CredentialRuleEnum, new_mt) + +return CredentialRuleEnum + diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialStruct.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialStruct.lua new file mode 100644 index 0000000000..d58c170334 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialStruct.lua @@ -0,0 +1,77 @@ +local data_types = require "st.matter.data_types" +local StructureABC = require "st.matter.data_types.base_defs.StructureABC" + +local CredentialStruct = {} +local new_mt = StructureABC.new_mt({NAME = "CredentialStruct", ID = data_types.name_to_id_map["Structure"]}) + +CredentialStruct.field_defs = { + { + name = "credential_type", + field_id = 0, + is_nullable = false, + is_optional = false, + data_type = require "DoorLock.types.CredentialTypeEnum", + }, + { + name = "credential_index", + field_id = 1, + is_nullable = false, + is_optional = false, + data_type = require "st.matter.data_types.Uint16", + }, +} + +CredentialStruct.init = function(cls, tbl) + local o = {} + o.elements = {} + o.num_elements = 0 + setmetatable(o, new_mt) + for idx, field_def in ipairs(cls.field_defs) do + if (not field_def.is_optional and not field_def.is_nullable) and not tbl[field_def.name] then + error("Missing non optional or non_nullable field: " .. field_def.name) + else + o.elements[field_def.name] = data_types.validate_or_build_type(tbl[field_def.name], field_def.data_type, field_def.name) + o.elements[field_def.name].field_id = field_def.field_id + o.num_elements = o.num_elements + 1 + end + end + return o +end + +CredentialStruct.serialize = function(self, buf, include_control, tag) + return data_types['Structure'].serialize(self.elements, buf, include_control, tag) +end + +new_mt.__call = CredentialStruct.init +new_mt.__index.serialize = CredentialStruct.serialize + +CredentialStruct.augment_type = function(self, val) + local elems = {} + local num_elements = 0 + for _, v in pairs(val.elements) do + for _, field_def in ipairs(self.field_defs) do + if field_def.field_id == v.field_id and + field_def.is_nullable and + (v.value == nil and v.elements == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name) + num_elements = num_elements + 1 + elseif field_def.field_id == v.field_id and not + (field_def.is_optional and v.value == nil) then + elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name) + num_elements = num_elements + 1 + if field_def.element_type ~= nil then + for i, e in ipairs(elems[field_def.name].elements) do + elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type) + end + end + end + end + end + val.elements = elems + val.num_elements = num_elements + setmetatable(val, new_mt) +end + +setmetatable(CredentialStruct, new_mt) + +return CredentialStruct \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialTypeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialTypeEnum.lua new file mode 100644 index 0000000000..0a09054948 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/CredentialTypeEnum.lua @@ -0,0 +1,48 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local CredentialTypeEnum = {} +local new_mt = UintABC.new_mt({NAME = "CredentialTypeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.PROGRAMMINGPIN] = "PROGRAMMINGPIN", + [self.PIN] = "PIN", + [self.RFID] = "RFID", + [self.FINGERPRINT] = "FINGERPRINT", + [self.FINGER_VEIN] = "FINGER_VEIN", + [self.FACE] = "FACE", + [self.ALIRO_CREDENTIAL_ISSUER_KEY] = "ALIRO_CREDENTIAL_ISSUER_KEY", + [self.ALIRO_EVICTABLE_ENDPOINT_KEY] = "ALIRO_EVICTABLE_ENDPOINT_KEY", + [self.ALIRO_NON_EVICTABLE_ENDPOINT_KEY] = "ALIRO_NON_EVICTABLE_ENDPOINT_KEY", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.PROGRAMMINGPIN = 0x00 +new_mt.__index.PIN = 0x01 +new_mt.__index.RFID = 0x02 +new_mt.__index.FINGERPRINT = 0x03 +new_mt.__index.FINGER_VEIN = 0x04 +new_mt.__index.FACE = 0x05 +new_mt.__index.ALIRO_CREDENTIAL_ISSUER_KEY = 0x06 +new_mt.__index.ALIRO_EVICTABLE_ENDPOINT_KEY = 0x07 +new_mt.__index.ALIRO_NON_EVICTABLE_ENDPOINT_KEY = 0x08 + +CredentialTypeEnum.PROGRAMMINGPIN = 0x00 +CredentialTypeEnum.PIN = 0x01 +CredentialTypeEnum.RFID = 0x02 +CredentialTypeEnum.FINGERPRINT = 0x03 +CredentialTypeEnum.FINGER_VEIN = 0x04 +CredentialTypeEnum.FACE = 0x05 +CredentialTypeEnum.ALIRO_CREDENTIAL_ISSUER_KEY = 0x06 +CredentialTypeEnum.ALIRO_EVICTABLE_ENDPOINT_KEY = 0x07 +CredentialTypeEnum.ALIRO_NON_EVICTABLE_ENDPOINT_KEY = 0x08 + +CredentialTypeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(CredentialTypeEnum, new_mt) + +return CredentialTypeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DataOperationTypeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DataOperationTypeEnum.lua new file mode 100644 index 0000000000..4aa540aae4 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DataOperationTypeEnum.lua @@ -0,0 +1,30 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DataOperationTypeEnum = {} +local new_mt = UintABC.new_mt({NAME = "DataOperationTypeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.ADD] = "ADD", + [self.CLEAR] = "CLEAR", + [self.MODIFY] = "MODIFY", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.ADD = 0x00 +new_mt.__index.CLEAR = 0x01 +new_mt.__index.MODIFY = 0x02 + +DataOperationTypeEnum.ADD = 0x00 +DataOperationTypeEnum.CLEAR = 0x01 +DataOperationTypeEnum.MODIFY = 0x02 + +DataOperationTypeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DataOperationTypeEnum, new_mt) + +return DataOperationTypeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DaysMaskMap.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DaysMaskMap.lua new file mode 100644 index 0000000000..b4c7ea7f21 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DaysMaskMap.lua @@ -0,0 +1,169 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DaysMaskMap = {} +local new_mt = UintABC.new_mt({NAME = "DaysMaskMap", ID = data_types.name_to_id_map["Uint8"]}, 1) + +DaysMaskMap.BASE_MASK = 0xFFFF +DaysMaskMap.SUNDAY = 0x0001 +DaysMaskMap.MONDAY = 0x0002 +DaysMaskMap.TUESDAY = 0x0004 +DaysMaskMap.WEDNESDAY = 0x0008 +DaysMaskMap.THURSDAY = 0x0010 +DaysMaskMap.FRIDAY = 0x0020 +DaysMaskMap.SATURDAY = 0x0040 + +DaysMaskMap.mask_fields = { + BASE_MASK = 0xFFFF, + SUNDAY = 0x0001, + MONDAY = 0x0002, + TUESDAY = 0x0004, + WEDNESDAY = 0x0008, + THURSDAY = 0x0010, + FRIDAY = 0x0020, + SATURDAY = 0x0040, +} + +DaysMaskMap.is_sunday_set = function(self) + return (self.value & self.SUNDAY) ~= 0 +end + +DaysMaskMap.set_sunday = function(self) + if self.value ~= nil then + self.value = self.value | self.SUNDAY + else + self.value = self.SUNDAY + end +end + +DaysMaskMap.unset_sunday = function(self) + self.value = self.value & (~self.SUNDAY & self.BASE_MASK) +end + +DaysMaskMap.is_monday_set = function(self) + return (self.value & self.MONDAY) ~= 0 +end + +DaysMaskMap.set_monday = function(self) + if self.value ~= nil then + self.value = self.value | self.MONDAY + else + self.value = self.MONDAY + end +end + +DaysMaskMap.unset_monday = function(self) + self.value = self.value & (~self.MONDAY & self.BASE_MASK) +end + +DaysMaskMap.is_tuesday_set = function(self) + return (self.value & self.TUESDAY) ~= 0 +end + +DaysMaskMap.set_tuesday = function(self) + if self.value ~= nil then + self.value = self.value | self.TUESDAY + else + self.value = self.TUESDAY + end +end + +DaysMaskMap.unset_tuesday = function(self) + self.value = self.value & (~self.TUESDAY & self.BASE_MASK) +end + +DaysMaskMap.is_wednesday_set = function(self) + return (self.value & self.WEDNESDAY) ~= 0 +end + +DaysMaskMap.set_wednesday = function(self) + if self.value ~= nil then + self.value = self.value | self.WEDNESDAY + else + self.value = self.WEDNESDAY + end +end + +DaysMaskMap.unset_wednesday = function(self) + self.value = self.value & (~self.WEDNESDAY & self.BASE_MASK) +end + +DaysMaskMap.is_thursday_set = function(self) + return (self.value & self.THURSDAY) ~= 0 +end + +DaysMaskMap.set_thursday = function(self) + if self.value ~= nil then + self.value = self.value | self.THURSDAY + else + self.value = self.THURSDAY + end +end + +DaysMaskMap.unset_thursday = function(self) + self.value = self.value & (~self.THURSDAY & self.BASE_MASK) +end + +DaysMaskMap.is_friday_set = function(self) + return (self.value & self.FRIDAY) ~= 0 +end + +DaysMaskMap.set_friday = function(self) + if self.value ~= nil then + self.value = self.value | self.FRIDAY + else + self.value = self.FRIDAY + end +end + +DaysMaskMap.unset_friday = function(self) + self.value = self.value & (~self.FRIDAY & self.BASE_MASK) +end + +DaysMaskMap.is_saturday_set = function(self) + return (self.value & self.SATURDAY) ~= 0 +end + +DaysMaskMap.set_saturday = function(self) + if self.value ~= nil then + self.value = self.value | self.SATURDAY + else + self.value = self.SATURDAY + end +end + +DaysMaskMap.unset_saturday = function(self) + self.value = self.value & (~self.SATURDAY & self.BASE_MASK) +end + +DaysMaskMap.mask_methods = { + is_sunday_set = DaysMaskMap.is_sunday_set, + set_sunday = DaysMaskMap.set_sunday, + unset_sunday = DaysMaskMap.unset_sunday, + is_monday_set = DaysMaskMap.is_monday_set, + set_monday = DaysMaskMap.set_monday, + unset_monday = DaysMaskMap.unset_monday, + is_tuesday_set = DaysMaskMap.is_tuesday_set, + set_tuesday = DaysMaskMap.set_tuesday, + unset_tuesday = DaysMaskMap.unset_tuesday, + is_wednesday_set = DaysMaskMap.is_wednesday_set, + set_wednesday = DaysMaskMap.set_wednesday, + unset_wednesday = DaysMaskMap.unset_wednesday, + is_thursday_set = DaysMaskMap.is_thursday_set, + set_thursday = DaysMaskMap.set_thursday, + unset_thursday = DaysMaskMap.unset_thursday, + is_friday_set = DaysMaskMap.is_friday_set, + set_friday = DaysMaskMap.set_friday, + unset_friday = DaysMaskMap.unset_friday, + is_saturday_set = DaysMaskMap.is_saturday_set, + set_saturday = DaysMaskMap.set_saturday, + unset_saturday = DaysMaskMap.unset_saturday, +} + +DaysMaskMap.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DaysMaskMap, new_mt) + +return DaysMaskMap \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlKeypadOperationEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlKeypadOperationEventMask.lua new file mode 100644 index 0000000000..06dd9b829b --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlKeypadOperationEventMask.lua @@ -0,0 +1,190 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlKeypadOperationEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlKeypadOperationEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlKeypadOperationEventMask.BASE_MASK = 0xFFFF +DlKeypadOperationEventMask.UNKNOWN = 0x0001 +DlKeypadOperationEventMask.LOCK = 0x0002 +DlKeypadOperationEventMask.UNLOCK = 0x0004 +DlKeypadOperationEventMask.LOCK_INVALIDPIN = 0x0008 +DlKeypadOperationEventMask.LOCK_INVALID_SCHEDULE = 0x0010 +DlKeypadOperationEventMask.UNLOCK_INVALID_CODE = 0x0020 +DlKeypadOperationEventMask.UNLOCK_INVALID_SCHEDULE = 0x0040 +DlKeypadOperationEventMask.NON_ACCESS_USER_OP_EVENT = 0x0080 + +DlKeypadOperationEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + LOCK = 0x0002, + UNLOCK = 0x0004, + LOCK_INVALIDPIN = 0x0008, + LOCK_INVALID_SCHEDULE = 0x0010, + UNLOCK_INVALID_CODE = 0x0020, + UNLOCK_INVALID_SCHEDULE = 0x0040, + NON_ACCESS_USER_OP_EVENT = 0x0080, +} + +DlKeypadOperationEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlKeypadOperationEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlKeypadOperationEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_lock_set = function(self) + return (self.value & self.LOCK) ~= 0 +end + +DlKeypadOperationEventMask.set_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK + else + self.value = self.LOCK + end +end + +DlKeypadOperationEventMask.unset_lock = function(self) + self.value = self.value & (~self.LOCK & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_unlock_set = function(self) + return (self.value & self.UNLOCK) ~= 0 +end + +DlKeypadOperationEventMask.set_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK + else + self.value = self.UNLOCK + end +end + +DlKeypadOperationEventMask.unset_unlock = function(self) + self.value = self.value & (~self.UNLOCK & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_lock_invalidpin_set = function(self) + return (self.value & self.LOCK_INVALIDPIN) ~= 0 +end + +DlKeypadOperationEventMask.set_lock_invalidpin = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK_INVALIDPIN + else + self.value = self.LOCK_INVALIDPIN + end +end + +DlKeypadOperationEventMask.unset_lock_invalidpin = function(self) + self.value = self.value & (~self.LOCK_INVALIDPIN & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_lock_invalid_schedule_set = function(self) + return (self.value & self.LOCK_INVALID_SCHEDULE) ~= 0 +end + +DlKeypadOperationEventMask.set_lock_invalid_schedule = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK_INVALID_SCHEDULE + else + self.value = self.LOCK_INVALID_SCHEDULE + end +end + +DlKeypadOperationEventMask.unset_lock_invalid_schedule = function(self) + self.value = self.value & (~self.LOCK_INVALID_SCHEDULE & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_unlock_invalid_code_set = function(self) + return (self.value & self.UNLOCK_INVALID_CODE) ~= 0 +end + +DlKeypadOperationEventMask.set_unlock_invalid_code = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK_INVALID_CODE + else + self.value = self.UNLOCK_INVALID_CODE + end +end + +DlKeypadOperationEventMask.unset_unlock_invalid_code = function(self) + self.value = self.value & (~self.UNLOCK_INVALID_CODE & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_unlock_invalid_schedule_set = function(self) + return (self.value & self.UNLOCK_INVALID_SCHEDULE) ~= 0 +end + +DlKeypadOperationEventMask.set_unlock_invalid_schedule = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK_INVALID_SCHEDULE + else + self.value = self.UNLOCK_INVALID_SCHEDULE + end +end + +DlKeypadOperationEventMask.unset_unlock_invalid_schedule = function(self) + self.value = self.value & (~self.UNLOCK_INVALID_SCHEDULE & self.BASE_MASK) +end + +DlKeypadOperationEventMask.is_non_access_user_op_event_set = function(self) + return (self.value & self.NON_ACCESS_USER_OP_EVENT) ~= 0 +end + +DlKeypadOperationEventMask.set_non_access_user_op_event = function(self) + if self.value ~= nil then + self.value = self.value | self.NON_ACCESS_USER_OP_EVENT + else + self.value = self.NON_ACCESS_USER_OP_EVENT + end +end + +DlKeypadOperationEventMask.unset_non_access_user_op_event = function(self) + self.value = self.value & (~self.NON_ACCESS_USER_OP_EVENT & self.BASE_MASK) +end + +DlKeypadOperationEventMask.mask_methods = { + is_unknown_set = DlKeypadOperationEventMask.is_unknown_set, + set_unknown = DlKeypadOperationEventMask.set_unknown, + unset_unknown = DlKeypadOperationEventMask.unset_unknown, + is_lock_set = DlKeypadOperationEventMask.is_lock_set, + set_lock = DlKeypadOperationEventMask.set_lock, + unset_lock = DlKeypadOperationEventMask.unset_lock, + is_unlock_set = DlKeypadOperationEventMask.is_unlock_set, + set_unlock = DlKeypadOperationEventMask.set_unlock, + unset_unlock = DlKeypadOperationEventMask.unset_unlock, + is_lock_invalidpin_set = DlKeypadOperationEventMask.is_lock_invalidpin_set, + set_lock_invalidpin = DlKeypadOperationEventMask.set_lock_invalidpin, + unset_lock_invalidpin = DlKeypadOperationEventMask.unset_lock_invalidpin, + is_lock_invalid_schedule_set = DlKeypadOperationEventMask.is_lock_invalid_schedule_set, + set_lock_invalid_schedule = DlKeypadOperationEventMask.set_lock_invalid_schedule, + unset_lock_invalid_schedule = DlKeypadOperationEventMask.unset_lock_invalid_schedule, + is_unlock_invalid_code_set = DlKeypadOperationEventMask.is_unlock_invalid_code_set, + set_unlock_invalid_code = DlKeypadOperationEventMask.set_unlock_invalid_code, + unset_unlock_invalid_code = DlKeypadOperationEventMask.unset_unlock_invalid_code, + is_unlock_invalid_schedule_set = DlKeypadOperationEventMask.is_unlock_invalid_schedule_set, + set_unlock_invalid_schedule = DlKeypadOperationEventMask.set_unlock_invalid_schedule, + unset_unlock_invalid_schedule = DlKeypadOperationEventMask.unset_unlock_invalid_schedule, + is_non_access_user_op_event_set = DlKeypadOperationEventMask.is_non_access_user_op_event_set, + set_non_access_user_op_event = DlKeypadOperationEventMask.set_non_access_user_op_event, + unset_non_access_user_op_event = DlKeypadOperationEventMask.unset_non_access_user_op_event, +} + +DlKeypadOperationEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlKeypadOperationEventMask, new_mt) + +return DlKeypadOperationEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlKeypadProgrammingEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlKeypadProgrammingEventMask.lua new file mode 100644 index 0000000000..d7b3c1c6f6 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlKeypadProgrammingEventMask.lua @@ -0,0 +1,127 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlKeypadProgrammingEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlKeypadProgrammingEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlKeypadProgrammingEventMask.BASE_MASK = 0xFFFF +DlKeypadProgrammingEventMask.UNKNOWN = 0x0001 +DlKeypadProgrammingEventMask.PROGRAMMINGPIN_CHANGED = 0x0002 +DlKeypadProgrammingEventMask.PIN_ADDED = 0x0004 +DlKeypadProgrammingEventMask.PIN_CLEARED = 0x0008 +DlKeypadProgrammingEventMask.PIN_CHANGED = 0x0010 + +DlKeypadProgrammingEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + PROGRAMMINGPIN_CHANGED = 0x0002, + PIN_ADDED = 0x0004, + PIN_CLEARED = 0x0008, + PIN_CHANGED = 0x0010, +} + +DlKeypadProgrammingEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlKeypadProgrammingEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlKeypadProgrammingEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlKeypadProgrammingEventMask.is_programmingpin_changed_set = function(self) + return (self.value & self.PROGRAMMINGPIN_CHANGED) ~= 0 +end + +DlKeypadProgrammingEventMask.set_programmingpin_changed = function(self) + if self.value ~= nil then + self.value = self.value | self.PROGRAMMINGPIN_CHANGED + else + self.value = self.PROGRAMMINGPIN_CHANGED + end +end + +DlKeypadProgrammingEventMask.unset_programmingpin_changed = function(self) + self.value = self.value & (~self.PROGRAMMINGPIN_CHANGED & self.BASE_MASK) +end + +DlKeypadProgrammingEventMask.is_pin_added_set = function(self) + return (self.value & self.PIN_ADDED) ~= 0 +end + +DlKeypadProgrammingEventMask.set_pin_added = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_ADDED + else + self.value = self.PIN_ADDED + end +end + +DlKeypadProgrammingEventMask.unset_pin_added = function(self) + self.value = self.value & (~self.PIN_ADDED & self.BASE_MASK) +end + +DlKeypadProgrammingEventMask.is_pin_cleared_set = function(self) + return (self.value & self.PIN_CLEARED) ~= 0 +end + +DlKeypadProgrammingEventMask.set_pin_cleared = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_CLEARED + else + self.value = self.PIN_CLEARED + end +end + +DlKeypadProgrammingEventMask.unset_pin_cleared = function(self) + self.value = self.value & (~self.PIN_CLEARED & self.BASE_MASK) +end + +DlKeypadProgrammingEventMask.is_pin_changed_set = function(self) + return (self.value & self.PIN_CHANGED) ~= 0 +end + +DlKeypadProgrammingEventMask.set_pin_changed = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_CHANGED + else + self.value = self.PIN_CHANGED + end +end + +DlKeypadProgrammingEventMask.unset_pin_changed = function(self) + self.value = self.value & (~self.PIN_CHANGED & self.BASE_MASK) +end + +DlKeypadProgrammingEventMask.mask_methods = { + is_unknown_set = DlKeypadProgrammingEventMask.is_unknown_set, + set_unknown = DlKeypadProgrammingEventMask.set_unknown, + unset_unknown = DlKeypadProgrammingEventMask.unset_unknown, + is_programmingpin_changed_set = DlKeypadProgrammingEventMask.is_programmingpin_changed_set, + set_programmingpin_changed = DlKeypadProgrammingEventMask.set_programmingpin_changed, + unset_programmingpin_changed = DlKeypadProgrammingEventMask.unset_programmingpin_changed, + is_pin_added_set = DlKeypadProgrammingEventMask.is_pin_added_set, + set_pin_added = DlKeypadProgrammingEventMask.set_pin_added, + unset_pin_added = DlKeypadProgrammingEventMask.unset_pin_added, + is_pin_cleared_set = DlKeypadProgrammingEventMask.is_pin_cleared_set, + set_pin_cleared = DlKeypadProgrammingEventMask.set_pin_cleared, + unset_pin_cleared = DlKeypadProgrammingEventMask.unset_pin_cleared, + is_pin_changed_set = DlKeypadProgrammingEventMask.is_pin_changed_set, + set_pin_changed = DlKeypadProgrammingEventMask.set_pin_changed, + unset_pin_changed = DlKeypadProgrammingEventMask.unset_pin_changed, +} + +DlKeypadProgrammingEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlKeypadProgrammingEventMask, new_mt) + +return DlKeypadProgrammingEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlLocalProgrammingFeatures.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlLocalProgrammingFeatures.lua new file mode 100644 index 0000000000..937a59daf9 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlLocalProgrammingFeatures.lua @@ -0,0 +1,106 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlLocalProgrammingFeatures = {} +local new_mt = UintABC.new_mt({NAME = "DlLocalProgrammingFeatures", ID = data_types.name_to_id_map["Uint8"]}, 1) + +DlLocalProgrammingFeatures.BASE_MASK = 0xFFFF +DlLocalProgrammingFeatures.ADD_USERS_CREDENTIALS_SCHEDULES_LOCALLY = 0x0001 +DlLocalProgrammingFeatures.MODIFY_USERS_CREDENTIALS_SCHEDULES_LOCALLY = 0x0002 +DlLocalProgrammingFeatures.CLEAR_USERS_CREDENTIALS_SCHEDULES_LOCALLY = 0x0004 +DlLocalProgrammingFeatures.ADJUST_LOCK_SETTINGS_LOCALLY = 0x0008 + +DlLocalProgrammingFeatures.mask_fields = { + BASE_MASK = 0xFFFF, + ADD_USERS_CREDENTIALS_SCHEDULES_LOCALLY = 0x0001, + MODIFY_USERS_CREDENTIALS_SCHEDULES_LOCALLY = 0x0002, + CLEAR_USERS_CREDENTIALS_SCHEDULES_LOCALLY = 0x0004, + ADJUST_LOCK_SETTINGS_LOCALLY = 0x0008, +} + +DlLocalProgrammingFeatures.is_add_users_credentials_schedules_locally_set = function(self) + return (self.value & self.ADD_USERS_CREDENTIALS_SCHEDULES_LOCALLY) ~= 0 +end + +DlLocalProgrammingFeatures.set_add_users_credentials_schedules_locally = function(self) + if self.value ~= nil then + self.value = self.value | self.ADD_USERS_CREDENTIALS_SCHEDULES_LOCALLY + else + self.value = self.ADD_USERS_CREDENTIALS_SCHEDULES_LOCALLY + end +end + +DlLocalProgrammingFeatures.unset_add_users_credentials_schedules_locally = function(self) + self.value = self.value & (~self.ADD_USERS_CREDENTIALS_SCHEDULES_LOCALLY & self.BASE_MASK) +end + +DlLocalProgrammingFeatures.is_modify_users_credentials_schedules_locally_set = function(self) + return (self.value & self.MODIFY_USERS_CREDENTIALS_SCHEDULES_LOCALLY) ~= 0 +end + +DlLocalProgrammingFeatures.set_modify_users_credentials_schedules_locally = function(self) + if self.value ~= nil then + self.value = self.value | self.MODIFY_USERS_CREDENTIALS_SCHEDULES_LOCALLY + else + self.value = self.MODIFY_USERS_CREDENTIALS_SCHEDULES_LOCALLY + end +end + +DlLocalProgrammingFeatures.unset_modify_users_credentials_schedules_locally = function(self) + self.value = self.value & (~self.MODIFY_USERS_CREDENTIALS_SCHEDULES_LOCALLY & self.BASE_MASK) +end + +DlLocalProgrammingFeatures.is_clear_users_credentials_schedules_locally_set = function(self) + return (self.value & self.CLEAR_USERS_CREDENTIALS_SCHEDULES_LOCALLY) ~= 0 +end + +DlLocalProgrammingFeatures.set_clear_users_credentials_schedules_locally = function(self) + if self.value ~= nil then + self.value = self.value | self.CLEAR_USERS_CREDENTIALS_SCHEDULES_LOCALLY + else + self.value = self.CLEAR_USERS_CREDENTIALS_SCHEDULES_LOCALLY + end +end + +DlLocalProgrammingFeatures.unset_clear_users_credentials_schedules_locally = function(self) + self.value = self.value & (~self.CLEAR_USERS_CREDENTIALS_SCHEDULES_LOCALLY & self.BASE_MASK) +end + +DlLocalProgrammingFeatures.is_adjust_lock_settings_locally_set = function(self) + return (self.value & self.ADJUST_LOCK_SETTINGS_LOCALLY) ~= 0 +end + +DlLocalProgrammingFeatures.set_adjust_lock_settings_locally = function(self) + if self.value ~= nil then + self.value = self.value | self.ADJUST_LOCK_SETTINGS_LOCALLY + else + self.value = self.ADJUST_LOCK_SETTINGS_LOCALLY + end +end + +DlLocalProgrammingFeatures.unset_adjust_lock_settings_locally = function(self) + self.value = self.value & (~self.ADJUST_LOCK_SETTINGS_LOCALLY & self.BASE_MASK) +end + +DlLocalProgrammingFeatures.mask_methods = { + is_add_users_credentials_schedules_locally_set = DlLocalProgrammingFeatures.is_add_users_credentials_schedules_locally_set, + set_add_users_credentials_schedules_locally = DlLocalProgrammingFeatures.set_add_users_credentials_schedules_locally, + unset_add_users_credentials_schedules_locally = DlLocalProgrammingFeatures.unset_add_users_credentials_schedules_locally, + is_modify_users_credentials_schedules_locally_set = DlLocalProgrammingFeatures.is_modify_users_credentials_schedules_locally_set, + set_modify_users_credentials_schedules_locally = DlLocalProgrammingFeatures.set_modify_users_credentials_schedules_locally, + unset_modify_users_credentials_schedules_locally = DlLocalProgrammingFeatures.unset_modify_users_credentials_schedules_locally, + is_clear_users_credentials_schedules_locally_set = DlLocalProgrammingFeatures.is_clear_users_credentials_schedules_locally_set, + set_clear_users_credentials_schedules_locally = DlLocalProgrammingFeatures.set_clear_users_credentials_schedules_locally, + unset_clear_users_credentials_schedules_locally = DlLocalProgrammingFeatures.unset_clear_users_credentials_schedules_locally, + is_adjust_lock_settings_locally_set = DlLocalProgrammingFeatures.is_adjust_lock_settings_locally_set, + set_adjust_lock_settings_locally = DlLocalProgrammingFeatures.set_adjust_lock_settings_locally, + unset_adjust_lock_settings_locally = DlLocalProgrammingFeatures.unset_adjust_lock_settings_locally, +} + +DlLocalProgrammingFeatures.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlLocalProgrammingFeatures, new_mt) + +return DlLocalProgrammingFeatures \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlLockState.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlLockState.lua new file mode 100644 index 0000000000..49fa7d2eb6 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlLockState.lua @@ -0,0 +1,33 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlLockState = {} +local new_mt = UintABC.new_mt({NAME = "DlLockState", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.NOT_FULLY_LOCKED] = "NOT_FULLY_LOCKED", + [self.LOCKED] = "LOCKED", + [self.UNLOCKED] = "UNLOCKED", + [self.UNLATCHED] = "UNLATCHED", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.NOT_FULLY_LOCKED = 0x00 +new_mt.__index.LOCKED = 0x01 +new_mt.__index.UNLOCKED = 0x02 +new_mt.__index.UNLATCHED = 0x03 + +DlLockState.NOT_FULLY_LOCKED = 0x00 +DlLockState.LOCKED = 0x01 +DlLockState.UNLOCKED = 0x02 +DlLockState.UNLATCHED = 0x03 + +DlLockState.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlLockState, new_mt) + +return DlLockState \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlManualOperationEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlManualOperationEventMask.lua new file mode 100644 index 0000000000..9c9803125d --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlManualOperationEventMask.lua @@ -0,0 +1,253 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlManualOperationEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlManualOperationEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlManualOperationEventMask.BASE_MASK = 0xFFFF +DlManualOperationEventMask.UNKNOWN = 0x0001 +DlManualOperationEventMask.THUMBTURN_LOCK = 0x0002 +DlManualOperationEventMask.THUMBTURN_UNLOCK = 0x0004 +DlManualOperationEventMask.ONE_TOUCH_LOCK = 0x0008 +DlManualOperationEventMask.KEY_LOCK = 0x0010 +DlManualOperationEventMask.KEY_UNLOCK = 0x0020 +DlManualOperationEventMask.AUTO_LOCK = 0x0040 +DlManualOperationEventMask.SCHEDULE_LOCK = 0x0080 +DlManualOperationEventMask.SCHEDULE_UNLOCK = 0x0100 +DlManualOperationEventMask.MANUAL_LOCK = 0x0200 +DlManualOperationEventMask.MANUAL_UNLOCK = 0x0400 + +DlManualOperationEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + THUMBTURN_LOCK = 0x0002, + THUMBTURN_UNLOCK = 0x0004, + ONE_TOUCH_LOCK = 0x0008, + KEY_LOCK = 0x0010, + KEY_UNLOCK = 0x0020, + AUTO_LOCK = 0x0040, + SCHEDULE_LOCK = 0x0080, + SCHEDULE_UNLOCK = 0x0100, + MANUAL_LOCK = 0x0200, + MANUAL_UNLOCK = 0x0400, +} + +DlManualOperationEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlManualOperationEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlManualOperationEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlManualOperationEventMask.is_thumbturn_lock_set = function(self) + return (self.value & self.THUMBTURN_LOCK) ~= 0 +end + +DlManualOperationEventMask.set_thumbturn_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.THUMBTURN_LOCK + else + self.value = self.THUMBTURN_LOCK + end +end + +DlManualOperationEventMask.unset_thumbturn_lock = function(self) + self.value = self.value & (~self.THUMBTURN_LOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_thumbturn_unlock_set = function(self) + return (self.value & self.THUMBTURN_UNLOCK) ~= 0 +end + +DlManualOperationEventMask.set_thumbturn_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.THUMBTURN_UNLOCK + else + self.value = self.THUMBTURN_UNLOCK + end +end + +DlManualOperationEventMask.unset_thumbturn_unlock = function(self) + self.value = self.value & (~self.THUMBTURN_UNLOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_one_touch_lock_set = function(self) + return (self.value & self.ONE_TOUCH_LOCK) ~= 0 +end + +DlManualOperationEventMask.set_one_touch_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.ONE_TOUCH_LOCK + else + self.value = self.ONE_TOUCH_LOCK + end +end + +DlManualOperationEventMask.unset_one_touch_lock = function(self) + self.value = self.value & (~self.ONE_TOUCH_LOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_key_lock_set = function(self) + return (self.value & self.KEY_LOCK) ~= 0 +end + +DlManualOperationEventMask.set_key_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.KEY_LOCK + else + self.value = self.KEY_LOCK + end +end + +DlManualOperationEventMask.unset_key_lock = function(self) + self.value = self.value & (~self.KEY_LOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_key_unlock_set = function(self) + return (self.value & self.KEY_UNLOCK) ~= 0 +end + +DlManualOperationEventMask.set_key_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.KEY_UNLOCK + else + self.value = self.KEY_UNLOCK + end +end + +DlManualOperationEventMask.unset_key_unlock = function(self) + self.value = self.value & (~self.KEY_UNLOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_auto_lock_set = function(self) + return (self.value & self.AUTO_LOCK) ~= 0 +end + +DlManualOperationEventMask.set_auto_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.AUTO_LOCK + else + self.value = self.AUTO_LOCK + end +end + +DlManualOperationEventMask.unset_auto_lock = function(self) + self.value = self.value & (~self.AUTO_LOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_schedule_lock_set = function(self) + return (self.value & self.SCHEDULE_LOCK) ~= 0 +end + +DlManualOperationEventMask.set_schedule_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.SCHEDULE_LOCK + else + self.value = self.SCHEDULE_LOCK + end +end + +DlManualOperationEventMask.unset_schedule_lock = function(self) + self.value = self.value & (~self.SCHEDULE_LOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_schedule_unlock_set = function(self) + return (self.value & self.SCHEDULE_UNLOCK) ~= 0 +end + +DlManualOperationEventMask.set_schedule_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.SCHEDULE_UNLOCK + else + self.value = self.SCHEDULE_UNLOCK + end +end + +DlManualOperationEventMask.unset_schedule_unlock = function(self) + self.value = self.value & (~self.SCHEDULE_UNLOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_manual_lock_set = function(self) + return (self.value & self.MANUAL_LOCK) ~= 0 +end + +DlManualOperationEventMask.set_manual_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.MANUAL_LOCK + else + self.value = self.MANUAL_LOCK + end +end + +DlManualOperationEventMask.unset_manual_lock = function(self) + self.value = self.value & (~self.MANUAL_LOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.is_manual_unlock_set = function(self) + return (self.value & self.MANUAL_UNLOCK) ~= 0 +end + +DlManualOperationEventMask.set_manual_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.MANUAL_UNLOCK + else + self.value = self.MANUAL_UNLOCK + end +end + +DlManualOperationEventMask.unset_manual_unlock = function(self) + self.value = self.value & (~self.MANUAL_UNLOCK & self.BASE_MASK) +end + +DlManualOperationEventMask.mask_methods = { + is_unknown_set = DlManualOperationEventMask.is_unknown_set, + set_unknown = DlManualOperationEventMask.set_unknown, + unset_unknown = DlManualOperationEventMask.unset_unknown, + is_thumbturn_lock_set = DlManualOperationEventMask.is_thumbturn_lock_set, + set_thumbturn_lock = DlManualOperationEventMask.set_thumbturn_lock, + unset_thumbturn_lock = DlManualOperationEventMask.unset_thumbturn_lock, + is_thumbturn_unlock_set = DlManualOperationEventMask.is_thumbturn_unlock_set, + set_thumbturn_unlock = DlManualOperationEventMask.set_thumbturn_unlock, + unset_thumbturn_unlock = DlManualOperationEventMask.unset_thumbturn_unlock, + is_one_touch_lock_set = DlManualOperationEventMask.is_one_touch_lock_set, + set_one_touch_lock = DlManualOperationEventMask.set_one_touch_lock, + unset_one_touch_lock = DlManualOperationEventMask.unset_one_touch_lock, + is_key_lock_set = DlManualOperationEventMask.is_key_lock_set, + set_key_lock = DlManualOperationEventMask.set_key_lock, + unset_key_lock = DlManualOperationEventMask.unset_key_lock, + is_key_unlock_set = DlManualOperationEventMask.is_key_unlock_set, + set_key_unlock = DlManualOperationEventMask.set_key_unlock, + unset_key_unlock = DlManualOperationEventMask.unset_key_unlock, + is_auto_lock_set = DlManualOperationEventMask.is_auto_lock_set, + set_auto_lock = DlManualOperationEventMask.set_auto_lock, + unset_auto_lock = DlManualOperationEventMask.unset_auto_lock, + is_schedule_lock_set = DlManualOperationEventMask.is_schedule_lock_set, + set_schedule_lock = DlManualOperationEventMask.set_schedule_lock, + unset_schedule_lock = DlManualOperationEventMask.unset_schedule_lock, + is_schedule_unlock_set = DlManualOperationEventMask.is_schedule_unlock_set, + set_schedule_unlock = DlManualOperationEventMask.set_schedule_unlock, + unset_schedule_unlock = DlManualOperationEventMask.unset_schedule_unlock, + is_manual_lock_set = DlManualOperationEventMask.is_manual_lock_set, + set_manual_lock = DlManualOperationEventMask.set_manual_lock, + unset_manual_lock = DlManualOperationEventMask.unset_manual_lock, + is_manual_unlock_set = DlManualOperationEventMask.is_manual_unlock_set, + set_manual_unlock = DlManualOperationEventMask.set_manual_unlock, + unset_manual_unlock = DlManualOperationEventMask.unset_manual_unlock, +} + +DlManualOperationEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlManualOperationEventMask, new_mt) + +return DlManualOperationEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRFIDOperationEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRFIDOperationEventMask.lua new file mode 100644 index 0000000000..3877280e5e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRFIDOperationEventMask.lua @@ -0,0 +1,169 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlRFIDOperationEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlRFIDOperationEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlRFIDOperationEventMask.BASE_MASK = 0xFFFF +DlRFIDOperationEventMask.UNKNOWN = 0x0001 +DlRFIDOperationEventMask.LOCK = 0x0002 +DlRFIDOperationEventMask.UNLOCK = 0x0004 +DlRFIDOperationEventMask.LOCK_INVALIDRFID = 0x0008 +DlRFIDOperationEventMask.LOCK_INVALID_SCHEDULE = 0x0010 +DlRFIDOperationEventMask.UNLOCK_INVALIDRFID = 0x0020 +DlRFIDOperationEventMask.UNLOCK_INVALID_SCHEDULE = 0x0040 + +DlRFIDOperationEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + LOCK = 0x0002, + UNLOCK = 0x0004, + LOCK_INVALIDRFID = 0x0008, + LOCK_INVALID_SCHEDULE = 0x0010, + UNLOCK_INVALIDRFID = 0x0020, + UNLOCK_INVALID_SCHEDULE = 0x0040, +} + +DlRFIDOperationEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlRFIDOperationEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlRFIDOperationEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlRFIDOperationEventMask.is_lock_set = function(self) + return (self.value & self.LOCK) ~= 0 +end + +DlRFIDOperationEventMask.set_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK + else + self.value = self.LOCK + end +end + +DlRFIDOperationEventMask.unset_lock = function(self) + self.value = self.value & (~self.LOCK & self.BASE_MASK) +end + +DlRFIDOperationEventMask.is_unlock_set = function(self) + return (self.value & self.UNLOCK) ~= 0 +end + +DlRFIDOperationEventMask.set_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK + else + self.value = self.UNLOCK + end +end + +DlRFIDOperationEventMask.unset_unlock = function(self) + self.value = self.value & (~self.UNLOCK & self.BASE_MASK) +end + +DlRFIDOperationEventMask.is_lock_invalidrfid_set = function(self) + return (self.value & self.LOCK_INVALIDRFID) ~= 0 +end + +DlRFIDOperationEventMask.set_lock_invalidrfid = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK_INVALIDRFID + else + self.value = self.LOCK_INVALIDRFID + end +end + +DlRFIDOperationEventMask.unset_lock_invalidrfid = function(self) + self.value = self.value & (~self.LOCK_INVALIDRFID & self.BASE_MASK) +end + +DlRFIDOperationEventMask.is_lock_invalid_schedule_set = function(self) + return (self.value & self.LOCK_INVALID_SCHEDULE) ~= 0 +end + +DlRFIDOperationEventMask.set_lock_invalid_schedule = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK_INVALID_SCHEDULE + else + self.value = self.LOCK_INVALID_SCHEDULE + end +end + +DlRFIDOperationEventMask.unset_lock_invalid_schedule = function(self) + self.value = self.value & (~self.LOCK_INVALID_SCHEDULE & self.BASE_MASK) +end + +DlRFIDOperationEventMask.is_unlock_invalidrfid_set = function(self) + return (self.value & self.UNLOCK_INVALIDRFID) ~= 0 +end + +DlRFIDOperationEventMask.set_unlock_invalidrfid = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK_INVALIDRFID + else + self.value = self.UNLOCK_INVALIDRFID + end +end + +DlRFIDOperationEventMask.unset_unlock_invalidrfid = function(self) + self.value = self.value & (~self.UNLOCK_INVALIDRFID & self.BASE_MASK) +end + +DlRFIDOperationEventMask.is_unlock_invalid_schedule_set = function(self) + return (self.value & self.UNLOCK_INVALID_SCHEDULE) ~= 0 +end + +DlRFIDOperationEventMask.set_unlock_invalid_schedule = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK_INVALID_SCHEDULE + else + self.value = self.UNLOCK_INVALID_SCHEDULE + end +end + +DlRFIDOperationEventMask.unset_unlock_invalid_schedule = function(self) + self.value = self.value & (~self.UNLOCK_INVALID_SCHEDULE & self.BASE_MASK) +end + +DlRFIDOperationEventMask.mask_methods = { + is_unknown_set = DlRFIDOperationEventMask.is_unknown_set, + set_unknown = DlRFIDOperationEventMask.set_unknown, + unset_unknown = DlRFIDOperationEventMask.unset_unknown, + is_lock_set = DlRFIDOperationEventMask.is_lock_set, + set_lock = DlRFIDOperationEventMask.set_lock, + unset_lock = DlRFIDOperationEventMask.unset_lock, + is_unlock_set = DlRFIDOperationEventMask.is_unlock_set, + set_unlock = DlRFIDOperationEventMask.set_unlock, + unset_unlock = DlRFIDOperationEventMask.unset_unlock, + is_lock_invalidrfid_set = DlRFIDOperationEventMask.is_lock_invalidrfid_set, + set_lock_invalidrfid = DlRFIDOperationEventMask.set_lock_invalidrfid, + unset_lock_invalidrfid = DlRFIDOperationEventMask.unset_lock_invalidrfid, + is_lock_invalid_schedule_set = DlRFIDOperationEventMask.is_lock_invalid_schedule_set, + set_lock_invalid_schedule = DlRFIDOperationEventMask.set_lock_invalid_schedule, + unset_lock_invalid_schedule = DlRFIDOperationEventMask.unset_lock_invalid_schedule, + is_unlock_invalidrfid_set = DlRFIDOperationEventMask.is_unlock_invalidrfid_set, + set_unlock_invalidrfid = DlRFIDOperationEventMask.set_unlock_invalidrfid, + unset_unlock_invalidrfid = DlRFIDOperationEventMask.unset_unlock_invalidrfid, + is_unlock_invalid_schedule_set = DlRFIDOperationEventMask.is_unlock_invalid_schedule_set, + set_unlock_invalid_schedule = DlRFIDOperationEventMask.set_unlock_invalid_schedule, + unset_unlock_invalid_schedule = DlRFIDOperationEventMask.unset_unlock_invalid_schedule, +} + +DlRFIDOperationEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlRFIDOperationEventMask, new_mt) + +return DlRFIDOperationEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRFIDProgrammingEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRFIDProgrammingEventMask.lua new file mode 100644 index 0000000000..439f0ebbff --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRFIDProgrammingEventMask.lua @@ -0,0 +1,85 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlRFIDProgrammingEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlRFIDProgrammingEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlRFIDProgrammingEventMask.BASE_MASK = 0xFFFF +DlRFIDProgrammingEventMask.UNKNOWN = 0x0001 +DlRFIDProgrammingEventMask.RFID_CODE_ADDED = 0x0020 +DlRFIDProgrammingEventMask.RFID_CODE_CLEARED = 0x0040 + +DlRFIDProgrammingEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + RFID_CODE_ADDED = 0x0020, + RFID_CODE_CLEARED = 0x0040, +} + +DlRFIDProgrammingEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlRFIDProgrammingEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlRFIDProgrammingEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlRFIDProgrammingEventMask.is_rfid_code_added_set = function(self) + return (self.value & self.RFID_CODE_ADDED) ~= 0 +end + +DlRFIDProgrammingEventMask.set_rfid_code_added = function(self) + if self.value ~= nil then + self.value = self.value | self.RFID_CODE_ADDED + else + self.value = self.RFID_CODE_ADDED + end +end + +DlRFIDProgrammingEventMask.unset_rfid_code_added = function(self) + self.value = self.value & (~self.RFID_CODE_ADDED & self.BASE_MASK) +end + +DlRFIDProgrammingEventMask.is_rfid_code_cleared_set = function(self) + return (self.value & self.RFID_CODE_CLEARED) ~= 0 +end + +DlRFIDProgrammingEventMask.set_rfid_code_cleared = function(self) + if self.value ~= nil then + self.value = self.value | self.RFID_CODE_CLEARED + else + self.value = self.RFID_CODE_CLEARED + end +end + +DlRFIDProgrammingEventMask.unset_rfid_code_cleared = function(self) + self.value = self.value & (~self.RFID_CODE_CLEARED & self.BASE_MASK) +end + +DlRFIDProgrammingEventMask.mask_methods = { + is_unknown_set = DlRFIDProgrammingEventMask.is_unknown_set, + set_unknown = DlRFIDProgrammingEventMask.set_unknown, + unset_unknown = DlRFIDProgrammingEventMask.unset_unknown, + is_rfid_code_added_set = DlRFIDProgrammingEventMask.is_rfid_code_added_set, + set_rfid_code_added = DlRFIDProgrammingEventMask.set_rfid_code_added, + unset_rfid_code_added = DlRFIDProgrammingEventMask.unset_rfid_code_added, + is_rfid_code_cleared_set = DlRFIDProgrammingEventMask.is_rfid_code_cleared_set, + set_rfid_code_cleared = DlRFIDProgrammingEventMask.set_rfid_code_cleared, + unset_rfid_code_cleared = DlRFIDProgrammingEventMask.unset_rfid_code_cleared, +} + +DlRFIDProgrammingEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlRFIDProgrammingEventMask, new_mt) + +return DlRFIDProgrammingEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRemoteOperationEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRemoteOperationEventMask.lua new file mode 100644 index 0000000000..0dfed6af72 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRemoteOperationEventMask.lua @@ -0,0 +1,169 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlRemoteOperationEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlRemoteOperationEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlRemoteOperationEventMask.BASE_MASK = 0xFFFF +DlRemoteOperationEventMask.UNKNOWN = 0x0001 +DlRemoteOperationEventMask.LOCK = 0x0002 +DlRemoteOperationEventMask.UNLOCK = 0x0004 +DlRemoteOperationEventMask.LOCK_INVALID_CODE = 0x0008 +DlRemoteOperationEventMask.LOCK_INVALID_SCHEDULE = 0x0010 +DlRemoteOperationEventMask.UNLOCK_INVALID_CODE = 0x0020 +DlRemoteOperationEventMask.UNLOCK_INVALID_SCHEDULE = 0x0040 + +DlRemoteOperationEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + LOCK = 0x0002, + UNLOCK = 0x0004, + LOCK_INVALID_CODE = 0x0008, + LOCK_INVALID_SCHEDULE = 0x0010, + UNLOCK_INVALID_CODE = 0x0020, + UNLOCK_INVALID_SCHEDULE = 0x0040, +} + +DlRemoteOperationEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlRemoteOperationEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlRemoteOperationEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlRemoteOperationEventMask.is_lock_set = function(self) + return (self.value & self.LOCK) ~= 0 +end + +DlRemoteOperationEventMask.set_lock = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK + else + self.value = self.LOCK + end +end + +DlRemoteOperationEventMask.unset_lock = function(self) + self.value = self.value & (~self.LOCK & self.BASE_MASK) +end + +DlRemoteOperationEventMask.is_unlock_set = function(self) + return (self.value & self.UNLOCK) ~= 0 +end + +DlRemoteOperationEventMask.set_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK + else + self.value = self.UNLOCK + end +end + +DlRemoteOperationEventMask.unset_unlock = function(self) + self.value = self.value & (~self.UNLOCK & self.BASE_MASK) +end + +DlRemoteOperationEventMask.is_lock_invalid_code_set = function(self) + return (self.value & self.LOCK_INVALID_CODE) ~= 0 +end + +DlRemoteOperationEventMask.set_lock_invalid_code = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK_INVALID_CODE + else + self.value = self.LOCK_INVALID_CODE + end +end + +DlRemoteOperationEventMask.unset_lock_invalid_code = function(self) + self.value = self.value & (~self.LOCK_INVALID_CODE & self.BASE_MASK) +end + +DlRemoteOperationEventMask.is_lock_invalid_schedule_set = function(self) + return (self.value & self.LOCK_INVALID_SCHEDULE) ~= 0 +end + +DlRemoteOperationEventMask.set_lock_invalid_schedule = function(self) + if self.value ~= nil then + self.value = self.value | self.LOCK_INVALID_SCHEDULE + else + self.value = self.LOCK_INVALID_SCHEDULE + end +end + +DlRemoteOperationEventMask.unset_lock_invalid_schedule = function(self) + self.value = self.value & (~self.LOCK_INVALID_SCHEDULE & self.BASE_MASK) +end + +DlRemoteOperationEventMask.is_unlock_invalid_code_set = function(self) + return (self.value & self.UNLOCK_INVALID_CODE) ~= 0 +end + +DlRemoteOperationEventMask.set_unlock_invalid_code = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK_INVALID_CODE + else + self.value = self.UNLOCK_INVALID_CODE + end +end + +DlRemoteOperationEventMask.unset_unlock_invalid_code = function(self) + self.value = self.value & (~self.UNLOCK_INVALID_CODE & self.BASE_MASK) +end + +DlRemoteOperationEventMask.is_unlock_invalid_schedule_set = function(self) + return (self.value & self.UNLOCK_INVALID_SCHEDULE) ~= 0 +end + +DlRemoteOperationEventMask.set_unlock_invalid_schedule = function(self) + if self.value ~= nil then + self.value = self.value | self.UNLOCK_INVALID_SCHEDULE + else + self.value = self.UNLOCK_INVALID_SCHEDULE + end +end + +DlRemoteOperationEventMask.unset_unlock_invalid_schedule = function(self) + self.value = self.value & (~self.UNLOCK_INVALID_SCHEDULE & self.BASE_MASK) +end + +DlRemoteOperationEventMask.mask_methods = { + is_unknown_set = DlRemoteOperationEventMask.is_unknown_set, + set_unknown = DlRemoteOperationEventMask.set_unknown, + unset_unknown = DlRemoteOperationEventMask.unset_unknown, + is_lock_set = DlRemoteOperationEventMask.is_lock_set, + set_lock = DlRemoteOperationEventMask.set_lock, + unset_lock = DlRemoteOperationEventMask.unset_lock, + is_unlock_set = DlRemoteOperationEventMask.is_unlock_set, + set_unlock = DlRemoteOperationEventMask.set_unlock, + unset_unlock = DlRemoteOperationEventMask.unset_unlock, + is_lock_invalid_code_set = DlRemoteOperationEventMask.is_lock_invalid_code_set, + set_lock_invalid_code = DlRemoteOperationEventMask.set_lock_invalid_code, + unset_lock_invalid_code = DlRemoteOperationEventMask.unset_lock_invalid_code, + is_lock_invalid_schedule_set = DlRemoteOperationEventMask.is_lock_invalid_schedule_set, + set_lock_invalid_schedule = DlRemoteOperationEventMask.set_lock_invalid_schedule, + unset_lock_invalid_schedule = DlRemoteOperationEventMask.unset_lock_invalid_schedule, + is_unlock_invalid_code_set = DlRemoteOperationEventMask.is_unlock_invalid_code_set, + set_unlock_invalid_code = DlRemoteOperationEventMask.set_unlock_invalid_code, + unset_unlock_invalid_code = DlRemoteOperationEventMask.unset_unlock_invalid_code, + is_unlock_invalid_schedule_set = DlRemoteOperationEventMask.is_unlock_invalid_schedule_set, + set_unlock_invalid_schedule = DlRemoteOperationEventMask.set_unlock_invalid_schedule, + unset_unlock_invalid_schedule = DlRemoteOperationEventMask.unset_unlock_invalid_schedule, +} + +DlRemoteOperationEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlRemoteOperationEventMask, new_mt) + +return DlRemoteOperationEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRemoteProgrammingEventMask.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRemoteProgrammingEventMask.lua new file mode 100644 index 0000000000..c0a14c5e1a --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlRemoteProgrammingEventMask.lua @@ -0,0 +1,169 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlRemoteProgrammingEventMask = {} +local new_mt = UintABC.new_mt({NAME = "DlRemoteProgrammingEventMask", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlRemoteProgrammingEventMask.BASE_MASK = 0xFFFF +DlRemoteProgrammingEventMask.UNKNOWN = 0x0001 +DlRemoteProgrammingEventMask.PROGRAMMINGPIN_CHANGED = 0x0002 +DlRemoteProgrammingEventMask.PIN_ADDED = 0x0004 +DlRemoteProgrammingEventMask.PIN_CLEARED = 0x0008 +DlRemoteProgrammingEventMask.PIN_CHANGED = 0x0010 +DlRemoteProgrammingEventMask.RFID_CODE_ADDED = 0x0020 +DlRemoteProgrammingEventMask.RFID_CODE_CLEARED = 0x0040 + +DlRemoteProgrammingEventMask.mask_fields = { + BASE_MASK = 0xFFFF, + UNKNOWN = 0x0001, + PROGRAMMINGPIN_CHANGED = 0x0002, + PIN_ADDED = 0x0004, + PIN_CLEARED = 0x0008, + PIN_CHANGED = 0x0010, + RFID_CODE_ADDED = 0x0020, + RFID_CODE_CLEARED = 0x0040, +} + +DlRemoteProgrammingEventMask.is_unknown_set = function(self) + return (self.value & self.UNKNOWN) ~= 0 +end + +DlRemoteProgrammingEventMask.set_unknown = function(self) + if self.value ~= nil then + self.value = self.value | self.UNKNOWN + else + self.value = self.UNKNOWN + end +end + +DlRemoteProgrammingEventMask.unset_unknown = function(self) + self.value = self.value & (~self.UNKNOWN & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.is_programmingpin_changed_set = function(self) + return (self.value & self.PROGRAMMINGPIN_CHANGED) ~= 0 +end + +DlRemoteProgrammingEventMask.set_programmingpin_changed = function(self) + if self.value ~= nil then + self.value = self.value | self.PROGRAMMINGPIN_CHANGED + else + self.value = self.PROGRAMMINGPIN_CHANGED + end +end + +DlRemoteProgrammingEventMask.unset_programmingpin_changed = function(self) + self.value = self.value & (~self.PROGRAMMINGPIN_CHANGED & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.is_pin_added_set = function(self) + return (self.value & self.PIN_ADDED) ~= 0 +end + +DlRemoteProgrammingEventMask.set_pin_added = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_ADDED + else + self.value = self.PIN_ADDED + end +end + +DlRemoteProgrammingEventMask.unset_pin_added = function(self) + self.value = self.value & (~self.PIN_ADDED & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.is_pin_cleared_set = function(self) + return (self.value & self.PIN_CLEARED) ~= 0 +end + +DlRemoteProgrammingEventMask.set_pin_cleared = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_CLEARED + else + self.value = self.PIN_CLEARED + end +end + +DlRemoteProgrammingEventMask.unset_pin_cleared = function(self) + self.value = self.value & (~self.PIN_CLEARED & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.is_pin_changed_set = function(self) + return (self.value & self.PIN_CHANGED) ~= 0 +end + +DlRemoteProgrammingEventMask.set_pin_changed = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_CHANGED + else + self.value = self.PIN_CHANGED + end +end + +DlRemoteProgrammingEventMask.unset_pin_changed = function(self) + self.value = self.value & (~self.PIN_CHANGED & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.is_rfid_code_added_set = function(self) + return (self.value & self.RFID_CODE_ADDED) ~= 0 +end + +DlRemoteProgrammingEventMask.set_rfid_code_added = function(self) + if self.value ~= nil then + self.value = self.value | self.RFID_CODE_ADDED + else + self.value = self.RFID_CODE_ADDED + end +end + +DlRemoteProgrammingEventMask.unset_rfid_code_added = function(self) + self.value = self.value & (~self.RFID_CODE_ADDED & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.is_rfid_code_cleared_set = function(self) + return (self.value & self.RFID_CODE_CLEARED) ~= 0 +end + +DlRemoteProgrammingEventMask.set_rfid_code_cleared = function(self) + if self.value ~= nil then + self.value = self.value | self.RFID_CODE_CLEARED + else + self.value = self.RFID_CODE_CLEARED + end +end + +DlRemoteProgrammingEventMask.unset_rfid_code_cleared = function(self) + self.value = self.value & (~self.RFID_CODE_CLEARED & self.BASE_MASK) +end + +DlRemoteProgrammingEventMask.mask_methods = { + is_unknown_set = DlRemoteProgrammingEventMask.is_unknown_set, + set_unknown = DlRemoteProgrammingEventMask.set_unknown, + unset_unknown = DlRemoteProgrammingEventMask.unset_unknown, + is_programmingpin_changed_set = DlRemoteProgrammingEventMask.is_programmingpin_changed_set, + set_programmingpin_changed = DlRemoteProgrammingEventMask.set_programmingpin_changed, + unset_programmingpin_changed = DlRemoteProgrammingEventMask.unset_programmingpin_changed, + is_pin_added_set = DlRemoteProgrammingEventMask.is_pin_added_set, + set_pin_added = DlRemoteProgrammingEventMask.set_pin_added, + unset_pin_added = DlRemoteProgrammingEventMask.unset_pin_added, + is_pin_cleared_set = DlRemoteProgrammingEventMask.is_pin_cleared_set, + set_pin_cleared = DlRemoteProgrammingEventMask.set_pin_cleared, + unset_pin_cleared = DlRemoteProgrammingEventMask.unset_pin_cleared, + is_pin_changed_set = DlRemoteProgrammingEventMask.is_pin_changed_set, + set_pin_changed = DlRemoteProgrammingEventMask.set_pin_changed, + unset_pin_changed = DlRemoteProgrammingEventMask.unset_pin_changed, + is_rfid_code_added_set = DlRemoteProgrammingEventMask.is_rfid_code_added_set, + set_rfid_code_added = DlRemoteProgrammingEventMask.set_rfid_code_added, + unset_rfid_code_added = DlRemoteProgrammingEventMask.unset_rfid_code_added, + is_rfid_code_cleared_set = DlRemoteProgrammingEventMask.is_rfid_code_cleared_set, + set_rfid_code_cleared = DlRemoteProgrammingEventMask.set_rfid_code_cleared, + unset_rfid_code_cleared = DlRemoteProgrammingEventMask.unset_rfid_code_cleared, +} + +DlRemoteProgrammingEventMask.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlRemoteProgrammingEventMask, new_mt) + +return DlRemoteProgrammingEventMask \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlStatus.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlStatus.lua new file mode 100644 index 0000000000..b681fd8018 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlStatus.lua @@ -0,0 +1,42 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlStatus = {} +local new_mt = UintABC.new_mt({NAME = "DlStatus", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.SUCCESS] = "SUCCESS", + [self.FAILURE] = "FAILURE", + [self.DUPLICATE] = "DUPLICATE", + [self.OCCUPIED] = "OCCUPIED", + [self.INVALID_FIELD] = "INVALID_FIELD", + [self.RESOURCE_EXHAUSTED] = "RESOURCE_EXHAUSTED", + [self.NOT_FOUND] = "NOT_FOUND", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.SUCCESS = 0x00 +new_mt.__index.FAILURE = 0x01 +new_mt.__index.DUPLICATE = 0x02 +new_mt.__index.OCCUPIED = 0x03 +new_mt.__index.INVALID_FIELD = 0x85 +new_mt.__index.RESOURCE_EXHAUSTED = 0x89 +new_mt.__index.NOT_FOUND = 0x8B + +DlStatus.SUCCESS = 0x00 +DlStatus.FAILURE = 0x01 +DlStatus.DUPLICATE = 0x02 +DlStatus.OCCUPIED = 0x03 +DlStatus.INVALID_FIELD = 0x85 +DlStatus.RESOURCE_EXHAUSTED = 0x89 +DlStatus.NOT_FOUND = 0x8B + +DlStatus.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlStatus, new_mt) + +return DlStatus \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DlSupportedOperatingModes.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlSupportedOperatingModes.lua new file mode 100644 index 0000000000..5e529146c2 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DlSupportedOperatingModes.lua @@ -0,0 +1,127 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DlSupportedOperatingModes = {} +local new_mt = UintABC.new_mt({NAME = "DlSupportedOperatingModes", ID = data_types.name_to_id_map["Uint16"]}, 2) + +DlSupportedOperatingModes.BASE_MASK = 0xFFFF +DlSupportedOperatingModes.NORMAL = 0x0001 +DlSupportedOperatingModes.VACATION = 0x0002 +DlSupportedOperatingModes.PRIVACY = 0x0004 +DlSupportedOperatingModes.NO_REMOTE_LOCK_UNLOCK = 0x0008 +DlSupportedOperatingModes.PASSAGE = 0x0010 + +DlSupportedOperatingModes.mask_fields = { + BASE_MASK = 0xFFFF, + NORMAL = 0x0001, + VACATION = 0x0002, + PRIVACY = 0x0004, + NO_REMOTE_LOCK_UNLOCK = 0x0008, + PASSAGE = 0x0010, +} + +DlSupportedOperatingModes.is_normal_set = function(self) + return (self.value & self.NORMAL) ~= 0 +end + +DlSupportedOperatingModes.set_normal = function(self) + if self.value ~= nil then + self.value = self.value | self.NORMAL + else + self.value = self.NORMAL + end +end + +DlSupportedOperatingModes.unset_normal = function(self) + self.value = self.value & (~self.NORMAL & self.BASE_MASK) +end + +DlSupportedOperatingModes.is_vacation_set = function(self) + return (self.value & self.VACATION) ~= 0 +end + +DlSupportedOperatingModes.set_vacation = function(self) + if self.value ~= nil then + self.value = self.value | self.VACATION + else + self.value = self.VACATION + end +end + +DlSupportedOperatingModes.unset_vacation = function(self) + self.value = self.value & (~self.VACATION & self.BASE_MASK) +end + +DlSupportedOperatingModes.is_privacy_set = function(self) + return (self.value & self.PRIVACY) ~= 0 +end + +DlSupportedOperatingModes.set_privacy = function(self) + if self.value ~= nil then + self.value = self.value | self.PRIVACY + else + self.value = self.PRIVACY + end +end + +DlSupportedOperatingModes.unset_privacy = function(self) + self.value = self.value & (~self.PRIVACY & self.BASE_MASK) +end + +DlSupportedOperatingModes.is_no_remote_lock_unlock_set = function(self) + return (self.value & self.NO_REMOTE_LOCK_UNLOCK) ~= 0 +end + +DlSupportedOperatingModes.set_no_remote_lock_unlock = function(self) + if self.value ~= nil then + self.value = self.value | self.NO_REMOTE_LOCK_UNLOCK + else + self.value = self.NO_REMOTE_LOCK_UNLOCK + end +end + +DlSupportedOperatingModes.unset_no_remote_lock_unlock = function(self) + self.value = self.value & (~self.NO_REMOTE_LOCK_UNLOCK & self.BASE_MASK) +end + +DlSupportedOperatingModes.is_passage_set = function(self) + return (self.value & self.PASSAGE) ~= 0 +end + +DlSupportedOperatingModes.set_passage = function(self) + if self.value ~= nil then + self.value = self.value | self.PASSAGE + else + self.value = self.PASSAGE + end +end + +DlSupportedOperatingModes.unset_passage = function(self) + self.value = self.value & (~self.PASSAGE & self.BASE_MASK) +end + +DlSupportedOperatingModes.mask_methods = { + is_normal_set = DlSupportedOperatingModes.is_normal_set, + set_normal = DlSupportedOperatingModes.set_normal, + unset_normal = DlSupportedOperatingModes.unset_normal, + is_vacation_set = DlSupportedOperatingModes.is_vacation_set, + set_vacation = DlSupportedOperatingModes.set_vacation, + unset_vacation = DlSupportedOperatingModes.unset_vacation, + is_privacy_set = DlSupportedOperatingModes.is_privacy_set, + set_privacy = DlSupportedOperatingModes.set_privacy, + unset_privacy = DlSupportedOperatingModes.unset_privacy, + is_no_remote_lock_unlock_set = DlSupportedOperatingModes.is_no_remote_lock_unlock_set, + set_no_remote_lock_unlock = DlSupportedOperatingModes.set_no_remote_lock_unlock, + unset_no_remote_lock_unlock = DlSupportedOperatingModes.unset_no_remote_lock_unlock, + is_passage_set = DlSupportedOperatingModes.is_passage_set, + set_passage = DlSupportedOperatingModes.set_passage, + unset_passage = DlSupportedOperatingModes.unset_passage, +} + +DlSupportedOperatingModes.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DlSupportedOperatingModes, new_mt) + +return DlSupportedOperatingModes \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockDayOfWeek.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockDayOfWeek.lua new file mode 100644 index 0000000000..9a03693d35 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockDayOfWeek.lua @@ -0,0 +1,169 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorLockDayOfWeek = {} +local new_mt = UintABC.new_mt({NAME = "DoorLockDayOfWeek", ID = data_types.name_to_id_map["Uint8"]}, 1) + +DoorLockDayOfWeek.BASE_MASK = 0xFFFF +DoorLockDayOfWeek.SUNDAY = 0x0001 +DoorLockDayOfWeek.MONDAY = 0x0002 +DoorLockDayOfWeek.TUESDAY = 0x0004 +DoorLockDayOfWeek.WEDNESDAY = 0x0008 +DoorLockDayOfWeek.THURSDAY = 0x0010 +DoorLockDayOfWeek.FRIDAY = 0x0020 +DoorLockDayOfWeek.SATURDAY = 0x0040 + +DoorLockDayOfWeek.mask_fields = { + BASE_MASK = 0xFFFF, + SUNDAY = 0x0001, + MONDAY = 0x0002, + TUESDAY = 0x0004, + WEDNESDAY = 0x0008, + THURSDAY = 0x0010, + FRIDAY = 0x0020, + SATURDAY = 0x0040, +} + +DoorLockDayOfWeek.is_sunday_set = function(self) + return (self.value & self.SUNDAY) ~= 0 +end + +DoorLockDayOfWeek.set_sunday = function(self) + if self.value ~= nil then + self.value = self.value | self.SUNDAY + else + self.value = self.SUNDAY + end +end + +DoorLockDayOfWeek.unset_sunday = function(self) + self.value = self.value & (~self.SUNDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.is_monday_set = function(self) + return (self.value & self.MONDAY) ~= 0 +end + +DoorLockDayOfWeek.set_monday = function(self) + if self.value ~= nil then + self.value = self.value | self.MONDAY + else + self.value = self.MONDAY + end +end + +DoorLockDayOfWeek.unset_monday = function(self) + self.value = self.value & (~self.MONDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.is_tuesday_set = function(self) + return (self.value & self.TUESDAY) ~= 0 +end + +DoorLockDayOfWeek.set_tuesday = function(self) + if self.value ~= nil then + self.value = self.value | self.TUESDAY + else + self.value = self.TUESDAY + end +end + +DoorLockDayOfWeek.unset_tuesday = function(self) + self.value = self.value & (~self.TUESDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.is_wednesday_set = function(self) + return (self.value & self.WEDNESDAY) ~= 0 +end + +DoorLockDayOfWeek.set_wednesday = function(self) + if self.value ~= nil then + self.value = self.value | self.WEDNESDAY + else + self.value = self.WEDNESDAY + end +end + +DoorLockDayOfWeek.unset_wednesday = function(self) + self.value = self.value & (~self.WEDNESDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.is_thursday_set = function(self) + return (self.value & self.THURSDAY) ~= 0 +end + +DoorLockDayOfWeek.set_thursday = function(self) + if self.value ~= nil then + self.value = self.value | self.THURSDAY + else + self.value = self.THURSDAY + end +end + +DoorLockDayOfWeek.unset_thursday = function(self) + self.value = self.value & (~self.THURSDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.is_friday_set = function(self) + return (self.value & self.FRIDAY) ~= 0 +end + +DoorLockDayOfWeek.set_friday = function(self) + if self.value ~= nil then + self.value = self.value | self.FRIDAY + else + self.value = self.FRIDAY + end +end + +DoorLockDayOfWeek.unset_friday = function(self) + self.value = self.value & (~self.FRIDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.is_saturday_set = function(self) + return (self.value & self.SATURDAY) ~= 0 +end + +DoorLockDayOfWeek.set_saturday = function(self) + if self.value ~= nil then + self.value = self.value | self.SATURDAY + else + self.value = self.SATURDAY + end +end + +DoorLockDayOfWeek.unset_saturday = function(self) + self.value = self.value & (~self.SATURDAY & self.BASE_MASK) +end + +DoorLockDayOfWeek.mask_methods = { + is_sunday_set = DoorLockDayOfWeek.is_sunday_set, + set_sunday = DoorLockDayOfWeek.set_sunday, + unset_sunday = DoorLockDayOfWeek.unset_sunday, + is_monday_set = DoorLockDayOfWeek.is_monday_set, + set_monday = DoorLockDayOfWeek.set_monday, + unset_monday = DoorLockDayOfWeek.unset_monday, + is_tuesday_set = DoorLockDayOfWeek.is_tuesday_set, + set_tuesday = DoorLockDayOfWeek.set_tuesday, + unset_tuesday = DoorLockDayOfWeek.unset_tuesday, + is_wednesday_set = DoorLockDayOfWeek.is_wednesday_set, + set_wednesday = DoorLockDayOfWeek.set_wednesday, + unset_wednesday = DoorLockDayOfWeek.unset_wednesday, + is_thursday_set = DoorLockDayOfWeek.is_thursday_set, + set_thursday = DoorLockDayOfWeek.set_thursday, + unset_thursday = DoorLockDayOfWeek.unset_thursday, + is_friday_set = DoorLockDayOfWeek.is_friday_set, + set_friday = DoorLockDayOfWeek.set_friday, + unset_friday = DoorLockDayOfWeek.unset_friday, + is_saturday_set = DoorLockDayOfWeek.is_saturday_set, + set_saturday = DoorLockDayOfWeek.set_saturday, + unset_saturday = DoorLockDayOfWeek.unset_saturday, +} + +DoorLockDayOfWeek.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorLockDayOfWeek, new_mt) + +return DoorLockDayOfWeek \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockOperationEventCode.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockOperationEventCode.lua new file mode 100644 index 0000000000..556fdff0cd --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockOperationEventCode.lua @@ -0,0 +1,66 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorLockOperationEventCode = {} +local new_mt = UintABC.new_mt({NAME = "DoorLockOperationEventCode", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNKNOWN_OR_MFG_SPECIFIC] = "UNKNOWN_OR_MFG_SPECIFIC", + [self.LOCK] = "LOCK", + [self.UNLOCK] = "UNLOCK", + [self.LOCK_INVALID_PIN_OR_ID] = "LOCK_INVALID_PIN_OR_ID", + [self.LOCK_INVALID_SCHEDULE] = "LOCK_INVALID_SCHEDULE", + [self.UNLOCK_INVALID_PIN_OR_ID] = "UNLOCK_INVALID_PIN_OR_ID", + [self.UNLOCK_INVALID_SCHEDULE] = "UNLOCK_INVALID_SCHEDULE", + [self.ONE_TOUCH_LOCK] = "ONE_TOUCH_LOCK", + [self.KEY_LOCK] = "KEY_LOCK", + [self.KEY_UNLOCK] = "KEY_UNLOCK", + [self.AUTO_LOCK] = "AUTO_LOCK", + [self.SCHEDULE_LOCK] = "SCHEDULE_LOCK", + [self.SCHEDULE_UNLOCK] = "SCHEDULE_UNLOCK", + [self.MANUAL_LOCK] = "MANUAL_LOCK", + [self.MANUAL_UNLOCK] = "MANUAL_UNLOCK", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNKNOWN_OR_MFG_SPECIFIC = 0x00 +new_mt.__index.LOCK = 0x01 +new_mt.__index.UNLOCK = 0x02 +new_mt.__index.LOCK_INVALID_PIN_OR_ID = 0x03 +new_mt.__index.LOCK_INVALID_SCHEDULE = 0x04 +new_mt.__index.UNLOCK_INVALID_PIN_OR_ID = 0x05 +new_mt.__index.UNLOCK_INVALID_SCHEDULE = 0x06 +new_mt.__index.ONE_TOUCH_LOCK = 0x07 +new_mt.__index.KEY_LOCK = 0x08 +new_mt.__index.KEY_UNLOCK = 0x09 +new_mt.__index.AUTO_LOCK = 0x0A +new_mt.__index.SCHEDULE_LOCK = 0x0B +new_mt.__index.SCHEDULE_UNLOCK = 0x0C +new_mt.__index.MANUAL_LOCK = 0x0D +new_mt.__index.MANUAL_UNLOCK = 0x0E + +DoorLockOperationEventCode.UNKNOWN_OR_MFG_SPECIFIC = 0x00 +DoorLockOperationEventCode.LOCK = 0x01 +DoorLockOperationEventCode.UNLOCK = 0x02 +DoorLockOperationEventCode.LOCK_INVALID_PIN_OR_ID = 0x03 +DoorLockOperationEventCode.LOCK_INVALID_SCHEDULE = 0x04 +DoorLockOperationEventCode.UNLOCK_INVALID_PIN_OR_ID = 0x05 +DoorLockOperationEventCode.UNLOCK_INVALID_SCHEDULE = 0x06 +DoorLockOperationEventCode.ONE_TOUCH_LOCK = 0x07 +DoorLockOperationEventCode.KEY_LOCK = 0x08 +DoorLockOperationEventCode.KEY_UNLOCK = 0x09 +DoorLockOperationEventCode.AUTO_LOCK = 0x0A +DoorLockOperationEventCode.SCHEDULE_LOCK = 0x0B +DoorLockOperationEventCode.SCHEDULE_UNLOCK = 0x0C +DoorLockOperationEventCode.MANUAL_LOCK = 0x0D +DoorLockOperationEventCode.MANUAL_UNLOCK = 0x0E + +DoorLockOperationEventCode.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorLockOperationEventCode, new_mt) + +return DoorLockOperationEventCode \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockProgrammingEventCode.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockProgrammingEventCode.lua new file mode 100644 index 0000000000..ffb91d592f --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockProgrammingEventCode.lua @@ -0,0 +1,42 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorLockProgrammingEventCode = {} +local new_mt = UintABC.new_mt({NAME = "DoorLockProgrammingEventCode", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNKNOWN_OR_MFG_SPECIFIC] = "UNKNOWN_OR_MFG_SPECIFIC", + [self.MASTER_CODE_CHANGED] = "MASTER_CODE_CHANGED", + [self.PIN_ADDED] = "PIN_ADDED", + [self.PIN_DELETED] = "PIN_DELETED", + [self.PIN_CHANGED] = "PIN_CHANGED", + [self.ID_ADDED] = "ID_ADDED", + [self.ID_DELETED] = "ID_DELETED", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNKNOWN_OR_MFG_SPECIFIC = 0x00 +new_mt.__index.MASTER_CODE_CHANGED = 0x01 +new_mt.__index.PIN_ADDED = 0x02 +new_mt.__index.PIN_DELETED = 0x03 +new_mt.__index.PIN_CHANGED = 0x04 +new_mt.__index.ID_ADDED = 0x05 +new_mt.__index.ID_DELETED = 0x06 + +DoorLockProgrammingEventCode.UNKNOWN_OR_MFG_SPECIFIC = 0x00 +DoorLockProgrammingEventCode.MASTER_CODE_CHANGED = 0x01 +DoorLockProgrammingEventCode.PIN_ADDED = 0x02 +DoorLockProgrammingEventCode.PIN_DELETED = 0x03 +DoorLockProgrammingEventCode.PIN_CHANGED = 0x04 +DoorLockProgrammingEventCode.ID_ADDED = 0x05 +DoorLockProgrammingEventCode.ID_DELETED = 0x06 + +DoorLockProgrammingEventCode.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorLockProgrammingEventCode, new_mt) + +return DoorLockProgrammingEventCode \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockSetPinOrIdStatus.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockSetPinOrIdStatus.lua new file mode 100644 index 0000000000..6e32459354 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockSetPinOrIdStatus.lua @@ -0,0 +1,33 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorLockSetPinOrIdStatus = {} +local new_mt = UintABC.new_mt({NAME = "DoorLockSetPinOrIdStatus", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.SUCCESS] = "SUCCESS", + [self.GENERAL_FAILURE] = "GENERAL_FAILURE", + [self.MEMORY_FULL] = "MEMORY_FULL", + [self.DUPLICATE_CODE_ERROR] = "DUPLICATE_CODE_ERROR", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.SUCCESS = 0x00 +new_mt.__index.GENERAL_FAILURE = 0x01 +new_mt.__index.MEMORY_FULL = 0x02 +new_mt.__index.DUPLICATE_CODE_ERROR = 0x03 + +DoorLockSetPinOrIdStatus.SUCCESS = 0x00 +DoorLockSetPinOrIdStatus.GENERAL_FAILURE = 0x01 +DoorLockSetPinOrIdStatus.MEMORY_FULL = 0x02 +DoorLockSetPinOrIdStatus.DUPLICATE_CODE_ERROR = 0x03 + +DoorLockSetPinOrIdStatus.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorLockSetPinOrIdStatus, new_mt) + +return DoorLockSetPinOrIdStatus \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockUserStatus.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockUserStatus.lua new file mode 100644 index 0000000000..b755a48bb5 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockUserStatus.lua @@ -0,0 +1,33 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorLockUserStatus = {} +local new_mt = UintABC.new_mt({NAME = "DoorLockUserStatus", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.AVAILABLE] = "AVAILABLE", + [self.OCCUPIED_ENABLED] = "OCCUPIED_ENABLED", + [self.OCCUPIED_DISABLED] = "OCCUPIED_DISABLED", + [self.NOT_SUPPORTED] = "NOT_SUPPORTED", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.AVAILABLE = 0x00 +new_mt.__index.OCCUPIED_ENABLED = 0x01 +new_mt.__index.OCCUPIED_DISABLED = 0x03 +new_mt.__index.NOT_SUPPORTED = 0xFF + +DoorLockUserStatus.AVAILABLE = 0x00 +DoorLockUserStatus.OCCUPIED_ENABLED = 0x01 +DoorLockUserStatus.OCCUPIED_DISABLED = 0x03 +DoorLockUserStatus.NOT_SUPPORTED = 0xFF + +DoorLockUserStatus.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorLockUserStatus, new_mt) + +return DoorLockUserStatus \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockUserType.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockUserType.lua new file mode 100644 index 0000000000..b8f6724f46 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorLockUserType.lua @@ -0,0 +1,39 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorLockUserType = {} +local new_mt = UintABC.new_mt({NAME = "DoorLockUserType", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNRESTRICTED] = "UNRESTRICTED", + [self.YEAR_DAY_SCHEDULE_USER] = "YEAR_DAY_SCHEDULE_USER", + [self.WEEK_DAY_SCHEDULE_USER] = "WEEK_DAY_SCHEDULE_USER", + [self.MASTER_USER] = "MASTER_USER", + [self.NON_ACCESS_USER] = "NON_ACCESS_USER", + [self.NOT_SUPPORTED] = "NOT_SUPPORTED", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNRESTRICTED = 0x00 +new_mt.__index.YEAR_DAY_SCHEDULE_USER = 0x01 +new_mt.__index.WEEK_DAY_SCHEDULE_USER = 0x02 +new_mt.__index.MASTER_USER = 0x03 +new_mt.__index.NON_ACCESS_USER = 0x04 +new_mt.__index.NOT_SUPPORTED = 0xFF + +DoorLockUserType.UNRESTRICTED = 0x00 +DoorLockUserType.YEAR_DAY_SCHEDULE_USER = 0x01 +DoorLockUserType.WEEK_DAY_SCHEDULE_USER = 0x02 +DoorLockUserType.MASTER_USER = 0x03 +DoorLockUserType.NON_ACCESS_USER = 0x04 +DoorLockUserType.NOT_SUPPORTED = 0xFF + +DoorLockUserType.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorLockUserType, new_mt) + +return DoorLockUserType \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorStateEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorStateEnum.lua new file mode 100644 index 0000000000..ae01ab195c --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/DoorStateEnum.lua @@ -0,0 +1,39 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local DoorStateEnum = {} +local new_mt = UintABC.new_mt({NAME = "DoorStateEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.DOOR_OPEN] = "DOOR_OPEN", + [self.DOOR_CLOSED] = "DOOR_CLOSED", + [self.DOOR_JAMMED] = "DOOR_JAMMED", + [self.DOOR_FORCED_OPEN] = "DOOR_FORCED_OPEN", + [self.DOOR_UNSPECIFIED_ERROR] = "DOOR_UNSPECIFIED_ERROR", + [self.DOOR_AJAR] = "DOOR_AJAR", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.DOOR_OPEN = 0x00 +new_mt.__index.DOOR_CLOSED = 0x01 +new_mt.__index.DOOR_JAMMED = 0x02 +new_mt.__index.DOOR_FORCED_OPEN = 0x03 +new_mt.__index.DOOR_UNSPECIFIED_ERROR = 0x04 +new_mt.__index.DOOR_AJAR = 0x05 + +DoorStateEnum.DOOR_OPEN = 0x00 +DoorStateEnum.DOOR_CLOSED = 0x01 +DoorStateEnum.DOOR_JAMMED = 0x02 +DoorStateEnum.DOOR_FORCED_OPEN = 0x03 +DoorStateEnum.DOOR_UNSPECIFIED_ERROR = 0x04 +DoorStateEnum.DOOR_AJAR = 0x05 + +DoorStateEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(DoorStateEnum, new_mt) + +return DoorStateEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/Feature.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/Feature.lua new file mode 100644 index 0000000000..d45915c86c --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/Feature.lua @@ -0,0 +1,361 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local Feature = {} +local new_mt = UintABC.new_mt({NAME = "Feature", ID = data_types.name_to_id_map["Uint32"]}, 4) + +Feature.BASE_MASK = 0xFFFF +Feature.PIN_CREDENTIAL = 0x0001 +Feature.RFID_CREDENTIAL = 0x0002 +Feature.FINGER_CREDENTIALS = 0x0004 +Feature.LOGGING = 0x0008 +Feature.WEEK_DAY_ACCESS_SCHEDULES = 0x0010 +Feature.DOOR_POSITION_SENSOR = 0x0020 +Feature.FACE_CREDENTIALS = 0x0040 +Feature.CREDENTIALS_OVER_THE_AIR_ACCESS = 0x0080 +Feature.USER = 0x0100 +Feature.NOTIFICATION = 0x0200 +Feature.YEAR_DAY_ACCESS_SCHEDULES = 0x0400 +Feature.HOLIDAY_SCHEDULES = 0x0800 +Feature.UNBOLT = 0x1000 +Feature.ALIRO_PROVISIONING = 0x2000 +Feature.ALIROBLEUWB = 0x4000 + +Feature.mask_fields = { + BASE_MASK = 0xFFFF, + PIN_CREDENTIAL = 0x0001, + RFID_CREDENTIAL = 0x0002, + FINGER_CREDENTIALS = 0x0004, + LOGGING = 0x0008, + WEEK_DAY_ACCESS_SCHEDULES = 0x0010, + DOOR_POSITION_SENSOR = 0x0020, + FACE_CREDENTIALS = 0x0040, + CREDENTIALS_OVER_THE_AIR_ACCESS = 0x0080, + USER = 0x0100, + NOTIFICATION = 0x0200, + YEAR_DAY_ACCESS_SCHEDULES = 0x0400, + HOLIDAY_SCHEDULES = 0x0800, + UNBOLT = 0x1000, + ALIRO_PROVISIONING = 0x2000, + ALIROBLEUWB = 0x4000, +} + +Feature.is_pin_credential_set = function(self) + return (self.value & self.PIN_CREDENTIAL) ~= 0 +end + +Feature.set_pin_credential = function(self) + if self.value ~= nil then + self.value = self.value | self.PIN_CREDENTIAL + else + self.value = self.PIN_CREDENTIAL + end +end + +Feature.unset_pin_credential = function(self) + self.value = self.value & (~self.PIN_CREDENTIAL & self.BASE_MASK) +end + +Feature.is_rfid_credential_set = function(self) + return (self.value & self.RFID_CREDENTIAL) ~= 0 +end + +Feature.set_rfid_credential = function(self) + if self.value ~= nil then + self.value = self.value | self.RFID_CREDENTIAL + else + self.value = self.RFID_CREDENTIAL + end +end + +Feature.unset_rfid_credential = function(self) + self.value = self.value & (~self.RFID_CREDENTIAL & self.BASE_MASK) +end + +Feature.is_finger_credentials_set = function(self) + return (self.value & self.FINGER_CREDENTIALS) ~= 0 +end + +Feature.set_finger_credentials = function(self) + if self.value ~= nil then + self.value = self.value | self.FINGER_CREDENTIALS + else + self.value = self.FINGER_CREDENTIALS + end +end + +Feature.unset_finger_credentials = function(self) + self.value = self.value & (~self.FINGER_CREDENTIALS & self.BASE_MASK) +end + +Feature.is_logging_set = function(self) + return (self.value & self.LOGGING) ~= 0 +end + +Feature.set_logging = function(self) + if self.value ~= nil then + self.value = self.value | self.LOGGING + else + self.value = self.LOGGING + end +end + +Feature.unset_logging = function(self) + self.value = self.value & (~self.LOGGING & self.BASE_MASK) +end + +Feature.is_week_day_access_schedules_set = function(self) + return (self.value & self.WEEK_DAY_ACCESS_SCHEDULES) ~= 0 +end + +Feature.set_week_day_access_schedules = function(self) + if self.value ~= nil then + self.value = self.value | self.WEEK_DAY_ACCESS_SCHEDULES + else + self.value = self.WEEK_DAY_ACCESS_SCHEDULES + end +end + +Feature.unset_week_day_access_schedules = function(self) + self.value = self.value & (~self.WEEK_DAY_ACCESS_SCHEDULES & self.BASE_MASK) +end + +Feature.is_door_position_sensor_set = function(self) + return (self.value & self.DOOR_POSITION_SENSOR) ~= 0 +end + +Feature.set_door_position_sensor = function(self) + if self.value ~= nil then + self.value = self.value | self.DOOR_POSITION_SENSOR + else + self.value = self.DOOR_POSITION_SENSOR + end +end + +Feature.unset_door_position_sensor = function(self) + self.value = self.value & (~self.DOOR_POSITION_SENSOR & self.BASE_MASK) +end + +Feature.is_face_credentials_set = function(self) + return (self.value & self.FACE_CREDENTIALS) ~= 0 +end + +Feature.set_face_credentials = function(self) + if self.value ~= nil then + self.value = self.value | self.FACE_CREDENTIALS + else + self.value = self.FACE_CREDENTIALS + end +end + +Feature.unset_face_credentials = function(self) + self.value = self.value & (~self.FACE_CREDENTIALS & self.BASE_MASK) +end + +Feature.is_credentials_over_the_air_access_set = function(self) + return (self.value & self.CREDENTIALS_OVER_THE_AIR_ACCESS) ~= 0 +end + +Feature.set_credentials_over_the_air_access = function(self) + if self.value ~= nil then + self.value = self.value | self.CREDENTIALS_OVER_THE_AIR_ACCESS + else + self.value = self.CREDENTIALS_OVER_THE_AIR_ACCESS + end +end + +Feature.unset_credentials_over_the_air_access = function(self) + self.value = self.value & (~self.CREDENTIALS_OVER_THE_AIR_ACCESS & self.BASE_MASK) +end + +Feature.is_user_set = function(self) + return (self.value & self.USER) ~= 0 +end + +Feature.set_user = function(self) + if self.value ~= nil then + self.value = self.value | self.USER + else + self.value = self.USER + end +end + +Feature.unset_user = function(self) + self.value = self.value & (~self.USER & self.BASE_MASK) +end + +Feature.is_notification_set = function(self) + return (self.value & self.NOTIFICATION) ~= 0 +end + +Feature.set_notification = function(self) + if self.value ~= nil then + self.value = self.value | self.NOTIFICATION + else + self.value = self.NOTIFICATION + end +end + +Feature.unset_notification = function(self) + self.value = self.value & (~self.NOTIFICATION & self.BASE_MASK) +end + +Feature.is_year_day_access_schedules_set = function(self) + return (self.value & self.YEAR_DAY_ACCESS_SCHEDULES) ~= 0 +end + +Feature.set_year_day_access_schedules = function(self) + if self.value ~= nil then + self.value = self.value | self.YEAR_DAY_ACCESS_SCHEDULES + else + self.value = self.YEAR_DAY_ACCESS_SCHEDULES + end +end + +Feature.unset_year_day_access_schedules = function(self) + self.value = self.value & (~self.YEAR_DAY_ACCESS_SCHEDULES & self.BASE_MASK) +end + +Feature.is_holiday_schedules_set = function(self) + return (self.value & self.HOLIDAY_SCHEDULES) ~= 0 +end + +Feature.set_holiday_schedules = function(self) + if self.value ~= nil then + self.value = self.value | self.HOLIDAY_SCHEDULES + else + self.value = self.HOLIDAY_SCHEDULES + end +end + +Feature.unset_holiday_schedules = function(self) + self.value = self.value & (~self.HOLIDAY_SCHEDULES & self.BASE_MASK) +end + +Feature.is_unbolt_set = function(self) + return (self.value & self.UNBOLT) ~= 0 +end + +Feature.set_unbolt = function(self) + if self.value ~= nil then + self.value = self.value | self.UNBOLT + else + self.value = self.UNBOLT + end +end + +Feature.unset_unbolt = function(self) + self.value = self.value & (~self.UNBOLT & self.BASE_MASK) +end + +Feature.is_aliro_provisioning_set = function(self) + return (self.value & self.ALIRO_PROVISIONING) ~= 0 +end + +Feature.set_aliro_provisioning = function(self) + if self.value ~= nil then + self.value = self.value | self.ALIRO_PROVISIONING + else + self.value = self.ALIRO_PROVISIONING + end +end + +Feature.unset_aliro_provisioning = function(self) + self.value = self.value & (~self.ALIRO_PROVISIONING & self.BASE_MASK) +end + +Feature.is_alirobleuwb_set = function(self) + return (self.value & self.ALIROBLEUWB) ~= 0 +end + +Feature.set_alirobleuwb = function(self) + if self.value ~= nil then + self.value = self.value | self.ALIROBLEUWB + else + self.value = self.ALIROBLEUWB + end +end + +Feature.unset_alirobleuwb = function(self) + self.value = self.value & (~self.ALIROBLEUWB & self.BASE_MASK) +end + +function Feature.bits_are_valid(feature) + local max = + Feature.PIN_CREDENTIAL | + Feature.RFID_CREDENTIAL | + Feature.FINGER_CREDENTIALS | + Feature.LOGGING | + Feature.WEEK_DAY_ACCESS_SCHEDULES | + Feature.DOOR_POSITION_SENSOR | + Feature.FACE_CREDENTIALS | + Feature.CREDENTIALS_OVER_THE_AIR_ACCESS | + Feature.USER | + Feature.NOTIFICATION | + Feature.YEAR_DAY_ACCESS_SCHEDULES | + Feature.HOLIDAY_SCHEDULES | + Feature.UNBOLT | + Feature.ALIRO_PROVISIONING | + Feature.ALIROBLEUWB + if (feature <= max) and (feature >= 1) then + return true + else + return false + end +end + +Feature.mask_methods = { + is_pin_credential_set = Feature.is_pin_credential_set, + set_pin_credential = Feature.set_pin_credential, + unset_pin_credential = Feature.unset_pin_credential, + is_rfid_credential_set = Feature.is_rfid_credential_set, + set_rfid_credential = Feature.set_rfid_credential, + unset_rfid_credential = Feature.unset_rfid_credential, + is_finger_credentials_set = Feature.is_finger_credentials_set, + set_finger_credentials = Feature.set_finger_credentials, + unset_finger_credentials = Feature.unset_finger_credentials, + is_logging_set = Feature.is_logging_set, + set_logging = Feature.set_logging, + unset_logging = Feature.unset_logging, + is_week_day_access_schedules_set = Feature.is_week_day_access_schedules_set, + set_week_day_access_schedules = Feature.set_week_day_access_schedules, + unset_week_day_access_schedules = Feature.unset_week_day_access_schedules, + is_door_position_sensor_set = Feature.is_door_position_sensor_set, + set_door_position_sensor = Feature.set_door_position_sensor, + unset_door_position_sensor = Feature.unset_door_position_sensor, + is_face_credentials_set = Feature.is_face_credentials_set, + set_face_credentials = Feature.set_face_credentials, + unset_face_credentials = Feature.unset_face_credentials, + is_credentials_over_the_air_access_set = Feature.is_credentials_over_the_air_access_set, + set_credentials_over_the_air_access = Feature.set_credentials_over_the_air_access, + unset_credentials_over_the_air_access = Feature.unset_credentials_over_the_air_access, + is_user_set = Feature.is_user_set, + set_user = Feature.set_user, + unset_user = Feature.unset_user, + is_notification_set = Feature.is_notification_set, + set_notification = Feature.set_notification, + unset_notification = Feature.unset_notification, + is_year_day_access_schedules_set = Feature.is_year_day_access_schedules_set, + set_year_day_access_schedules = Feature.set_year_day_access_schedules, + unset_year_day_access_schedules = Feature.unset_year_day_access_schedules, + is_holiday_schedules_set = Feature.is_holiday_schedules_set, + set_holiday_schedules = Feature.set_holiday_schedules, + unset_holiday_schedules = Feature.unset_holiday_schedules, + is_unbolt_set = Feature.is_unbolt_set, + set_unbolt = Feature.set_unbolt, + unset_unbolt = Feature.unset_unbolt, + is_aliro_provisioning_set = Feature.is_aliro_provisioning_set, + set_aliro_provisioning = Feature.set_aliro_provisioning, + unset_aliro_provisioning = Feature.unset_aliro_provisioning, + is_alirobleuwb_set = Feature.is_alirobleuwb_set, + set_alirobleuwb = Feature.set_alirobleuwb, + unset_alirobleuwb = Feature.unset_alirobleuwb, +} + +Feature.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(Feature, new_mt) + +return Feature \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/LockDataTypeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/LockDataTypeEnum.lua new file mode 100644 index 0000000000..a278831c3b --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/LockDataTypeEnum.lua @@ -0,0 +1,63 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local LockDataTypeEnum = {} +local new_mt = UintABC.new_mt({NAME = "LockDataTypeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNSPECIFIED] = "UNSPECIFIED", + [self.PROGRAMMING_CODE] = "PROGRAMMING_CODE", + [self.USER_INDEX] = "USER_INDEX", + [self.WEEK_DAY_SCHEDULE] = "WEEK_DAY_SCHEDULE", + [self.YEAR_DAY_SCHEDULE] = "YEAR_DAY_SCHEDULE", + [self.HOLIDAY_SCHEDULE] = "HOLIDAY_SCHEDULE", + [self.PIN] = "PIN", + [self.RFID] = "RFID", + [self.FINGERPRINT] = "FINGERPRINT", + [self.FINGER_VEIN] = "FINGER_VEIN", + [self.FACE] = "FACE", + [self.ALIRO_CREDENTIAL_ISSUER_KEY] = "ALIRO_CREDENTIAL_ISSUER_KEY", + [self.ALIRO_EVICTABLE_ENDPOINT_KEY] = "ALIRO_EVICTABLE_ENDPOINT_KEY", + [self.ALIRO_NON_EVICTABLE_ENDPOINT_KEY] = "ALIRO_NON_EVICTABLE_ENDPOINT_KEY", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNSPECIFIED = 0x00 +new_mt.__index.PROGRAMMING_CODE = 0x01 +new_mt.__index.USER_INDEX = 0x02 +new_mt.__index.WEEK_DAY_SCHEDULE = 0x03 +new_mt.__index.YEAR_DAY_SCHEDULE = 0x04 +new_mt.__index.HOLIDAY_SCHEDULE = 0x05 +new_mt.__index.PIN = 0x06 +new_mt.__index.RFID = 0x07 +new_mt.__index.FINGERPRINT = 0x08 +new_mt.__index.FINGER_VEIN = 0x09 +new_mt.__index.FACE = 0x0A +new_mt.__index.ALIRO_CREDENTIAL_ISSUER_KEY = 0x0B +new_mt.__index.ALIRO_EVICTABLE_ENDPOINT_KEY = 0x0C +new_mt.__index.ALIRO_NON_EVICTABLE_ENDPOINT_KEY = 0x0D + +LockDataTypeEnum.UNSPECIFIED = 0x00 +LockDataTypeEnum.PROGRAMMING_CODE = 0x01 +LockDataTypeEnum.USER_INDEX = 0x02 +LockDataTypeEnum.WEEK_DAY_SCHEDULE = 0x03 +LockDataTypeEnum.YEAR_DAY_SCHEDULE = 0x04 +LockDataTypeEnum.HOLIDAY_SCHEDULE = 0x05 +LockDataTypeEnum.PIN = 0x06 +LockDataTypeEnum.RFID = 0x07 +LockDataTypeEnum.FINGERPRINT = 0x08 +LockDataTypeEnum.FINGER_VEIN = 0x09 +LockDataTypeEnum.FACE = 0x0A +LockDataTypeEnum.ALIRO_CREDENTIAL_ISSUER_KEY = 0x0B +LockDataTypeEnum.ALIRO_EVICTABLE_ENDPOINT_KEY = 0x0C +LockDataTypeEnum.ALIRO_NON_EVICTABLE_ENDPOINT_KEY = 0x0D + +LockDataTypeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(LockDataTypeEnum, new_mt) + +return LockDataTypeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/LockOperationTypeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/LockOperationTypeEnum.lua new file mode 100644 index 0000000000..3d28c27a7e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/LockOperationTypeEnum.lua @@ -0,0 +1,36 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local LockOperationTypeEnum = {} +local new_mt = UintABC.new_mt({NAME = "LockOperationTypeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.LOCK] = "LOCK", + [self.UNLOCK] = "UNLOCK", + [self.NON_ACCESS_USER_EVENT] = "NON_ACCESS_USER_EVENT", + [self.FORCED_USER_EVENT] = "FORCED_USER_EVENT", + [self.UNLATCH] = "UNLATCH", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.LOCK = 0x00 +new_mt.__index.UNLOCK = 0x01 +new_mt.__index.NON_ACCESS_USER_EVENT = 0x02 +new_mt.__index.FORCED_USER_EVENT = 0x03 +new_mt.__index.UNLATCH = 0x04 + +LockOperationTypeEnum.LOCK = 0x00 +LockOperationTypeEnum.UNLOCK = 0x01 +LockOperationTypeEnum.NON_ACCESS_USER_EVENT = 0x02 +LockOperationTypeEnum.FORCED_USER_EVENT = 0x03 +LockOperationTypeEnum.UNLATCH = 0x04 + +LockOperationTypeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(LockOperationTypeEnum, new_mt) + +return LockOperationTypeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/OperatingModeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/OperatingModeEnum.lua new file mode 100644 index 0000000000..fc6c61c757 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/OperatingModeEnum.lua @@ -0,0 +1,36 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local OperatingModeEnum = {} +local new_mt = UintABC.new_mt({NAME = "OperatingModeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.NORMAL] = "NORMAL", + [self.VACATION] = "VACATION", + [self.PRIVACY] = "PRIVACY", + [self.NO_REMOTE_LOCK_UNLOCK] = "NO_REMOTE_LOCK_UNLOCK", + [self.PASSAGE] = "PASSAGE", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.NORMAL = 0x00 +new_mt.__index.VACATION = 0x01 +new_mt.__index.PRIVACY = 0x02 +new_mt.__index.NO_REMOTE_LOCK_UNLOCK = 0x03 +new_mt.__index.PASSAGE = 0x04 + +OperatingModeEnum.NORMAL = 0x00 +OperatingModeEnum.VACATION = 0x01 +OperatingModeEnum.PRIVACY = 0x02 +OperatingModeEnum.NO_REMOTE_LOCK_UNLOCK = 0x03 +OperatingModeEnum.PASSAGE = 0x04 + +OperatingModeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(OperatingModeEnum, new_mt) + +return OperatingModeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/OperationErrorEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/OperationErrorEnum.lua new file mode 100644 index 0000000000..79da0a7c58 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/OperationErrorEnum.lua @@ -0,0 +1,36 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local OperationErrorEnum = {} +local new_mt = UintABC.new_mt({NAME = "OperationErrorEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNSPECIFIED] = "UNSPECIFIED", + [self.INVALID_CREDENTIAL] = "INVALID_CREDENTIAL", + [self.DISABLED_USER_DENIED] = "DISABLED_USER_DENIED", + [self.RESTRICTED] = "RESTRICTED", + [self.INSUFFICIENT_BATTERY] = "INSUFFICIENT_BATTERY", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNSPECIFIED = 0x00 +new_mt.__index.INVALID_CREDENTIAL = 0x01 +new_mt.__index.DISABLED_USER_DENIED = 0x02 +new_mt.__index.RESTRICTED = 0x03 +new_mt.__index.INSUFFICIENT_BATTERY = 0x04 + +OperationErrorEnum.UNSPECIFIED = 0x00 +OperationErrorEnum.INVALID_CREDENTIAL = 0x01 +OperationErrorEnum.DISABLED_USER_DENIED = 0x02 +OperationErrorEnum.RESTRICTED = 0x03 +OperationErrorEnum.INSUFFICIENT_BATTERY = 0x04 + +OperationErrorEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(OperationErrorEnum, new_mt) + +return OperationErrorEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/OperationSourceEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/OperationSourceEnum.lua new file mode 100644 index 0000000000..5d5e9ef592 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/OperationSourceEnum.lua @@ -0,0 +1,54 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local OperationSourceEnum = {} +local new_mt = UintABC.new_mt({NAME = "OperationSourceEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNSPECIFIED] = "UNSPECIFIED", + [self.MANUAL] = "MANUAL", + [self.PROPRIETARY_REMOTE] = "PROPRIETARY_REMOTE", + [self.KEYPAD] = "KEYPAD", + [self.AUTO] = "AUTO", + [self.BUTTON] = "BUTTON", + [self.SCHEDULE] = "SCHEDULE", + [self.REMOTE] = "REMOTE", + [self.RFID] = "RFID", + [self.BIOMETRIC] = "BIOMETRIC", + [self.ALIRO] = "ALIRO", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNSPECIFIED = 0x00 +new_mt.__index.MANUAL = 0x01 +new_mt.__index.PROPRIETARY_REMOTE = 0x02 +new_mt.__index.KEYPAD = 0x03 +new_mt.__index.AUTO = 0x04 +new_mt.__index.BUTTON = 0x05 +new_mt.__index.SCHEDULE = 0x06 +new_mt.__index.REMOTE = 0x07 +new_mt.__index.RFID = 0x08 +new_mt.__index.BIOMETRIC = 0x09 +new_mt.__index.ALIRO = 0x0A + +OperationSourceEnum.UNSPECIFIED = 0x00 +OperationSourceEnum.MANUAL = 0x01 +OperationSourceEnum.PROPRIETARY_REMOTE = 0x02 +OperationSourceEnum.KEYPAD = 0x03 +OperationSourceEnum.AUTO = 0x04 +OperationSourceEnum.BUTTON = 0x05 +OperationSourceEnum.SCHEDULE = 0x06 +OperationSourceEnum.REMOTE = 0x07 +OperationSourceEnum.RFID = 0x08 +OperationSourceEnum.BIOMETRIC = 0x09 +OperationSourceEnum.ALIRO = 0x0A + +OperationSourceEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(OperationSourceEnum, new_mt) + +return OperationSourceEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/UserStatusEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/UserStatusEnum.lua new file mode 100644 index 0000000000..11e20c7a3a --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/UserStatusEnum.lua @@ -0,0 +1,30 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local UserStatusEnum = {} +local new_mt = UintABC.new_mt({NAME = "UserStatusEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.AVAILABLE] = "AVAILABLE", + [self.OCCUPIED_ENABLED] = "OCCUPIED_ENABLED", + [self.OCCUPIED_DISABLED] = "OCCUPIED_DISABLED", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.AVAILABLE = 0x00 +new_mt.__index.OCCUPIED_ENABLED = 0x01 +new_mt.__index.OCCUPIED_DISABLED = 0x03 + +UserStatusEnum.AVAILABLE = 0x00 +UserStatusEnum.OCCUPIED_ENABLED = 0x01 +UserStatusEnum.OCCUPIED_DISABLED = 0x03 + +UserStatusEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(UserStatusEnum, new_mt) + +return UserStatusEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/UserTypeEnum.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/UserTypeEnum.lua new file mode 100644 index 0000000000..9d00c2b940 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/UserTypeEnum.lua @@ -0,0 +1,51 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local UserTypeEnum = {} +local new_mt = UintABC.new_mt({NAME = "UserTypeEnum", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNRESTRICTED_USER] = "UNRESTRICTED_USER", + [self.YEAR_DAY_SCHEDULE_USER] = "YEAR_DAY_SCHEDULE_USER", + [self.WEEK_DAY_SCHEDULE_USER] = "WEEK_DAY_SCHEDULE_USER", + [self.PROGRAMMING_USER] = "PROGRAMMING_USER", + [self.NON_ACCESS_USER] = "NON_ACCESS_USER", + [self.FORCED_USER] = "FORCED_USER", + [self.DISPOSABLE_USER] = "DISPOSABLE_USER", + [self.EXPIRING_USER] = "EXPIRING_USER", + [self.SCHEDULE_RESTRICTED_USER] = "SCHEDULE_RESTRICTED_USER", + [self.REMOTE_ONLY_USER] = "REMOTE_ONLY_USER", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNRESTRICTED_USER = 0x00 +new_mt.__index.YEAR_DAY_SCHEDULE_USER = 0x01 +new_mt.__index.WEEK_DAY_SCHEDULE_USER = 0x02 +new_mt.__index.PROGRAMMING_USER = 0x03 +new_mt.__index.NON_ACCESS_USER = 0x04 +new_mt.__index.FORCED_USER = 0x05 +new_mt.__index.DISPOSABLE_USER = 0x06 +new_mt.__index.EXPIRING_USER = 0x07 +new_mt.__index.SCHEDULE_RESTRICTED_USER = 0x08 +new_mt.__index.REMOTE_ONLY_USER = 0x09 + +UserTypeEnum.UNRESTRICTED_USER = 0x00 +UserTypeEnum.YEAR_DAY_SCHEDULE_USER = 0x01 +UserTypeEnum.WEEK_DAY_SCHEDULE_USER = 0x02 +UserTypeEnum.PROGRAMMING_USER = 0x03 +UserTypeEnum.NON_ACCESS_USER = 0x04 +UserTypeEnum.FORCED_USER = 0x05 +UserTypeEnum.DISPOSABLE_USER = 0x06 +UserTypeEnum.EXPIRING_USER = 0x07 +UserTypeEnum.SCHEDULE_RESTRICTED_USER = 0x08 +UserTypeEnum.REMOTE_ONLY_USER = 0x09 + +UserTypeEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(UserTypeEnum, new_mt) + +return UserTypeEnum \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/DoorLock/types/init.lua b/drivers/SmartThings/matter-lock/src/DoorLock/types/init.lua new file mode 100644 index 0000000000..461d914f84 --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/DoorLock/types/init.lua @@ -0,0 +1,14 @@ +local types_mt = {} +types_mt.__types_cache = {} +types_mt.__index = function(self, key) + if types_mt.__types_cache[key] == nil then + types_mt.__types_cache[key] = require("DoorLock.types." .. key) + end + return types_mt.__types_cache[key] +end + +local DoorLockTypes = {} + +setmetatable(DoorLockTypes, types_mt) + +return DoorLockTypes \ No newline at end of file diff --git a/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua b/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua deleted file mode 100644 index 835b41de1a..0000000000 --- a/drivers/SmartThings/matter-lock/src/aqara-lock/init.lua +++ /dev/null @@ -1,146 +0,0 @@ --- 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. --- 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 capabilities = require "st.capabilities" -local clusters = require "st.matter.clusters" -local device_lib = require "st.device" - -local DoorLock = clusters.DoorLock -local AQARA_MANUFACTURER_ID = 0x115f - -local function is_aqara_products(opts, driver, device) - if device.network_type == device_lib.NETWORK_TYPE_MATTER and - device.manufacturer_info.vendor_id == AQARA_MANUFACTURER_ID then - return true - end - return false -end - -local function find_default_endpoint(device, cluster) - local res = device.MATTER_DEFAULT_ENDPOINT - local eps = device:get_endpoints(cluster) - table.sort(eps) - for _, v in ipairs(eps) do - if v ~= 0 then --0 is the matter RootNode endpoint - return v - end - end - device.log.warn(string.format("Did not find default endpoint, will use endpoint %d instead", device.MATTER_DEFAULT_ENDPOINT)) - return res -end - -local function component_to_endpoint(device, component_name) - return find_default_endpoint(device, clusters.DoorLock.ID) -end - -local function device_init(driver, device) - device:set_component_to_endpoint_fn(component_to_endpoint) - device:subscribe() - end - -local function device_added(driver, device) - device:emit_event(capabilities.lockAlarm.alarm.clear({state_change = true})) -end - -local function lock_state_handler(driver, device, ib, response) - local LockState = DoorLock.attributes.LockState - local attr = capabilities.lock.lock - local LOCK_STATE = { - [LockState.NOT_FULLY_LOCKED] = attr.not_fully_locked(), - [LockState.LOCKED] = attr.locked(), - [LockState.UNLOCKED] = attr.unlocked(), - } - - if ib.data.value ~= nil then - device:emit_event(LOCK_STATE[ib.data.value]) - else - device:emit_event(LOCK_STATE[LockState.NOT_FULLY_LOCKED]) - end -end - -local function alarm_event_handler(driver, device, ib, response) - local DlAlarmCode = DoorLock.types.DlAlarmCode - local alarm_code = ib.data.elements.alarm_code - if alarm_code.value == DlAlarmCode.LOCK_JAMMED then - device:emit_event(capabilities.lockAlarm.alarm.unableToLockTheDoor({state_change = true})) - elseif alarm_code.value == DlAlarmCode.LOCK_FACTORY_RESET then - device:emit_event(capabilities.lockAlarm.alarm.lockFactoryReset({state_change = true})) - elseif alarm_code.value == DlAlarmCode.WRONG_CODE_ENTRY_LIMIT then - device:emit_event(capabilities.lockAlarm.alarm.attemptsExceeded({state_change = true})) - elseif alarm_code.value == DlAlarmCode.FRONT_ESCEUTCHEON_REMOVED then - device:emit_event(capabilities.lockAlarm.alarm.damaged({state_change = true})) - elseif alarm_code.value == DlAlarmCode.DOOR_FORCED_OPEN then - device:emit_event(capabilities.lockAlarm.alarm.forcedOpeningAttempt({state_change = true})) - end -end - -local function handle_refresh(driver, device, command) - local req = DoorLock.attributes.LockState:read(device) - device:send(req) -end - -local function handle_lock(driver, device, command) - local ep = device:component_to_endpoint(command.component) - device:send(DoorLock.server.commands.LockDoor(device, ep)) -end - -local function handle_unlock(driver, device, command) - local ep = device:component_to_endpoint(command.component) - device:send(DoorLock.server.commands.UnlockDoor(device, ep)) -end - -local aqara_lock_handler = { - NAME = "Aqara Lock Handler", - lifecycle_handlers = { - init = device_init, - added = device_added, - }, - matter_handlers = { - attr = { - [DoorLock.ID] = { - [DoorLock.attributes.LockState.ID] = lock_state_handler - }, - }, - event = { - [DoorLock.ID] = { - [DoorLock.events.DoorLockAlarm.ID] = alarm_event_handler - }, - }, - }, - subscribed_attributes = { - [capabilities.lock.ID] = {DoorLock.attributes.LockState} - }, - subscribed_events = { - [capabilities.lockAlarm.ID] = { - DoorLock.events.DoorLockAlarm - }, - }, - capability_handlers = { - [capabilities.lock.ID] = { - [capabilities.lock.commands.lock.NAME] = handle_lock, - [capabilities.lock.commands.unlock.NAME] = handle_unlock, - }, - [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = handle_refresh - }, - }, - supported_capabilities = { - capabilities.lock, - capabilities.lockAlarm - }, - can_handle = is_aqara_products -} - -return aqara_lock_handler - diff --git a/drivers/SmartThings/matter-lock/src/init.lua b/drivers/SmartThings/matter-lock/src/init.lua index 53f75a14c1..ccb3110c08 100755 --- a/drivers/SmartThings/matter-lock/src/init.lua +++ b/drivers/SmartThings/matter-lock/src/init.lua @@ -36,8 +36,8 @@ local function set_cota_credential(device, credential_index) if cota_cred == nil then -- Shouldn't happen but defensive to try to figure out if we need the cota cred and set it. device:send(DoorLock.attributes.RequirePINforRemoteOperation:read(device, #eps > 0 and eps[1] or 1)) - device.thread:call_with_delay(2, function(t) set_cota_credential(device, credential_index) end) - elseif not cota_cred then + return + elseif cota_cred == false then device.log.debug("Device does not require PIN for remote operation. Not setting COTA credential") return end @@ -426,19 +426,22 @@ end local function handle_reload_all_codes(driver, device, command) if (device:get_field(lock_utils.CHECKING_CREDENTIAL) == nil) then + lock_utils.lock_codes_event(device, {}) device:set_field(lock_utils.CHECKING_CREDENTIAL, 1) else device.log.info(string.format("Delaying scanning since currently checking credential %d", device:get_field(lock_utils.CHECKING_CREDENTIAL))) device.thread:call_with_delay(2, function(t) handle_reload_all_codes(driver, device, command) end) return end - device:emit_event(capabilities.lockCodes.scanCodes("Scanning")) - device:send( - clusters.DoorLock.server.commands.GetCredentialStatus( - device, device:component_to_endpoint(command.component), - {credential_type = DoorLock.types.DlCredentialType.PIN, credential_index = device:get_field(lock_utils.CHECKING_CREDENTIAL)} + device.thread:call_with_delay(5, function(t) + device:emit_event(capabilities.lockCodes.scanCodes("Scanning")) + device:send( + clusters.DoorLock.server.commands.GetCredentialStatus( + device, device:component_to_endpoint(command.component), + {credential_type = DoorLock.types.DlCredentialType.PIN, credential_index = device:get_field(lock_utils.CHECKING_CREDENTIAL)} + ) ) - ) + end) end local function handle_request_code(driver, device, command) @@ -633,7 +636,7 @@ local matter_lock_driver = { capabilities.batteryLevel, }, sub_drivers = { - require("aqara-lock"), + require("new-matter-lock"), }, lifecycle_handlers = {init = device_init, added = device_added}, } diff --git a/drivers/SmartThings/matter-lock/src/lock_utils.lua b/drivers/SmartThings/matter-lock/src/lock_utils.lua index 8bb788d7cc..d9c43c30d2 100644 --- a/drivers/SmartThings/matter-lock/src/lock_utils.lua +++ b/drivers/SmartThings/matter-lock/src/lock_utils.lua @@ -25,7 +25,20 @@ local lock_utils = { COTA_CODE_NAME = "ST Remote Operation Code", COTA_CRED_INDEX = "cotaCredIndex", NONFUNCTIONAL = "nonFunctional", - COTA_READ_INITIALIZED = "cotaReadInitialized" + COTA_READ_INITIALIZED = "cotaReadInitialized", + BUSY_STATE = "busyState", + COMMAND_NAME = "commandName", + USER_NAME = "userName", + USER_INDEX = "userIndex", + USER_TYPE = "userType", + CRED_INDEX = "credentialIndex", + CRED_DATA = "credentialData", + SCHEDULE_INDEX = "scheduleIndex", + SCHEDULE_WEEK_DAYS = "scheduleWeekDays", + SCHEDULE_START_HOUR = "scheduleStartHour", + SCHEDULE_START_MINUTE = "scheduleStartMinute", + SCHEDULE_END_HOUR = "scheduleEndHour", + SCHEDULE_END_MINUTE = "scheduleEndMinute" } local capabilities = require "st.capabilities" local json = require "st.json" diff --git a/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua new file mode 100644 index 0000000000..c4cefed6cf --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/new-matter-lock/init.lua @@ -0,0 +1,1693 @@ +-- 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. +-- 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 device_lib = require "st.device" +local capabilities = require "st.capabilities" +local clusters = require "st.matter.clusters" +local im = require "st.matter.interaction_model" +local utils = require "st.utils" +local lock_utils = require "lock_utils" + +local version = require "version" +if version.api < 10 then + clusters.DoorLock = require "DoorLock" +end + +local DoorLock = clusters.DoorLock +local INITIAL_COTA_INDEX = 1 +local ALL_INDEX = 0xFFFE + +local NEW_MATTER_LOCK_PRODUCTS = { + {0x115f, 0x2802}, -- AQARA, U200 + {0x115f, 0x2801}, -- AQARA, U300 + {0x10E1, 0x2002} -- VDA +} + +local subscribed_attributes = { + [capabilities.lock.ID] = { + DoorLock.attributes.LockState + }, + [capabilities.remoteControlStatus.ID] = { + DoorLock.attributes.OperatingMode + }, + [capabilities.lockUsers.ID] = { + DoorLock.attributes.NumberOfTotalUsersSupported + }, + [capabilities.lockCredentials.ID] = { + DoorLock.attributes.NumberOfPINUsersSupported, + DoorLock.attributes.MaxPINCodeLength, + DoorLock.attributes.MinPINCodeLength, + DoorLock.attributes.RequirePINforRemoteOperation + }, + [capabilities.lockSchedules.ID] = { + DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser, + DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser + } +} + +local subscribed_events = { + [capabilities.lock.ID] = { + DoorLock.events.LockOperation + }, + [capabilities.lockAlarm.ID] = { + DoorLock.events.DoorLockAlarm + }, + [capabilities.lockUsers.ID] = { + DoorLock.events.LockUserChange + } +} + +local function is_new_matter_lock_products(opts, driver, device) + if device.network_type ~= device_lib.NETWORK_TYPE_MATTER then + return false + end + for _, p in ipairs(NEW_MATTER_LOCK_PRODUCTS) do + if device.manufacturer_info.vendor_id == p[1] and + device.manufacturer_info.product_id == p[2] then + return true + end + end + return false +end + +local function find_default_endpoint(device, cluster) + local res = device.MATTER_DEFAULT_ENDPOINT + local eps = device:get_endpoints(cluster) + table.sort(eps) + for _, v in ipairs(eps) do + if v ~= 0 then --0 is the matter RootNode endpoint + return v + end + end + device.log.warn(string.format("Did not find default endpoint, will use endpoint %d instead", device.MATTER_DEFAULT_ENDPOINT)) + return res +end + +local function component_to_endpoint(device, component_name) + return find_default_endpoint(device, clusters.DoorLock.ID) +end + +local function device_init(driver, device) + device:set_component_to_endpoint_fn(component_to_endpoint) + for cap_id, attributes in pairs(subscribed_attributes) do + if device:supports_capability_by_id(cap_id) then + for _, attr in ipairs(attributes) do + device:add_subscribed_attribute(attr) + end + end + end + for cap_id, events in pairs(subscribed_events) do + if device:supports_capability_by_id(cap_id) then + for _, e in ipairs(events) do + device:add_subscribed_event(e) + end + end + end + device:subscribe() + end + +local function device_added(driver, device) + device:emit_event(capabilities.lockAlarm.alarm.clear({state_change = true})) +end + +local function do_configure(driver, device) + local user_eps = device:get_endpoints(DoorLock.ID, {feature_bitmap = DoorLock.types.Feature.USER}) + 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 profile_name = "lock" + if #user_eps > 0 then + profile_name = profile_name .. "-user" + if #pin_eps > 0 then + profile_name = profile_name .. "-pin" + end + if #week_schedule_eps + #year_schedule_eps > 0 then + 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}) +end + +local function info_changed(driver, device, event, args) + if device.profile.id == args.old_st_store.profile.id then + return + end + for cap_id, attributes in pairs(subscribed_attributes) do + if device:supports_capability_by_id(cap_id) then + for _, attr in ipairs(attributes) do + device:add_subscribed_attribute(attr) + end + end + end + for cap_id, events in pairs(subscribed_events) do + if device:supports_capability_by_id(cap_id) then + for _, e in ipairs(events) do + device:add_subscribed_event(e) + end + end + end + device:subscribe() +end + +-- This function check busy_state and if busy_state is false, set it to true(current time) +local function check_busy_state(device) + local c_time = os.time() + local busy_state = device:get_field(lock_utils.BUSY_STATE) or false + if busy_state == false or c_time - busy_state > 10 then + device:set_field(lock_utils.BUSY_STATE, c_time, {persist = true}) + return false + else + return true + end +end + +-- Matter Handler +---------------- +-- Lock State -- +---------------- +local function lock_state_handler(driver, device, ib, response) + local LockState = DoorLock.attributes.LockState + local attr = capabilities.lock.lock + local LOCK_STATE = { + [LockState.NOT_FULLY_LOCKED] = attr.not_fully_locked(), + [LockState.LOCKED] = attr.locked(), + [LockState.UNLOCKED] = attr.unlocked(), + } + + -- The lock state is usually updated in lock_state_handler and lock_op_event_handler, respectively. + -- In this case, two events occur. To prevent this, when both functions are called, + -- it send the event after 1 second so that no event occurs in the lock_state_handler. + device.thread:call_with_delay(1, function () + if ib.data.value ~= nil then + device:emit_event(LOCK_STATE[ib.data.value]) + else + device.log.warn("Lock State is nil") + end + end) +end + +--------------------- +-- Operating Modes -- +--------------------- +local function operating_modes_handler(driver, device, ib, response) + local status = capabilities.remoteControlStatus.remoteControlEnabled + local op_type = DoorLock.types.OperatingModeEnum + local opMode_map = { + [op_type.NORMAL] = true, + [op_type.VACATION] = true, + [op_type.PRIVACY] = false, + [op_type.NO_REMOTE_LOCK_UNLOCK] = false, + [op_type.PASSAGE] = false, + } + local result = opMode_map[ib.data.value] + if result == true then + device:emit_event(status("true", {visibility = {displayed = true}})) + device:emit_event(capabilities.lock.supportedLockCommands({"lock", "unlock"}, {visibility = {displayed = false}})) + elseif result == false then + device:emit_event(status("false", {visibility = {displayed = true}})) + device:emit_event(capabilities.lock.supportedLockCommands({}, {visibility = {displayed = false}})) + end +end +------------------------------------- +-- Number Of Total Users Supported -- +------------------------------------- +local function total_users_supported_handler(driver, device, ib, response) + device:emit_event(capabilities.lockUsers.totalUsersSupported(ib.data.value, {visibility = {displayed = false}})) +end + +---------------------------------- +-- Number Of PIN Users Supported -- +---------------------------------- +local function pin_users_supported_handler(driver, device, ib, response) + device:emit_event(capabilities.lockCredentials.pinUsersSupported(ib.data.value, {visibility = {displayed = false}})) +end + +------------------------- +-- Min PIN Code Length -- +------------------------- +local function min_pin_code_len_handler(driver, device, ib, response) + device:emit_event(capabilities.lockCredentials.minPinCodeLen(ib.data.value, {visibility = {displayed = false}})) +end + +------------------------- +-- Max PIN Code Length -- +------------------------- +local function max_pin_code_len_handler(driver, device, ib, response) + device:emit_event(capabilities.lockCredentials.maxPinCodeLen(ib.data.value, {visibility = {displayed = false}})) +end + +-------------------------------------- +-- Require PIN For Remote Operation -- +-------------------------------------- +local function set_cota_credential(device, credential_index) + local eps = device:get_endpoints(DoorLock.ID) + local cota_cred = device:get_field(lock_utils.COTA_CRED) + if cota_cred == nil then + -- Shouldn't happen but defensive to try to figure out if we need the cota cred and set it. + device:send(DoorLock.attributes.RequirePINforRemoteOperation:read(device, #eps > 0 and eps[1] or 1)) + return + elseif cota_cred == false then + device.log.debug("Device does not require PIN for remote operation. Not setting COTA credential") + return + end + + -- Check Busy State + if check_busy_state(device) == true then + device.log.debug("delaying setting COTA credential since a credential is currently being set") + device.thread:call_with_delay(2, function(t) + set_cota_credential(device, credential_index) + end) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, "addCota") + device:set_field(lock_utils.CRED_INDEX, credential_index) + device:set_field(lock_utils.COTA_CRED_INDEX, credential_index, {persist = true}) + device:set_field(lock_utils.USER_TYPE, "remote") + + -- Send command + device.log.info(string.format("Attempting to set COTA credential at index %s", credential_index)) + local credential = { + credential_type = DoorLock.types.CredentialTypeEnum.PIN, + credential_index = credential_index + } + device:send(DoorLock.server.commands.SetCredential( + device, + #eps > 0 and eps[1] or 1, + DoorLock.types.DataOperationTypeEnum.ADD, + credential, + device:get_field(lock_utils.COTA_CRED), + nil, -- nil user_index creates a new user + DoorLock.types.UserStatusEnum.OCCUPIED_ENABLED, + DoorLock.types.UserTypeEnum.REMOTE_ONLY_USER + )) +end + +local function generate_cota_cred_for_device(device) + local len = device:get_latest_state("main", capabilities.lockCredentials.ID, capabilities.lockCredentials.maxPinCodeLen.NAME) or 6 + local cred_data = math.floor(math.random() * (10 ^ len)) + cred_data = string.format("%0" .. tostring(len) .. "d", cred_data) + device:set_field(lock_utils.COTA_CRED, cred_data, {persist = true}) +end + +local function apply_cota_credentials_if_absent(device) + if not device:get_field(lock_utils.COTA_CRED) then + -- Process after all other info blocks have been dispatched to ensure MaxPINCodeLength has been processed + device.thread:call_with_delay(0, function(t) + generate_cota_cred_for_device(device) + -- delay needed to allow test to override the random credential data + device.thread:call_with_delay(0, function(t) + -- Attempt to set cota credential at the lowest index + set_cota_credential(device, INITIAL_COTA_INDEX) + end) + end) + end +end + +local function require_remote_pin_handler(driver, device, ib, response) + if ib.data.value then + apply_cota_credentials_if_absent(device) + else + device:set_field(lock_utils.COTA_CRED, false, {persist = true}) + end +end + +----------------------------------------------------- +-- Number Of Week Day Schedules Supported Per User -- +----------------------------------------------------- +local function max_week_schedule_of_user_handler(driver, device, ib, response) + device:emit_event(capabilities.lockSchedules.weekDaySchedulesPerUser(ib.data.value, {visibility = {displayed = false}})) +end + +----------------------------------------------------- +-- Number Of Year Day Schedules Supported Per User -- +----------------------------------------------------- +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 + +-- Capability Handler +----------------- +-- Lock/Unlock -- +----------------- +local function handle_lock(driver, device, command) + local ep = device:component_to_endpoint(command.component) + local cota_cred = device:get_field(lock_utils.COTA_CRED) + if cota_cred then + device:send( + DoorLock.server.commands.LockDoor(device, ep, cota_cred) + ) + else + device:send(DoorLock.server.commands.LockDoor(device, ep)) + end +end + +local function handle_unlock(driver, device, command) + local ep = device:component_to_endpoint(command.component) + local cota_cred = device:get_field(lock_utils.COTA_CRED) + if cota_cred then + device:send( + DoorLock.server.commands.UnlockDoor(device, ep, cota_cred) + ) + else + device:send(DoorLock.server.commands.UnlockDoor(device, ep)) + end +end + +---------------- +-- User Table -- +---------------- +local function add_user_to_table(device, userIdx, usrType) + -- Get latest user table + local user_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockUsers.ID, + capabilities.lockUsers.users.NAME, + {} + )) + + -- Add new entry to table + table.insert(user_table, {userIndex = userIdx, userType = usrType}) + device:emit_event(capabilities.lockUsers.users(user_table, {visibility = {displayed = false}})) +end + +local function update_user_in_table(device, userIdx, usrType) + -- Get latest user table + local user_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockUsers.ID, + capabilities.lockUsers.users.NAME, + {} + )) + + -- Find user entry + local i = 0 + for index, entry in pairs(user_table) do + if entry.userIndex == userIdx then + i = index + break + end + end + + -- Update user entry + if i ~= 0 then + user_table[i].userType = usrType + device:emit_event(capabilities.lockUsers.users(user_table, {visibility = {displayed = false}})) + end +end + +local function delete_user_from_table(device, userIdx) + -- If User Index is ALL_INDEX, remove all entry from the table + if userIdx == ALL_INDEX then + device:emit_event(capabilities.lockUsers.users({}, {visibility = {displayed = false}})) + return + end + + -- Get latest user table + local user_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockUsers.ID, + capabilities.lockUsers.users.NAME, + {} + )) + + -- Remove element from user table + for index, entry in pairs(user_table) do + if entry.userIndex == userIdx then + table.remove(user_table, index) + break + end + end + device:emit_event(capabilities.lockUsers.users(user_table, {visibility = {displayed = false}})) +end + +---------------------- +-- Credential Table -- +---------------------- +local function add_credential_to_table(device, userIdx, credIdx, credType) + -- Get latest credential table + local cred_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockCredentials.ID, + capabilities.lockCredentials.credentials.NAME, + {} + )) + + -- Add new entry to table + table.insert(cred_table, {userIndex = userIdx, credentialIndex = credIdx, credentialType = credType}) + device:emit_event(capabilities.lockCredentials.credentials(cred_table, {visibility = {displayed = false}})) +end + +local function delete_credential_from_table(device, credIdx) + -- If Credential Index is ALL_INDEX, remove all entries from the table + if credIdx == ALL_INDEX then + device:emit_event(capabilities.lockCredentials.credentials({}, {visibility = {displayed = false}})) + return + end + + -- Get latest credential table + local cred_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockCredentials.ID, + capabilities.lockCredentials.credentials.NAME, + {} + )) + + -- Delete an entry from credential table + local userIdx = 0 + for index, entry in pairs(cred_table) do + if entry.credentialIndex == credIdx then + table.remove(cred_table, index) + userIdx = entry.userIndex + break + end + end + + device:emit_event(capabilities.lockCredentials.credentials(cred_table, {visibility = {displayed = false}})) + return userIdx +end + +local function delete_credential_from_table_as_user(device, userIdx) + -- If User Index is ALL_INDEX, remove all entry from the table + if userIdx == ALL_INDEX then + device:emit_event(capabilities.lockCredentials.credentials({}, {visibility = {displayed = false}})) + return + end + + -- Get latest credential table + local cred_table = device:get_latest_state( + "main", + capabilities.lockCredentials.ID, + capabilities.lockCredentials.credentials.NAME + ) or {} + local new_cred_table = {} + + -- Re-create credential table + for index, entry in pairs(cred_table) do + if entry.userIndex ~= userIdx then + table.insert(new_cred_table, entry) + end + end + + device:emit_event(capabilities.lockCredentials.credentials(new_cred_table, {visibility = {displayed = false}})) +end + +----------------------------- +-- Week Day Schedule Table -- +----------------------------- +local WEEK_DAY_MAP = { + ["Sunday"] = 1, + ["Monday"] = 2, + ["Tuesday"] = 4, + ["Wednesday"] = 8, + ["Thursday"] = 16, + ["Friday"] = 32, + ["Saturday"] = 64, +} + +local function add_week_schedule_to_table(device, userIdx, scheduleIdx, schedule) + -- Get latest week day schedule table + local week_schedule_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockSchedules.ID, + capabilities.lockSchedules.weekDaySchedules.NAME, + {} + )) + + -- Find schedule for specific user + local i = 0 + for index, entry in pairs(week_schedule_table) do + if entry.userIndex == userIdx then + i = index + end + end + + -- Re-create weekDays list + local weekDayList = {} + for _, weekday in ipairs(schedule.weekDays) do + table.insert(weekDayList, weekday) + end + + if i ~= 0 then -- Add schedule for existing user + -- Exclude same scheduleIdx + local new_schedule_table = {} + for index, entry in pairs(week_schedule_table[i].schedules) do + if entry.scheduleIndex ~= scheduleIdx then + table.insert(new_schedule_table, entry) + end + end + -- Add new entry to table + table.insert( + new_schedule_table, + { + scheduleIndex = scheduleIdx, + weekdays = weekDayList, + startHour = schedule.startHour, + startMinute = schedule.startMinute, + endHour = schedule.endHour, + endMinute = schedule.endMinute + } + ) + -- Update schedule for specific user + week_schedule_table[i].schedules = new_schedule_table + else -- Add schedule for new user + table.insert( + week_schedule_table, + { + userIndex = userIdx, + schedules = {{ + scheduleIndex = scheduleIdx, + weekdays = weekDayList, + startHour = schedule.startHour, + startMinute = schedule.startMinute, + endHour = schedule.endHour, + endMinute = schedule.endMinute + }} + } + ) + end + + device:emit_event(capabilities.lockSchedules.weekDaySchedules(week_schedule_table, {visibility = {displayed = false}})) +end + +local function delete_week_schedule_to_table(device, userIdx, scheduleIdx) + -- Get latest week day schedule table + local week_schedule_table = utils.deep_copy(device:get_latest_state( + "main", + capabilities.lockSchedules.ID, + capabilities.lockSchedules.weekDaySchedules.NAME, + {} + )) + + -- Find schedule for specific user + local i = 0 + for index, entry in pairs(week_schedule_table) do + if entry.userIndex == userIdx then + i = index + end + end + + -- When there is no userIndex in the table + if i == 0 then + return + end + + -- Re-create schedule table for the user + local new_schedule_table = {} + for index, entry in pairs(week_schedule_table[i].schedules) do + if entry.scheduleIndex ~= scheduleIdx then + table.insert(new_schedule_table, entry) + end + end + + -- If user has no schedule, remove user from the table + if #new_schedule_table == 0 then + table.remove(week_schedule_table, i) + else + week_schedule_table[i].schedules = new_schedule_table + end + + device:emit_event(capabilities.lockSchedules.weekDaySchedules(week_schedule_table, {visibility = {displayed = false}})) +end + +-------------- +-- Add User -- +-------------- +local function handle_add_user(driver, device, command) + -- Get parameters + local cmdName = "addUser" + local userName = command.args.userName + local userType = command.args.userType + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, INITIAL_COTA_INDEX, {persist = true}) + device:set_field(lock_utils.USER_NAME, userName, {persist = true}) + device:set_field(lock_utils.USER_TYPE, userType, {persist = true}) + + -- Get available user index + local ep = device:component_to_endpoint(command.component) + device:send(DoorLock.server.commands.GetUser(device, ep, INITIAL_COTA_INDEX)) +end + +----------------- +-- Update User -- +----------------- +local function handle_update_user(driver, device, command) + -- Get parameters + local cmdName = "updateUser" + local userIdx = command.args.userIndex + local userName = command.args.userName + local userType = command.args.lockUserType + local userTypeMatter = DoorLock.types.UserTypeEnum.UNRESTRICTED_USER + if userType == "guest" then + userTypeMatter = DoorLock.types.UserTypeEnum.SCHEDULE_RESTRICTED_USER + end + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + device:set_field(lock_utils.USER_TYPE, userType, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send( + DoorLock.server.commands.SetUser( + device, ep, + DoorLock.types.DataOperationTypeEnum.MODIFY, -- Operation Type: Add(0), Modify(2) + userIdx, -- User Index + userName, -- User Name + nil, -- Unique ID + nil, -- User Status + userTypeMatter, -- User Type + nil -- Credential Rule + ) + ) +end + +----------------------- +-- Get User Response -- +----------------------- +local function get_user_response_handler(driver, device, ib, response) + local elements = ib.info_block.data.elements + local userIdx = elements.user_index.value + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local status = "success" + if ib.status == DoorLock.types.DlStatus.FAILURE then + status = "failure" + elseif ib.status == DoorLock.types.DlStatus.INVALID_FIELD then + status = "invalidCommand" + end + if status ~= "success" then + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + statusCode = status + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + end + + local ep = find_default_endpoint(device, DoorLock.ID) + local status = elements.user_status.value + local maxUser = device:get_latest_state( + "main", + capabilities.lockUsers.ID, + capabilities.lockUsers.totalUsersSupported.NAME + ) or 10 + + -- Found available user index + if status == nil or status == DoorLock.types.UserStatusEnum.AVAILABLE then + local userName = device:get_field(lock_utils.USER_NAME) + local userType = device:get_field(lock_utils.USER_TYPE) + local userTypeMatter = DoorLock.types.UserTypeEnum.UNRESTRICTED_USER + if userType == "guest" then + userTypeMatter = DoorLock.types.UserTypeEnum.SCHEDULE_RESTRICTED_USER + end + + -- Save values to field + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + + -- Send command + device:send( + DoorLock.server.commands.SetUser( + device, ep, + DoorLock.types.DataOperationTypeEnum.ADD, -- Operation Type: Add(0), Modify(2) + userIdx, -- User Index + userName, -- User Name + nil, -- Unique ID + nil, -- User Status + userTypeMatter, -- User Type + nil -- Credential Rule + ) + ) + elseif userIdx >= maxUser then -- There's no available user index + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + statusCode = "resourceExhausted" + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + else -- Check next user index + device:send(DoorLock.server.commands.GetUser(device, ep, userIdx + 1)) + end +end + +----------------------- +-- Set User Response -- +----------------------- +local function set_user_response_handler(driver, device, ib, response) + -- Get result + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local userIdx = device:get_field(lock_utils.USER_INDEX) + local userType = device:get_field(lock_utils.USER_TYPE) + local status = "success" + if ib.status == DoorLock.types.DlStatus.FAILURE then + status = "failure" + elseif ib.status == DoorLock.types.DlStatus.OCCUPIED then + status = "occupied" + elseif ib.status == DoorLock.types.DlStatus.INVALID_FIELD then + status = "invalidCommand" + end + + -- Update User in table + if status == "success" then + if cmdName == "addUser" then + add_user_to_table(device, userIdx, userType) + elseif cmdName == "updateUser" then + update_user_in_table(device, userIdx, userType) + end + else + device.log.warn(string.format("Failed to set user: %s", status)) + end + + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + statusCode = status + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) +end + +----------------- +-- Delete User -- +----------------- +local function handle_delete_user(driver, device, command) + -- Get parameters + local cmdName = "deleteUser" + local userIdx = command.args.userIndex + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send(DoorLock.server.commands.ClearUser(device, ep, userIdx)) +end + +---------------------- +-- Delete All Users -- +---------------------- +local function handle_delete_all_users(driver, device, command) + -- Get parameters + local cmdName = "deleteAllUsers" + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, ALL_INDEX, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send(DoorLock.server.commands.ClearUser(device, ep, ALL_INDEX)) +end + +------------------------- +-- Clear User Response -- +------------------------- +local function clear_user_response_handler(driver, device, ib, response) + -- Get result + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local userIdx = device:get_field(lock_utils.USER_INDEX) + local status = "success" + if ib.status == DoorLock.types.DlStatus.FAILURE then + status = "failure" + elseif ib.status == DoorLock.types.DlStatus.INVALID_FIELD then + status = "invalidCommand" + end + + -- Delete User and Credential from table + if status == "success" then + delete_user_from_table(device, userIdx) + delete_credential_from_table_as_user(device, userIdx) + else + device.log.warn(string.format("Failed to clear user: %s", status)) + end + + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + statusCode = status + } + local event = capabilities.lockUsers.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + }) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) +end + +-------------------- +-- Add Credential -- +-------------------- +local function handle_add_credential(driver, device, command) + -- Get parameters + local cmdName = "addCredential" + local userIdx = command.args.userIndex + if userIdx == 0 then + userIdx = nil + end + local userType = command.args.userType + local userTypeMatter = DoorLock.types.UserTypeEnum.UNRESTRICTED_USER + if userType == "guest" then + userTypeMatter = DoorLock.types.UserTypeEnum.SCHEDULE_RESTRICTED_USER + end + local credential = { + credential_type = DoorLock.types.CredentialTypeEnum.PIN, + credential_index = INITIAL_COTA_INDEX + } + local credData = command.args.credentialData + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + device:set_field(lock_utils.USER_TYPE, userType, {persist = true}) + device:set_field(lock_utils.CRED_INDEX, INITIAL_COTA_INDEX, {persist = true}) + device:set_field(lock_utils.CRED_DATA, credData, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send( + DoorLock.server.commands.SetCredential( + device, ep, + DoorLock.types.DataOperationTypeEnum.ADD, -- Data Operation Type: Add(0), Modify(2) + credential, -- Credential + credData, -- Credential Data + userIdx, -- User Index + nil, -- User Status + userTypeMatter -- User Type + ) + ) +end + +----------------------- +-- Update Credential -- +----------------------- +local function handle_update_credential(driver, device, command) + -- Get parameters + local cmdName = "updateCredential" + local userIdx = command.args.userIndex + local credIdx = command.args.credentialIndex + local credential = { + credential_type = DoorLock.types.CredentialTypeEnum.PIN, + credential_index = credIdx + } + local credData = command.args.credentialData + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + device:set_field(lock_utils.CRED_INDEX, credIdx, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send( + DoorLock.server.commands.SetCredential( + device, ep, + DoorLock.types.DataOperationTypeEnum.MODIFY, -- Data Operation Type: Add(0), Modify(2) + credential, -- Credential + credData, -- Credential Data + userIdx, -- User Index + nil, -- User Status + nil -- User Type + ) + ) +end + +----------------------------- +-- Set Credential Response -- +----------------------------- +local RESPONSE_STATUS_MAP = { + [DoorLock.types.DlStatus.FAILURE] = "failure", + [DoorLock.types.DlStatus.DUPLICATE] = "duplicate", + [DoorLock.types.DlStatus.OCCUPIED] = "occupied", + [DoorLock.types.DlStatus.INVALID_FIELD] = "invalidCommand", + [DoorLock.types.DlStatus.RESOURCE_EXHAUSTED] = "resourceExhausted", + [DoorLock.types.DlStatus.NOT_FOUND] = "failure" +} + +local function set_credential_response_handler(driver, device, ib, response) + if ib.status ~= im.InteractionResponse.Status.SUCCESS then + device.log.error("Failed to set credential for device") + return + end + + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local credData = device:get_field(lock_utils.CRED_DATA) + if cmdName == "addCota" then + credData = device:get_field(lock_utils.COTA_CRED) + end + local userIdx = device:get_field(lock_utils.USER_INDEX) + local credIdx = device:get_field(lock_utils.CRED_INDEX) + local status = "success" + local elements = ib.info_block.data.elements + if elements.status.value == DoorLock.types.DlStatus.SUCCESS then + -- Don't save user and credential for COTA + if cmdName == "addCota" then + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + return + end + + -- If user is added also, update User table + if userIdx == nil then + local userType = device:get_field(lock_utils.USER_TYPE) + add_user_to_table(device, elements.user_index.value, userType) + end + + -- Update Credential table + userIdx = elements.user_index.value + if cmdName == "addCredential" then + add_credential_to_table(device, userIdx, credIdx, "pin") + end + + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + credentialIndex = credIdx, + statusCode = status + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + return + end + + -- Update commandResult + status = RESPONSE_STATUS_MAP[elements.status.value] + device.log.warn(string.format("Failed to set credential: %s", status)) + + -- Set commandResult to error status + if status == "duplicate" and cmdName == "addCota" then + generate_cota_cred_for_device(device) + device.thread:call_with_delay(0, function(t) set_cota_credential(device, credIdx) end) + return + elseif status ~= "occupied" then + local result = { + commandName = cmdName, + statusCode = status + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + return + end + + if elements.next_credential_index.value ~= nil then + -- Get parameters + local credIdx = elements.next_credential_index.value + local credential = { + credential_type = DoorLock.types.CredentialTypeEnum.PIN, + credential_index = credIdx, + } + local userIdx = device:get_field(lock_utils.USER_INDEX) + local userType = device:get_field(lock_utils.USER_TYPE) + local userTypeMatter = DoorLock.types.UserTypeEnum.UNRESTRICTED_USER + if userType == "guest" then + userTypeMatter = DoorLock.types.UserTypeEnum.SCHEDULE_RESTRICTED_USER + elseif userType == "remote" then + userTypeMatter = DoorLock.types.UserTypeEnum.REMOTE_ONLY_USER + end + + device:set_field(lock_utils.CRED_INDEX, credIdx, {persist = true}) + + -- Send command + local ep = find_default_endpoint(device, DoorLock.ID) + device:send( + DoorLock.server.commands.SetCredential( + device, ep, + DoorLock.types.DataOperationTypeEnum.ADD, -- Data Operation Type: Add(0), Modify(2) + credential, -- Credential + credData, -- Credential Data + userIdx, -- User Index + nil, -- User Status + userTypeMatter -- User Type + ) + ) + else + local result = { + commandName = cmdName, + statusCode = "resourceExhausted" -- No more available credential index + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) + end +end + +----------------------- +-- Delete Credential -- +----------------------- +local function handle_delete_credential(driver, device, command) + -- Get parameters + local cmdName = "deleteCredential" + local credIdx = command.args.credentialIndex + local credential = { + credential_type = DoorLock.types.CredentialTypeEnum.PIN, + credential_index = credIdx, + } + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.CRED_INDEX, credIdx, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send(DoorLock.server.commands.ClearCredential(device, ep, credential)) +end + +---------------------------- +-- Delete All Credentials -- +---------------------------- +local function handle_delete_all_credentials(driver, device, command) + -- Get parameters + local cmdName = "deleteAllCredentials" + local credential = { + credential_type = DoorLock.types.CredentialTypeEnum.PIN, + credential_index = ALL_INDEX, + } + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.CRED_INDEX, ALL_INDEX, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send(DoorLock.server.commands.ClearCredential(device, ep, credential)) +end + +------------------------------- +-- Clear Credential Response -- +------------------------------- +local function clear_credential_response_handler(driver, device, ib, response) + -- Get result + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local credIdx = device:get_field(lock_utils.CRED_INDEX) + local status = "success" + if ib.status == DoorLock.types.DlStatus.FAILURE then + status = "failure" + elseif ib.status == DoorLock.types.DlStatus.INVALID_FIELD then + status = "invalidCommand" + end + + -- Delete User in table + local userIdx = 0 + if status == "success" then + userIdx = delete_credential_from_table(device, credIdx) + if userIdx == 0 then + userIdx = nil + end + else + device.log.warn(string.format("Failed to clear credential: %s", status)) + end + + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + credentialIndex = credIdx, + statusCode = status + } + local event = capabilities.lockCredentials.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) +end + +--------------------------- +-- Set Week Day Schedule -- +--------------------------- +local function handle_set_week_day_schedule(driver, device, command) + -- Get parameters + local cmdName = "setWeekDaySchedule" + local scheduleIdx = command.args.scheduleIndex + local userIdx = command.args.userIndex + local schedule = command.args.schedule + local wDays = {} + local scheduleBit = 0 + for _, weekDay in ipairs(schedule.weekDays) do + scheduleBit = scheduleBit + WEEK_DAY_MAP[weekDay] + table.insert(wDays, weekDay) + end + local startHour = schedule.startHour + local startMinute = schedule.startMinute + local endHour = schedule.endHour + local endMinute = schedule.endMinute + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockSchedules.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + device:set_field(lock_utils.SCHEDULE_INDEX, scheduleIdx, {persist = true}) + device:set_field(lock_utils.SCHEDULE_WEEK_DAYS, wDays, {persist = true}) + device:set_field(lock_utils.SCHEDULE_START_HOUR, startHour, {persist = true}) + device:set_field(lock_utils.SCHEDULE_START_MINUTE, startMinute, {persist = true}) + device:set_field(lock_utils.SCHEDULE_END_HOUR, endHour, {persist = true}) + device:set_field(lock_utils.SCHEDULE_END_MINUTE, endMinute, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send( + DoorLock.server.commands.SetWeekDaySchedule( + device, ep, + scheduleIdx, -- Week Day Schedule Index + userIdx, -- User Index + scheduleBit, -- Days Mask + startHour, -- Start Hour + startMinute, -- Start Minute + endHour, -- End Hour + endMinute -- End Minute + ) + ) +end + +------------------------------------ +-- Set Week Day Schedule Response -- +------------------------------------ +local function set_week_day_schedule_handler(driver, device, ib, response) + -- Get result + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local userIdx = device:get_field(lock_utils.USER_INDEX) + local scheduleIdx = device:get_field(lock_utils.SCHEDULE_INDEX) + local days = device:get_field(lock_utils.SCHEDULE_WEEK_DAYS) + local sHour = device:get_field(lock_utils.SCHEDULE_START_HOUR) + local sMinute = device:get_field(lock_utils.SCHEDULE_START_MINUTE) + local eHour = device:get_field(lock_utils.SCHEDULE_END_HOUR) + local eMinute = device:get_field(lock_utils.SCHEDULE_END_MINUTE) + local schedule = { + weekDays = days, + startHour = sHour, + startMinute = sMinute, + endHour = eHour, + endMinute = eMinute + } + local status = "success" + if ib.status == DoorLock.types.DlStatus.FAILURE then + status = "failure" + elseif ib.status == DoorLock.types.DlStatus.INVALID_FIELD then + status = "invalidCommand" + end + + -- Add Week Day Schedule to table + if status == "success" then + add_week_schedule_to_table(device, userIdx, scheduleIdx, schedule) + else + device.log.warn(string.format("Failed to set week day schedule: %s", status)) + end + + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + scheduleIndex = scheduleIdx, + statusCode = status + } + local event = capabilities.lockSchedules.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) +end + +----------------------------- +-- Clear Week Day Schedule -- +----------------------------- +local function handle_clear_week_day_schedule(driver, device, command) + -- Get parameters + local cmdName = "clearWeekDaySchedules" + local scheduleIdx = command.args.scheduleIndex + local userIdx = command.args.userIndex + + -- Check busy state + local busy = check_busy_state(device) + if busy == true then + local result = { + commandName = cmdName, + statusCode = "busy" + } + local event = capabilities.lockSchedules.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + return + end + + -- Save values to field + device:set_field(lock_utils.COMMAND_NAME, cmdName, {persist = true}) + device:set_field(lock_utils.SCHEDULE_INDEX, scheduleIdx, {persist = true}) + device:set_field(lock_utils.USER_INDEX, userIdx, {persist = true}) + + -- Send command + local ep = device:component_to_endpoint(command.component) + device:send(DoorLock.server.commands.ClearWeekDaySchedule(device, ep, scheduleIdx, userIdx)) +end + +------------------------------------ +-- Clear Week Day Schedule Response -- +------------------------------------ +local function clear_week_day_schedule_handler(driver, device, ib, response) + -- Get result + local cmdName = device:get_field(lock_utils.COMMAND_NAME) + local scheduleIdx = device:get_field(lock_utils.SCHEDULE_INDEX) + local userIdx = device:get_field(lock_utils.USER_INDEX) + local status = "success" + if ib.status == DoorLock.types.DlStatus.FAILURE then + status = "failure" + elseif ib.status == DoorLock.types.DlStatus.INVALID_FIELD then + status = "invalidCommand" + end + + -- Delete Week Day Schedule to table + if status == "success" then + delete_week_schedule_to_table(device, userIdx, scheduleIdx) + else + device.log.warn(string.format("Failed to clear week day schedule: %s", status)) + end + + -- Update commandResult + local result = { + commandName = cmdName, + userIndex = userIdx, + scheduleIndex = scheduleIdx, + statusCode = status + } + local event = capabilities.lockSchedules.commandResult( + result, + { + state_change = true, + visibility = {displayed = false} + } + ) + device:emit_event(event) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) +end + +--------------------------- +-- Set Year Day Schedule -- +--------------------------- +local function handle_set_year_day_schedule(driver, device, command) +end + +----------------------------- +-- Clear Year Day Schedule -- +----------------------------- +local function handle_clear_year_day_schedule(driver, device, command) +end + +---------------- +-- Lock Alarm -- +---------------- +local function alarm_event_handler(driver, device, ib, response) + local DlAlarmCode = DoorLock.types.DlAlarmCode + local alarm_code = ib.data.elements.alarm_code + if alarm_code.value == DlAlarmCode.LOCK_JAMMED then + device:emit_event(capabilities.lockAlarm.alarm.unableToLockTheDoor({state_change = true})) + elseif alarm_code.value == DlAlarmCode.LOCK_FACTORY_RESET then + device:emit_event(capabilities.lockAlarm.alarm.lockFactoryReset({state_change = true})) + elseif alarm_code.value == DlAlarmCode.WRONG_CODE_ENTRY_LIMIT then + device:emit_event(capabilities.lockAlarm.alarm.attemptsExceeded({state_change = true})) + elseif alarm_code.value == DlAlarmCode.FRONT_ESCEUTCHEON_REMOVED then + device:emit_event(capabilities.lockAlarm.alarm.damaged({state_change = true})) + elseif alarm_code.value == DlAlarmCode.DOOR_FORCED_OPEN then + device:emit_event(capabilities.lockAlarm.alarm.forcedOpeningAttempt({state_change = true})) + end +end + +-------------------- +-- Lock Operation -- +-------------------- +local function lock_op_event_handler(driver, device, ib, response) + local opType = ib.data.elements.lock_operation_type + local opSource = ib.data.elements.operation_source + local userIdx = ib.data.elements.user_index + -- TODO: This handler can check fabric index and exclude other fabric events + + if opType == nil or opSource == nil then + return + end + + local Type = DoorLock.types.LockOperationTypeEnum + local Lock = capabilities.lock.lock + if opType.value == Type.LOCK then + opType = Lock.locked + elseif opType.value == Type.UNLOCK then + opType = Lock.unlocked + elseif opType.value == Type.UNLATCH then + opType = Lock.locked + else + return + end + + local Source = DoorLock.types.OperationSourceEnum + if opSource.value == Source.UNSPECIFIED then + opSource = nil + elseif opSource.value == Source.MANUAL then + opSource = "manual" + elseif opSource.value == Source.PROPRIETARY_REMOTE then + opSource = "proprietaryRemote" + elseif opSource.value == Source.KEYPAD then + opSource = "keypad" + elseif opSource.value == Source.AUTO then + opSource = "auto" + elseif opSource.value == Source.BUTTON then + opSource = "button" + elseif opSource.value == Source.SCHEDULE then + opSource = nil + elseif opSource.value == Source.REMOTE then + opSource = "command" + elseif opSource.value == Source.RFID then + opSource = "rfid" + elseif opSource.value == Source.BIOMETRIC then + opSource = "keypad" + elseif opSource.value == Source.ALIRO then + opSource = nil + else + opSource =nil + end + + if userIdx ~= nil then + userIdx = userIdx.value + end + + local data_obj = {method = opSource, userIndex = userIdx} + device:emit_event(opType({data = data_obj, state_change = true})) +end + +local function handle_refresh(driver, device, command) + local req = DoorLock.attributes.LockState:read(device) + device:send(req) + device:set_field(lock_utils.BUSY_STATE, false, {persist = true}) +end + +local new_matter_lock_handler = { + NAME = "New Matter Lock Handler", + lifecycle_handlers = { + init = device_init, + added = device_added, + doConfigure = do_configure, + infoChanged = info_changed, + }, + matter_handlers = { + attr = { + [DoorLock.ID] = { + [DoorLock.attributes.LockState.ID] = lock_state_handler, + [DoorLock.attributes.OperatingMode.ID] = operating_modes_handler, + [DoorLock.attributes.NumberOfTotalUsersSupported.ID] = total_users_supported_handler, + [DoorLock.attributes.NumberOfPINUsersSupported.ID] = pin_users_supported_handler, + [DoorLock.attributes.MinPINCodeLength.ID] = min_pin_code_len_handler, + [DoorLock.attributes.MaxPINCodeLength.ID] = max_pin_code_len_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, + } + }, + event = { + [DoorLock.ID] = { + [DoorLock.events.DoorLockAlarm.ID] = alarm_event_handler, + [DoorLock.events.LockOperation.ID] = lock_op_event_handler, + }, + }, + cmd_response = { + [DoorLock.ID] = { + [DoorLock.server.commands.SetUser.ID] = set_user_response_handler, + [DoorLock.client.commands.GetUserResponse.ID] = get_user_response_handler, + [DoorLock.server.commands.ClearUser.ID] = clear_user_response_handler, + [DoorLock.client.commands.SetCredentialResponse.ID] = set_credential_response_handler, + [DoorLock.server.commands.ClearCredential.ID] = clear_credential_response_handler, + [DoorLock.server.commands.SetWeekDaySchedule.ID] = set_week_day_schedule_handler, + [DoorLock.server.commands.ClearWeekDaySchedule.ID] = clear_week_day_schedule_handler, + }, + }, + }, + subscribed_attributes = subscribed_attributes, + subscribed_events = subscribed_events, + capability_handlers = { + [capabilities.lock.ID] = { + [capabilities.lock.commands.lock.NAME] = handle_lock, + [capabilities.lock.commands.unlock.NAME] = handle_unlock, + }, + [capabilities.lockUsers.ID] = { + [capabilities.lockUsers.commands.addUser.NAME] = handle_add_user, + [capabilities.lockUsers.commands.updateUser.NAME] = handle_update_user, + [capabilities.lockUsers.commands.deleteUser.NAME] = handle_delete_user, + [capabilities.lockUsers.commands.deleteAllUsers.NAME] = handle_delete_all_users, + }, + [capabilities.lockCredentials.ID] = { + [capabilities.lockCredentials.commands.addCredential.NAME] = handle_add_credential, + [capabilities.lockCredentials.commands.updateCredential.NAME] = handle_update_credential, + [capabilities.lockCredentials.commands.deleteCredential.NAME] = handle_delete_credential, + [capabilities.lockCredentials.commands.deleteAllCredentials.NAME] = handle_delete_all_credentials, + }, + [capabilities.lockSchedules.ID] = { + [capabilities.lockSchedules.commands.setWeekDaySchedule.NAME] = handle_set_week_day_schedule, + [capabilities.lockSchedules.commands.clearWeekDaySchedules.NAME] = handle_clear_week_day_schedule, + [capabilities.lockSchedules.commands.setYearDaySchedule.NAME] = handle_set_year_day_schedule, + [capabilities.lockSchedules.commands.clearYearDaySchedules.NAME] = handle_clear_year_day_schedule, + }, + [capabilities.refresh.ID] = {[capabilities.refresh.commands.refresh.NAME] = handle_refresh} + }, + supported_capabilities = { + capabilities.lock, + capabilities.lockUsers, + capabilities.lockCredentials, + capabilities.lockSchedules + }, + can_handle = is_new_matter_lock_products +} + +return new_matter_lock_handler diff --git a/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua index 9b2cd282ed..b64324d8f7 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_aqara_matter_lock.lua @@ -19,7 +19,7 @@ local t_utils = require "integration_test.utils" local clusters = require "st.matter.clusters" local mock_device = test.mock_device.build_test_matter_device({ - profile = t_utils.get_profile_definition("lock-lockalarm-nobattery.yml"), + profile = t_utils.get_profile_definition("lock-user-pin.yml"), manufacturer_info = { vendor_id = 0x115f, product_id = 0x2802, @@ -53,7 +53,15 @@ local mock_device = test.mock_device.build_test_matter_device({ local function test_init() local subscribe_request = clusters.DoorLock.attributes.LockState:subscribe(mock_device) + subscribe_request:merge(clusters.DoorLock.attributes.OperatingMode:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.attributes.NumberOfTotalUsersSupported:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.attributes.MinPINCodeLength:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.events.LockOperation:subscribe(mock_device)) subscribe_request:merge(clusters.DoorLock.events.DoorLockAlarm:subscribe(mock_device)) + subscribe_request:merge(clusters.DoorLock.events.LockUserChange:subscribe(mock_device)) test.socket["matter"]:__expect_send({mock_device.id, subscribe_request}) test.mock_device.add_test_device(mock_device) end @@ -99,64 +107,61 @@ test.register_message_test( } ) -test.register_message_test( - "Handle received LockState.LOCKED from Matter device.", { - { - channel = "matter", - direction = "receive", - message = { +test.register_coroutine_test( + "Handle received LockState.LOCKED from Matter device.", + function() + test.socket.matter:__queue_receive( + { mock_device.id, clusters.DoorLock.attributes.LockState:build_test_report_data( mock_device, 1, clusters.DoorLock.attributes.LockState.LOCKED ), - }, - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.lock.lock.locked()), - }, - } + } + ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.mock_time.advance_time(1) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.lock.locked()) + ) + end ) -test.register_message_test( - "Handle received LockState.UNLOCKED from Matter device.", { - { - channel = "matter", - direction = "receive", - message = { +test.register_coroutine_test( + "Handle received LockState.UNLOCKED from Matter device.", + function() + test.socket.matter:__queue_receive( + { mock_device.id, clusters.DoorLock.attributes.LockState:build_test_report_data( mock_device, 1, clusters.DoorLock.attributes.LockState.UNLOCKED ), - }, - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.lock.lock.unlocked()), - }, - } + } + ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.mock_time.advance_time(1) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.lock.unlocked()) + ) + end ) -test.register_message_test( - "Handle received LockState.NOT_FULLY_LOCKED from Matter device.", { - { - channel = "matter", - direction = "receive", - message = { +test.register_coroutine_test( + "Handle received LockState.NOT_FULLY_LOCKED from Matter device.", + function() + test.socket.matter:__queue_receive( + { mock_device.id, clusters.DoorLock.attributes.LockState:build_test_report_data( mock_device, 1, clusters.DoorLock.attributes.LockState.NOT_FULLY_LOCKED ), - }, - }, - { - channel = "capability", - direction = "send", - message = mock_device:generate_test_message("main", capabilities.lock.lock.not_fully_locked()), - }, - } + } + ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.mock_time.advance_time(1) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.lock.not_fully_locked()) + ) + end ) local function refresh_commands(dev) diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua index dd83af4651..e1775074ff 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_codes.lua @@ -76,6 +76,15 @@ end test.set_test_init_function(test_init) local expect_reload_all_codes_messages = function(dev) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", capabilities.lockCodes.lockCodes( + json.encode({}), {visibility = {displayed = false}} + ) + ) + ) + test.timer.__create_and_queue_test_time_advance_timer(5, "oneshot") + test.mock_time.advance_time(5) local credential = types.DlCredential({credential_type = types.DlCredentialType.PIN, credential_index = 1}) test.socket.capability:__expect_send( dev:generate_test_message( @@ -459,6 +468,15 @@ test.register_coroutine_test( {capability = capabilities.lockCodes.ID, command = "reloadAllCodes", args = {}}, } ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", capabilities.lockCodes.lockCodes( + json.encode({}), {visibility = {displayed = false}} + ) + ) + ) + test.timer.__create_and_queue_test_time_advance_timer(5, "oneshot") + test.mock_time.advance_time(5) local credential = types.DlCredential({credential_type = types.DlCredentialType.PIN, credential_index = 1}) test.socket.capability:__expect_send( mock_device:generate_test_message( @@ -469,7 +487,6 @@ test.register_coroutine_test( {mock_device.id, DoorLock.server.commands.GetCredentialStatus(mock_device, 10, credential)} ) test.wait_for_events() - test.socket.matter:__queue_receive( { mock_device.id, @@ -479,14 +496,38 @@ test.register_coroutine_test( 1, --user_index nil, --creator fabric index nil, --last modified fabric index - nil + 2 --next credential index ), } ) test.socket.capability:__expect_send( mock_device:generate_test_message( "main", capabilities.lockCodes - .codeChanged("1 deleted", {data = {codeName = "Code 1"}, state_change = true}) + .codeChanged("1 unset", {data = {codeName = "Code 1"}, state_change = true}) + ) + ) + credential = types.DlCredential({credential_type = types.DlCredentialType.PIN, credential_index = 2}) + test.socket.matter:__expect_send( + {mock_device.id, DoorLock.server.commands.GetCredentialStatus(mock_device, 10, credential)} + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.GetCredentialStatusResponse:build_test_command_response( + mock_device, 10, -- endpoint + true, --credential exists + 2, --user_index + nil, --creator fabric index + nil, --last modified fabric index + nil --next credential index + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", capabilities.lockCodes + .codeChanged("2 set", {data = {codeName = "Code 2"}, state_change = true}) ) ) test.socket.capability:__expect_send( @@ -511,6 +552,7 @@ test.register_coroutine_test( ) end ) + test.register_coroutine_test( "Deleting a user code should be handled", function() init_code_slot(1, "initialName", mock_device) diff --git a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua index a4752fb843..fce2dcdc87 100644 --- a/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua +++ b/drivers/SmartThings/matter-lock/src/test/test_matter_lock_cota.lua @@ -77,6 +77,15 @@ end test.set_test_init_function(test_init) local expect_reload_all_codes_messages = function(dev) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", capabilities.lockCodes.lockCodes( + json.encode({}), {visibility = {displayed = false}} + ) + ) + ) + test.timer.__create_and_queue_test_time_advance_timer(5, "oneshot") + test.mock_time.advance_time(5) local credential = types.DlCredential({credential_type = types.DlCredentialType.PIN, credential_index = 1}) test.socket.capability:__expect_send( dev:generate_test_message( diff --git a/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua b/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua new file mode 100644 index 0000000000..836ad6fb7e --- /dev/null +++ b/drivers/SmartThings/matter-lock/src/test/test_new_matter_lock.lua @@ -0,0 +1,2005 @@ +-- Copyright 2023 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 DoorLock = clusters.DoorLock +local types = DoorLock.types +local lock_utils = require "lock_utils" + +local mock_device = test.mock_device.build_test_matter_device({ + profile = t_utils.get_profile_definition("lock-user-pin-schedule.yml"), + manufacturer_info = { + vendor_id = 0x115f, + product_id = 0x2802, + }, + endpoints = { + { + endpoint_id = 0, + clusters = { + { cluster_id = clusters.BasicInformation.ID, cluster_type = "SERVER" }, + }, + device_types = { + { device_type_id = 0x0016, device_type_revision = 1 } -- RootNode + } + }, + { + endpoint_id = 1, + clusters = { + { + cluster_id = DoorLock.ID, + cluster_type = "SERVER", + cluster_revision = 1, + feature_map = 0x0181, -- PIN & USR & COTA + } + }, + device_types = { + { device_type_id = 0x000A, device_type_revision = 1 } -- Door Lock + } + } + } +}) + +local function test_init() + local subscribe_request = DoorLock.attributes.LockState:subscribe(mock_device) + subscribe_request:merge(DoorLock.attributes.OperatingMode:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.NumberOfTotalUsersSupported:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.NumberOfPINUsersSupported:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.MaxPINCodeLength:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.MinPINCodeLength:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.RequirePINforRemoteOperation:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser:subscribe(mock_device)) + subscribe_request:merge(DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser:subscribe(mock_device)) + subscribe_request:merge(DoorLock.events.LockOperation:subscribe(mock_device)) + subscribe_request:merge(DoorLock.events.DoorLockAlarm:subscribe(mock_device)) + subscribe_request:merge(DoorLock.events.LockUserChange: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_coroutine_test( + "Assert profile applied over doConfigure", + function() + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure" }) + mock_device:expect_metadata_update({ profile = "lock-user-pin" }) + mock_device:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + +test.register_coroutine_test( + "Handle received OperatingMode(Normal, Vacation) from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.OperatingMode:build_test_report_data( + mock_device, 1, DoorLock.attributes.OperatingMode.NORMAL + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.remoteControlStatus.remoteControlEnabled("true", {visibility = {displayed = true}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.supportedLockCommands({"lock", "unlock"}, {visibility = {displayed = false}})) + ) + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.OperatingMode:build_test_report_data( + mock_device, 1, DoorLock.attributes.OperatingMode.VACATION + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.remoteControlStatus.remoteControlEnabled("true", {visibility = {displayed = true}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.supportedLockCommands({"lock", "unlock"}, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received OperatingMode(Privacy, No Remote Lock UnLock, Passage) from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.OperatingMode:build_test_report_data( + mock_device, 1, DoorLock.attributes.OperatingMode.PRIVACY + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.remoteControlStatus.remoteControlEnabled("false", {visibility = {displayed = true}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.supportedLockCommands({}, {visibility = {displayed = false}})) + ) + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.OperatingMode:build_test_report_data( + mock_device, 1, DoorLock.attributes.OperatingMode.NO_REMOTE_LOCK_UNLOCK + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.remoteControlStatus.remoteControlEnabled("false", {visibility = {displayed = true}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.supportedLockCommands({}, {visibility = {displayed = false}})) + ) + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.OperatingMode:build_test_report_data( + mock_device, 1, DoorLock.attributes.OperatingMode.PASSAGE + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.remoteControlStatus.remoteControlEnabled("false", {visibility = {displayed = true}})) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.supportedLockCommands({}, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received NumberOfTotalUsersSupported from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.NumberOfTotalUsersSupported:build_test_report_data( + mock_device, 1, DoorLock.attributes.NumberOfTotalUsersSupported(10) + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lockUsers.totalUsersSupported(10, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received NumberOfPINUsersSupported from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.NumberOfPINUsersSupported:build_test_report_data( + mock_device, 1, DoorLock.attributes.NumberOfPINUsersSupported(10) + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lockCredentials.pinUsersSupported(10, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received MinPINCodeLength from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.MinPINCodeLength:build_test_report_data( + mock_device, 1, DoorLock.attributes.MinPINCodeLength(6) + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lockCredentials.minPinCodeLen(6, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received MaxPINCodeLength from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.MaxPINCodeLength:build_test_report_data( + mock_device, 1, DoorLock.attributes.MaxPINCodeLength(8) + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lockCredentials.maxPinCodeLen(8, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received NumberOfWeekDaySchedulesSupportedPerUser from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser:build_test_report_data( + mock_device, 1, DoorLock.attributes.NumberOfWeekDaySchedulesSupportedPerUser(5) + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lockSchedules.weekDaySchedulesPerUser(5, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received NumberOfYearDaySchedulesSupportedPerUser from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser:build_test_report_data( + mock_device, 1, DoorLock.attributes.NumberOfYearDaySchedulesSupportedPerUser(5) + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lockSchedules.yearDaySchedulesPerUser(5, {visibility = {displayed = false}})) + ) + end +) + +test.register_coroutine_test( + "Handle received RequirePINforRemoteOperation(true) from Matter device.", + function() + test.socket.matter:__set_channel_ordering("relaxed") + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.RequirePINforRemoteOperation:build_test_report_data( + mock_device, 1, DoorLock.attributes.RequirePINforRemoteOperation(true) + ), + } + ) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.mock_time.advance_time(1) + test.wait_for_events() + mock_device:set_field(lock_utils.COTA_CRED, "654123", {persist = true}) --overwrite random cred for test expectation + test.timer.__create_and_queue_test_time_advance_timer(3, "oneshot") + + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + nil, -- user_index + DoorLock.types.UserStatusEnum.OCCUPIED_ENABLED, -- user_status + DoorLock.types.UserTypeEnum.REMOTE_ONLY_USER -- user_type + ), + } + ) + test.mock_time.advance_time(1) + test.wait_for_events() + + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.OCCUPIED, -- status + nil, -- user_index + 2 -- next_credential_index + ), + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 2} + ), -- credential + "654123", -- credential_data + nil, -- user_index + nil, -- user_status + DoorLock.types.UserTypeEnum.REMOTE_ONLY_USER -- user_type + ), + } + ) + end +) + +test.register_coroutine_test( +"Handle for duplicated pincode during COTA setting", +function() + test.socket.matter:__set_channel_ordering("relaxed") + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.RequirePINforRemoteOperation:build_test_report_data( + mock_device, 1, DoorLock.attributes.RequirePINforRemoteOperation(true) + ), + } + ) + test.timer.__create_and_queue_test_time_advance_timer(2, "oneshot") + test.mock_time.advance_time(1) + test.wait_for_events() + mock_device:set_field(lock_utils.COTA_CRED, "654123", {persist = true}) --overwrite random cred for test expectation + test.timer.__create_and_queue_test_time_advance_timer(3, "oneshot") + + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + nil, -- user_index + DoorLock.types.UserStatusEnum.OCCUPIED_ENABLED, -- user_status + DoorLock.types.UserTypeEnum.REMOTE_ONLY_USER -- user_type + ), + } + ) + test.mock_time.advance_time(1) + test.wait_for_events() + + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.DUPLICATE, -- status + 1, -- user_index + 2 -- next_credential_index + ), + } + ) + test.timer.__create_and_queue_test_time_advance_timer(11, "oneshot") + test.mock_time.advance_time(10) --trigger remote pin handling + test.wait_for_events() + mock_device:set_field(lock_utils.COTA_CRED, "654123", {persist = true}) --overwrite random cred for test expectation + test.timer.__create_and_queue_test_time_advance_timer(3, "oneshot") + + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + nil, -- user_index + DoorLock.types.UserStatusEnum.OCCUPIED_ENABLED, -- user_status + DoorLock.types.UserTypeEnum.REMOTE_ONLY_USER -- user_type + ), + } + ) + test.mock_time.advance_time(1) + test.wait_for_events() +end +) + +test.register_coroutine_test( + "Handle received RequirePINforRemoteOperation(false) from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.RequirePINforRemoteOperation:build_test_report_data( + mock_device, 1, DoorLock.attributes.RequirePINforRemoteOperation(false) + ), + } + ) + end +) + +test.register_coroutine_test( + "UnlockDoor uses cota cred when present", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + {capability = capabilities.lock.ID, command = "unlock", args = {}} + } + ) + mock_device:set_field(lock_utils.COTA_CRED, "654123") + test.socket.matter:__expect_send({ + mock_device.id, + clusters.DoorLock.server.commands.UnlockDoor(mock_device, 1, "654123"), + }) + end +) + +test.register_coroutine_test( + "LockDoor uses cota cred when present", function() + test.socket.capability:__queue_receive( + { + mock_device.id, + {capability = capabilities.lock.ID, command = "lock", args = {}} + } + ) + mock_device:set_field(lock_utils.COTA_CRED, "654123") + test.socket.matter:__expect_send({ + mock_device.id, + clusters.DoorLock.server.commands.LockDoor(mock_device, 1, "654123"), + }) + end +) + +test.register_message_test( + "Handle Lock command received from SmartThings.", { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + {capability = "lock", component = "main", command = "lock", args = {}}, + }, + }, + { + channel = "matter", + direction = "send", + message = {mock_device.id, DoorLock.server.commands.LockDoor(mock_device, 1)}, + }, + } +) + +test.register_message_test( + "Handle Unlock command received from SmartThings.", { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + {capability = "lock", component = "main", command = "unlock", args = {}}, + }, + }, + { + channel = "matter", + direction = "send", + message = { + mock_device.id, + DoorLock.server.commands.UnlockDoor(mock_device, 1), + }, + }, + } +) + +test.register_coroutine_test( + "Handle received LockState.LOCKED from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.LockState:build_test_report_data( + mock_device, 1, DoorLock.attributes.LockState.LOCKED + ), + } + ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.mock_time.advance_time(1) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.lock.locked()) + ) + end +) + +test.register_coroutine_test( + "Handle received LockState.UNLOCKED from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.LockState:build_test_report_data( + mock_device, 1, DoorLock.attributes.LockState.UNLOCKED + ), + } + ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.mock_time.advance_time(1) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.lock.unlocked()) + ) + end +) + +test.register_coroutine_test( + "Handle received LockState.NOT_FULLY_LOCKED from Matter device.", + function() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.attributes.LockState:build_test_report_data( + mock_device, 1, DoorLock.attributes.LockState.NOT_FULLY_LOCKED + ), + } + ) + test.timer.__create_and_queue_test_time_advance_timer(1, "oneshot") + test.mock_time.advance_time(1) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.lock.lock.not_fully_locked()) + ) + end +) + +local function refresh_commands(dev) + local req = DoorLock.attributes.LockState:read(dev) + return req +end + +test.register_message_test( + "Handle received refresh.", { + { + channel = "capability", + direction = "receive", + message = { + mock_device.id, + {capability = "refresh", component = "main", command = "refresh", args = {}}, + }, + }, + { + channel = "matter", + direction = "send", + message = {mock_device.id, refresh_commands(mock_device)}, + }, + } +) + +local AlarmCodeEnum = DoorLock.types.AlarmCodeEnum +test.register_message_test( + "Handle DoorLockAlarm event from Matter device.", { + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.DoorLockAlarm:build_test_event_report( + mock_device, 1, {alarm_code = AlarmCodeEnum.LOCK_JAMMED} + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.unableToLockTheDoor({state_change = true}) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.DoorLockAlarm:build_test_event_report( + mock_device, 1, {alarm_code = AlarmCodeEnum.LOCK_FACTORY_RESET} + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.lockFactoryReset({state_change = true}) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.DoorLockAlarm:build_test_event_report( + mock_device, 1, {alarm_code = AlarmCodeEnum.WRONG_CODE_ENTRY_LIMIT} + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.attemptsExceeded({state_change = true}) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.DoorLockAlarm:build_test_event_report( + mock_device, 1, {alarm_code = AlarmCodeEnum.FRONT_ESCEUTCHEON_REMOVED} + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.damaged({state_change = true}) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.DoorLockAlarm:build_test_event_report( + mock_device, 1, {alarm_code = AlarmCodeEnum.DOOR_FORCED_OPEN} + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.forcedOpeningAttempt({state_change = true}) + ), + }, + } +) + +test.register_message_test( + "Handle Lock Operation event from Matter device.", { + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLOCK, + operation_source = types.OperationSourceEnum.KEYPAD, + user_index = 1, + fabric_index = 1, + source_node = 1, + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ) + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.unlocked( + {data = {method = "keypad", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.LOCK, + operation_source = types.OperationSourceEnum.UNSPECIFIED, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.locked( + {data = {userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLATCH, + operation_source = types.OperationSourceEnum.MANUAL, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.locked( + {data = {method = "manual", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLOCK, + operation_source = types.OperationSourceEnum.PROPRIETARY_REMOTE, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.unlocked( + {data = {method = "proprietaryRemote", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.LOCK, + operation_source = types.OperationSourceEnum.AUTO, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.locked( + {data = {method = "auto", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLATCH, + operation_source = types.OperationSourceEnum.BUTTON, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.locked( + {data = {method = "button", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLOCK, + operation_source = types.OperationSourceEnum.SCHEDULE, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.unlocked( + {data = {userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.LOCK, + operation_source = types.OperationSourceEnum.REMOTE, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.locked( + {data = {method = "command", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLATCH, + operation_source = types.OperationSourceEnum.RFID, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.locked( + {data = {method = "rfid", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLOCK, + operation_source = types.OperationSourceEnum.BIOMETRIC, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.unlocked( + {data = {method = "keypad", userIndex = 1}, state_change = true} + ) + ), + }, + { + channel = "matter", + direction = "receive", + message = { + mock_device.id, + DoorLock.events.LockOperation:build_test_event_report( + mock_device, 1, + { + lock_operation_type = types.LockOperationTypeEnum.UNLOCK, + operation_source = types.OperationSourceEnum.ALIRO, + user_index = 1, + fabric_index = 1, + source_node = 1 + } + ), + }, + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message( + "main", + capabilities.lock.lock.unlocked( + {data = {userIndex = 1}, state_change = true} + ) + ), + } + } +) + +test.register_coroutine_test( + "Added lifecycle event lock nocodes nobattery", + function() + test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockAlarm.alarm.clear({state_change = true}) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Add User command received from SmartThings.", + function() + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "addUser", + args = {"Guest1", "adminMember"} + }, + }) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.GetUser( + mock_device, 1, + 1 -- user_index + ) + }) + test.wait_for_events() + test.socket.matter:__queue_receive({ + mock_device.id, + DoorLock.client.commands.GetUserResponse:build_test_command_response( + mock_device, 1, + 1, --user_index + nil, nil, nil, nil, nil, nil, nil, nil, nil + ), + }) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.SetUser( + mock_device, 1, + types.DataOperationTypeEnum.ADD, + 1, + "Guest1", + nil, + nil, + types.UserTypeEnum.UNRESTRICTED_USER, + nil + ) + }) + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.SetUser:build_test_command_response( + mock_device, 1 + ) + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.users({{userIndex = 1, userType = "adminMember"}}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="addUser", statusCode="success", userIndex=1}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Add User command received from SmartThings and commandResult is busy", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "addUser", + args = {"Guest1", "adminMember"} + }, + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="addUser", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Add User command received from SmartThings and commandResult is resourceExhausted", + function() + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "addUser", + args = {"Guest1", "adminMember"} + }, + }) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.GetUser( + mock_device, 1, + 1 -- user_index + ) + }) + test.wait_for_events() + test.socket.matter:__queue_receive({ + mock_device.id, + DoorLock.client.commands.GetUserResponse:build_test_command_response( + mock_device, 1, + 10, --user_index + nil, nil, + DoorLock.types.UserStatusEnum.OCCUPIED_ENABLED, --user_state + nil, nil, nil, nil, nil, nil + ), + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="addUser", statusCode="resourceExhausted", userIndex=10}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Update User command received from SmartThings.", + function() + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "updateUser", + args = {1, "Guest1", "adminMember"} + }, + }) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.SetUser( + mock_device, 1, + types.DataOperationTypeEnum.MODIFY, + 1, + "Guest1", + nil, + nil, + types.UserTypeEnum.UNRESTRICTED_USER, + nil + ) + }) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.SetUser:build_test_command_response( + mock_device, 1 + ) + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="updateUser", statusCode="success", userIndex=1}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + test.wait_for_events() + end +) + +test.register_coroutine_test( + "Update User command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "updateUser", + args = {1, "Guest1", "adminMember"} + }, + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="updateUser", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Delete User command received from SmartThings.", + function() + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "deleteUser", + args = {1} + }, + }) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.ClearUser( + mock_device, 1, + 1 + ) + }) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.ClearUser:build_test_command_response( + mock_device, 1 + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.users({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="deleteUser", statusCode="success", userIndex=1}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Delete User command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "deleteUser", + args = {1} + }, + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="deleteUser", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Delete All Users command received from SmartThings.", + function() + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "deleteAllUsers", + args = {} + }, + }) + test.socket.matter:__expect_send({ + mock_device.id, + DoorLock.server.commands.ClearUser( + mock_device, 1, + 0xFFFE + ) + }) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.ClearUser:build_test_command_response( + mock_device, 1 + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.users({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="deleteAllUsers", statusCode="success", userIndex=65534}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Delete All Users command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive({ + mock_device.id, + { + capability = capabilities.lockUsers.ID, + command = "deleteAllUsers", + args = {} + }, + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockUsers.commandResult( + {commandName="deleteAllUsers", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Add Credential command received from SmartThings.", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "addCredential", + args = {1, "adminMember", "pin", "654123"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + 1, -- user_index + nil, -- user_status + DoorLock.types.DlUserType.UNRESTRICTED_USER -- user_type + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.SUCCESS, -- status + 1, -- user_index + 2 -- next_credential_index + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials( + {{credentialIndex=1, credentialType="pin", userIndex=1}}, + {visibility={displayed=false}} + ) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="addCredential", credentialIndex=1, statusCode="success", userIndex=1}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Add Credential command received from SmartThings and commandResult is busy", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "addCredential", + args = {1, "adminMember", "pin", "654123"} + }, + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="addCredential", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Add Credential command received from SmartThings and commandResult is invalidCommand", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "addCredential", + args = {1, "adminMember", "pin", "654123"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + 1, -- user_index + nil, -- user_status + DoorLock.types.DlUserType.UNRESTRICTED_USER -- user_type + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.INVALID_FIELD, -- status + 1, -- user_index + 2 -- next_credential_index + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="addCredential", statusCode="invalidCommand"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Add Credential command received from SmartThings and user_index is occupied", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "addCredential", + args = {1, "adminMember", "pin", "654123"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + 1, -- user_index + nil, -- user_status + DoorLock.types.DlUserType.UNRESTRICTED_USER -- user_type + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.OCCUPIED, -- status + 1, -- user_index + 2 -- next_credential_index + ), + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 2} + ), -- credential + "654123", -- credential_data + 1, -- user_index + nil, -- user_status + DoorLock.types.DlUserType.UNRESTRICTED_USER -- user_type + ), + } + ) + test.wait_for_events() + end +) + +test.register_coroutine_test( + "Add Credential command received from SmartThings and commandResult is resourceExhausted", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "addCredential", + args = {1, "adminMember", "pin", "654123"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.ADD, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + 1, -- user_index + nil, -- user_status + DoorLock.types.DlUserType.UNRESTRICTED_USER -- user_type + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.OCCUPIED, -- status + 1, -- user_index + nil -- next_credential_index + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="addCredential", statusCode="resourceExhausted"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Update Credential command received from SmartThings.", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "updateCredential", + args = {1, 1, "pin", "654123"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetCredential( + mock_device, 1, -- endpoint + DoorLock.types.DataOperationTypeEnum.MODIFY, -- operation_type + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ), -- credential + "654123", -- credential_data + 1, -- user_index + nil, -- user_status + nil -- user_type + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.client.commands.SetCredentialResponse:build_test_command_response( + mock_device, 1, + DoorLock.types.DlStatus.SUCCESS, -- status + 1, -- user_index + 2 -- next_credential_index + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="updateCredential", credentialIndex=1, statusCode="success", userIndex=1}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Update Credential command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "updateCredential", + args = {1, 1, "pin", "654123"} + }, + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="updateCredential", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Delete Credential command received from SmartThings.", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "deleteCredential", + args = {1, "pin"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.ClearCredential( + mock_device, 1, -- endpoint + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 1} + ) + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.ClearCredential:build_test_command_response( + mock_device, 1 + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="deleteCredential", credentialIndex=1, statusCode="success"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Delete Credential command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "deleteCredential", + args = {1, "pin"} + }, + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="deleteCredential", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Delete all Credentials command received from SmartThings.", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "deleteAllCredentials", + args = {"pin"} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.ClearCredential( + mock_device, 1, -- endpoint + DoorLock.types.CredentialStruct( + {credential_type = DoorLock.types.CredentialTypeEnum.PIN, credential_index = 0xFFFE} + ) + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.ClearCredential:build_test_command_response( + mock_device, 1 + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.credentials({}, {visibility={displayed=false}}) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="deleteAllCredentials", credentialIndex=65534, statusCode="success"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Delete all Credentials command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockCredentials.ID, + command = "deleteAllCredentials", + args = {"pin"} + }, + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockCredentials.commandResult( + {commandName="deleteAllCredentials", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Add Week Day Schedule command received from SmartThings.", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockSchedules.ID, + command = "setWeekDaySchedule", + args = {1, 1, {weekDays={"Monday"}, startHour=12, startMinute=30, endHour=17, endMinute=30}} + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.SetWeekDaySchedule( + mock_device, 1, -- endpoint + 1, -- Week Day Schedule Index + 1, -- User Index + 2, -- Days Mask + 12, -- Start Hour + 30, -- Start Minute + 17, -- End Hour + 30 -- End Minute + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.SetWeekDaySchedule:build_test_command_response( + mock_device, 1 + ) + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.weekDaySchedules( + {{ + userIndex=1, + schedules={{ + scheduleIndex=1, + weekdays={"Monday"}, + startHour=12, + startMinute=30, + endHour=17, + endMinute=30 + }}, + }}, + {visibility={displayed=false}} + ) + ) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.commandResult( + {commandName="setWeekDaySchedule", userIndex=1, scheduleIndex=1, statusCode="success"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Add Week Day Schedule command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockSchedules.ID, + command = "setWeekDaySchedule", + args = {1, 1, {weekDays={"Monday"}, startHour=12, startMinute=30, endHour=17, endMinute=30}} + }, + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.commandResult( + {commandName="setWeekDaySchedule", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Handle Clear Week Day Schedule command received from SmartThings.", + function() + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockSchedules.ID, + command = "clearWeekDaySchedules", + args = { + 1, -- user index + 1, -- schedule index + } + }, + } + ) + test.socket.matter:__expect_send( + { + mock_device.id, + DoorLock.server.commands.ClearWeekDaySchedule( + mock_device, 1, -- endpoint + 1, -- schedule index + 1 -- user index + ), + } + ) + test.wait_for_events() + test.socket.matter:__queue_receive( + { + mock_device.id, + DoorLock.server.commands.ClearWeekDaySchedule:build_test_command_response( + mock_device, 1 + ), + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.commandResult( + {commandName="clearWeekDaySchedules", userIndex = 1, scheduleIndex=1, statusCode="success"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.register_coroutine_test( + "Clear Week Day Schedule command received from SmartThings and send busy state", + function() + mock_device:set_field(lock_utils.BUSY_STATE, os.time(), {persist = true}) + test.socket.capability:__queue_receive( + { + mock_device.id, + { + capability = capabilities.lockSchedules.ID, + command = "clearWeekDaySchedules", + args = { + 1, -- user index + 1, -- schedule index + } + }, + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message( + "main", + capabilities.lockSchedules.commandResult( + {commandName="clearWeekDaySchedules", statusCode="busy"}, + {state_change=true, visibility={displayed=false}} + ) + ) + ) + end +) + +test.run_registered_tests()