Skip to content

Matter Smoke CO Alarm: Add new subscribed attribute, add new profile #2145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: smoke-co-comeas-colevel-battery
components:
- id: main
capabilities:
- id: smokeDetector
version: 1
- id: carbonMonoxideDetector
version: 1
- id: carbonMonoxideMeasurement
version: 1
- id: carbonMonoxideHealthConcern
version: 1
- id: battery
version: 1
- id: hardwareFault
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: SmokeDetector
17 changes: 17 additions & 0 deletions drivers/SmartThings/matter-sensor/src/smoke-co-alarm/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ local supported_profiles =
"smoke-battery",
"smoke-co-comeas",
"smoke-co-comeas-battery",
"smoke-co-comeas-colevel-battery",
"smoke-co-temp-humidity-comeas",
"smoke-co-temp-humidity-comeas-battery"
}
Expand Down Expand Up @@ -247,6 +248,18 @@ local function handle_battery_percent_remaining(driver, device, ib, response)
end
end

local level_strings = {
[clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.UNKNOWN] = "unknown",
[clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.LOW] = "good",
[clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.MEDIUM] = "moderate",
[clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.HIGH] = "unhealthy",
[clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.CRITICAL] = "hazardous",
}

local function carbon_monoxide_level_handler(driver, device, ib, response)
device:emit_event_for_endpoint(ib.endpoint_id, capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern(level_strings[ib.data.value]))
end

local function do_configure(driver, device)
local battery_feature_eps = device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY})
if #battery_feature_eps > 0 then
Expand Down Expand Up @@ -275,6 +288,7 @@ local matter_smoke_co_alarm_handler = {
[clusters.CarbonMonoxideConcentrationMeasurement.ID] = {
[clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue.ID] = carbon_monoxide_attr_handler,
[clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit.ID] = carbon_monoxide_unit_attr_handler,
[clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue.ID] = carbon_monoxide_level_handler,
},
[clusters.PowerSource.ID] = {
[clusters.PowerSource.attributes.AttributeList.ID] = power_source_attribute_list_handler,
Expand Down Expand Up @@ -307,6 +321,9 @@ local matter_smoke_co_alarm_handler = {
clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit,
},
[capabilities.carbonMonoxideHealthConcern.ID] = {
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue,
},
[capabilities.batteryLevel.ID] = {
clusters.PowerSource.attributes.BatChargeLevel,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ local mock_device = test.mock_device.build_test_matter_device({
}
})

local mock_device_colevel = test.mock_device.build_test_matter_device({
profile = t_utils.get_profile_definition("co-comeas-colevel-battery.yml"),
manufacturer_info = {
vendor_id = 0x0000,
product_id = 0x0000,
},
endpoints = {
{
endpoint_id = 0,
clusters = {
{cluster_id = clusters.Basic.ID, cluster_type = "SERVER"},
},
device_types = {
{device_type_id = 0x0016, device_type_revision = 1} -- RootNode
}
},
{
endpoint_id = 1,
clusters = {
{cluster_id = clusters.SmokeCoAlarm.ID, cluster_type = "SERVER", feature_map = clusters.SmokeCoAlarm.types.Feature.CO_ALARM},
{cluster_id = clusters.CarbonMonoxideConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = clusters.CarbonMonoxideConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT | clusters.CarbonMonoxideConcentrationMeasurement.types.Feature.LEVEL_INDICATION},
{cluster_id = clusters.PowerSource.ID, cluster_type = "SERVER", feature_map = clusters.PowerSource.types.PowerSourceFeature.BATTERY},
},
device_types = {
{device_type_id = 0x0076, device_type_revision = 1} -- Smoke CO Alarm
}
}
}
})

local cluster_subscribe_list = {
clusters.SmokeCoAlarm.attributes.SmokeState,
clusters.SmokeCoAlarm.attributes.TestInProgress,
Expand Down Expand Up @@ -87,6 +117,27 @@ local function test_init()
test.mock_device.add_test_device(mock_device)
end

local cluster_subscribe_list_colevel = {
clusters.SmokeCoAlarm.attributes.TestInProgress,
clusters.SmokeCoAlarm.attributes.COState,
clusters.SmokeCoAlarm.attributes.HardwareFaultAlert,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue,
clusters.PowerSource.attributes.BatPercentRemaining,
}

local function test_init_colevel()
local subscribe_request = cluster_subscribe_list_colevel[1]:subscribe(mock_device_colevel)
for i, cluster in ipairs(cluster_subscribe_list_colevel) do
if i > 1 then
subscribe_request:merge(cluster:subscribe(mock_device_colevel))
end
end
test.socket.matter:__expect_send({mock_device_colevel.id, subscribe_request})
test.mock_device.add_test_device(mock_device_colevel)
end

test.set_test_init_function(test_init)

test.register_message_test(
Expand Down Expand Up @@ -134,6 +185,58 @@ test.register_message_test(
}
)

test.register_coroutine_test(
"Level value reports should generate events",
function()
test.socket.matter:__queue_receive({
mock_device_colevel.id,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue:build_test_report_data(
mock_device_colevel, 1, clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.UNKNOWN
)
})
test.socket.capability:__expect_send(
mock_device_colevel:generate_test_message("main", capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern.unknown())
)
test.socket.matter:__queue_receive({
mock_device_colevel.id,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue:build_test_report_data(
mock_device_colevel, 1, clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.LOW
)
})
test.socket.capability:__expect_send(
mock_device_colevel:generate_test_message("main", capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern.good())
)
test.socket.matter:__queue_receive({
mock_device_colevel.id,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue:build_test_report_data(
mock_device_colevel, 1, clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.MEDIUM
)
})
test.socket.capability:__expect_send(
mock_device_colevel:generate_test_message("main", capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern.moderate())
)
test.socket.matter:__queue_receive({
mock_device_colevel.id,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue:build_test_report_data(
mock_device_colevel, 1, clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.HIGH
)
})
test.socket.capability:__expect_send(
mock_device_colevel:generate_test_message("main", capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern.unhealthy())
)
test.socket.matter:__queue_receive({
mock_device_colevel.id,
clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue:build_test_report_data(
mock_device_colevel, 1, clusters.CarbonMonoxideConcentrationMeasurement.types.LevelValueEnum.CRITICAL
)
})
test.socket.capability:__expect_send(
mock_device_colevel:generate_test_message("main", capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern.hazardous())
)
end,
{ test_init = test_init_colevel }
)

test.register_message_test(
"Test CO state handler",
{
Expand Down
Loading