Skip to content

Commit 426c668

Browse files
authored
Matter Sensor: Streamline do_configure function in air quality sensor subdriver (#1594)
refactor do_configure function in the air quality sensor sub-driver.
1 parent 9093cf9 commit 426c668

File tree

2 files changed

+211
-99
lines changed

2 files changed

+211
-99
lines changed

drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua

Lines changed: 70 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -164,130 +164,101 @@ local supported_profiles =
164164
"aqs-temp-humidity-tvoc-level-pm25-meas",
165165
}
166166

167-
local function configure(driver, device)
168-
-- we have to read the unit before reports of values will do anything
169-
for _, cluster in ipairs(units_required) do
170-
device:send(cluster.attributes.MeasurementUnit:read(device))
167+
local AIR_QUALITY_MAP = {
168+
{capabilities.carbonMonoxideMeasurement.ID, "-co", clusters.CarbonMonoxideConcentrationMeasurement},
169+
{capabilities.carbonMonoxideHealthConcern.ID, "-co", clusters.CarbonMonoxideConcentrationMeasurement},
170+
{capabilities.carbonDioxideMeasurement.ID, "-co2", clusters.CarbonDioxideConcentrationMeasurement},
171+
{capabilities.carbonDioxideHealthConcern.ID, "-co2", clusters.CarbonDioxideConcentrationMeasurement},
172+
{capabilities.nitrogenDioxideHealthConcern.ID, "-no2", clusters.NitrogenDioxideConcentrationMeasurement},
173+
{capabilities.nitrogenDioxideMeasurement.ID, "-no2", clusters.NitrogenDioxideConcentrationMeasurement},
174+
{capabilities.ozoneHealthConcern.ID, "-ozone", clusters.OzoneConcentrationMeasurement},
175+
{capabilities.ozoneMeasurement.ID, "-ozone", clusters.OzoneConcentrationMeasurement},
176+
{capabilities.formaldehydeMeasurement.ID, "-ch2o", clusters.FormaldehydeConcentrationMeasurement},
177+
{capabilities.formaldehydeHealthConcern.ID, "-ch2o", clusters.FormaldehydeConcentrationMeasurement},
178+
{capabilities.veryFineDustHealthConcern.ID, "-pm1", clusters.Pm1ConcentrationMeasurement},
179+
{capabilities.veryFineDustSensor.ID, "-pm1", clusters.Pm1ConcentrationMeasurement},
180+
{capabilities.fineDustSensor.ID, "-pm25", clusters.Pm25ConcentrationMeasurement},
181+
{capabilities.fineDustHealthConcern.ID, "-pm25", clusters.Pm25ConcentrationMeasurement},
182+
{capabilities.dustSensor.ID, "-pm10", clusters.Pm10ConcentrationMeasurement},
183+
{capabilities.dustHealthConcern.ID, "-pm10", clusters.Pm10ConcentrationMeasurement},
184+
{capabilities.radonHealthConcern.ID, "-radon", clusters.RadonConcentrationMeasurement},
185+
{capabilities.radonMeasurement.ID, "-radon", clusters.RadonConcentrationMeasurement},
186+
{capabilities.tvocHealthConcern.ID, "-tvoc", clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement},
187+
{capabilities.tvocMeasurement.ID, "-tvoc", clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement},
188+
}
189+
190+
local function create_level_measurement_profile(device)
191+
local meas_name, level_name = "", ""
192+
for _, details in ipairs(AIR_QUALITY_MAP) do
193+
local cap_id = details[1]
194+
local cluster = details[3]
195+
-- capability describes either a HealthConcern or Measurement/Sensor
196+
if (cap_id:match("HealthConcern$")) then
197+
local attr_eps = embedded_cluster_utils.get_endpoints(device, cluster.ID, { feature_bitmap = cluster.types.Feature.LEVEL_INDICATION })
198+
if #attr_eps > 0 then
199+
level_name = level_name .. details[2]
200+
end
201+
elseif (cap_id:match("Measurement$") or cap_id:match("Sensor$")) then
202+
local attr_eps = embedded_cluster_utils.get_endpoints(device, cluster.ID, { feature_bitmap = cluster.types.Feature.NUMERIC_MEASUREMENT })
203+
if #attr_eps > 0 then
204+
meas_name = meas_name .. details[2]
205+
end
206+
end
171207
end
208+
return meas_name, level_name
209+
end
172210

