Skip to content

Commit 40c1b69

Browse files
authored
Update the doConfigure Logic in Matter Thermostat (#1662)
Refactor the doConfigure logic in the Matter Thermostat driver
1 parent 426c668 commit 40c1b69

File tree

1 file changed

+113
-85
lines changed
  • drivers/SmartThings/matter-thermostat/src

1 file changed

+113
-85
lines changed

drivers/SmartThings/matter-thermostat/src/init.lua

Lines changed: 113 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -357,94 +357,136 @@ local function create_level_measurement_profile(device)
357357
return meas_name, level_name
358358
end
359359

360-
local function do_configure(driver, device)
361-
local heat_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.HEATING})
362-
local cool_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.COOLING})
363-
local thermo_eps = device:get_endpoints(clusters.Thermostat.ID)
360+
local function create_air_quality_sensor_profile(device)
361+
local aqs_eps = embedded_cluster_utils.get_endpoints(device, clusters.AirQuality.ID)
362+
local profile_name = ""
363+
if #aqs_eps > 0 then
364+
profile_name = profile_name .. "-aqs"
365+
end
366+
local meas_name, level_name = create_level_measurement_profile(device)
367+
if meas_name ~= "" then
368+
profile_name = profile_name .. meas_name .. "-meas"
369+
end
370+
if level_name ~= "" then
371+
profile_name = profile_name .. level_name .. "-level"
372+
end
373+
return profile_name
374+
end
375+
376+
local function create_fan_profile(device)
364377
local fan_eps = device:get_endpoints(clusters.FanControl.ID)
365378
local wind_eps = device:get_endpoints(clusters.FanControl.ID, {feature_bitmap = clusters.FanControl.types.FanControlFeature.WIND})
366379
local rock_eps = device:get_endpoints(clusters.FanControl.ID, {feature_bitmap = clusters.FanControl.types.Feature.ROCKING})
367-
local humidity_eps = device:get_endpoints(clusters.RelativeHumidityMeasurement.ID)
368-
local battery_eps = device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY})
369-
-- use get_endpoints for embedded clusters
380+
local profile_name = ""
381+
if #fan_eps > 0 then
382+
profile_name = profile_name .. "-fan"
383+
end
384+
if #rock_eps > 0 then
385+
profile_name = profile_name .. "-rock"
386+
end
387+
if #wind_eps > 0 then
388+
profile_name = profile_name .. "-wind"
389+
end
390+
return profile_name
391+
end
392+
393+
local function create_air_purifier_profile(device)
370394
local hepa_filter_eps = embedded_cluster_utils.get_endpoints(device, clusters.HepaFilterMonitoring.ID)
371395
local ac_filter_eps = embedded_cluster_utils.get_endpoints(device, clusters.ActivatedCarbonFilterMonitoring.ID)
372-
local aqs_eps = embedded_cluster_utils.get_endpoints(device, clusters.AirQuality.ID)
396+
local fan_eps_seen = false
397+
local profile_name = "air-purifier"
398+
if #hepa_filter_eps > 0 then
399+
profile_name = profile_name .. "-hepa"
400+
end
401+
if #ac_filter_eps > 0 then
402+
profile_name = profile_name .. "-ac"
403+
end
404+
405+
-- air purifier profiles include -fan later in the name for historical reasons.
406+
-- save this information for use at that point.
407+
local fan_profile = create_fan_profile(device)
408+
if fan_profile ~= "" then
409+
fan_eps_seen = true
410+
end
411+
fan_profile = string.gsub(fan_profile, "-fan", "")
412+
profile_name = profile_name .. fan_profile
413+
414+
return profile_name, fan_eps_seen
415+
end
416+
417+
local function create_thermostat_modes_profile(device)
418+
local heat_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.HEATING})
419+
local cool_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.COOLING})
420+
421+
local thermostat_modes = ""
422+
if #heat_eps == 0 and #cool_eps == 0 then
423+
device.log.warn_with({hub_logs=true}, "Device does not support either heating or cooling. No matching profile")
424+
return "No Heating nor Cooling Support"
425+
elseif #heat_eps > 0 and #cool_eps == 0 then
426+
thermostat_modes = thermostat_modes .. "-heating-only"
427+
elseif #cool_eps > 0 and #heat_eps == 0 then
428+
thermostat_modes = thermostat_modes .. "-cooling-only"
429+
end
430+
return thermostat_modes
431+
end
432+
433+
local function do_configure(driver, device)
434+
local thermostat_eps = device:get_endpoints(clusters.Thermostat.ID)
435+
local humidity_eps = device:get_endpoints(clusters.RelativeHumidityMeasurement.ID)
436+
local battery_eps = device:get_endpoints(clusters.PowerSource.ID, {feature_bitmap = clusters.PowerSource.types.PowerSourceFeature.BATTERY})
373437
local device_type = get_device_type(driver, device)
374-
local profile_name = "thermostat"
438+
local profile_name
375439
if device_type == RAC_DEVICE_TYPE_ID then
376440
profile_name = "room-air-conditioner"
377441

