Skip to content

Commit 35fac43

Browse files
Support the battery capability in smoke/co subdriver
This change adds support for the battery percentage for devices that support the BatPercentRemaining attribute from the PowerSource cluster in addition to the battery level from the SmokeCoAlarm cluster.
1 parent 9d3589f commit 35fac43

9 files changed

+317
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: co
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: carbonMonoxideDetector
6+
version: 1
7+
- id: batteryLevel
8+
version: 1
9+
- id: battery
10+
version: 1
11+
- id: hardwareFault
12+
version: 1
13+
- id: firmwareUpdate
14+
version: 1
15+
- id: refresh
16+
version: 1
17+
categories:
18+
- name: SmokeDetector
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: co-comeas
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: carbonMonoxideDetector
6+
version: 1
7+
- id: carbonMonoxideMeasurement
8+
version: 1
9+
- id: batteryLevel
10+
version: 1
11+
- id: battery
12+
version: 1
13+
- id: hardwareFault
14+
version: 1
15+
- id: firmwareUpdate
16+
version: 1
17+
- id: refresh
18+
version: 1
19+
categories:
20+
- name: SmokeDetector
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: smoke
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: smokeDetector
6+
version: 1
7+
- id: hardwareFault
8+
version: 1
9+
- id: batteryLevel
10+
version: 1
11+
- id: battery
12+
version: 1
13+
- id: firmwareUpdate
14+
version: 1
15+
- id: refresh
16+
version: 1
17+
categories:
18+
- name: SmokeDetector
19+
preferences:
20+
- preferenceId: certifiedpreferences.smokeSensorSensitivity
21+
explicit: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: smoke-co
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: smokeDetector
6+
version: 1
7+
- id: carbonMonoxideDetector
8+
version: 1
9+
- id: batteryLevel
10+
version: 1
11+
- id: battery
12+
version: 1
13+
- id: hardwareFault
14+
version: 1
15+
- id: firmwareUpdate
16+
version: 1
17+
- id: refresh
18+
version: 1
19+
categories:
20+
- name: SmokeDetector
21+
preferences:
22+
- preferenceId: certifiedpreferences.smokeSensorSensitivity
23+
explicit: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: smoke-co-comeas
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: smokeDetector
6+
version: 1
7+
- id: carbonMonoxideDetector
8+
version: 1
9+
- id: carbonMonoxideMeasurement
10+
version: 1
11+
- id: batteryLevel
12+
version: 1
13+
- id: battery
14+
version: 1
15+
- id: hardwareFault
16+
version: 1
17+
- id: firmwareUpdate
18+
version: 1
19+
- id: refresh
20+
version: 1
21+
categories:
22+
- name: SmokeDetector
23+
preferences:
24+
- preferenceId: certifiedpreferences.smokeSensorSensitivity
25+
explicit: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: smoke-co-temp-humidity-comeas
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: smokeDetector
6+
version: 1
7+
- id: carbonMonoxideDetector
8+
version: 1
9+
- id: relativeHumidityMeasurement
10+
version: 1
11+
- id: temperatureMeasurement
12+
version: 1
13+
- id: carbonMonoxideMeasurement
14+
version: 1
15+
- id: batteryLevel
16+
version: 1
17+
- id: battery
18+
version: 1
19+
- id: hardwareFault
20+
version: 1
21+
- id: firmwareUpdate
22+
version: 1
23+
- id: refresh
24+
version: 1
25+
categories:
26+
- name: SmokeDetector
27+
preferences:
28+
- preferenceId: certifiedpreferences.smokeSensorSensitivity
29+
explicit: true
30+
- preferenceId: tempOffset
31+
explicit: true
32+
- preferenceId: humidityOffset
33+
explicit: true

drivers/SmartThings/matter-sensor/src/smoke-co-alarm/init.lua

+41-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ local CARBON_MONOXIDE_MEASUREMENT_UNIT = "CarbonMonoxideConcentrationMeasurement
2020
local SMOKE_CO_ALARM_DEVICE_TYPE_ID = 0x0076
2121
local PROFILE_MATCHED = "__profile_matched"
2222

23+
local HUE_MANUFACTURER_ID = 0x100B
24+
25+
local battery_support = {
26+
NO_BATTERY = "NO_BATTERY",
27+
BATTERY_PERCENTAGE = "BATTERY_PERCENTAGE"
28+
}
29+
2330
local version = require "version"
2431
if version.api < 10 then
2532
clusters.SmokeCoAlarm = require "SmokeCoAlarm"
@@ -49,13 +56,18 @@ end
4956
local supported_profiles =
5057
{
5158
"co",
59+
"co-battery",
5260
"co-comeas",
61+
"co-comeas-battery",
5362
"smoke",
63+
"smoke-battey",
5464
"smoke-co-comeas",
55-
"smoke-co-temp-humidity-comeas"
65+
"smoke-co-comeas-battery",
66+
"smoke-co-temp-humidity-comeas",
67+
"smoke-co-temp-humidity-comeas-battery"
5668
}
5769

