Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions drivers/SmartThings/matter-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3073,6 +3073,41 @@ matterGeneric:
deviceTypes:
- id: 0x0142 # Camera
deviceProfileName: camera
- id: "matter/intercom"
deviceLabel: Matter Intercom
deviceTypes:
- id: 0x0140 # Intercom
deviceProfileName: camera
- id: "matter/audio/doorbell"
deviceLabel: Matter Audio DoorBell
deviceTypes:
- id: 0x0141 # Audio DoorBell
deviceProfileName: camera
- id: "matter/video/doorbell"
deviceLabel: Matter Video DoorBell
deviceTypes:
- id: 0x0143 # Video DoorBell
deviceProfileName: camera
- id: "matter/floodlight/camera"
deviceLabel: Matter Floodlight Camera
deviceTypes:
- id: 0x0144 # Floodlight Camera
deviceProfileName: camera
- id: "matter/snapshot/camera"
deviceLabel: Matter Snapshot Camera
deviceTypes:
- id: 0x0145 # Snapshot Camera
deviceProfileName: camera
- id: "matter/chime"
deviceLabel: Matter Chime
deviceTypes:
- id: 0x0146 # Chime
deviceProfileName: chime
- id: "matter/doorbell"
deviceLabel: Matter DoorBell
deviceTypes:
- id: 0x0148 # DoorBell
deviceProfileName: doorbell

matterThing:
- id: SmartThings/MatterThing
Expand Down
10 changes: 10 additions & 0 deletions drivers/SmartThings/matter-switch/profiles/chime.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: chime
components:
- id: main
capabilities:
- id: sounds
version: 1
optional: true
- id: audioMute
version: 1
optional: true
7 changes: 7 additions & 0 deletions drivers/SmartThings/matter-switch/profiles/doorbell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: doorbell
components:
- id: main
capabilities:
- id: button
version: 1
optional: true
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,28 @@ function CameraDeviceConfiguration.match_profile(device, status_light_enabled_pr
local speaker_component_capabilities = {}
local microphone_component_capabilities = {}
local doorbell_component_capabilities = {}
local profile = "camera"

local function has_server_cluster_type(cluster)
return cluster.cluster_type == "SERVER" or cluster.cluster_type == "BOTH"
end

local camera_endpoints = switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.CAMERA)
local camera_profile_device_types = {
fields.DEVICE_TYPE_ID.CAMERA.INTERCOM,
fields.DEVICE_TYPE_ID.CAMERA.AUDIO_DOORBELL,
fields.DEVICE_TYPE_ID.CAMERA.CAMERA,
fields.DEVICE_TYPE_ID.CAMERA.VIDEO_DOORBELL,
fields.DEVICE_TYPE_ID.CAMERA.FLOODLIGHT_CAMERA,
fields.DEVICE_TYPE_ID.CAMERA.SNAPSHOT_CAMERA,
}

local camera_endpoints = switch_utils.get_endpoints_by_device_type(device, camera_profile_device_types)
local chime_endpoints = switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.CAMERA.CHIME)
local doorbell_endpoints = switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.CAMERA.DOORBELL)

if #camera_endpoints > 0 then
-- get full list of camera endpoints, including chime and doorbell
camera_endpoints = switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.CAMERA)
local camera_ep = switch_utils.get_endpoint_info(device, camera_endpoints[1])
for _, ep_cluster in pairs(camera_ep.clusters or {}) do
if ep_cluster.cluster_id == clusters.CameraAvStreamManagement.ID and has_server_cluster_type(ep_cluster) then
Expand Down Expand Up @@ -111,40 +126,47 @@ function CameraDeviceConfiguration.match_profile(device, status_light_enabled_pr
table.insert(main_component_capabilities, capabilities.webrtc.ID)
end
end
end
local chime_endpoints = switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.CHIME)
if #chime_endpoints > 0 then
if #doorbell_endpoints > 0 then
table.insert(doorbell_component_capabilities, capabilities.button.ID)
CameraDeviceConfiguration.update_doorbell_component_map(device, doorbell_endpoints[1], camera_fields.profile_components.doorbell)
button_cfg.configure_buttons(device)
end
if #chime_endpoints > 0 then
table.insert(main_component_capabilities, capabilities.sounds.ID)
end
if status_light_enabled_present then
table.insert(status_led_component_capabilities, capabilities.switch.ID)
end
if status_light_brightness_present then
table.insert(status_led_component_capabilities, capabilities.mode.ID)
end
if #status_led_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.statusLed, status_led_component_capabilities})
end
if #speaker_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.speaker, speaker_component_capabilities})
end
if #microphone_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.microphone, microphone_component_capabilities})
end
if #doorbell_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.doorbell, doorbell_component_capabilities})
end
elseif #chime_endpoints > 0 then
table.insert(main_component_capabilities, capabilities.sounds.ID)
end
local doorbell_endpoints = switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.DOORBELL)
if #doorbell_endpoints > 0 then
table.insert(doorbell_component_capabilities, capabilities.button.ID)
CameraDeviceConfiguration.update_doorbell_component_map(device, doorbell_endpoints[1])
table.insert(main_component_capabilities, capabilities.audioMute.ID)
profile = "chime"
elseif #doorbell_endpoints > 0 then
table.insert(main_component_capabilities, capabilities.button.ID)
CameraDeviceConfiguration.update_doorbell_component_map(device, doorbell_endpoints[1], camera_fields.profile_components.main)
button_cfg.configure_buttons(device)
end
if status_light_enabled_present then
table.insert(status_led_component_capabilities, capabilities.switch.ID)
end
if status_light_brightness_present then
table.insert(status_led_component_capabilities, capabilities.mode.ID)
profile = "doorbell"
end