378442
if #humidity_eps > 0 then
379443
profile_name = profile_name .. "-humidity"
380444
end
381-
if #fan_eps > 0 then
382-
profile_name = profile_name .. "-fan"
383-
if #wind_eps > 0 then
384-
profile_name = profile_name .. "-wind"
385-
end
386-
end
387445

388-
if #heat_eps > 0 and #cool_eps > 0 then
446+
-- Room AC does not support the rocking feature of FanControl.
447+
local fan_name = create_fan_profile(device)
448+
fan_name = string.gsub(fan_name, "-rock", "")
449+
profile_name = profile_name .. fan_name
450+
451+
local thermostat_modes = create_thermostat_modes_profile(device)
452+
if thermostat_modes == "" then
389453
profile_name = profile_name .. "-heating-cooling"
390454
else
391-
device.log.warn_with({hub_logs=true}, "Room AC does not support both heating and cooling. No matching profile")
455+
device.log.warn_with({hub_logs=true}, "Device does not support both heating and cooling. No matching profile")
392456
return
393457
end
394458

395459
if profile_name == "room-air-conditioner-humidity-fan-wind-heating-cooling" then
396460
profile_name = "room-air-conditioner"
397461
end
398462

399-
device.log.info_with({hub_logs=true}, string.format("Updating device profile to %s.", profile_name))
400-
device:try_update_metadata({profile = profile_name})
401463
elseif device_type == FAN_DEVICE_TYPE_ID then
402-
profile_name = "fan"
403-
if #rock_eps > 0 then
404-
profile_name = profile_name .. "-rock"
405-
end
406-
if #wind_eps > 0 then
407-
profile_name = profile_name .. "-wind"
408-
end
464+
profile_name = create_fan_profile(device)
465+
-- remove leading "-"
466+
profile_name = string.sub(profile_name, 2)
409467
if profile_name == "fan" then
410468
profile_name = "fan-generic"
411469
end
412470

413-
device.log.info_with({hub_logs=true}, string.format("Updating device profile to %s.", profile_name))
414-
device:try_update_metadata({profile = profile_name})
415471
elseif device_type == AP_DEVICE_TYPE_ID then
416-
profile_name = "air-purifier"
417-
if #hepa_filter_eps > 0 and #ac_filter_eps > 0 then
418-
profile_name = profile_name .. "-hepa" .. "-ac"
419-
elseif #hepa_filter_eps > 0 then
420-
profile_name = profile_name .. "-hepa"
421-
elseif #ac_filter_eps > 0 then
422-
profile_name = profile_name .. "-ac"
423-
end
424-
if #rock_eps > 0 then
425-
profile_name = profile_name .. "-rock"
426-
end
427-
if #wind_eps > 0 then
428-
profile_name = profile_name .. "-wind"
429-
end
430-
431-
if #thermo_eps > 0 then
472+
local fan_eps_found
473+
profile_name, fan_eps_found = create_air_purifier_profile(device)
474+
if #thermostat_eps > 0 then
432475
profile_name = profile_name .. "-thermostat"
433-
if #humidity_eps > 0 and #fan_eps > 0 then
434-
profile_name = profile_name .. "-humidity" .. "-fan"
435-
elseif #humidity_eps > 0 then
476+
477+
if #humidity_eps > 0 then
436478
profile_name = profile_name .. "-humidity"
437-
elseif #fan_eps > 0 then
479+
end
480+
481+
if fan_eps_found then
438482
profile_name = profile_name .. "-fan"
439483
end
440484