58-
local function match_profile(device)
70+
local function match_profile(device, battery_supported)
5971
local smoke_eps = embedded_cluster_utils.get_endpoints(device, clusters.SmokeCoAlarm.ID, {feature_bitmap = clusters.SmokeCoAlarm.types.Feature.SMOKE_ALARM})
6072
local co_eps = embedded_cluster_utils.get_endpoints(device, clusters.SmokeCoAlarm.ID, {feature_bitmap = clusters.SmokeCoAlarm.types.Feature.CO_ALARM})
6173
local temp_eps = embedded_cluster_utils.get_endpoints(device, clusters.TemperatureMeasurement.ID)
@@ -84,6 +96,9 @@ local function match_profile(device)
8496
if #co_level_eps > 0 then
8597
profile_name = profile_name .. "-colevel"
8698
end
99+
if battery_supported == battery_support.BATTERY_PERCENTAGE then
100+
profile_name = profile_name .. "-battery"
101+
end
87102

88103
-- remove leading "-"
89104
profile_name = string.sub(profile_name, 2)
@@ -108,7 +123,13 @@ end
108123

109124
local function device_init(driver, device)
110125
if not device:get_field(PROFILE_MATCHED) then
111-
match_profile(device)
126+
local battery_feature_eps = device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY})
127+
-- Hue devices support the PowerSource cluster but don't support reporting battery percentage remaining
128+
if #battery_feature_eps > 0 and device.manufacturer_info.vendor_id ~= HUE_MANUFACTURER_ID then
129+
device:send(clusters.PowerSource.attributes.AttributeList:read())
130+
else
131+
match_profile(device, battery_support.NO_BATTERY)
132+
end
112133
end
113134
device:subscribe()
114135
end
@@ -201,6 +222,16 @@ local function battery_alert_attr_handler(driver, device, ib, response)
201222
end
202223
end
203224

225+
local function power_source_attribute_list_handler(driver, device, ib, response)
226+
for _, attr in ipairs(ib.data.elements) do
227+
-- Re-profile the device if BatPercentRemaining (Attribute ID 0x0C) is available
228+
if attr.value == 0x0C then
229+
match_profile(device, battery_support.BATTERY_PERCENTAGE)
230+
return
231+
end
232+
end
233+
end
234+
204235
local matter_smoke_co_alarm_handler = {
205236
NAME = "matter-smoke-co-alarm",
206237
lifecycle_handlers = {
@@ -219,7 +250,10 @@ local matter_smoke_co_alarm_handler = {
219250
[clusters.CarbonMonoxideConcentrationMeasurement.ID] = {
220251
[clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue.ID] = carbon_monoxide_attr_handler,
221252
[clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit.ID] = carbon_monoxide_unit_attr_handler,
222-
}
253+
},
254+
[clusters.PowerSource.ID] = {
255+
[clusters.PowerSource.attributes.AttributeList.ID] = power_source_attribute_list_handler,
256+
},
223257
},
224258
},
225259
subscribed_attributes = {
@@ -246,6 +280,9 @@ local matter_smoke_co_alarm_handler = {
246280
},
247281
[capabilities.batteryLevel.ID] = {
248282
clusters.SmokeCoAlarm.attributes.BatteryAlert,
283+
},
284+
[capabilities.batteryLevel.ID] = {
285+
clusters.PowerSource.attributes.BatPercentRemaining,
249286
}
250287
},
251288
can_handle = is_matter_smoke_co_alarm

drivers/SmartThings/matter-sensor/src/test/test_matter_smoke_co_alarm.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ local cluster_subscribe_list = {
7373
}
7474

7575
local function test_init()
76+
local read_attribute_list = clusters.PowerSource.attributes.AttributeList:read()
77+
test.socket.matter:__expect_send({mock_device.id, read_attribute_list})
7678
local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device)
7779
for i, cluster in ipairs(cluster_subscribe_list) do
7880
if i > 1 then
@@ -81,7 +83,6 @@ local function test_init()
8183
end
8284
test.socket.matter:__expect_send({mock_device.id, subscribe_request})
8385
test.mock_device.add_test_device(mock_device)
84-
mock_device:expect_metadata_update({ profile = "smoke-co-temp-humidity-comeas" })
8586
end
8687

8788
test.set_test_init_function(test_init)

0 commit comments

Comments
 (0)