table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.main, main_component_capabilities})
if #status_led_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.statusLed, status_led_component_capabilities})
end
if #speaker_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.speaker, speaker_component_capabilities})
end
if #microphone_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.microphone, microphone_component_capabilities})
end
if #doorbell_component_capabilities > 0 then
table.insert(optional_supported_component_capabilities, {camera_fields.profile_components.doorbell, doorbell_component_capabilities})
end
table.insert(optional_supported_component_capabilities, 1, {camera_fields.profile_components.main, main_component_capabilities})

if camera_utils.optional_capabilities_list_changed(optional_supported_component_capabilities, device.profile.components) then
device:try_update_metadata({profile = "camera", optional_component_capabilities = optional_supported_component_capabilities})
device:try_update_metadata({profile = profile, optional_component_capabilities = optional_supported_component_capabilities})
end
end

Expand Down Expand Up @@ -270,9 +292,13 @@ function CameraDeviceConfiguration.initialize_camera_capabilities(device)
init_camera_privacy_mode(device)
end

function CameraDeviceConfiguration.update_doorbell_component_map(device, ep)
function CameraDeviceConfiguration.update_doorbell_component_map(device, ep, component)
local component_map = device:get_field(fields.COMPONENT_TO_ENDPOINT_MAP) or {}
component_map.doorbell = ep
if component == camera_fields.profile_components.main then
component_map.main = ep
elseif component == camera_fields.profile_components.doorbell then
component_map.doorbell = ep
end
device:set_field(fields.COMPONENT_TO_ENDPOINT_MAP, component_map, {persist = true})
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ end
function CameraLifecycleHandlers.info_changed(driver, device, event, args)
if camera_utils.profile_changed(device.profile.components, args.old_st_store.profile.components) then
camera_cfg.initialize_camera_capabilities(device)
if #switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.DOORBELL) > 0 then
if #switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.CAMERA.DOORBELL) > 0 then
button_cfg.configure_buttons(device)
end
device:subscribe()
Expand Down
13 changes: 10 additions & 3 deletions drivers/SmartThings/matter-switch/src/switch_utils/fields.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,17 @@ SwitchFields.CURRENT_HUESAT_ATTR_MAX = 254
SwitchFields.DEVICE_TYPE_ID = {
AGGREGATOR = 0x000E,
BRIDGED_NODE = 0x0013,
CAMERA = 0x0142,
CHIME = 0x0146,
CAMERA = {
INTERCOM = 0x0140,
AUDIO_DOORBELL = 0x0141,
CAMERA = 0x0142,
VIDEO_DOORBELL = 0x0143,
FLOODLIGHT_CAMERA = 0x0144,
SNAPSHOT_CAMERA = 0x0145,
CHIME = 0x0146,
DOORBELL = 0x0148,
},
DIMMABLE_PLUG_IN_UNIT = 0x010B,
DOORBELL = 0x0143,
ELECTRICAL_SENSOR = 0x0510,
GENERIC_SWITCH = 0x000F,
MOUNTED_ON_OFF_CONTROL = 0x010F,
Expand Down
10 changes: 8 additions & 2 deletions drivers/SmartThings/matter-switch/src/switch_utils/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,19 @@ function utils.matter_handler(driver, device, response_block)
device.log.info(string.format("Fallback handler for %s", response_block))
end

-- get a list of endpoints for a specified device type.
-- get a list of endpoints for a specified device type or list of device types
function utils.get_endpoints_by_device_type(device, device_type_id)
local dt_eps = {}
for _, ep in ipairs(device.endpoints) do
for _, dt in ipairs(ep.device_types) do
if dt.device_type_id == device_type_id then
if type(device_type_id) == "table" then
if utils.tbl_contains(device_type_id, dt.device_type_id) then
table.insert(dt_eps, ep.endpoint_id)
break
end
elseif dt.device_type_id == device_type_id then
table.insert(dt_eps, ep.endpoint_id)
break
end
end
end
Expand Down
Loading
Loading