From 4352ad60a62d01b616406975112d59e4152e3038 Mon Sep 17 00:00:00 2001 From: Nick DeBoom Date: Mon, 6 Jan 2025 13:44:55 -0600 Subject: [PATCH 1/3] Use PPB for TVOC measurement units --- .../matter-sensor/src/air-quality-sensor/init.lua | 7 ++++--- .../src/test/test_matter_air_quality_sensor.lua | 15 +++++++++++++++ .../SmartThings/matter-thermostat/src/init.lua | 5 +++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua b/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua index 2b4560fe0a..eef5b0d60e 100644 --- a/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua +++ b/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua @@ -309,7 +309,7 @@ local unit_default = { [capabilities.fineDustSensor.NAME] = units.UGM3, [capabilities.dustSensor.NAME] = units.UGM3, [capabilities.radonMeasurement.NAME] = units.BQM3, - [capabilities.tvocMeasurement.NAME] = units.PPM + [capabilities.tvocMeasurement.NAME] = units.PPB } -- All ConcentrationMesurement clusters inherit from the same base cluster definitions, @@ -325,7 +325,8 @@ local level_strings = { local conversion_tables = { [units.PPM] = { - [units.PPM] = function(value) return utils.round(value) end + [units.PPM] = function(value) return utils.round(value) end, + [units.PPB] = function(value) return utils.round(value * (10^3)) end }, [units.PPB] = { [units.PPM] = function(value) return utils.round(value/(10^3)) end @@ -473,7 +474,7 @@ local matter_air_quality_sensor_handler = { [clusters.RadonConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.radonHealthConcern.radonHealthConcern) }, [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID] = { - [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.tvocMeasurement.NAME, capabilities.tvocMeasurement.tvocLevel, units.PPM), + [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.tvocMeasurement.NAME, capabilities.tvocMeasurement.tvocLevel, units.PPB), [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.tvocMeasurement.NAME), [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.tvocHealthConcern.tvocHealthConcern) } diff --git a/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua b/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua index f2dd259d7d..1f735898e5 100644 --- a/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua +++ b/drivers/SmartThings/matter-sensor/src/test/test_matter_air_quality_sensor.lua @@ -634,6 +634,21 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", capabilities.dustSensor.dustLevel({value = 18, unit = "μg/m^3"})) ) + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasurementUnit:build_test_report_data( + mock_device, 1, clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.types.MeasurementUnitEnum.PPM + ) + }) + test.socket.matter:__queue_receive({ + mock_device.id, + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasuredValue:build_test_report_data( + mock_device, 1, SinglePrecisionFloat(0, -1, .5) -- 0.750 ppm + ) + }) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.tvocMeasurement.tvocLevel({value = 750, unit = "ppb"})) + ) end ) diff --git a/drivers/SmartThings/matter-thermostat/src/init.lua b/drivers/SmartThings/matter-thermostat/src/init.lua index 20b6f2d64d..52db2a93e5 100644 --- a/drivers/SmartThings/matter-thermostat/src/init.lua +++ b/drivers/SmartThings/matter-thermostat/src/init.lua @@ -590,7 +590,7 @@ local unit_default = { [capabilities.fineDustSensor.NAME] = units.UGM3, [capabilities.dustSensor.NAME] = units.UGM3, [capabilities.radonMeasurement.NAME] = units.BQM3, - [capabilities.tvocMeasurement.NAME] = units.PPM + [capabilities.tvocMeasurement.NAME] = units.PPB } -- All ConcentrationMesurement clusters inherit from the same base cluster definitions, @@ -620,6 +620,7 @@ local molecular_weights = { local conversion_tables = { [units.PPM] = { [units.PPM] = function(value) return utils.round(value) end, + [units.PPB] = function(value) return utils.round(value * (10^3)) end, [units.UGM3] = function(value, molecular_weight) return utils.round((value * molecular_weight * 10^3) / MGM3_PPM_CONVERSION_FACTOR) end, [units.MGM3] = function(value, molecular_weight) return utils.round((value * molecular_weight) / MGM3_PPM_CONVERSION_FACTOR) end, }, @@ -1429,7 +1430,7 @@ local matter_driver_template = { [clusters.RadonConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.radonHealthConcern.radonHealthConcern) }, [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID] = { - [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.tvocMeasurement.NAME, capabilities.tvocMeasurement.tvocLevel, units.PPM), + [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.tvocMeasurement.NAME, capabilities.tvocMeasurement.tvocLevel, units.PPB), [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.tvocMeasurement.NAME), [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.tvocHealthConcern.tvocHealthConcern) } From fc65c2ba7c33351843e554e18b0fd5984a91620d Mon Sep 17 00:00:00 2001 From: Nick DeBoom Date: Tue, 7 Jan 2025 09:54:21 -0600 Subject: [PATCH 2/3] Add conversion from ppb -> ppb --- .../SmartThings/matter-sensor/src/air-quality-sensor/init.lua | 3 ++- drivers/SmartThings/matter-thermostat/src/init.lua | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua b/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua index eef5b0d60e..3164dc2a64 100644 --- a/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua +++ b/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua @@ -329,7 +329,8 @@ local conversion_tables = { [units.PPB] = function(value) return utils.round(value * (10^3)) end }, [units.PPB] = { - [units.PPM] = function(value) return utils.round(value/(10^3)) end + [units.PPM] = function(value) return utils.round(value/(10^3)) end, + [units.PPB] = function(value) return utils.round(value) end }, [units.PPT] = { [units.PPM] = function(value) return utils.round(value/(10^6)) end diff --git a/drivers/SmartThings/matter-thermostat/src/init.lua b/drivers/SmartThings/matter-thermostat/src/init.lua index 52db2a93e5..424b78d7b2 100644 --- a/drivers/SmartThings/matter-thermostat/src/init.lua +++ b/drivers/SmartThings/matter-thermostat/src/init.lua @@ -625,7 +625,8 @@ local conversion_tables = { [units.MGM3] = function(value, molecular_weight) return utils.round((value * molecular_weight) / MGM3_PPM_CONVERSION_FACTOR) end, }, [units.PPB] = { - [units.PPM] = function(value) return utils.round(value/(10^3)) end + [units.PPM] = function(value) return utils.round(value/(10^3)) end, + [units.PPB] = function(value) return utils.round(value) end, }, [units.PPT] = { [units.PPM] = function(value) return utils.round(value/(10^6)) end From 5911d09a1892e67028151da6c3deab5881097fae Mon Sep 17 00:00:00 2001 From: Nick DeBoom Date: Tue, 7 Jan 2025 14:40:57 -0600 Subject: [PATCH 3/3] Adding comment to explain TVOC units --- .../SmartThings/matter-sensor/src/air-quality-sensor/init.lua | 2 +- drivers/SmartThings/matter-thermostat/src/init.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua b/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua index b38f28e927..09dc5ad4d6 100644 --- a/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua +++ b/drivers/SmartThings/matter-sensor/src/air-quality-sensor/init.lua @@ -309,7 +309,7 @@ local unit_default = { [capabilities.fineDustSensor.NAME] = units.UGM3, [capabilities.dustSensor.NAME] = units.UGM3, [capabilities.radonMeasurement.NAME] = units.BQM3, - [capabilities.tvocMeasurement.NAME] = units.PPB + [capabilities.tvocMeasurement.NAME] = units.PPB -- TVOC is typically within the range of 0-5500 ppb, with good to moderate values being < 660 ppb } -- All ConcentrationMeasurement clusters inherit from the same base cluster definitions, diff --git a/drivers/SmartThings/matter-thermostat/src/init.lua b/drivers/SmartThings/matter-thermostat/src/init.lua index 424b78d7b2..7799091b24 100644 --- a/drivers/SmartThings/matter-thermostat/src/init.lua +++ b/drivers/SmartThings/matter-thermostat/src/init.lua @@ -590,7 +590,7 @@ local unit_default = { [capabilities.fineDustSensor.NAME] = units.UGM3, [capabilities.dustSensor.NAME] = units.UGM3, [capabilities.radonMeasurement.NAME] = units.BQM3, - [capabilities.tvocMeasurement.NAME] = units.PPB + [capabilities.tvocMeasurement.NAME] = units.PPB -- TVOC is typically within the range of 0-5500 ppb, with good to moderate values being < 660 ppb } -- All ConcentrationMesurement clusters inherit from the same base cluster definitions,