173-
-- check to see if device can switch to a more limited profile based on cluster support
211+
local function do_configure(driver, device)
174212
local temp_eps = embedded_cluster_utils.get_endpoints(device, clusters.TemperatureMeasurement.ID)
175213
local humidity_eps = embedded_cluster_utils.get_endpoints(device, clusters.RelativeHumidityMeasurement.ID)
176-
local co_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.CarbonMonoxideConcentrationMeasurement.ID, {feature_bitmap = clusters.CarbonMonoxideConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
177-
local co_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.CarbonMonoxideConcentrationMeasurement.ID, {feature_bitmap = clusters.CarbonMonoxideConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
178-
local co2_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.CarbonDioxideConcentrationMeasurement.ID, {feature_bitmap = clusters.CarbonDioxideConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
179-
local co2_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.CarbonDioxideConcentrationMeasurement.ID, {feature_bitmap = clusters.CarbonDioxideConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
180-
local no2_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.NitrogenDioxideConcentrationMeasurement.ID, {feature_bitmap = clusters.NitrogenDioxideConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
181-
local no2_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.NitrogenDioxideConcentrationMeasurement.ID, {feature_bitmap = clusters.NitrogenDioxideConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
182-
local ozone_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.OzoneConcentrationMeasurement.ID, {feature_bitmap = clusters.OzoneConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
183-
local ozone_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.OzoneConcentrationMeasurement.ID, {feature_bitmap = clusters.OzoneConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
184-
local formaldehyde_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.FormaldehydeConcentrationMeasurement.ID, {feature_bitmap = clusters.FormaldehydeConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
185-
local formaldehyde_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.FormaldehydeConcentrationMeasurement.ID, {feature_bitmap = clusters.FormaldehydeConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
186-
local pm1_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.Pm1ConcentrationMeasurement.ID, {feature_bitmap = clusters.Pm1ConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
187-
local pm1_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.Pm1ConcentrationMeasurement.ID, {feature_bitmap = clusters.Pm1ConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
188-
local pm2_5_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.Pm25ConcentrationMeasurement.ID, {feature_bitmap = clusters.Pm25ConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
189-
local pm2_5_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.Pm25ConcentrationMeasurement.ID, {feature_bitmap = clusters.Pm25ConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
190-
local pm10_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.Pm10ConcentrationMeasurement.ID, {feature_bitmap = clusters.Pm10ConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
191-
local pm10_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.Pm10ConcentrationMeasurement.ID, {feature_bitmap = clusters.Pm10ConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
192-
local radon_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.RadonConcentrationMeasurement.ID, {feature_bitmap = clusters.RadonConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
193-
local radon_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.RadonConcentrationMeasurement.ID, {feature_bitmap = clusters.RadonConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
194-
local tvoc_level_eps = embedded_cluster_utils.get_endpoints(device, clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID, {feature_bitmap = clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.types.Feature.LEVEL_INDICATION})
195-
local tvoc_meas_eps = embedded_cluster_utils.get_endpoints(device, clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID, {feature_bitmap = clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.types.Feature.NUMERIC_MEASUREMENT})
214+
215+
-- we have to read the unit before reports of values will do anything
216+
for _, cluster in ipairs(units_required) do
217+
device:send(cluster.attributes.MeasurementUnit:read(device))
218+
end
196219

197220
local profile_name = "aqs"
198-
local level_indication_support = ""
199-
local numeric_measurement_support = ""
200221

201222
if #temp_eps > 0 then
202223
profile_name = profile_name .. "-temp"
203224
end
204225
if #humidity_eps > 0 then
205226
profile_name = profile_name .. "-humidity"
206227
end
207-
if #co_level_eps > 0 then
208-
level_indication_support = level_indication_support .. "-co"
209-
end
210-
if #co2_level_eps > 0 then
211-
level_indication_support = level_indication_support .. "-co2"
212-
end
213-
if #no2_level_eps > 0 then
214-
level_indication_support = level_indication_support .. "-no2"
215-
end
216-
if #ozone_level_eps > 0 then
217-
level_indication_support = level_indication_support .. "-ozone"
218-
end
219-
if #formaldehyde_level_eps > 0 then
220-
level_indication_support = level_indication_support .. "-formaldehyde"
221-
end
222-
if #pm1_level_eps > 0 then
223-
level_indication_support = level_indication_support .. "-pm1"
224-
end
225-
if #pm2_5_level_eps > 0 then
226-
level_indication_support = level_indication_support .. "-pm25"
227-
end
228-
if #pm10_level_eps > 0 then
229-
level_indication_support = level_indication_support .. "-pm10"
230-
end
231-
if #radon_level_eps > 0 then
232-
level_indication_support = level_indication_support .. "-radon"
233-
end
234-
if #tvoc_level_eps > 0 then
235-
level_indication_support = level_indication_support .. "-tvoc"
236-
end
228+
229+
local meas_name, level_name = create_level_measurement_profile(device)
230+
237231
-- If all endpoints are supported, use '-all' in the profile name so that it
238232
-- remains under the profile name character limit
239-
if level_indication_support == "-co-co2-no2-ozone-formaldehyde-pm1-pm25-pm10-radon-tvoc" then
240-
level_indication_support = "-all"
233+
if level_name == "-co-co2-no2-ozone-ch2o-pm1-pm25-pm10-radon-tvoc" then
234+
level_name = "-all"
241235
end
242-
if level_indication_support ~= "" then
243-
profile_name = profile_name .. level_indication_support .. "-level"
236+
if level_name ~= "" then
237+
profile_name = profile_name .. level_name .. "-level"
244238
end
245239

246-
if #co_meas_eps > 0 then
247-
numeric_measurement_support = numeric_measurement_support .. "-co"
248-
end
249-
if #co2_meas_eps > 0 then
250-
numeric_measurement_support = numeric_measurement_support .. "-co2"
251-
end
252-
if #no2_meas_eps > 0 then
253-
numeric_measurement_support = numeric_measurement_support .. "-no2"
254-
end
255-
if #ozone_meas_eps > 0 then
256-
numeric_measurement_support = numeric_measurement_support .. "-ozone"
257-
end
258-
if #formaldehyde_meas_eps > 0 then
259-
numeric_measurement_support = numeric_measurement_support .. "-formaldehyde"
260-
end
261-
if #pm1_meas_eps > 0 then
262-
numeric_measurement_support = numeric_measurement_support .. "-pm1"
263-
end
264-
if #pm2_5_meas_eps > 0 then
265-
numeric_measurement_support = numeric_measurement_support .. "-pm25"
266-
end
267-
if #pm10_meas_eps > 0 then
268-
numeric_measurement_support = numeric_measurement_support .. "-pm10"
269-
end
270-
if #radon_meas_eps > 0 then
271-
numeric_measurement_support = numeric_measurement_support .. "-radon"
272-
end
273-
if #tvoc_meas_eps > 0 then
274-
numeric_measurement_support = numeric_measurement_support .. "-tvoc"
275-
end
276240
-- If all endpoints are supported, use '-all' in the profile name so that it
277241
-- remains under the profile name character limit
278-
if numeric_measurement_support == "-co-co2-no2-ozone-formaldehyde-pm1-pm25-pm10-radon-tvoc" then
279-
numeric_measurement_support = "-all"
242+
if meas_name == "-co-co2-no2-ozone-ch2o-pm1-pm25-pm10-radon-tvoc" then
243+
meas_name = "-all"
280244
end
281-
if numeric_measurement_support ~= "" then
282-
profile_name = profile_name .. numeric_measurement_support .. "-meas"
245+
if meas_name ~= "" then
246+
profile_name = profile_name .. meas_name .. "-meas"
283247
end
284248

285249
if not tbl_contains(supported_profiles, profile_name) then
286250
device.log.warn_with({hub_logs=true}, string.format("No matching profile for device. Tried to use profile %s", profile_name))
287-
if #co_meas_eps > 0 or #no2_meas_eps > 0 or #ozone_meas_eps > 0 or #formaldehyde_meas_eps > 0 or
288-
#pm1_meas_eps > 0 or #pm10_meas_eps > 0 or #radon_meas_eps > 0 then
251+
252+
local function meas_find(sub_name)
253+
return string.match(meas_name, sub_name) ~= nil
254+
end
255+
256+
-- try to best match to existing profiles
257+
-- these checks, meas_find("co%-") and meas_find("co$"), match the string to co and NOT co2.
258+
if meas_find("co%-") or meas_find("co$") or meas_find("no2") or meas_find("ozone") or meas_find("ch2o") or
259+
meas_find("pm1") or meas_find("pm10") or meas_find("radon") then
289260
profile_name = "aqs-temp-humidity-all-meas"
290-
elseif #humidity_eps > 0 or #temp_eps > 0 or #co2_meas_eps > 0 or #pm2_5_meas_eps > 0 or #tvoc_meas_eps > 0 then
261+
elseif #humidity_eps > 0 or #temp_eps > 0 or meas_find("co2") or meas_find("pm25") or meas_find("tvoc") then
291262
profile_name = "aqs-temp-humidity-co2-pm25-tvoc-meas"
292263
else
293264
-- device only supports air quality at this point
@@ -445,7 +416,7 @@ local matter_air_quality_sensor_handler = {
445416
NAME = "matter-air-quality-sensor",
446417
lifecycle_handlers = {
447418
init = device_init,
448-
doConfigure = configure
419+
doConfigure = do_configure
449420
},
450421
matter_handlers = {
451422
attr = {

0 commit comments

Comments
 (0)