@@ -20,9 +20,12 @@ local embedded_cluster_utils = require "embedded-cluster-utils"
20
20
local log = require " log"
21
21
local AIR_QUALITY_SENSOR_DEVICE_TYPE_ID = 0x002C
22
22
23
+ local SUPPORTED_COMPONENT_CAPABILITIES = " __supported_component_capabilities"
24
+
25
+
23
26
-- Include driver-side definitions when lua libs api version is < 10
24
27
local version = require " version"
25
- if version .api < 10 then
28
+ if version .api < 14 then
26
29
clusters .AirQuality = require " AirQuality"
27
30
clusters .CarbonMonoxideConcentrationMeasurement = require " CarbonMonoxideConcentrationMeasurement"
28
31
clusters .CarbonDioxideConcentrationMeasurement = require " CarbonDioxideConcentrationMeasurement"
@@ -210,7 +213,28 @@ local function create_level_measurement_profile(device)
210
213
return meas_name , level_name
211
214
end
212
215
213
- local function do_configure (driver , device )
216
+ local function supported_level_measurements (device )
217
+ local measurement_caps , level_caps = {}, {}
218
+ for _ , details in ipairs (AIR_QUALITY_MAP ) do
219
+ local cap_id = details [1 ]
220
+ local cluster = details [3 ]
221
+ -- capability describes either a HealthConcern or Measurement/Sensor
222
+ if (cap_id :match (" HealthConcern$" )) then
223
+ local attr_eps = embedded_cluster_utils .get_endpoints (device , cluster .ID , { feature_bitmap = cluster .types .Feature .LEVEL_INDICATION })
224
+ if # attr_eps > 0 then
225
+ table.insert (level_caps , cap_id )
226
+ end
227
+ elseif (cap_id :match (" Measurement$" ) or cap_id :match (" Sensor$" )) then
228
+ local attr_eps = embedded_cluster_utils .get_endpoints (device , cluster .ID , { feature_bitmap = cluster .types .Feature .NUMERIC_MEASUREMENT })
229
+ if # attr_eps > 0 then
230
+ table.insert (measurement_caps , cap_id )
231
+ end
232
+ end
233
+ end
234
+ return measurement_caps , level_caps
235
+ end
236
+
237
+ local function match_profile_switch (driver , device )
214
238
local temp_eps = embedded_cluster_utils .get_endpoints (device , clusters .TemperatureMeasurement .ID )
215
239
local humidity_eps = embedded_cluster_utils .get_endpoints (device , clusters .RelativeHumidityMeasurement .ID )
216
240
@@ -271,6 +295,68 @@ local function do_configure(driver, device)
271
295
device :try_update_metadata ({profile = profile_name })
272
296
end
273
297
298
+ local function supports_capability_by_id_modular (capability , component )
299
+ for comp_id , capabilities in pairs (self :get_field (SUPPORTED_COMPONENT_CAPABILITIES )) do
300
+ if (component == nil ) or (component == comp_id ) then
301
+ for _ , cap in ipairs (capabilities ) do
302
+ if cap == capability_id then
303
+ return true
304
+ end
305
+ end
306
+ end
307
+ end
308
+ return false
309
+ end
310
+
311
+ local function match_modular_profile (driver , device )
312
+ device :extend_device (" supports_capability_by_id" , supports_capability_by_id_modular )
313
+
314
+ local temp_eps = embedded_cluster_utils .get_endpoints (device , clusters .TemperatureMeasurement .ID )
315
+ local humidity_eps = embedded_cluster_utils .get_endpoints (device , clusters .RelativeHumidityMeasurement .ID )
316
+
317
+ -- we have to read the unit before reports of values will do anything
318
+ for _ , cluster in ipairs (units_required ) do
319
+ device :send (cluster .attributes .MeasurementUnit :read (device ))
320
+ end
321
+
322
+ local optional_supported_component_capabilities = {}
323
+ local main_component_capabilities = {}
324
+
325
+ if # temp_eps > 0 then
326
+ table.insert (main_component_capabilities , capabilities .temperatureMeasurement .ID )
327
+ end
328
+ if # humidity_eps > 0 then
329
+ table.insert (main_component_capabilities , capabilities .relativeHumidityMeasurement .ID )
330
+ end
331
+
332
+ local measurement_caps , level_caps = create_level_measurement_profile (device )
333
+
334
+ for _ , cap_id in measurement_caps do
335
+ table.insert (main_component_capabilities , cap_id )
336
+ end
337
+
338
+ for _ , cap_id in level_caps do
339
+ table.insert (main_component_capabilities , cap_id )
340
+ end
341
+
342
+ table.insert (optional_supported_component_capabilities , {" main" , main_component_capabilities })
343
+
344
+ -- TODO: also add mandatory capabilities
345
+ device :set_field (SUPPORTED_COMPONENT_CAPABILITIES , optional_supported_component_capabilities )
346
+
347
+ device .log .info_with ({hub_logs = true }, string.format (" CHT adding optional capabilities: %s" , utils .stringify_table (optional_supported_component_capabilities )))
348
+ device .log .info_with ({hub_logs = true }, string.format (" CHT Updating device profile to aqs-modular" ))
349
+ device :try_update_metadata ({profile = " aqs-modular" , optional_component_capabilities = optional_supported_component_capabilities })
350
+ end
351
+
352
+ local function do_configure (driver , device )
353
+ if version .api < 13 then
354
+ match_profile_switch (driver , device )
355
+ else
356
+ match_modular_profile (driver , device )
357
+ end
358
+ end
359
+
274
360
local function store_unit_factory (capability_name )
275
361
return function (driver , device , ib , response )
276
362
device :set_field (capability_name .. " _unit" , ib .data .value , {persist = true })
0 commit comments