441-
if #heat_eps == 0 and #cool_eps == 0 then
442-
device.log.warn_with({hub_logs=true}, "Thermostat does not support heating or cooling. No matching profile")
485+
local thermostat_modes = create_thermostat_modes_profile(device)
486+
if thermostat_modes == "No Heating nor Cooling Support" then
443487
return
444-
elseif #heat_eps > 0 and #cool_eps == 0 then
445-
profile_name = profile_name .. "-heating-only"
446-
elseif #cool_eps > 0 and #heat_eps == 0 then
447-
profile_name = profile_name .. "-cooling-only"
488+
else
489+
profile_name = profile_name .. thermostat_modes
448490
end
449491

450492
profile_name = profile_name .. "-nostate"
@@ -453,39 +495,26 @@ local function do_configure(driver, device)
453495
profile_name = profile_name .. "-nobattery"
454496
end
455497
end
498+
profile_name = profile_name .. create_air_quality_sensor_profile(device)
456499

457-
if #aqs_eps > 0 then
458-
profile_name = profile_name .. "-aqs"
459-
end
460-
461-
local meas_name, level_name = create_level_measurement_profile(device)
462-
463-
if meas_name ~= "" then
464-
profile_name = profile_name .. meas_name .. "-meas"
465-
end
500+
elseif #thermostat_eps > 0 then
501+
profile_name = "thermostat"
466502

467-
if level_name ~= "" then
468-
profile_name = profile_name .. level_name .. "-level"
503+
if #humidity_eps > 0 then
504+
profile_name = profile_name .. "-humidity"
469505
end
470506

471-
device.log.info_with({hub_logs=true}, string.format("Updating device profile to %s.", profile_name))
472-
device:try_update_metadata({profile = profile_name})
473-
elseif #thermo_eps == 1 then
474-
if #humidity_eps > 0 and #fan_eps > 0 then
475-
profile_name = profile_name .. "-humidity" .. "-fan"
476-
elseif #humidity_eps > 0 then
477-
profile_name = profile_name .. "-humidity"
478-
elseif #fan_eps > 0 then
507+
-- thermostat profiles support neither wind nor rocking FanControl attributes
508+
local fan_name = create_fan_profile(device)
509+
if fan_name ~= "" then
479510
profile_name = profile_name .. "-fan"
480511
end
481512

482-
if #heat_eps == 0 and #cool_eps == 0 then
483-
device.log.warn_with({hub_logs=true}, "Thermostat does not support heating or cooling. No matching profile")
513+
local thermostat_modes = create_thermostat_modes_profile(device)
514+
if thermostat_modes == "No Heating nor Cooling Support" then
484515
return
485-
elseif #heat_eps > 0 and #cool_eps == 0 then
486-
profile_name = profile_name .. "-heating-only"
487-
elseif #cool_eps > 0 and #heat_eps == 0 then
488-
profile_name = profile_name .. "-cooling-only"
516+
else
517+
profile_name = profile_name .. thermostat_modes
489518
end
490519

491520
-- TODO remove this in favor of reading Thermostat clusters AttributeList attribute
@@ -496,15 +525,14 @@ local function do_configure(driver, device)
496525
if #battery_eps == 0 then
497526
profile_name = profile_name .. "-nobattery"
498527
end
528+
else
529+
device.log.warn_with({hub_logs=true}, "Device type is not supported in thermostat driver")
530+
return
531+
end
499532

533+
if profile_name then
500534
device.log.info_with({hub_logs=true}, string.format("Updating device profile to %s.", profile_name))
501535
device:try_update_metadata({profile = profile_name})
502-
elseif #fan_eps == 1 then
503-
profile_name = "fan"
504-
device.log.info_with({hub_logs=true}, string.format("Updating device profile to %s.", profile_name))
505-
device:try_update_metadata({profile = profile_name})
506-
else
507-
device.log.warn_with({hub_logs=true}, "Device does not support thermostat cluster")
508536
end
509537
end
510538

0 commit comments

Comments
 (0)