From b5e4acfc97cb0a7973c875d23b72931f13d95044 Mon Sep 17 00:00:00 2001 From: Liu Yiding Date: Wed, 26 Jun 2024 10:54:08 +0800 Subject: [PATCH 01/18] Add TOTEM R60 Signed-off-by: Liu Yiding --- drivers/SmartThings/zigbee-lock/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zigbee-lock/fingerprints.yml b/drivers/SmartThings/zigbee-lock/fingerprints.yml index 7d913b1274..0e9aef7467 100644 --- a/drivers/SmartThings/zigbee-lock/fingerprints.yml +++ b/drivers/SmartThings/zigbee-lock/fingerprints.yml @@ -135,6 +135,11 @@ zigbeeManufacturer: manufacturer: TOTEM model: P30 deviceProfileName: lock-battery + - id: TOTEM/R60 + deviceLabel: TOTEM Door Lock + manufacturer: TOTEM + model: R60 + deviceProfileName: lock-battery zigbeeGeneric: - id: "genericLock" deviceLabel: Zigbee Lock From 8459605477b22976a6af2d71814dea7e322ef0c4 Mon Sep 17 00:00:00 2001 From: Cooper Towns Date: Tue, 9 Jul 2024 15:29:12 -0500 Subject: [PATCH 02/18] Matter Sensor: resubscribe on profile switch Resubscribe whenever there is a profile switch so that new attributes can be subscribed to if the new profile includes new capabilities. --- .../SmartThings/matter-sensor/src/smoke-co-alarm/init.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-sensor/src/smoke-co-alarm/init.lua b/drivers/SmartThings/matter-sensor/src/smoke-co-alarm/init.lua index 5139cab624..015cb88be2 100644 --- a/drivers/SmartThings/matter-sensor/src/smoke-co-alarm/init.lua +++ b/drivers/SmartThings/matter-sensor/src/smoke-co-alarm/init.lua @@ -129,6 +129,11 @@ local function info_changed(self, device, event, args) end end end + + -- resubscribe to new attributes as needed if a profile switch occured + if device.profile.id ~= args.old_st_store.profile.id then + device:subscribe() + end end -- Matter Handlers -- From ad83a5d55cfce305eec671b651c6bec3ea5adb90 Mon Sep 17 00:00:00 2001 From: Liu Yiding Date: Wed, 26 Jun 2024 10:54:08 +0800 Subject: [PATCH 03/18] Add TOTEM P70 Signed-off-by: Liu Yiding --- drivers/SmartThings/zigbee-lock/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zigbee-lock/fingerprints.yml b/drivers/SmartThings/zigbee-lock/fingerprints.yml index 0e9aef7467..c28fb94bfd 100644 --- a/drivers/SmartThings/zigbee-lock/fingerprints.yml +++ b/drivers/SmartThings/zigbee-lock/fingerprints.yml @@ -140,6 +140,11 @@ zigbeeManufacturer: manufacturer: TOTEM model: R60 deviceProfileName: lock-battery + - id: TOTEM/P70 + deviceLabel: TOTEM Door Lock + manufacturer: TOTEM + model: P70 + deviceProfileName: lock-battery zigbeeGeneric: - id: "genericLock" deviceLabel: Zigbee Lock From 51a697e69ba03fd2e0cee602bb7a3ed252760b45 Mon Sep 17 00:00:00 2001 From: Harrison Carter <137556605+hcarter-775@users.noreply.github.com> Date: Thu, 11 Jul 2024 15:37:49 -0500 Subject: [PATCH 04/18] Matter Thermostat extend Air Quality Sensor (#1479) Allows for profiles to be created that use any combination of AQS, thermostat, and fan device types. Also adds a new profile that includes much of this extended functionality. * new cluster definitions imported to thermostat * greater unit conversion inclusion * do_configure logic updated to include aqs and ap + thermostat profiles * added air purifier test cases for unit conversion and device configuration --- ...a-ac-aqs-co2-tvoc-meas-co2-radon-level.yml | 43 ++ ...h2o-meas-pm10-pm25-ch2o-no2-tvoc-level.yml | 61 +++ .../profiles/air-purifier-hepa-aqs.yml | 26 ++ .../matter-thermostat/src/AirQuality/init.lua | 59 +++ .../server/attributes/AcceptedCommandList.lua | 75 ++++ .../server/attributes/AirQuality.lua | 68 +++ .../server/attributes/AttributeList.lua | 75 ++++ .../server/attributes/EventList.lua | 75 ++++ .../src/AirQuality/server/attributes/init.lua | 24 + .../src/AirQuality/types/AirQualityEnum.lua | 45 ++ .../src/AirQuality/types/Feature.lua | 120 +++++ .../src/AirQuality/types/init.lua | 15 + .../init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../src/ConcentrationMeasurement/init.lua | 108 +++++ .../server/attributes/LevelValue.lua | 70 +++ .../server/attributes/MeasuredValue.lua | 70 +++ .../server/attributes/MeasurementUnit.lua | 69 +++ .../server/attributes/init.lua | 24 + .../types/Feature.lua | 164 +++++++ .../types/LevelValueEnum.lua | 39 ++ .../types/MeasurementUnitEnum.lua | 48 ++ .../ConcentrationMeasurement/types/init.lua | 15 + .../init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../OzoneConcentrationMeasurement/init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../src/Pm10ConcentrationMeasurement/init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../src/Pm1ConcentrationMeasurement/init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../src/Pm25ConcentrationMeasurement/init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../RadonConcentrationMeasurement/init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../init.lua | 44 ++ .../server/attributes/LevelValue.lua | 41 ++ .../server/attributes/MeasuredValue.lua | 56 +++ .../server/attributes/MeasurementUnit.lua | 45 ++ .../server/attributes/init.lua | 24 + .../src/embedded-cluster-utils.lua | 24 +- .../matter-thermostat/src/init.lua | 411 +++++++++++++++++- .../src/test/test_matter_air_purifier.lua | 352 ++++++++++++++- 74 files changed, 4174 insertions(+), 6 deletions(-) create mode 100644 drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-aqs-co2-tvoc-meas-co2-radon-level.yml create mode 100644 drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level.yml create mode 100644 drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-aqs.yml create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AcceptedCommandList.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AirQuality.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AttributeList.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/EventList.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/types/AirQualityEnum.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/types/Feature.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/AirQuality/types/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/Feature.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/LevelValueEnum.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/MeasurementUnitEnum.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/init.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/LevelValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasuredValue.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasurementUnit.lua create mode 100644 drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/init.lua diff --git a/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-aqs-co2-tvoc-meas-co2-radon-level.yml b/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-aqs-co2-tvoc-meas-co2-radon-level.yml new file mode 100644 index 0000000000..9bf3605968 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-aqs-co2-tvoc-meas-co2-radon-level.yml @@ -0,0 +1,43 @@ +name: air-purifier-hepa-ac-aqs-co2-tvoc-meas-co2-radon-level +components: +- id: main + label: Main + capabilities: + - id: airPurifierFanMode + version: 1 + - id: fanSpeedPercent + version: 1 + - id: airQualityHealthConcern + version: 1 + - id: carbonDioxideHealthConcern + version: 1 + - id: carbonDioxideMeasurement + version: 1 + - id: radonHealthConcern + version: 1 + - id: tvocMeasurement + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: AirPurifier +- id: hepaFilter + label: Hepa Filter + capabilities: + - id: filterState + version: 1 + - id: filterStatus + version: 1 + categories: + - name: AirPurifier +- id: activatedCarbonFilter + label: Activated Carbon Filter + capabilities: + - id: filterState + version: 1 + - id: filterStatus + version: 1 + categories: + - name: AirPurifier diff --git a/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level.yml b/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level.yml new file mode 100644 index 0000000000..21dc60d1df --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level.yml @@ -0,0 +1,61 @@ +name: air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level +components: +- id: main + label: Main + capabilities: + - id: airPurifierFanMode + version: 1 + - id: fanSpeedPercent + version: 1 + - id: windMode + version: 1 + - id: thermostatHeatingSetpoint + version: 1 + - id: thermostatMode + version: 1 + - id: temperatureMeasurement + version: 1 + - id: dustSensor + version: 1 + - id: formaldehydeMeasurement + version: 1 + - id: relativeHumidityMeasurement + version: 1 + - id: airQualityHealthConcern + version: 1 + - id: dustHealthConcern + version: 1 + - id: fineDustHealthConcern + version: 1 + - id: formaldehydeHealthConcern + version: 1 + - id: nitrogenDioxideHealthConcern + version: 1 + - id: tvocHealthConcern + version: 1 + - id: thermostatOperatingState + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: AirPurifier +- id: hepaFilter + label: Hepa Filter + capabilities: + - id: filterState + version: 1 + - id: filterStatus + version: 1 + categories: + - name: AirPurifier +- id: activatedCarbonFilter + label: Activated Carbon Filter + capabilities: + - id: filterState + version: 1 + - id: filterStatus + version: 1 + categories: + - name: AirPurifier diff --git a/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-aqs.yml b/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-aqs.yml new file mode 100644 index 0000000000..f17f9695bd --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/profiles/air-purifier-hepa-aqs.yml @@ -0,0 +1,26 @@ +name: air-purifier-hepa-aqs +components: +- id: main + label: Main + capabilities: + - id: airQualityHealthConcern + version: 1 + - id: airPurifierFanMode + version: 1 + - id: fanSpeedPercent + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: AirPurifier +- id: hepaFilter + label: Hepa filter + capabilities: + - id: filterState + version: 1 + - id: filterStatus + version: 1 + categories: + - name: AirPurifier \ No newline at end of file diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/init.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/init.lua new file mode 100644 index 0000000000..78e77fce51 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/init.lua @@ -0,0 +1,59 @@ +local cluster_base = require "st.matter.cluster_base" +local AirQualityServerAttributes = require "AirQuality.server.attributes" +local AirQualityTypes = require "AirQuality.types" + +local AirQuality = {} + +AirQuality.ID = 0x005B +AirQuality.NAME = "AirQuality" +AirQuality.server = {} +AirQuality.client = {} +AirQuality.server.attributes = AirQualityServerAttributes:set_parent_cluster(AirQuality) +AirQuality.types = AirQualityTypes + +function AirQuality:get_attribute_by_id(attr_id) + local attr_id_map = { + [0x0000] = "AirQuality", + [0xFFF9] = "AcceptedCommandList", + [0xFFFA] = "EventList", + [0xFFFB] = "AttributeList", + } + local attr_name = attr_id_map[attr_id] + if attr_name ~= nil then + return self.attributes[attr_name] + end + return nil +end + +-- Attribute Mapping +AirQuality.attribute_direction_map = { + ["AirQuality"] = "server", + ["AcceptedCommandList"] = "server", + ["EventList"] = "server", + ["AttributeList"] = "server", +} + +AirQuality.FeatureMap = AirQuality.types.Feature + +function AirQuality.are_features_supported(feature, feature_map) + if (AirQuality.FeatureMap.bits_are_valid(feature)) then + return (feature & feature_map) == feature + end + return false +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = AirQuality.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, AirQuality.NAME)) + end + return AirQuality[direction].attributes[key] +end +AirQuality.attributes = {} +setmetatable(AirQuality.attributes, attribute_helper_mt) + +setmetatable(AirQuality, {__index = cluster_base}) + +return AirQuality + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AcceptedCommandList.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AcceptedCommandList.lua new file mode 100644 index 0000000000..6a8d95df1d --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AcceptedCommandList.lua @@ -0,0 +1,75 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AcceptedCommandList = { + ID = 0xFFF9, + NAME = "AcceptedCommandList", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.Uint32", +} + +function AcceptedCommandList:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, AcceptedCommandList.element_type) + end +end + +function AcceptedCommandList:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AcceptedCommandList:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AcceptedCommandList:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AcceptedCommandList:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AcceptedCommandList:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AcceptedCommandList:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AcceptedCommandList, {__call = AcceptedCommandList.new_value, __index = AcceptedCommandList.base_type}) +return AcceptedCommandList + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AirQuality.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AirQuality.lua new file mode 100644 index 0000000000..f92f43543a --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AirQuality.lua @@ -0,0 +1,68 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AirQuality = { + ID = 0x0000, + NAME = "AirQuality", + base_type = require "AirQuality.types.AirQualityEnum", +} + +function AirQuality:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function AirQuality:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AirQuality:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AirQuality:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AirQuality:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AirQuality:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(AirQuality, {__call = AirQuality.new_value, __index = AirQuality.base_type}) +return AirQuality + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AttributeList.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AttributeList.lua new file mode 100644 index 0000000000..93e96817e6 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/AttributeList.lua @@ -0,0 +1,75 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local AttributeList = { + ID = 0xFFFB, + NAME = "AttributeList", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.Uint32", +} + +function AttributeList:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, AttributeList.element_type) + end +end + +function AttributeList:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function AttributeList:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AttributeList:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function AttributeList:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function AttributeList:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function AttributeList:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(AttributeList, {__call = AttributeList.new_value, __index = AttributeList.base_type}) +return AttributeList + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/EventList.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/EventList.lua new file mode 100644 index 0000000000..69155cd7ca --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/EventList.lua @@ -0,0 +1,75 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local EventList = { + ID = 0xFFFA, + NAME = "EventList", + base_type = require "st.matter.data_types.Array", + element_type = require "st.matter.data_types.Uint32", +} + +function EventList:augment_type(data_type_obj) + for i, v in ipairs(data_type_obj.elements) do + data_type_obj.elements[i] = data_types.validate_or_build_type(v, EventList.element_type) + end +end + +function EventList:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function EventList:read(device, endpoint_id) + return cluster_base.read( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function EventList:subscribe(device, endpoint_id) + return cluster_base.subscribe( + device, + endpoint_id, + self._cluster.ID, + self.ID, + nil + ) +end + +function EventList:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function EventList:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function EventList:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(EventList, {__call = EventList.new_value, __index = EventList.base_type}) +return EventList + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/init.lua new file mode 100644 index 0000000000..aef3b476a9 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("AirQuality.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local AirQualityServerAttributes = {} + +function AirQualityServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(AirQualityServerAttributes, attr_mt) + +return AirQualityServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/types/AirQualityEnum.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/types/AirQualityEnum.lua new file mode 100644 index 0000000000..317a42dc9b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/types/AirQualityEnum.lua @@ -0,0 +1,45 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local AirQualityEnum = {} +-- Note: the name here is intentionally set to Uint8 to maintain backwards compatibility +-- with how types were handled in api < 10. +local new_mt = UintABC.new_mt({NAME = "Uint8", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNKNOWN] = "UNKNOWN", + [self.GOOD] = "GOOD", + [self.FAIR] = "FAIR", + [self.MODERATE] = "MODERATE", + [self.POOR] = "POOR", + [self.VERY_POOR] = "VERY_POOR", + [self.EXTREMELY_POOR] = "EXTREMELY_POOR", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNKNOWN = 0x00 +new_mt.__index.GOOD = 0x01 +new_mt.__index.FAIR = 0x02 +new_mt.__index.MODERATE = 0x03 +new_mt.__index.POOR = 0x04 +new_mt.__index.VERY_POOR = 0x05 +new_mt.__index.EXTREMELY_POOR = 0x06 + +AirQualityEnum.UNKNOWN = 0x00 +AirQualityEnum.GOOD = 0x01 +AirQualityEnum.FAIR = 0x02 +AirQualityEnum.MODERATE = 0x03 +AirQualityEnum.POOR = 0x04 +AirQualityEnum.VERY_POOR = 0x05 +AirQualityEnum.EXTREMELY_POOR = 0x06 + +AirQualityEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(AirQualityEnum, new_mt) + +return AirQualityEnum + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/types/Feature.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/types/Feature.lua new file mode 100644 index 0000000000..86b90ce627 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/types/Feature.lua @@ -0,0 +1,120 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local Feature = {} +local new_mt = UintABC.new_mt({NAME = "Feature", ID = data_types.name_to_id_map["Uint32"]}, 4) + +Feature.BASE_MASK = 0xFFFF +Feature.FAIR = 0x0001 +Feature.MODERATE = 0x0002 +Feature.VERY_POOR = 0x0004 +Feature.EXTREMELY_POOR = 0x0008 + +Feature.mask_fields = { + BASE_MASK = 0xFFFF, + FAIR = 0x0001, + MODERATE = 0x0002, + VERY_POOR = 0x0004, + EXTREMELY_POOR = 0x0008, +} + +Feature.is_fair_set = function(self) + return (self.value & self.FAIR) ~= 0 +end + +Feature.set_fair = function(self) + if self.value ~= nil then + self.value = self.value | self.FAIR + else + self.value = self.FAIR + end +end + +Feature.unset_fair = function(self) + self.value = self.value & (~self.FAIR & self.BASE_MASK) +end + +Feature.is_moderate_set = function(self) + return (self.value & self.MODERATE) ~= 0 +end + +Feature.set_moderate = function(self) + if self.value ~= nil then + self.value = self.value | self.MODERATE + else + self.value = self.MODERATE + end +end + +Feature.unset_moderate = function(self) + self.value = self.value & (~self.MODERATE & self.BASE_MASK) +end + +Feature.is_very_poor_set = function(self) + return (self.value & self.VERY_POOR) ~= 0 +end + +Feature.set_very_poor = function(self) + if self.value ~= nil then + self.value = self.value | self.VERY_POOR + else + self.value = self.VERY_POOR + end +end + +Feature.unset_very_poor = function(self) + self.value = self.value & (~self.VERY_POOR & self.BASE_MASK) +end + +Feature.is_extremely_poor_set = function(self) + return (self.value & self.EXTREMELY_POOR) ~= 0 +end + +Feature.set_extremely_poor = function(self) + if self.value ~= nil then + self.value = self.value | self.EXTREMELY_POOR + else + self.value = self.EXTREMELY_POOR + end +end + +Feature.unset_extremely_poor = function(self) + self.value = self.value & (~self.EXTREMELY_POOR & self.BASE_MASK) +end + +function Feature.bits_are_valid(feature) + local max = + Feature.FAIR | + Feature.MODERATE | + Feature.VERY_POOR | + Feature.EXTREMELY_POOR + if (feature <= max) and (feature >= 1) then + return true + else + return false + end +end + +Feature.mask_methods = { + is_fair_set = Feature.is_fair_set, + set_fair = Feature.set_fair, + unset_fair = Feature.unset_fair, + is_moderate_set = Feature.is_moderate_set, + set_moderate = Feature.set_moderate, + unset_moderate = Feature.unset_moderate, + is_very_poor_set = Feature.is_very_poor_set, + set_very_poor = Feature.set_very_poor, + unset_very_poor = Feature.unset_very_poor, + is_extremely_poor_set = Feature.is_extremely_poor_set, + set_extremely_poor = Feature.set_extremely_poor, + unset_extremely_poor = Feature.unset_extremely_poor, +} + +Feature.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(Feature, new_mt) + +return Feature + diff --git a/drivers/SmartThings/matter-thermostat/src/AirQuality/types/init.lua b/drivers/SmartThings/matter-thermostat/src/AirQuality/types/init.lua new file mode 100644 index 0000000000..88a2b861b7 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/AirQuality/types/init.lua @@ -0,0 +1,15 @@ +local types_mt = {} +types_mt.__types_cache = {} +types_mt.__index = function(self, key) + if types_mt.__types_cache[key] == nil then + types_mt.__types_cache[key] = require("AirQuality.types." .. key) + end + return types_mt.__types_cache[key] +end + +local AirQualityTypes = {} + +setmetatable(AirQualityTypes, types_mt) + +return AirQualityTypes + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..f5109f8943 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local CarbonDioxideConcentrationMeasurementServerAttributes = require "CarbonDioxideConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local CarbonDioxideConcentrationMeasurement = {} + +CarbonDioxideConcentrationMeasurement.ID = 0x040D +CarbonDioxideConcentrationMeasurement.NAME = "CarbonDioxideConcentrationMeasurement" +CarbonDioxideConcentrationMeasurement.server = {} +CarbonDioxideConcentrationMeasurement.client = {} +CarbonDioxideConcentrationMeasurement.server.attributes = CarbonDioxideConcentrationMeasurementServerAttributes:set_parent_cluster(CarbonDioxideConcentrationMeasurement) +CarbonDioxideConcentrationMeasurement.types = ConcentrationMeasurement.types + +function CarbonDioxideConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function CarbonDioxideConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +CarbonDioxideConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +CarbonDioxideConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function CarbonDioxideConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = CarbonDioxideConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, CarbonDioxideConcentrationMeasurement.NAME)) + end + return CarbonDioxideConcentrationMeasurement[direction].attributes[key] +end +CarbonDioxideConcentrationMeasurement.attributes = {} +setmetatable(CarbonDioxideConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(CarbonDioxideConcentrationMeasurement, {__index = cluster_base}) + +return CarbonDioxideConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..93583c2080 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonDioxideConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("CarbonDioxideConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local CarbonDioxideConcentrationMeasurementServerAttributes = {} + +function CarbonDioxideConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(CarbonDioxideConcentrationMeasurementServerAttributes, attr_mt) + +return CarbonDioxideConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..e8cdb487f5 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local CarbonMonoxideConcentrationMeasurementServerAttributes = require "CarbonMonoxideConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local CarbonMonoxideConcentrationMeasurement = {} + +CarbonMonoxideConcentrationMeasurement.ID = 0x040C +CarbonMonoxideConcentrationMeasurement.NAME = "CarbonMonoxideConcentrationMeasurement" +CarbonMonoxideConcentrationMeasurement.server = {} +CarbonMonoxideConcentrationMeasurement.client = {} +CarbonMonoxideConcentrationMeasurement.server.attributes = CarbonMonoxideConcentrationMeasurementServerAttributes:set_parent_cluster(CarbonMonoxideConcentrationMeasurement) +CarbonMonoxideConcentrationMeasurement.types = ConcentrationMeasurement.types + +function CarbonMonoxideConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function CarbonMonoxideConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +CarbonMonoxideConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +CarbonMonoxideConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function CarbonMonoxideConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = CarbonMonoxideConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, CarbonMonoxideConcentrationMeasurement.NAME)) + end + return CarbonMonoxideConcentrationMeasurement[direction].attributes[key] +end +CarbonMonoxideConcentrationMeasurement.attributes = {} +setmetatable(CarbonMonoxideConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(CarbonMonoxideConcentrationMeasurement, {__index = cluster_base}) + +return CarbonMonoxideConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..2307e8977d --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/CarbonMonoxideConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("CarbonMonoxideConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local CarbonMonoxideConcentrationMeasurementServerAttributes = {} + +function CarbonMonoxideConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(CarbonMonoxideConcentrationMeasurementServerAttributes, attr_mt) + +return CarbonMonoxideConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..596d1bfe80 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/init.lua @@ -0,0 +1,108 @@ +local cluster_base = require "st.matter.cluster_base" +local ConcentrationMeasurementServerAttributes = require "ConcentrationMeasurement.server.attributes" +local ConcentrationMeasurementTypes = require "ConcentrationMeasurement.types" + +local ConcentrationMeasurement = {} + +ConcentrationMeasurement.ID = 0x040C +ConcentrationMeasurement.NAME = "CarbonMonoxideConcentrationMeasurement" +ConcentrationMeasurement.server = {} +ConcentrationMeasurement.client = {} +ConcentrationMeasurement.server.attributes = ConcentrationMeasurementServerAttributes:set_parent_cluster(ConcentrationMeasurement) +ConcentrationMeasurement.types = ConcentrationMeasurementTypes + +function ConcentrationMeasurement:get_attribute_by_id(attr_id) + local attr_id_map = { + [0x0000] = "MeasuredValue", + [0x0001] = "MinMeasuredValue", + [0x0002] = "MaxMeasuredValue", + [0x0003] = "PeakMeasuredValue", + [0x0004] = "PeakMeasuredValueWindow", + [0x0005] = "AverageMeasuredValue", + [0x0006] = "AverageMeasuredValueWindow", + [0x0007] = "Uncertainty", + [0x0008] = "MeasurementUnit", + [0x0009] = "MeasurementMedium", + [0x000A] = "LevelValue", + [0xFFF9] = "AcceptedCommandList", + [0xFFFA] = "EventList", + [0xFFFB] = "AttributeList", + } + local attr_name = attr_id_map[attr_id] + if attr_name ~= nil then + return self.attributes[attr_name] + end + return nil +end + +function ConcentrationMeasurement:get_server_command_by_id(command_id) + local server_id_map = { + } + if server_id_map[command_id] ~= nil then + return self.server.commands[server_id_map[command_id]] + end + return nil +end + +ConcentrationMeasurement.attribute_direction_map = { + ["MeasuredValue"] = "server", + ["MinMeasuredValue"] = "server", + ["MaxMeasuredValue"] = "server", + ["PeakMeasuredValue"] = "server", + ["PeakMeasuredValueWindow"] = "server", + ["AverageMeasuredValue"] = "server", + ["AverageMeasuredValueWindow"] = "server", + ["Uncertainty"] = "server", + ["MeasurementUnit"] = "server", + ["MeasurementMedium"] = "server", + ["LevelValue"] = "server", + ["AcceptedCommandList"] = "server", + ["EventList"] = "server", + ["AttributeList"] = "server", +} + +ConcentrationMeasurement.command_direction_map = { +} + +ConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function ConcentrationMeasurement.are_features_supported(feature, feature_map) + if (ConcentrationMeasurement.FeatureMap.bits_are_valid(feature)) then + return (feature & feature_map) == feature + end + return false +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = ConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, ConcentrationMeasurement.NAME)) + end + return ConcentrationMeasurement[direction].attributes[key] +end +ConcentrationMeasurement.attributes = {} +setmetatable(ConcentrationMeasurement.attributes, attribute_helper_mt) + +local command_helper_mt = {} +command_helper_mt.__index = function(self, key) + local direction = ConcentrationMeasurement.command_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown command %s on cluster %s", key, ConcentrationMeasurement.NAME)) + end + return ConcentrationMeasurement[direction].commands[key] +end +ConcentrationMeasurement.commands = {} +setmetatable(ConcentrationMeasurement.commands, command_helper_mt) + +local event_helper_mt = {} +event_helper_mt.__index = function(self, key) + return ConcentrationMeasurement.server.events[key] +end +ConcentrationMeasurement.events = {} +setmetatable(ConcentrationMeasurement.events, event_helper_mt) + +setmetatable(ConcentrationMeasurement, {__index = cluster_base}) + +return ConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..e7023a336c --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,70 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function LevelValue:read(device, endpoint_id, cluster_id) + return cluster_base.read( + device, + endpoint_id, + cluster_id, + self.ID, + nil --event_id + ) +end + + +function LevelValue:subscribe(device, endpoint_id, cluster_id) + return cluster_base.subscribe( + device, + endpoint_id, + cluster_id, + self.ID, + nil --event_id + ) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status, + cluster_id +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + cluster_id, + self.ID, + data, + status + ) +end + +function LevelValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..c658d2d3aa --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,70 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + local o = self.base_type(table.unpack({...})) + + return o +end + +function MeasuredValue:read(device, endpoint_id, cluster_id) + return cluster_base.read( + device, + endpoint_id, + cluster_id, + self.ID, + nil --event_id + ) +end + + +function MeasuredValue:subscribe(device, endpoint_id, cluster_id) + return cluster_base.subscribe( + device, + endpoint_id, + cluster_id, + self.ID, + nil --event_id + ) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status, + cluster_id +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + cluster_id, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..3d50e8b97b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,69 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + local o = self.base_type(table.unpack({...})) + self:augment_type(o) + return o +end + +function MeasurementUnit:read(device, endpoint_id, cluster_id) + return cluster_base.read( + device, + endpoint_id, + cluster_id, + self.ID, + nil --event_id + ) +end + +function MeasurementUnit:subscribe(device, endpoint_id, cluster_id) + return cluster_base.subscribe( + device, + endpoint_id, + cluster_id, + self.ID, + nil --event_id + ) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status, + cluster_id +) + local data = data_types.validate_or_build_type(value, self.base_type) + self:augment_type(data) + return cluster_base.build_test_report_data( + device, + endpoint_id, + cluster_id, + self.ID, + data, + status + ) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..a1a0092151 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("ConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local ConcentrationMeasurementServerAttributes = {} + +function ConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(ConcentrationMeasurementServerAttributes, attr_mt) + +return ConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/Feature.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/Feature.lua new file mode 100644 index 0000000000..9aa2413903 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/Feature.lua @@ -0,0 +1,164 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local Feature = {} +local new_mt = UintABC.new_mt({NAME = "Feature", ID = data_types.name_to_id_map["Uint32"]}, 4) + +Feature.BASE_MASK = 0xFFFF +Feature.NUMERIC_MEASUREMENT = 0x0001 +Feature.LEVEL_INDICATION = 0x0002 +Feature.MEDIUM_LEVEL = 0x0004 +Feature.CRITICAL_LEVEL = 0x0008 +Feature.PEAK_MEASUREMENT = 0x0010 +Feature.AVERAGE_MEASUREMENT = 0x0020 + +Feature.mask_fields = { + BASE_MASK = 0xFFFF, + NUMERIC_MEASUREMENT = 0x0001, + LEVEL_INDICATION = 0x0002, + MEDIUM_LEVEL = 0x0004, + CRITICAL_LEVEL = 0x0008, + PEAK_MEASUREMENT = 0x0010, + AVERAGE_MEASUREMENT = 0x0020, +} + +Feature.is_numeric_measurement_set = function(self) + return (self.value & self.NUMERIC_MEASUREMENT) ~= 0 +end + +Feature.set_numeric_measurement = function(self) + if self.value ~= nil then + self.value = self.value | self.NUMERIC_MEASUREMENT + else + self.value = self.NUMERIC_MEASUREMENT + end +end + +Feature.unset_numeric_measurement = function(self) + self.value = self.value & (~self.NUMERIC_MEASUREMENT & self.BASE_MASK) +end + +Feature.is_level_indication_set = function(self) + return (self.value & self.LEVEL_INDICATION) ~= 0 +end + +Feature.set_level_indication = function(self) + if self.value ~= nil then + self.value = self.value | self.LEVEL_INDICATION + else + self.value = self.LEVEL_INDICATION + end +end + +Feature.unset_level_indication = function(self) + self.value = self.value & (~self.LEVEL_INDICATION & self.BASE_MASK) +end + +Feature.is_medium_level_set = function(self) + return (self.value & self.MEDIUM_LEVEL) ~= 0 +end + +Feature.set_medium_level = function(self) + if self.value ~= nil then + self.value = self.value | self.MEDIUM_LEVEL + else + self.value = self.MEDIUM_LEVEL + end +end + +Feature.unset_medium_level = function(self) + self.value = self.value & (~self.MEDIUM_LEVEL & self.BASE_MASK) +end + +Feature.is_critical_level_set = function(self) + return (self.value & self.CRITICAL_LEVEL) ~= 0 +end + +Feature.set_critical_level = function(self) + if self.value ~= nil then + self.value = self.value | self.CRITICAL_LEVEL + else + self.value = self.CRITICAL_LEVEL + end +end + +Feature.unset_critical_level = function(self) + self.value = self.value & (~self.CRITICAL_LEVEL & self.BASE_MASK) +end + +Feature.is_peak_measurement_set = function(self) + return (self.value & self.PEAK_MEASUREMENT) ~= 0 +end + +Feature.set_peak_measurement = function(self) + if self.value ~= nil then + self.value = self.value | self.PEAK_MEASUREMENT + else + self.value = self.PEAK_MEASUREMENT + end +end + +Feature.unset_peak_measurement = function(self) + self.value = self.value & (~self.PEAK_MEASUREMENT & self.BASE_MASK) +end + +Feature.is_average_measurement_set = function(self) + return (self.value & self.AVERAGE_MEASUREMENT) ~= 0 +end + +Feature.set_average_measurement = function(self) + if self.value ~= nil then + self.value = self.value | self.AVERAGE_MEASUREMENT + else + self.value = self.AVERAGE_MEASUREMENT + end +end + +Feature.unset_average_measurement = function(self) + self.value = self.value & (~self.AVERAGE_MEASUREMENT & self.BASE_MASK) +end + +function Feature.bits_are_valid(feature) + local max = + Feature.NUMERIC_MEASUREMENT | + Feature.LEVEL_INDICATION | + Feature.MEDIUM_LEVEL | + Feature.CRITICAL_LEVEL | + Feature.PEAK_MEASUREMENT | + Feature.AVERAGE_MEASUREMENT + if (feature <= max) and (feature >= 1) then + return true + else + return false + end +end + +Feature.mask_methods = { + is_numeric_measurement_set = Feature.is_numeric_measurement_set, + set_numeric_measurement = Feature.set_numeric_measurement, + unset_numeric_measurement = Feature.unset_numeric_measurement, + is_level_indication_set = Feature.is_level_indication_set, + set_level_indication = Feature.set_level_indication, + unset_level_indication = Feature.unset_level_indication, + is_medium_level_set = Feature.is_medium_level_set, + set_medium_level = Feature.set_medium_level, + unset_medium_level = Feature.unset_medium_level, + is_critical_level_set = Feature.is_critical_level_set, + set_critical_level = Feature.set_critical_level, + unset_critical_level = Feature.unset_critical_level, + is_peak_measurement_set = Feature.is_peak_measurement_set, + set_peak_measurement = Feature.set_peak_measurement, + unset_peak_measurement = Feature.unset_peak_measurement, + is_average_measurement_set = Feature.is_average_measurement_set, + set_average_measurement = Feature.set_average_measurement, + unset_average_measurement = Feature.unset_average_measurement, +} + +Feature.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(Feature, new_mt) + +return Feature + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/LevelValueEnum.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/LevelValueEnum.lua new file mode 100644 index 0000000000..b1264d72b8 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/LevelValueEnum.lua @@ -0,0 +1,39 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local LevelValueEnum = {} +-- Note: the name here is intentionally set to Uint8 to maintain backwards compatibility +-- with how types were handled in api < 10. +local new_mt = UintABC.new_mt({NAME = "Uint8", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.UNKNOWN] = "UNKNOWN", + [self.LOW] = "LOW", + [self.MEDIUM] = "MEDIUM", + [self.HIGH] = "HIGH", + [self.CRITICAL] = "CRITICAL", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.UNKNOWN = 0x00 +new_mt.__index.LOW = 0x01 +new_mt.__index.MEDIUM = 0x02 +new_mt.__index.HIGH = 0x03 +new_mt.__index.CRITICAL = 0x04 + +LevelValueEnum.UNKNOWN = 0x00 +LevelValueEnum.LOW = 0x01 +LevelValueEnum.MEDIUM = 0x02 +LevelValueEnum.HIGH = 0x03 +LevelValueEnum.CRITICAL = 0x04 + +LevelValueEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(LevelValueEnum, new_mt) + +return LevelValueEnum + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/MeasurementUnitEnum.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/MeasurementUnitEnum.lua new file mode 100644 index 0000000000..c8302c5cc4 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/MeasurementUnitEnum.lua @@ -0,0 +1,48 @@ +local data_types = require "st.matter.data_types" +local UintABC = require "st.matter.data_types.base_defs.UintABC" + +local MeasurementUnitEnum = {} +-- Note: the name here is intentionally set to Uint8 to maintain backwards compatibility +-- with how types were handled in api < 10. +local new_mt = UintABC.new_mt({NAME = "Uint8", ID = data_types.name_to_id_map["Uint8"]}, 1) +new_mt.__index.pretty_print = function(self) + local name_lookup = { + [self.PPM] = "PPM", + [self.PPB] = "PPB", + [self.PPT] = "PPT", + [self.MGM3] = "MGM3", + [self.UGM3] = "UGM3", + [self.NGM3] = "NGM3", + [self.PM3] = "PM3", + [self.BQM3] = "BQM3", + } + return string.format("%s: %s", self.field_name or self.NAME, name_lookup[self.value] or string.format("%d", self.value)) +end +new_mt.__tostring = new_mt.__index.pretty_print + +new_mt.__index.PPM = 0x00 +new_mt.__index.PPB = 0x01 +new_mt.__index.PPT = 0x02 +new_mt.__index.MGM3 = 0x03 +new_mt.__index.UGM3 = 0x04 +new_mt.__index.NGM3 = 0x05 +new_mt.__index.PM3 = 0x06 +new_mt.__index.BQM3 = 0x07 + +MeasurementUnitEnum.PPM = 0x00 +MeasurementUnitEnum.PPB = 0x01 +MeasurementUnitEnum.PPT = 0x02 +MeasurementUnitEnum.MGM3 = 0x03 +MeasurementUnitEnum.UGM3 = 0x04 +MeasurementUnitEnum.NGM3 = 0x05 +MeasurementUnitEnum.PM3 = 0x06 +MeasurementUnitEnum.BQM3 = 0x07 + +MeasurementUnitEnum.augment_type = function(cls, val) + setmetatable(val, new_mt) +end + +setmetatable(MeasurementUnitEnum, new_mt) + +return MeasurementUnitEnum + diff --git a/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/init.lua b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/init.lua new file mode 100644 index 0000000000..f6da1e6b62 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/ConcentrationMeasurement/types/init.lua @@ -0,0 +1,15 @@ +local types_mt = {} +types_mt.__types_cache = {} +types_mt.__index = function(self, key) + if types_mt.__types_cache[key] == nil then + types_mt.__types_cache[key] = require("ConcentrationMeasurement.types." .. key) + end + return types_mt.__types_cache[key] +end + +local ConcentrationMeasurementTypes = {} + +setmetatable(ConcentrationMeasurementTypes, types_mt) + +return ConcentrationMeasurementTypes + diff --git a/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..5920a9dc66 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local FormaldehydeConcentrationMeasurementServerAttributes = require "FormaldehydeConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local FormaldehydeConcentrationMeasurement = {} + +FormaldehydeConcentrationMeasurement.ID = 0x042B +FormaldehydeConcentrationMeasurement.NAME = "FormaldehydeConcentrationMeasurement" +FormaldehydeConcentrationMeasurement.server = {} +FormaldehydeConcentrationMeasurement.client = {} +FormaldehydeConcentrationMeasurement.server.attributes = FormaldehydeConcentrationMeasurementServerAttributes:set_parent_cluster(FormaldehydeConcentrationMeasurement) +FormaldehydeConcentrationMeasurement.types = ConcentrationMeasurement.types + +function FormaldehydeConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function FormaldehydeConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +FormaldehydeConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +FormaldehydeConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function FormaldehydeConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = FormaldehydeConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, FormaldehydeConcentrationMeasurement.NAME)) + end + return FormaldehydeConcentrationMeasurement[direction].attributes[key] +end +FormaldehydeConcentrationMeasurement.attributes = {} +setmetatable(FormaldehydeConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(FormaldehydeConcentrationMeasurement, {__index = cluster_base}) + +return FormaldehydeConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..37900b0fb1 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/FormaldehydeConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("FormaldehydeConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local FormaldehydeConcentrationMeasurementServerAttributes = {} + +function FormaldehydeConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(FormaldehydeConcentrationMeasurementServerAttributes, attr_mt) + +return FormaldehydeConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..b60e71050a --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local NitrogenDioxideConcentrationMeasurementServerAttributes = require "NitrogenDioxideConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local NitrogenDioxideConcentrationMeasurement = {} + +NitrogenDioxideConcentrationMeasurement.ID = 0x0413 +NitrogenDioxideConcentrationMeasurement.NAME = "NitrogenDioxideConcentrationMeasurement" +NitrogenDioxideConcentrationMeasurement.server = {} +NitrogenDioxideConcentrationMeasurement.client = {} +NitrogenDioxideConcentrationMeasurement.server.attributes = NitrogenDioxideConcentrationMeasurementServerAttributes:set_parent_cluster(NitrogenDioxideConcentrationMeasurement) +NitrogenDioxideConcentrationMeasurement.types = ConcentrationMeasurement.types + +function NitrogenDioxideConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function NitrogenDioxideConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +NitrogenDioxideConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +NitrogenDioxideConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function NitrogenDioxideConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = NitrogenDioxideConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, NitrogenDioxideConcentrationMeasurement.NAME)) + end + return NitrogenDioxideConcentrationMeasurement[direction].attributes[key] +end +NitrogenDioxideConcentrationMeasurement.attributes = {} +setmetatable(NitrogenDioxideConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(NitrogenDioxideConcentrationMeasurement, {__index = cluster_base}) + +return NitrogenDioxideConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..06c3d6dd55 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/NitrogenDioxideConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("NitrogenDioxideConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local NitrogenDioxideConcentrationMeasurementServerAttributes = {} + +function NitrogenDioxideConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(NitrogenDioxideConcentrationMeasurementServerAttributes, attr_mt) + +return NitrogenDioxideConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..83fd04857e --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local OzoneConcentrationMeasurementServerAttributes = require "OzoneConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local OzoneConcentrationMeasurement = {} + +OzoneConcentrationMeasurement.ID = 0x0415 +OzoneConcentrationMeasurement.NAME = "OzoneConcentrationMeasurement" +OzoneConcentrationMeasurement.server = {} +OzoneConcentrationMeasurement.client = {} +OzoneConcentrationMeasurement.server.attributes = OzoneConcentrationMeasurementServerAttributes:set_parent_cluster(OzoneConcentrationMeasurement) +OzoneConcentrationMeasurement.types = ConcentrationMeasurement.types + +function OzoneConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function OzoneConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +OzoneConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +OzoneConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function OzoneConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = OzoneConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, OzoneConcentrationMeasurement.NAME)) + end + return OzoneConcentrationMeasurement[direction].attributes[key] +end +OzoneConcentrationMeasurement.attributes = {} +setmetatable(OzoneConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(OzoneConcentrationMeasurement, {__index = cluster_base}) + +return OzoneConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..fe0048cd99 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/OzoneConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("OzoneConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local OzoneConcentrationMeasurementServerAttributes = {} + +function OzoneConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(OzoneConcentrationMeasurementServerAttributes, attr_mt) + +return OzoneConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..98eebd407e --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local Pm10ConcentrationMeasurementServerAttributes = require "Pm10ConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local Pm10ConcentrationMeasurement = {} + +Pm10ConcentrationMeasurement.ID = 0x042D +Pm10ConcentrationMeasurement.NAME = "Pm10ConcentrationMeasurement" +Pm10ConcentrationMeasurement.server = {} +Pm10ConcentrationMeasurement.client = {} +Pm10ConcentrationMeasurement.server.attributes = Pm10ConcentrationMeasurementServerAttributes:set_parent_cluster(Pm10ConcentrationMeasurement) +Pm10ConcentrationMeasurement.types = ConcentrationMeasurement.types + +function Pm10ConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function Pm10ConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +Pm10ConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +Pm10ConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function Pm10ConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = Pm10ConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, Pm10ConcentrationMeasurement.NAME)) + end + return Pm10ConcentrationMeasurement[direction].attributes[key] +end +Pm10ConcentrationMeasurement.attributes = {} +setmetatable(Pm10ConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(Pm10ConcentrationMeasurement, {__index = cluster_base}) + +return Pm10ConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..55f08c7e43 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm10ConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("Pm10ConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local Pm10ConcentrationMeasurementServerAttributes = {} + +function Pm10ConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(Pm10ConcentrationMeasurementServerAttributes, attr_mt) + +return Pm10ConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..0b3caa3bd2 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local Pm1ConcentrationMeasurementServerAttributes = require "Pm1ConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local Pm1ConcentrationMeasurement = {} + +Pm1ConcentrationMeasurement.ID = 0x042C +Pm1ConcentrationMeasurement.NAME = "Pm1ConcentrationMeasurement" +Pm1ConcentrationMeasurement.server = {} +Pm1ConcentrationMeasurement.client = {} +Pm1ConcentrationMeasurement.server.attributes = Pm1ConcentrationMeasurementServerAttributes:set_parent_cluster(Pm1ConcentrationMeasurement) +Pm1ConcentrationMeasurement.types = ConcentrationMeasurement.types + +function Pm1ConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function Pm1ConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +Pm1ConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +Pm1ConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function Pm1ConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = Pm1ConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, Pm1ConcentrationMeasurement.NAME)) + end + return Pm1ConcentrationMeasurement[direction].attributes[key] +end +Pm1ConcentrationMeasurement.attributes = {} +setmetatable(Pm1ConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(Pm1ConcentrationMeasurement, {__index = cluster_base}) + +return Pm1ConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..f668e41a07 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm1ConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("Pm1ConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local Pm1ConcentrationMeasurementServerAttributes = {} + +function Pm1ConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(Pm1ConcentrationMeasurementServerAttributes, attr_mt) + +return Pm1ConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..5234346d60 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local Pm25ConcentrationMeasurementServerAttributes = require "Pm25ConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local Pm25ConcentrationMeasurement = {} + +Pm25ConcentrationMeasurement.ID = 0x042A +Pm25ConcentrationMeasurement.NAME = "Pm25ConcentrationMeasurement" +Pm25ConcentrationMeasurement.server = {} +Pm25ConcentrationMeasurement.client = {} +Pm25ConcentrationMeasurement.server.attributes = Pm25ConcentrationMeasurementServerAttributes:set_parent_cluster(Pm25ConcentrationMeasurement) +Pm25ConcentrationMeasurement.types = ConcentrationMeasurement.types + +function Pm25ConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function Pm25ConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +Pm25ConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +Pm25ConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function Pm25ConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = Pm25ConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, Pm25ConcentrationMeasurement.NAME)) + end + return Pm25ConcentrationMeasurement[direction].attributes[key] +end +Pm25ConcentrationMeasurement.attributes = {} +setmetatable(Pm25ConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(Pm25ConcentrationMeasurement, {__index = cluster_base}) + +return Pm25ConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..2c7d5fce7b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/Pm25ConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("Pm25ConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local Pm25ConcentrationMeasurementServerAttributes = {} + +function Pm25ConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(Pm25ConcentrationMeasurementServerAttributes, attr_mt) + +return Pm25ConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..2a4cc04a0d --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local RadonConcentrationMeasurementServerAttributes = require "RadonConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local RadonConcentrationMeasurement = {} + +RadonConcentrationMeasurement.ID = 0x042F +RadonConcentrationMeasurement.NAME = "RadonConcentrationMeasurement" +RadonConcentrationMeasurement.server = {} +RadonConcentrationMeasurement.client = {} +RadonConcentrationMeasurement.server.attributes = RadonConcentrationMeasurementServerAttributes:set_parent_cluster(RadonConcentrationMeasurement) +RadonConcentrationMeasurement.types = ConcentrationMeasurement.types + +function RadonConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function RadonConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +RadonConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +RadonConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function RadonConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = RadonConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, RadonConcentrationMeasurement.NAME)) + end + return RadonConcentrationMeasurement[direction].attributes[key] +end +RadonConcentrationMeasurement.attributes = {} +setmetatable(RadonConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(RadonConcentrationMeasurement, {__index = cluster_base}) + +return RadonConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..b83ef67bfc --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/RadonConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("RadonConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local RadonConcentrationMeasurementServerAttributes = {} + +function RadonConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(RadonConcentrationMeasurementServerAttributes, attr_mt) + +return RadonConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/init.lua b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/init.lua new file mode 100644 index 0000000000..a99c1dea50 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/init.lua @@ -0,0 +1,44 @@ +local cluster_base = require "st.matter.cluster_base" +local TotalVolatileOrganicCompoundsConcentrationMeasurementServerAttributes = require "TotalVolatileOrganicCompoundsConcentrationMeasurement.server.attributes" +local ConcentrationMeasurement = require "ConcentrationMeasurement" + +local TotalVolatileOrganicCompoundsConcentrationMeasurement = {} + +TotalVolatileOrganicCompoundsConcentrationMeasurement.ID = 0x042E +TotalVolatileOrganicCompoundsConcentrationMeasurement.NAME = "TotalVolatileOrganicCompoundsConcentrationMeasurement" +TotalVolatileOrganicCompoundsConcentrationMeasurement.server = {} +TotalVolatileOrganicCompoundsConcentrationMeasurement.client = {} +TotalVolatileOrganicCompoundsConcentrationMeasurement.server.attributes = TotalVolatileOrganicCompoundsConcentrationMeasurementServerAttributes:set_parent_cluster(TotalVolatileOrganicCompoundsConcentrationMeasurement) +TotalVolatileOrganicCompoundsConcentrationMeasurement.types = ConcentrationMeasurement.types + +function TotalVolatileOrganicCompoundsConcentrationMeasurement:get_attribute_by_id(attr_id) + return ConcentrationMeasurement:get_attribute_by_id(attr_id) +end + +function TotalVolatileOrganicCompoundsConcentrationMeasurement:get_server_command_by_id(command_id) + return ConcentrationMeasurement:get_server_command_by_id(command_id) +end + +TotalVolatileOrganicCompoundsConcentrationMeasurement.attribute_direction_map = ConcentrationMeasurement.attribute_direction_map + +TotalVolatileOrganicCompoundsConcentrationMeasurement.FeatureMap = ConcentrationMeasurement.types.Feature + +function TotalVolatileOrganicCompoundsConcentrationMeasurement.are_features_supported(feature, feature_map) + return ConcentrationMeasurement.are_features_supported(feature, feature_map) +end + +local attribute_helper_mt = {} +attribute_helper_mt.__index = function(self, key) + local direction = TotalVolatileOrganicCompoundsConcentrationMeasurement.attribute_direction_map[key] + if direction == nil then + error(string.format("Referenced unknown attribute %s on cluster %s", key, TotalVolatileOrganicCompoundsConcentrationMeasurement.NAME)) + end + return TotalVolatileOrganicCompoundsConcentrationMeasurement[direction].attributes[key] +end +TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes = {} +setmetatable(TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes, attribute_helper_mt) + +setmetatable(TotalVolatileOrganicCompoundsConcentrationMeasurement, {__index = cluster_base}) + +return TotalVolatileOrganicCompoundsConcentrationMeasurement + diff --git a/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/LevelValue.lua b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/LevelValue.lua new file mode 100644 index 0000000000..50127a3537 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/LevelValue.lua @@ -0,0 +1,41 @@ +local ConcentrationMeasurementServerAttributesLevelValue = require "ConcentrationMeasurement.server.attributes.LevelValue" + +local LevelValue = { + ID = 0x000A, + NAME = "LevelValue", + base_type = require "ConcentrationMeasurement.types.LevelValueEnum", +} + +function LevelValue:new_value(...) + ConcentrationMeasurementServerAttributesLevelValue:new_value(...) +end + +function LevelValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:read(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesLevelValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function LevelValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function LevelValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesLevelValue:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function LevelValue:deserialize(tlv_buf) + return ConcentrationMeasurementServerAttributesLevelValue:deserialize(tlv_buf) +end + +setmetatable(LevelValue, {__call = LevelValue.new_value, __index = LevelValue.base_type}) +return LevelValue + diff --git a/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasuredValue.lua b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasuredValue.lua new file mode 100644 index 0000000000..763bbaa17b --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasuredValue.lua @@ -0,0 +1,56 @@ +local cluster_base = require "st.matter.cluster_base" +local data_types = require "st.matter.data_types" +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasuredValue = require "ConcentrationMeasurement.server.attributes.MeasuredValue" + + +local MeasuredValue = { + ID = 0x0000, + NAME = "MeasuredValue", + base_type = require "st.matter.data_types.SinglePrecisionFloat", +} + +function MeasuredValue:new_value(...) + return ConcentrationMeasurementServerAttributesMeasuredValue:new_value(...) +end + +function MeasuredValue:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:read(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasuredValue:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasuredValue:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasuredValue:build_test_report_data( + device, + endpoint_id, + value, + status +) + local data = data_types.validate_or_build_type(value, self.base_type) + + return cluster_base.build_test_report_data( + device, + endpoint_id, + self._cluster.ID, + self.ID, + data, + status + ) +end + +function MeasuredValue:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + + return data +end + +setmetatable(MeasuredValue, {__call = MeasuredValue.new_value, __index = MeasuredValue.base_type}) +return MeasuredValue + diff --git a/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasurementUnit.lua b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasurementUnit.lua new file mode 100644 index 0000000000..d18f14b09f --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/MeasurementUnit.lua @@ -0,0 +1,45 @@ +local TLVParser = require "st.matter.TLV.TLVParser" +local ConcentrationMeasurementServerAttributesMeasurementUnit = require "ConcentrationMeasurement.server.attributes.MeasurementUnit" + + +local MeasurementUnit = { + ID = 0x0008, + NAME = "MeasurementUnit", + base_type = require "ConcentrationMeasurement.types.MeasurementUnitEnum", +} + +function MeasurementUnit:new_value(...) + return ConcentrationMeasurementServerAttributesMeasurementUnit:new_value(...) +end + +function MeasurementUnit:read(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:read(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:subscribe(device, endpoint_id) + return ConcentrationMeasurementServerAttributesMeasurementUnit:subscribe(device, endpoint_id, self._cluster.ID) +end + +function MeasurementUnit:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +function MeasurementUnit:build_test_report_data( + device, + endpoint_id, + value, + status +) + return ConcentrationMeasurementServerAttributesMeasurementUnit:build_test_report_data(device, endpoint_id, value, status, self._cluster.ID) +end + +function MeasurementUnit:deserialize(tlv_buf) + local data = TLVParser.decode_tlv(tlv_buf) + self:augment_type(data) + return data +end + +setmetatable(MeasurementUnit, {__call = MeasurementUnit.new_value, __index = MeasurementUnit.base_type}) +return MeasurementUnit + diff --git a/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/init.lua b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/init.lua new file mode 100644 index 0000000000..c0c1b65c37 --- /dev/null +++ b/drivers/SmartThings/matter-thermostat/src/TotalVolatileOrganicCompoundsConcentrationMeasurement/server/attributes/init.lua @@ -0,0 +1,24 @@ +local attr_mt = {} +attr_mt.__attr_cache = {} +attr_mt.__index = function(self, key) + if attr_mt.__attr_cache[key] == nil then + local req_loc = string.format("TotalVolatileOrganicCompoundsConcentrationMeasurement.server.attributes.%s", key) + local raw_def = require(req_loc) + local cluster = rawget(self, "_cluster") + raw_def:set_parent_cluster(cluster) + attr_mt.__attr_cache[key] = raw_def + end + return attr_mt.__attr_cache[key] +end + +local TotalVolatileOrganicCompoundsConcentrationMeasurementServerAttributes = {} + +function TotalVolatileOrganicCompoundsConcentrationMeasurementServerAttributes:set_parent_cluster(cluster) + self._cluster = cluster + return self +end + +setmetatable(TotalVolatileOrganicCompoundsConcentrationMeasurementServerAttributes, attr_mt) + +return TotalVolatileOrganicCompoundsConcentrationMeasurementServerAttributes + diff --git a/drivers/SmartThings/matter-thermostat/src/embedded-cluster-utils.lua b/drivers/SmartThings/matter-thermostat/src/embedded-cluster-utils.lua index 2fd948d7ee..fd4ab43240 100644 --- a/drivers/SmartThings/matter-thermostat/src/embedded-cluster-utils.lua +++ b/drivers/SmartThings/matter-thermostat/src/embedded-cluster-utils.lua @@ -6,13 +6,35 @@ local version = require "version" if version.api < 10 then clusters.HepaFilterMonitoring = require "HepaFilterMonitoring" clusters.ActivatedCarbonFilterMonitoring = require "ActivatedCarbonFilterMonitoring" + clusters.AirQuality = require "AirQuality" + clusters.CarbonMonoxideConcentrationMeasurement = require "CarbonMonoxideConcentrationMeasurement" + clusters.CarbonDioxideConcentrationMeasurement = require "CarbonDioxideConcentrationMeasurement" + clusters.FormaldehydeConcentrationMeasurement = require "FormaldehydeConcentrationMeasurement" + clusters.NitrogenDioxideConcentrationMeasurement = require "NitrogenDioxideConcentrationMeasurement" + clusters.OzoneConcentrationMeasurement = require "OzoneConcentrationMeasurement" + clusters.Pm1ConcentrationMeasurement = require "Pm1ConcentrationMeasurement" + clusters.Pm10ConcentrationMeasurement = require "Pm10ConcentrationMeasurement" + clusters.Pm25ConcentrationMeasurement = require "Pm25ConcentrationMeasurement" + clusters.RadonConcentrationMeasurement = require "RadonConcentrationMeasurement" + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement = require "TotalVolatileOrganicCompoundsConcentrationMeasurement" end local embedded_cluster_utils = {} local embedded_clusters = { [clusters.HepaFilterMonitoring.ID] = clusters.HepaFilterMonitoring, - [clusters.ActivatedCarbonFilterMonitoring.ID] = clusters.ActivatedCarbonFilterMonitoring + [clusters.ActivatedCarbonFilterMonitoring.ID] = clusters.ActivatedCarbonFilterMonitoring, + [clusters.AirQuality.ID] = clusters.AirQuality, + [clusters.CarbonMonoxideConcentrationMeasurement.ID] = clusters.CarbonMonoxideConcentrationMeasurement, + [clusters.CarbonDioxideConcentrationMeasurement.ID] = clusters.CarbonDioxideConcentrationMeasurement, + [clusters.FormaldehydeConcentrationMeasurement.ID] = clusters.FormaldehydeConcentrationMeasurement, + [clusters.NitrogenDioxideConcentrationMeasurement.ID] = clusters.NitrogenDioxideConcentrationMeasurement, + [clusters.OzoneConcentrationMeasurement.ID] = clusters.OzoneConcentrationMeasurement, + [clusters.Pm1ConcentrationMeasurement.ID] = clusters.Pm1ConcentrationMeasurement, + [clusters.Pm10ConcentrationMeasurement.ID] = clusters.Pm10ConcentrationMeasurement, + [clusters.Pm25ConcentrationMeasurement.ID] = clusters.Pm25ConcentrationMeasurement, + [clusters.RadonConcentrationMeasurement.ID] = clusters.RadonConcentrationMeasurement, + [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID] = clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement, } function embedded_cluster_utils.get_endpoints(device, cluster_id, opts) diff --git a/drivers/SmartThings/matter-thermostat/src/init.lua b/drivers/SmartThings/matter-thermostat/src/init.lua index 7475c38d82..d2baf107f5 100644 --- a/drivers/SmartThings/matter-thermostat/src/init.lua +++ b/drivers/SmartThings/matter-thermostat/src/init.lua @@ -26,6 +26,17 @@ local version = require "version" if version.api < 10 then clusters.HepaFilterMonitoring = require "HepaFilterMonitoring" clusters.ActivatedCarbonFilterMonitoring = require "ActivatedCarbonFilterMonitoring" + clusters.AirQuality = require "AirQuality" + clusters.CarbonMonoxideConcentrationMeasurement = require "CarbonMonoxideConcentrationMeasurement" + clusters.CarbonDioxideConcentrationMeasurement = require "CarbonDioxideConcentrationMeasurement" + clusters.FormaldehydeConcentrationMeasurement = require "FormaldehydeConcentrationMeasurement" + clusters.NitrogenDioxideConcentrationMeasurement = require "NitrogenDioxideConcentrationMeasurement" + clusters.OzoneConcentrationMeasurement = require "OzoneConcentrationMeasurement" + clusters.Pm1ConcentrationMeasurement = require "Pm1ConcentrationMeasurement" + clusters.Pm10ConcentrationMeasurement = require "Pm10ConcentrationMeasurement" + clusters.Pm25ConcentrationMeasurement = require "Pm25ConcentrationMeasurement" + clusters.RadonConcentrationMeasurement = require "RadonConcentrationMeasurement" + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement = require "TotalVolatileOrganicCompoundsConcentrationMeasurement" -- new modes add in Matter 1.2 clusters.Thermostat.types.ThermostatSystemMode.DRY = 0x8 clusters.Thermostat.types.ThermostatSystemMode.SLEEP = 0x9 @@ -62,6 +73,8 @@ local RAC_DEVICE_TYPE_ID = 0x0072 local AP_DEVICE_TYPE_ID = 0x002D local FAN_DEVICE_TYPE_ID = 0x002B +local MGM3_PPM_CONVERSION_FACTOR = 24.45 + local setpoint_limit_device_field = { MIN_SETPOINT_DEADBAND_CHECKED = "MIN_SETPOINT_DEADBAND_CHECKED", MIN_HEAT = "MIN_HEAT", @@ -131,6 +144,77 @@ local subscribed_attributes = { [capabilities.filterStatus.ID] = { clusters.HepaFilterMonitoring.attributes.ChangeIndication, clusters.ActivatedCarbonFilterMonitoring.attributes.ChangeIndication + }, + [capabilities.airQualityHealthConcern.ID] = { + clusters.AirQuality.attributes.AirQuality + }, + [capabilities.carbonMonoxideMeasurement.ID] = { + clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue, + clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.carbonMonoxideHealthConcern.ID] = { + clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.carbonDioxideMeasurement.ID] = { + clusters.CarbonDioxideConcentrationMeasurement.attributes.MeasuredValue, + clusters.CarbonDioxideConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.carbonDioxideHealthConcern.ID] = { + clusters.CarbonDioxideConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.nitrogenDioxideMeasurement.ID] = { + clusters.NitrogenDioxideConcentrationMeasurement.attributes.MeasuredValue, + clusters.NitrogenDioxideConcentrationMeasurement.attributes.MeasurementUnit + }, + [capabilities.nitrogenDioxideHealthConcern.ID] = { + clusters.NitrogenDioxideConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.ozoneMeasurement.ID] = { + clusters.OzoneConcentrationMeasurement.attributes.MeasuredValue, + clusters.OzoneConcentrationMeasurement.attributes.MeasurementUnit + }, + [capabilities.ozoneHealthConcern.ID] = { + clusters.OzoneConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.formaldehydeMeasurement.ID] = { + clusters.FormaldehydeConcentrationMeasurement.attributes.MeasuredValue, + clusters.FormaldehydeConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.formaldehydeHealthConcern.ID] = { + clusters.FormaldehydeConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.veryFineDustSensor.ID] = { + clusters.Pm1ConcentrationMeasurement.attributes.MeasuredValue, + clusters.Pm1ConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.veryFineDustHealthConcern.ID] = { + clusters.Pm1ConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.fineDustHealthConcern.ID] = { + clusters.Pm25ConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.dustSensor.ID] = { + clusters.Pm25ConcentrationMeasurement.attributes.MeasuredValue, + clusters.Pm25ConcentrationMeasurement.attributes.MeasurementUnit, + clusters.Pm10ConcentrationMeasurement.attributes.MeasuredValue, + clusters.Pm10ConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.dustHealthConcern.ID] = { + clusters.Pm10ConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.radonMeasurement.ID] = { + clusters.RadonConcentrationMeasurement.attributes.MeasuredValue, + clusters.RadonConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.radonHealthConcern.ID] = { + clusters.RadonConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.tvocMeasurement.ID] = { + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasuredValue, + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.tvocHealthConcern.ID] = { + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.LevelValue } } @@ -212,6 +296,50 @@ local function get_device_type(driver, device) return false end +local AIR_QUALITY_MAP = { + {capabilities.carbonDioxideMeasurement.ID, "-co2", clusters.CarbonDioxideConcentrationMeasurement}, + {capabilities.carbonDioxideHealthConcern.ID, "-co2", clusters.CarbonDioxideConcentrationMeasurement}, + {capabilities.carbonMonoxideMeasurement.ID, "-co", clusters.CarbonMonoxideConcentrationMeasurement}, + {capabilities.carbonMonoxideHealthConcern.ID, "-co", clusters.CarbonMonoxideConcentrationMeasurement}, + {capabilities.dustSensor.ID, "-pm10", clusters.Pm10ConcentrationMeasurement}, + {capabilities.dustHealthConcern.ID, "-pm10", clusters.Pm10ConcentrationMeasurement}, + {capabilities.fineDustSensor.ID, "-pm25", clusters.Pm25ConcentrationMeasurement}, + {capabilities.fineDustHealthConcern.ID, "-pm25", clusters.Pm25ConcentrationMeasurement}, + {capabilities.formaldehydeMeasurement.ID, "-ch2o", clusters.FormaldehydeConcentrationMeasurement}, + {capabilities.formaldehydeHealthConcern.ID, "-ch2o", clusters.FormaldehydeConcentrationMeasurement}, + {capabilities.nitrogenDioxideHealthConcern.ID, "-no2", clusters.NitrogenDioxideConcentrationMeasurement}, + {capabilities.nitrogenDioxideMeasurement.ID, "-no2", clusters.NitrogenDioxideConcentrationMeasurement}, + {capabilities.ozoneHealthConcern.ID, "-ozone", clusters.OzoneConcentrationMeasurement}, + {capabilities.ozoneMeasurement.ID, "-ozone", clusters.OzoneConcentrationMeasurement}, + {capabilities.radonHealthConcern.ID, "-radon", clusters.RadonConcentrationMeasurement}, + {capabilities.radonMeasurement.ID, "-radon", clusters.RadonConcentrationMeasurement}, + {capabilities.tvocHealthConcern.ID, "-tvoc", clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement}, + {capabilities.tvocMeasurement.ID, "-tvoc", clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement}, + {capabilities.veryFineDustHealthConcern.ID, "-pm1", clusters.Pm1ConcentrationMeasurement}, + {capabilities.veryFineDustSensor.ID, "-pm1", clusters.Pm1ConcentrationMeasurement}, +} + +local function create_level_measurement_profile(device) + local meas_name, level_name = "", "" + for _, details in ipairs(AIR_QUALITY_MAP) do + local cap_id = details[1] + local cluster = details[3] + -- capability describes either a HealthConcern or Measurement/Sensor + if (cap_id:match("HealthConcern$")) then + local attr_eps = embedded_cluster_utils.get_endpoints(device, cluster.ID, { feature_bitmap = cluster.types.Feature.LEVEL_INDICATION }) + if #attr_eps > 0 then + level_name = level_name .. details[2] + end + elseif (cap_id:match("Measurement$") or cap_id:match("Sensor$")) then + local attr_eps = embedded_cluster_utils.get_endpoints(device, cluster.ID, { feature_bitmap = cluster.types.Feature.NUMERIC_MEASUREMENT }) + if #attr_eps > 0 then + meas_name = meas_name .. details[2] + end + end + end + return meas_name, level_name +end + local function do_configure(driver, device) local heat_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.HEATING}) local cool_eps = device:get_endpoints(clusters.Thermostat.ID, {feature_bitmap = clusters.Thermostat.types.ThermostatFeature.COOLING}) @@ -223,15 +351,14 @@ local function do_configure(driver, device) -- use get_endpoints for embedded clusters local hepa_filter_eps = embedded_cluster_utils.get_endpoints(device, clusters.HepaFilterMonitoring.ID) local ac_filter_eps = embedded_cluster_utils.get_endpoints(device, clusters.ActivatedCarbonFilterMonitoring.ID) + local aqs_eps = embedded_cluster_utils.get_endpoints(device, clusters.AirQuality.ID) local device_type = get_device_type(driver, device) local profile_name = "thermostat" - --Note: we have not encountered thermostats with multiple endpoints that support the Thermostat cluster if device_type == RAC_DEVICE_TYPE_ID then device.log.warn_with({hub_logs=true}, "Room Air Conditioner supports only one profile") elseif device_type == FAN_DEVICE_TYPE_ID then device.log.warn_with({hub_logs=true}, "Fan supports only one profile") elseif device_type == AP_DEVICE_TYPE_ID then - -- currently no profile switching for Air Purifier profile_name = "air-purifier" if #hepa_filter_eps > 0 and #ac_filter_eps > 0 then profile_name = profile_name .. "-hepa" .. "-ac" @@ -243,6 +370,50 @@ local function do_configure(driver, device) if #wind_eps > 0 then profile_name = profile_name .. "-wind" end + + if #thermo_eps > 0 then + profile_name = profile_name .. "-thermostat" + if #humidity_eps > 0 and #fan_eps > 0 then + profile_name = profile_name .. "-humidity" .. "-fan" + elseif #humidity_eps > 0 then + profile_name = profile_name .. "-humidity" + elseif #fan_eps > 0 then + profile_name = profile_name .. "-fan" + end + + if #heat_eps == 0 and #cool_eps == 0 then + device.log.warn_with({hub_logs=true}, "Thermostat does not support heating or cooling. No matching profile") + return + elseif #heat_eps > 0 and #cool_eps == 0 then + profile_name = profile_name .. "-heating-only" + elseif #cool_eps > 0 and #heat_eps == 0 then + profile_name = profile_name .. "-cooling-only" + end + + -- TODO remove this in favor of reading Thermostat clusters AttributeList attribute + -- to determine support for ThermostatRunningState + -- Add nobattery profiles if updated + profile_name = profile_name .. "-nostate" + + if #battery_eps == 0 then + profile_name = profile_name .. "-nobattery" + end + end + + if #aqs_eps > 0 then + profile_name = profile_name .. "-aqs" + end + + local meas_name, level_name = create_level_measurement_profile(device) + + if meas_name ~= "" then + profile_name = profile_name .. meas_name .. "-meas" + end + + if level_name ~= "" then + profile_name = profile_name .. level_name .. "-level" + end + device.log.info_with({hub_logs=true}, string.format("Updating device profile to %s.", profile_name)) device:try_update_metadata({profile = profile_name}) elseif #thermo_eps == 1 then @@ -283,13 +454,171 @@ local function do_configure(driver, device) end end - local function device_added(driver, device) device:send(clusters.Thermostat.attributes.ControlSequenceOfOperation:read(device)) device:send(clusters.FanControl.attributes.FanModeSequence:read(device)) device:send(clusters.FanControl.attributes.WindSupport:read(device)) end +local function store_unit_factory(capability_name) + return function(driver, device, ib, response) + device:set_field(capability_name.."_unit", ib.data.value, {persist = true}) + end +end + +local units = { + PPM = 0, + PPB = 1, + PPT = 2, + MGM3 = 3, + UGM3 = 4, + NGM3 = 5, + PM3 = 6, + BQM3 = 7, + PCIL = 0xFF -- not in matter spec +} + +local unit_strings = { + [units.PPM] = "ppm", + [units.PPB] = "ppb", + [units.PPT] = "ppt", + [units.MGM3] = "mg/m^3", + [units.NGM3] = "ng/m^3", + [units.UGM3] = "μg/m^3", + [units.BQM3] = "Bq/m^3", + [units.PCIL] = "pCi/L" +} + +local unit_default = { + [capabilities.carbonMonoxideMeasurement.NAME] = units.PPM, + [capabilities.carbonDioxideMeasurement.NAME] = units.PPM, + [capabilities.nitrogenDioxideMeasurement.NAME] = units.PPM, + [capabilities.ozoneMeasurement.NAME] = units.PPM, + [capabilities.formaldehydeMeasurement.NAME] = units.PPM, + [capabilities.veryFineDustSensor.NAME] = units.UGM3, + [capabilities.fineDustSensor.NAME] = units.UGM3, + [capabilities.dustSensor.NAME] = units.UGM3, + [capabilities.radonMeasurement.NAME] = units.BQM3, + [capabilities.tvocMeasurement.NAME] = units.PPM +} + +-- All ConcentrationMesurement clusters inherit from the same base cluster definitions, +-- so CarbonMonoxideConcentratinMeasurement is used below but the same enum types exist +-- in all ConcentrationMeasurement clusters +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", +} + +-- measured in g/mol +local molecular_weights = { + [capabilities.carbonDioxideMeasurement.NAME] = 44.010, + [capabilities.nitrogenDioxideMeasurement.NAME] = 28.014, + [capabilities.ozoneMeasurement.NAME] = 48.0, + [capabilities.formaldehydeMeasurement.NAME] = 30.031, + [capabilities.veryFineDustSensor.NAME] = "N/A", + [capabilities.fineDustSensor.NAME] = "N/A", + [capabilities.dustSensor.NAME] = "N/A", + [capabilities.radonMeasurement.NAME] = 222.018, + [capabilities.tvocMeasurement.NAME] = "N/A", +} + +local conversion_tables = { + [units.PPM] = { + [units.PPM] = function(value) return utils.round(value) 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, + }, + [units.PPB] = { + [units.PPM] = function(value) return utils.round(value/(10^3)) end + }, + [units.PPT] = { + [units.PPM] = function(value) return utils.round(value/(10^6)) end + }, + [units.MGM3] = { + [units.UGM3] = function(value) return utils.round(value * (10^3)) end, + [units.PPM] = function(value, molecular_weight) return utils.round((value * MGM3_PPM_CONVERSION_FACTOR) / molecular_weight) end, + }, + [units.UGM3] = { + [units.UGM3] = function(value) return utils.round(value) end, + [units.PPM] = function(value, molecular_weight) return utils.round((value * MGM3_PPM_CONVERSION_FACTOR) / (molecular_weight * 10^3)) end, + }, + [units.NGM3] = { + [units.UGM3] = function(value) return utils.round(value/(10^3)) end + }, + [units.BQM3] = { + [units.PCIL] = function(value) return utils.round(value/37) end + }, +} + +local function unit_conversion(value, from_unit, to_unit, capability_name) + local conversion_function = conversion_tables[from_unit][to_unit] + if not conversion_function then + log.info_with( {hub_logs = true} , string.format("Unsupported unit conversion from %s to %s", unit_strings[from_unit], unit_strings[to_unit])) + return + end + + if not value then + log.info_with( {hub_logs = true} , "unit conversion value is nil") + return + end + + return conversion_function(value, molecular_weights[capability_name]) +end + +local function measurementHandlerFactory(capability_name, attribute, target_unit) + return function(driver, device, ib, response) + local reporting_unit = device:get_field(capability_name.."_unit") + + if not reporting_unit then + reporting_unit = unit_default[capability_name] + device:set_field(capability_name.."_unit", reporting_unit, {persist = true}) + end + + local value = nil + if reporting_unit then + value = unit_conversion(ib.data.value, reporting_unit, target_unit, capability_name) + end + + if value then + device:emit_event_for_endpoint(ib.endpoint_id, attribute({value = value, unit = unit_strings[target_unit]})) + -- handle case where device profile supports both fineDustLevel and dustLevel + if capability_name == capabilities.fineDustSensor.NAME and device:supports_capability(capabilities.dustSensor) then + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.dustSensor.fineDustLevel({value = value, unit = unit_strings[target_unit]})) + end + end + end +end + +local function levelHandlerFactory(attribute) + return function(driver, device, ib, response) + device:emit_event_for_endpoint(ib.endpoint_id, attribute(level_strings[ib.data.value])) + end +end + +-- handlers +local function air_quality_attr_handler(driver, device, ib, response) + local state = ib.data.value + if state == 0 then -- Unknown + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.unknown()) + elseif state == 1 then -- Good + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.good()) + elseif state == 2 then -- Fair + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.moderate()) + elseif state == 3 then -- Moderate + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.slightlyUnhealthy()) + elseif state == 4 then -- Poor + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.unhealthy()) + elseif state == 5 then -- VeryPoor + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.veryUnhealthy()) + elseif state == 6 then -- ExtremelyPoor + device:emit_event_for_endpoint(ib.endpoint_id, capabilities.airQualityHealthConcern.airQualityHealthConcern.hazardous()) + end +end + local function on_off_attr_handler(driver, device, ib, response) if ib.data.value then device:emit_event_for_endpoint(ib.endpoint_id, capabilities.switch.switch.on()) @@ -897,6 +1226,59 @@ local matter_driver_template = { [clusters.ActivatedCarbonFilterMonitoring.ID] = { [clusters.ActivatedCarbonFilterMonitoring.attributes.Condition.ID] = activated_carbon_filter_condition_handler, [clusters.ActivatedCarbonFilterMonitoring.attributes.ChangeIndication.ID] = activated_carbon_filter_change_indication_handler + }, + [clusters.AirQuality.ID] = { + [clusters.AirQuality.attributes.AirQuality.ID] = air_quality_attr_handler, + }, + [clusters.CarbonMonoxideConcentrationMeasurement.ID] = { + [clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.carbonMonoxideMeasurement.NAME, capabilities.carbonMonoxideMeasurement.carbonMonoxideLevel, units.PPM), + [clusters.CarbonMonoxideConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.carbonMonoxideMeasurement.NAME), + [clusters.CarbonMonoxideConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.carbonMonoxideHealthConcern.carbonMonoxideHealthConcern), + }, + [clusters.CarbonDioxideConcentrationMeasurement.ID] = { + [clusters.CarbonDioxideConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.carbonDioxideMeasurement.NAME, capabilities.carbonDioxideMeasurement.carbonDioxide, units.PPM), + [clusters.CarbonDioxideConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.carbonDioxideMeasurement.NAME), + [clusters.CarbonDioxideConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.carbonDioxideHealthConcern.carbonDioxideHealthConcern), + }, + [clusters.NitrogenDioxideConcentrationMeasurement.ID] = { + [clusters.NitrogenDioxideConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.nitrogenDioxideMeasurement.NAME, capabilities.nitrogenDioxideMeasurement.nitrogenDioxide, units.PPM), + [clusters.NitrogenDioxideConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.nitrogenDioxideMeasurement.NAME), + [clusters.NitrogenDioxideConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.nitrogenDioxideHealthConcern.nitrogenDioxideHealthConcern) + }, + [clusters.OzoneConcentrationMeasurement.ID] = { + [clusters.OzoneConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.ozoneMeasurement.NAME, capabilities.ozoneMeasurement.ozone, units.PPM), + [clusters.OzoneConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.ozoneMeasurement.NAME), + [clusters.OzoneConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.ozoneHealthConcern.ozoneHealthConcern) + }, + [clusters.FormaldehydeConcentrationMeasurement.ID] = { + [clusters.FormaldehydeConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.formaldehydeMeasurement.NAME, capabilities.formaldehydeMeasurement.formaldehydeLevel, units.PPM), + [clusters.FormaldehydeConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.formaldehydeMeasurement.NAME), + [clusters.FormaldehydeConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.formaldehydeHealthConcern.formaldehydeHealthConcern), + }, + [clusters.Pm1ConcentrationMeasurement.ID] = { + [clusters.Pm1ConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.veryFineDustSensor.NAME, capabilities.veryFineDustSensor.veryFineDustLevel, units.UGM3), + [clusters.Pm1ConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.veryFineDustSensor.NAME), + [clusters.Pm1ConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.veryFineDustHealthConcern.veryFineDustHealthConcern), + }, + [clusters.Pm25ConcentrationMeasurement.ID] = { + [clusters.Pm25ConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.fineDustSensor.NAME, capabilities.fineDustSensor.fineDustLevel, units.UGM3), + [clusters.Pm25ConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.fineDustSensor.NAME), + [clusters.Pm25ConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.fineDustHealthConcern.fineDustHealthConcern), + }, + [clusters.Pm10ConcentrationMeasurement.ID] = { + [clusters.Pm10ConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.dustSensor.NAME, capabilities.dustSensor.dustLevel, units.UGM3), + [clusters.Pm10ConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.dustSensor.NAME), + [clusters.Pm10ConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.dustHealthConcern.dustHealthConcern), + }, + [clusters.RadonConcentrationMeasurement.ID] = { + [clusters.RadonConcentrationMeasurement.attributes.MeasuredValue.ID] = measurementHandlerFactory(capabilities.radonMeasurement.NAME, capabilities.radonMeasurement.radonLevel, units.PCIL), + [clusters.RadonConcentrationMeasurement.attributes.MeasurementUnit.ID] = store_unit_factory(capabilities.radonMeasurement.NAME), + [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.MeasurementUnit.ID] = store_unit_factory(capabilities.tvocMeasurement.NAME), + [clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.LevelValue.ID] = levelHandlerFactory(capabilities.tvocHealthConcern.tvocHealthConcern) } } }, @@ -950,7 +1332,28 @@ local matter_driver_template = { capabilities.windMode, capabilities.battery, capabilities.filterState, - capabilities.filterStatus + capabilities.filterStatus, + capabilities.airQualityHealthConcern, + capabilities.carbonDioxideHealthConcern, + capabilities.carbonDioxideMeasurement, + capabilities.carbonMonoxideHealthConcern, + capabilities.carbonMonoxideMeasurement, + capabilities.nitrogenDioxideHealthConcern, + capabilities.nitrogenDioxideMeasurement, + capabilities.ozoneHealthConcern, + capabilities.ozoneMeasurement, + capabilities.formaldehydeHealthConcern, + capabilities.formaldehydeMeasurement, + capabilities.veryFineDustHealthConcern, + capabilities.veryFineDustSensor, + capabilities.fineDustHealthConcern, + capabilities.fineDustSensor, + capabilities.dustSensor, + capabilities.dustHealthConcern, + capabilities.radonHealthConcern, + capabilities.radonMeasurement, + capabilities.tvocHealthConcern, + capabilities.tvocMeasurement }, } diff --git a/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua b/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua index aa52cb881c..9536cb28fe 100644 --- a/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua +++ b/drivers/SmartThings/matter-thermostat/src/test/test_matter_air_purifier.lua @@ -14,11 +14,23 @@ local test = require "integration_test" local capabilities = require "st.capabilities" local t_utils = require "integration_test.utils" +local SinglePrecisionFloat = require "st.matter.data_types.SinglePrecisionFloat" local clusters = require "st.matter.clusters" clusters.HepaFilterMonitoring = require "HepaFilterMonitoring" clusters.ActivatedCarbonFilterMonitoring = require "ActivatedCarbonFilterMonitoring" +clusters.AirQuality = require "AirQuality" +clusters.CarbonMonoxideConcentrationMeasurement = require "CarbonMonoxideConcentrationMeasurement" +clusters.CarbonDioxideConcentrationMeasurement = require "CarbonDioxideConcentrationMeasurement" +clusters.FormaldehydeConcentrationMeasurement = require "FormaldehydeConcentrationMeasurement" +clusters.NitrogenDioxideConcentrationMeasurement = require "NitrogenDioxideConcentrationMeasurement" +clusters.OzoneConcentrationMeasurement = require "OzoneConcentrationMeasurement" +clusters.Pm1ConcentrationMeasurement = require "Pm1ConcentrationMeasurement" +clusters.Pm10ConcentrationMeasurement = require "Pm10ConcentrationMeasurement" +clusters.Pm25ConcentrationMeasurement = require "Pm25ConcentrationMeasurement" +clusters.RadonConcentrationMeasurement = require "RadonConcentrationMeasurement" +clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement = require "TotalVolatileOrganicCompoundsConcentrationMeasurement" local mock_device = test.mock_device.build_test_matter_device({ profile = t_utils.get_profile_definition("air-purifier-hepa-ac-wind.yml"), @@ -47,6 +59,190 @@ local mock_device = test.mock_device.build_test_matter_device({ } }) +local mock_device_ap_aqs = test.mock_device.build_test_matter_device({ + profile = t_utils.get_profile_definition("air-purifier-hepa-ac-wind.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.FanControl.ID, cluster_type = "SERVER", feature_map = 0}, + {cluster_id = clusters.HepaFilterMonitoring.ID, cluster_type = "SERVER", feature_map = 0}, + {cluster_id = clusters.ActivatedCarbonFilterMonitoring.ID, cluster_type = "SERVER", feature_map = 0}, + }, + device_types = { + {device_type_id = 0x002D, device_type_revision = 1} -- AP + } + }, + { + endpoint_id = 3, + clusters = { + {cluster_id = clusters.AirQuality.ID, cluster_type = "SERVER"}, + {cluster_id = clusters.CarbonDioxideConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 3}, + {cluster_id = clusters.RadonConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 2}, + {cluster_id = clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 1}, + }, + device_types = { + {device_type_id = 0x002C, device_type_revision = 1} -- AQS + } + } + } +}) + +local mock_device_ap_thermo_aqs = test.mock_device.build_test_matter_device({ + profile = t_utils.get_profile_definition("air-purifier-hepa-ac-wind.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.FanControl.ID, cluster_type = "SERVER", feature_map = 63}, + {cluster_id = clusters.HepaFilterMonitoring.ID, cluster_type = "SERVER", feature_map = 7}, + {cluster_id = clusters.ActivatedCarbonFilterMonitoring.ID, cluster_type = "SERVER", feature_map = 7}, + }, + device_types = { + {device_type_id = 0x002D, device_type_revision = 1} -- AP + } + }, + { + endpoint_id = 3, + clusters = { + {cluster_id = clusters.AirQuality.ID, cluster_type = "SERVER"}, + {cluster_id = clusters.NitrogenDioxideConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 14}, + {cluster_id = clusters.Pm25ConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 15}, + {cluster_id = clusters.FormaldehydeConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 15}, + {cluster_id = clusters.Pm10ConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 15}, + {cluster_id = clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 14}, + }, + device_types = { + {device_type_id = 0x002C, device_type_revision = 1} -- AQS + } + }, + { + endpoint_id = 4, + clusters = { + {cluster_id = clusters.TemperatureMeasurement.ID, cluster_type = "SERVER", feature_map = 0}, + }, + device_types = { + {device_type_id = 0x0302, device_type_revision = 1} -- Temperature Sensor + } + }, + { + endpoint_id = 6, + clusters = { + {cluster_id = clusters.RelativeHumidityMeasurement.ID, cluster_type = "SERVER", feature_map = 0}, + }, + device_types = { + {device_type_id = 0x0307, device_type_revision = 1} -- Humidity Sensor + } + }, + { + endpoint_id = 7, + clusters = { + {cluster_id = clusters.Thermostat.ID, cluster_type = "SERVER", feature_map = 1}, + }, + device_types = { + {device_type_id = 0x0301, device_type_revision = 1} -- Thermostat + } + }, + } +}) + +local mock_device_ap_thermo_aqs_preconfigured = test.mock_device.build_test_matter_device({ + profile = t_utils.get_profile_definition("air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level.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.FanControl.ID, cluster_type = "SERVER", feature_map = 63}, + {cluster_id = clusters.HepaFilterMonitoring.ID, cluster_type = "SERVER", feature_map = 7}, + {cluster_id = clusters.ActivatedCarbonFilterMonitoring.ID, cluster_type = "SERVER", feature_map = 7}, + }, + device_types = { + {device_type_id = 0x002D, device_type_revision = 1} -- AP + } + }, + { + endpoint_id = 3, + clusters = { + {cluster_id = clusters.AirQuality.ID, cluster_type = "SERVER"}, + {cluster_id = clusters.NitrogenDioxideConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 14}, + {cluster_id = clusters.Pm25ConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 15}, + {cluster_id = clusters.FormaldehydeConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 15}, + {cluster_id = clusters.Pm10ConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 15}, + {cluster_id = clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.ID, cluster_type = "SERVER", feature_map = 14}, + }, + device_types = { + {device_type_id = 0x002C, device_type_revision = 1} -- AQS + } + }, + { + endpoint_id = 4, + clusters = { + {cluster_id = clusters.TemperatureMeasurement.ID, cluster_type = "SERVER", feature_map = 0}, + }, + device_types = { + {device_type_id = 0x0302, device_type_revision = 1} -- Temperature Sensor + } + }, + { + endpoint_id = 6, + clusters = { + {cluster_id = clusters.RelativeHumidityMeasurement.ID, cluster_type = "SERVER", feature_map = 0}, + }, + device_types = { + {device_type_id = 0x0307, device_type_revision = 1} -- Humidity Sensor + } + }, + { + endpoint_id = 7, + clusters = { + {cluster_id = clusters.Thermostat.ID, cluster_type = "SERVER", feature_map = 1}, + }, + device_types = { + {device_type_id = 0x0301, device_type_revision = 1} -- Thermostat + } + }, + } +}) + local cluster_subscribe_list = { clusters.FanControl.attributes.FanModeSequence, clusters.FanControl.attributes.FanMode, @@ -56,8 +252,82 @@ local cluster_subscribe_list = { clusters.HepaFilterMonitoring.attributes.ChangeIndication, clusters.HepaFilterMonitoring.attributes.Condition, clusters.ActivatedCarbonFilterMonitoring.attributes.ChangeIndication, - clusters.ActivatedCarbonFilterMonitoring.attributes.Condition + clusters.ActivatedCarbonFilterMonitoring.attributes.Condition, +} +local cluster_subscribe_list_configured = { + [capabilities.temperatureMeasurement.ID] = { + clusters.Thermostat.attributes.LocalTemperature, + clusters.TemperatureMeasurement.attributes.MeasuredValue, + clusters.TemperatureMeasurement.attributes.MinMeasuredValue, + clusters.TemperatureMeasurement.attributes.MaxMeasuredValue + }, + [capabilities.relativeHumidityMeasurement.ID] = { + clusters.RelativeHumidityMeasurement.attributes.MeasuredValue + }, + [capabilities.thermostatMode.ID] = { + clusters.Thermostat.attributes.SystemMode, + clusters.Thermostat.attributes.ControlSequenceOfOperation + }, + [capabilities.thermostatOperatingState.ID] = { + clusters.Thermostat.attributes.ThermostatRunningState + }, + [capabilities.thermostatFanMode.ID] = { + clusters.FanControl.attributes.FanModeSequence, + clusters.FanControl.attributes.FanMode + }, + [capabilities.thermostatHeatingSetpoint.ID] = { + clusters.Thermostat.attributes.OccupiedHeatingSetpoint, + clusters.Thermostat.attributes.AbsMinHeatSetpointLimit, + clusters.Thermostat.attributes.AbsMaxHeatSetpointLimit + }, + [capabilities.airPurifierFanMode.ID] = { + clusters.FanControl.attributes.FanModeSequence, + clusters.FanControl.attributes.FanMode + }, + [capabilities.fanSpeedPercent.ID] = { + clusters.FanControl.attributes.PercentCurrent + }, + [capabilities.windMode.ID] = { + clusters.FanControl.attributes.WindSupport, + clusters.FanControl.attributes.WindSetting + }, + [capabilities.filterState.ID] = { + clusters.HepaFilterMonitoring.attributes.Condition, + clusters.ActivatedCarbonFilterMonitoring.attributes.Condition + }, + [capabilities.filterStatus.ID] = { + clusters.HepaFilterMonitoring.attributes.ChangeIndication, + clusters.ActivatedCarbonFilterMonitoring.attributes.ChangeIndication + }, + [capabilities.airQualityHealthConcern.ID] = { + clusters.AirQuality.attributes.AirQuality + }, + [capabilities.nitrogenDioxideHealthConcern.ID] = { + clusters.NitrogenDioxideConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.formaldehydeMeasurement.ID] = { + clusters.FormaldehydeConcentrationMeasurement.attributes.MeasuredValue, + clusters.FormaldehydeConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.formaldehydeHealthConcern.ID] = { + clusters.FormaldehydeConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.fineDustHealthConcern.ID] = { + clusters.Pm25ConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.dustSensor.ID] = { + clusters.Pm25ConcentrationMeasurement.attributes.MeasuredValue, + clusters.Pm25ConcentrationMeasurement.attributes.MeasurementUnit, + clusters.Pm10ConcentrationMeasurement.attributes.MeasuredValue, + clusters.Pm10ConcentrationMeasurement.attributes.MeasurementUnit, + }, + [capabilities.dustHealthConcern.ID] = { + clusters.Pm10ConcentrationMeasurement.attributes.LevelValue, + }, + [capabilities.tvocHealthConcern.ID] = { + clusters.TotalVolatileOrganicCompoundsConcentrationMeasurement.attributes.LevelValue + } } local function test_init() @@ -72,6 +342,86 @@ local function test_init() end test.set_test_init_function(test_init) +local function test_init_ap_aqs() + local subscribe_request_ap_aqs = cluster_subscribe_list[1]:subscribe(mock_device_ap_aqs) + for i, cluster in ipairs(cluster_subscribe_list) do + if i > 1 then + subscribe_request_ap_aqs:merge(cluster:subscribe(mock_device_ap_aqs)) + end + end + test.socket.matter:__expect_send({mock_device_ap_aqs.id, subscribe_request_ap_aqs}) + test.mock_device.add_test_device(mock_device_ap_aqs) +end + +local function test_init_ap_thermo_aqs_preconfigured() + local subscribe_request = nil + for _, attributes in pairs(cluster_subscribe_list_configured) do + for _, attribute in ipairs(attributes) do + if subscribe_request == nil then + subscribe_request = attribute:subscribe(mock_device) + else + subscribe_request:merge(attribute:subscribe(mock_device)) + end + end + end + test.socket.matter:__expect_send({mock_device_ap_thermo_aqs_preconfigured.id, subscribe_request}) + test.mock_device.add_test_device(mock_device_ap_thermo_aqs_preconfigured) +end + +local function test_init_ap_thermo_aqs() + local subscribe_request_ap_aqs = cluster_subscribe_list[1]:subscribe(mock_device_ap_thermo_aqs) + for i, cluster in ipairs(cluster_subscribe_list) do + if i > 1 then + subscribe_request_ap_aqs:merge(cluster:subscribe(mock_device_ap_thermo_aqs)) + end + end + test.socket.matter:__expect_send({mock_device_ap_thermo_aqs.id, subscribe_request_ap_aqs}) + test.mock_device.add_test_device(mock_device_ap_thermo_aqs) +end + +test.register_coroutine_test( + "Test profile change on init for AP and AQS combined device type", + function() + test.socket.device_lifecycle:__queue_receive({ mock_device_ap_aqs.id, "doConfigure" }) + mock_device_ap_aqs:expect_metadata_update({ profile = "air-purifier-hepa-ac-aqs-co2-tvoc-meas-co2-radon-level" }) + mock_device_ap_aqs:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end, + { test_init = test_init_ap_aqs } +) + +test.register_coroutine_test( + "Test profile change on init for AP and Thermo and AQS combined device type", + function() + test.socket.device_lifecycle:__queue_receive({ mock_device_ap_thermo_aqs.id, "doConfigure" }) + mock_device_ap_thermo_aqs:expect_metadata_update({ profile = "air-purifier-hepa-ac-wind-thermostat-humidity-fan-heating-only-nostate-nobattery-aqs-pm10-pm25-ch2o-meas-pm10-pm25-ch2o-no2-tvoc-level" }) + mock_device_ap_thermo_aqs:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + print(mock_device_ap_thermo_aqs.profile) + end, + { test_init = test_init_ap_thermo_aqs } +) + +test.register_coroutine_test( + "Molecular weight conversion should be handled appropriately in unit_conversion", + function () + test.socket.matter:__queue_receive({ + mock_device_ap_thermo_aqs_preconfigured.id, + clusters.FormaldehydeConcentrationMeasurement.attributes.MeasurementUnit:build_test_report_data( + mock_device_ap_thermo_aqs_preconfigured, 1, clusters.FormaldehydeConcentrationMeasurement.types.MeasurementUnitEnum.MGM3 + ) + }) + test.socket.matter:__queue_receive({ + mock_device_ap_thermo_aqs_preconfigured.id, + clusters.FormaldehydeConcentrationMeasurement.attributes.MeasuredValue:build_test_report_data( + mock_device_ap_thermo_aqs_preconfigured, 1, SinglePrecisionFloat(0, 4, .11187500) + ) + }) + test.socket.capability:__expect_send( + mock_device_ap_thermo_aqs_preconfigured:generate_test_message("main", capabilities.formaldehydeMeasurement.formaldehydeLevel({value = 14, unit = "ppm"})) + ) + end, + { test_init = test_init_ap_thermo_aqs_preconfigured } +) + test.register_message_test( "setAirPurifierFanMode command should send the appropriate commands", { From 013dfbee1ed62a9e9bc309cef5b91bbc384ef320 Mon Sep 17 00:00:00 2001 From: Liu Yiding Date: Wed, 26 Jun 2024 10:54:08 +0800 Subject: [PATCH 05/18] Add TOTEM P90 Signed-off-by: Liu Yiding --- drivers/SmartThings/zigbee-lock/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/zigbee-lock/fingerprints.yml b/drivers/SmartThings/zigbee-lock/fingerprints.yml index c28fb94bfd..d1acdf47c0 100644 --- a/drivers/SmartThings/zigbee-lock/fingerprints.yml +++ b/drivers/SmartThings/zigbee-lock/fingerprints.yml @@ -145,6 +145,11 @@ zigbeeManufacturer: manufacturer: TOTEM model: P70 deviceProfileName: lock-battery + - id: TOTEM/P90 + deviceLabel: TOTEM Door Lock + manufacturer: TOTEM + model: P90 + deviceProfileName: lock-battery zigbeeGeneric: - id: "genericLock" deviceLabel: Zigbee Lock From 4d8e9e81d4f77ab8fed41526db27a5c8c32b274b Mon Sep 17 00:00:00 2001 From: wkhenon Date: Mon, 1 Jul 2024 12:09:04 -0400 Subject: [PATCH 06/18] Handle Zigbee Min, Max, and Measured Value temperatures --- .../SmartThings/zigbee-button/src/init.lua | 47 +++++++++++ .../src/test/test_ewelink_button.lua | 9 ++ .../src/test/test_samjin_button.lua | 8 ++ .../src/test/test_zigbee_button.lua | 83 ++++++++++++++++++- .../SmartThings/zigbee-contact/src/init.lua | 57 ++++++++++++- .../src/test/test_aqara_contact_sensor.lua | 9 ++ .../src/test/test_aurora_contact_sensor.lua | 9 ++ .../test/test_contact_temperature_sensor.lua | 8 ++ .../src/test/test_ecolink_contact.lua | 8 ++ .../src/test/test_ewelink_heiman_sensor.lua | 9 ++ .../src/test/test_frient_sensor.lua | 8 ++ .../src/test/test_orvibo_contact_sensor.lua | 9 ++ .../src/test/test_sengled_contact_sensor.lua | 9 ++ .../src/test/test_third_reality_contact.lua | 9 ++ .../src/test/test_zigbee_contact.lua | 39 +++++++++ .../zigbee-humidity-sensor/src/init.lua | 45 +++++++++- .../src/test/test_humidity_temperature.lua | 27 ++++++ .../test/test_humidity_temperature_sensor.lua | 27 ++++++ .../zigbee-motion-sensor/src/init.lua | 56 +++++++++++++ .../test_all_capabilities_zigbee_motion.lua | 49 +++++++++++ .../src/test/test_sengled_motion.lua | 9 ++ .../src/test/test_zigbee_motion_iris.lua | 16 ++++ .../test/test_zigbee_plugin_motion_sensor.lua | 17 ++++ .../zigbee-sound-sensor/src/init.lua | 35 ++++++++ .../src/test/test_zigbee_sound_sensor.lua | 53 ++++++++++++ .../zigbee-thermostat/src/init.lua | 48 +++++++++-- .../src/test/test_zigbee_thermostat.lua | 54 ++++++++++++ drivers/SmartThings/zigbee-vent/src/init.lua | 34 ++++++++ .../zigbee-vent/src/test/test_zigbee_vent.lua | 54 ++++++++++++ .../zigbee-water-leak-sensor/src/init.lua | 45 +++++++++- .../test_centralite_water_leak_sensor.lua | 8 ++ .../test/test_frient_water_leak_sensor.lua | 8 ++ .../test/test_samjin_water_leak_sensor.lua | 8 ++ .../test/test_sengled_water_leak_sensor.lua | 9 ++ .../src/test/test_sinope_zigbee_water.lua | 32 +++++++ .../test_smartthings_water_leak_sensor.lua | 8 ++ .../src/test/test_zigbee_water.lua | 59 +++++++++++++ .../src/test/test_zigbee_water_freeze.lua | 45 ++++++++++ 38 files changed, 1057 insertions(+), 10 deletions(-) diff --git a/drivers/SmartThings/zigbee-button/src/init.lua b/drivers/SmartThings/zigbee-button/src/init.lua index a0e4dec66e..d20bf31870 100644 --- a/drivers/SmartThings/zigbee-button/src/init.lua +++ b/drivers/SmartThings/zigbee-button/src/init.lua @@ -17,6 +17,12 @@ local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" local constants = require "st.zigbee.constants" local IASZone = (require "st.zigbee.zcl.clusters").IASZone +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement + +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} local generate_event_from_zone_status = function(driver, device, zone_status, zb_rx) local event @@ -65,10 +71,47 @@ local ias_zone_status_change_handler = function(driver, device, zb_rx) generate_event_from_zone_status(driver, device, zb_rx.body.zcl_body.zone_status, zb_rx) end +--- Default handler for Temperature min and max measured value on the Temperature measurement cluster +--- +--- This starts initially by performing the same conversion in the temperature_measurement_attr_handler function. +--- It then sets the field of whichever measured value is defined by the @param and checks if the fields +--- correctly compare +--- +--- @param minOrMax string the string that determines which attribute to set +--- @param driver Driver The current driver running containing necessary context for execution +--- @param device ZigbeeDevice The device this message was received from containing identifying information +--- @param value Int16 the value of the measured temperature +--- @param zb_rx containing the full message this report came in + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function added_handler(self, device) device:emit_event(capabilities.button.supportedButtonValues({"pushed","held","double"}, {visibility = { displayed = false }})) device:emit_event(capabilities.button.numberOfButtons({value = 1}, {visibility = { displayed = false }})) device:emit_event(capabilities.button.button.pushed({state_change = false})) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) end local zigbee_button_driver_template = { @@ -81,6 +124,10 @@ local zigbee_button_driver_template = { attr = { [IASZone.ID] = { [IASZone.attributes.ZoneStatus.ID] = ias_zone_status_attr_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } }, cluster = { diff --git a/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua b/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua index e9fe8c8724..894a579ea7 100644 --- a/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua +++ b/drivers/SmartThings/zigbee-button/src/test/test_ewelink_button.lua @@ -20,6 +20,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local OnOff = clusters.OnOff local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local button = capabilities.button @@ -64,6 +65,14 @@ test.register_coroutine_test( test.socket.capability:__expect_send( mock_device:generate_test_message("main", button.button.pushed({ state_change = false })) ) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) end ) diff --git a/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua b/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua index 9e986f097f..d6b8e744c3 100644 --- a/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua +++ b/drivers/SmartThings/zigbee-button/src/test/test_samjin_button.lua @@ -128,6 +128,14 @@ test.register_coroutine_test( attribute_id = "button", state = { value = "pushed" } } }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) -- test.socket.zigbee:__expect_send({ -- mock_device.id, -- PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) diff --git a/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua b/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua index 747e17241a..58cc4b83e6 100644 --- a/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua +++ b/drivers/SmartThings/zigbee-button/src/test/test_zigbee_button.lua @@ -17,6 +17,7 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IasEnrollResponseCode = require "st.zigbee.generated.zcl_clusters.IASZone.types.EnrollResponseCode" @@ -26,7 +27,7 @@ local ZoneStatusAttribute = IASZone.attributes.ZoneStatus local button_attr = capabilities.button.button local mock_device = test.mock_device.build_test_zigbee_device( - { profile = t_utils.get_profile_definition("button-profile.yml") } + { profile = t_utils.get_profile_definition("one-button-temp-battery.yml") } ) zigbee_test_utils.prepare_zigbee_env_info() local function test_init() @@ -159,6 +160,46 @@ test.register_message_test( } ) +test.register_message_test( + "Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_coroutine_test( "Health check should check all relevant attributes", function() @@ -182,6 +223,14 @@ test.register_coroutine_test( attribute_id = "button", state = { value = "pushed" } } }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) -- Battery has a max reporting interval of 21600 @@ -192,6 +241,10 @@ test.register_coroutine_test( PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) } ) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + }) end, { test_init = function() @@ -218,6 +271,12 @@ test.register_coroutine_test( IASZone.attributes.ZoneStatus:read(mock_device) } ) + test.socket.zigbee:__expect_send( + { + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + } + ) end ) @@ -237,6 +296,14 @@ test.register_coroutine_test( 1) } ) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:configure_reporting(mock_device, + 30, + 600, + 100) + } + ) test.socket.zigbee:__expect_send( { mock_device.id, @@ -245,6 +312,14 @@ test.register_coroutine_test( PowerConfiguration.ID) } ) + test.socket.zigbee:__expect_send( + { + mock_device.id, + zigbee_test_utils.build_bind_request(mock_device, + zigbee_test_utils.mock_hub_eui, + TemperatureMeasurement.ID) + } + ) test.socket.zigbee:__expect_send( { mock_device.id, @@ -263,6 +338,12 @@ test.register_coroutine_test( PowerConfiguration.attributes.BatteryPercentageRemaining:read(mock_device) } ) + test.socket.zigbee:__expect_send( + { + mock_device.id, + TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) + } + ) test.socket.zigbee:__expect_send( { mock_device.id, diff --git a/drivers/SmartThings/zigbee-contact/src/init.lua b/drivers/SmartThings/zigbee-contact/src/init.lua index 7a1dc6b237..6dbd542f41 100644 --- a/drivers/SmartThings/zigbee-contact/src/init.lua +++ b/drivers/SmartThings/zigbee-contact/src/init.lua @@ -16,9 +16,50 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local constants = require "st.zigbee.constants" local defaults = require "st.zigbee.defaults" +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement local configurationMap = require "configurations" local SMARTSENSE_MULTI_SENSOR_CUSTOM_PROFILE = 0xFC01 +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + +--- Default handler for Temperature min and max measured value on the Temperature measurement cluster +--- +--- This starts initially by performing the same conversion in the temperature_measurement_attr_handler function. +--- It then sets the field of whichever measured value is defined by the @param and checks if the fields +--- correctly compare +--- +--- @param minOrMax string the string that determines which attribute to set +--- @param driver Driver The current driver running containing necessary context for execution +--- @param device ZigbeeDevice The device this message was received from containing identifying information +--- @param value Int16 the value of the measured temperature +--- @param zb_rx containing the full message this report came in + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function device_init(driver, device) local configuration = configurationMap.get_device_configuration(device) if configuration ~= nil then @@ -29,6 +70,11 @@ local function device_init(driver, device) end end +local function added_handler(driver, device) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) +end + local zigbee_contact_driver_template = { supported_capabilities = { capabilities.contactSensor, @@ -37,11 +83,20 @@ local zigbee_contact_driver_template = { capabilities.threeAxis, capabilities.accelerationSensor }, + zigbee_handlers = { + attr = { + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, additional_zcl_profiles = { [SMARTSENSE_MULTI_SENSOR_CUSTOM_PROFILE] = true }, lifecycle_handlers = { - init = device_init + init = device_init, + added = added_handler, }, sub_drivers = { require("aqara"), diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua index 41e9ebce57..fa9667cd1d 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_aqara_contact_sensor.lua @@ -21,6 +21,7 @@ local data_types = require "st.zigbee.data_types" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -50,6 +51,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua index 1f36536d4e..40cc2c47be 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_aurora_contact_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua index bc139a0904..e05233ad48 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_contact_temperature_sensor.lua @@ -62,6 +62,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua b/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua index f254c108f9..a05f420166 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_ecolink_contact.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua index 3032ff3fc4..58c2c8d6b2 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_ewelink_heiman_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -60,6 +61,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua index db72c3a5c2..05c82b60b6 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_frient_sensor.lua @@ -62,6 +62,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua index dbf30b3d13..458af19546 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_orvibo_contact_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua b/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua index 623d55cce6..1950a22649 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_sengled_contact_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua b/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua index d0ddd9c6d9..07beb7c0dd 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_third_reality_contact.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua b/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua index 0c89cbb6aa..df1becb201 100644 --- a/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua +++ b/drivers/SmartThings/zigbee-contact/src/test/test_zigbee_contact.lua @@ -121,6 +121,29 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Battery percentage report should be handled", { @@ -142,6 +165,14 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) @@ -176,6 +207,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua index 0e19b78d02..cf1bb61b7c 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/init.lua @@ -15,8 +15,37 @@ local capabilities = require "st.capabilities" local ZigbeeDriver = require "st.zigbee" local defaults = require "st.zigbee.defaults" +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement local configurationMap = require "configurations" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function device_init(driver, device) local configuration = configurationMap.get_device_configuration(device) if configuration ~= nil then @@ -27,14 +56,28 @@ local function device_init(driver, device) end end +local function added_handler(driver, device) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) +end + local zigbee_humidity_driver = { supported_capabilities = { capabilities.battery, capabilities.relativeHumidityMeasurement, capabilities.temperatureMeasurement }, + zigbee_handlers = { + attr = { + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, lifecycle_handlers = { - init = device_init + init = device_init, + added = added_handler, }, sub_drivers = { require("aqara"), diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua index 3fa1b5719b..ca121baa9b 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature.lua @@ -52,6 +52,33 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Humidity report should be handled", { diff --git a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua index 1defdb1b71..7da190b523 100644 --- a/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua +++ b/drivers/SmartThings/zigbee-humidity-sensor/src/test/test_humidity_temperature_sensor.lua @@ -59,6 +59,33 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Humidity report should be handled", { diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/init.lua b/drivers/SmartThings/zigbee-motion-sensor/src/init.lua index 88e06eae68..5cc838177c 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/init.lua @@ -18,8 +18,48 @@ local defaults = require "st.zigbee.defaults" local constants = require "st.zigbee.constants" local zcl_clusters = require "st.zigbee.zcl.clusters" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local HAS_RECONFIGURED = "_has_reconfigured" +--- Default handler for Temperature min and max measured value on the Temperature measurement cluster +--- +--- This starts initially by performing the same conversion in the temperature_measurement_attr_handler function. +--- It then sets the field of whichever measured value is defined by the @param and checks if the fields +--- correctly compare +--- +--- @param minOrMax string the string that determines which attribute to set +--- @param driver Driver The current driver running containing necessary context for execution +--- @param device ZigbeeDevice The device this message was received from containing identifying information +--- @param value Int16 the value of the measured temperature +--- @param zb_rx containing the full message this report came in + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + -- TODO: Remove when available in lua libs -- This is a temporary method to lower battery consumption in several devices. -- Disparities were noted between DTH implementations and driver defaults. -sg @@ -38,6 +78,11 @@ local do_refresh = function(driver, device, command) end end +local added_handler = function(self, device) + device:send(zcl_clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(zcl_clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) +end + local zigbee_motion_driver = { supported_capabilities = { capabilities.motionSensor, @@ -47,11 +92,22 @@ local zigbee_motion_driver = { capabilities.presenceSensor, capabilities.contactSensor }, + zigbee_handlers = { + attr = { + [zcl_clusters.TemperatureMeasurement.ID] = { + [zcl_clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [zcl_clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, capability_handlers = { [capabilities.refresh.ID] = { [capabilities.refresh.commands.refresh.NAME] = do_refresh, } }, + lifecycle_handlers = { + added = added_handler + }, sub_drivers = { require("aqara"), require("aurora"), diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua index c68eb33ef9..520906cd8c 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_all_capabilities_zigbee_motion.lua @@ -117,6 +117,29 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Humidity report should be handled", { @@ -153,6 +176,8 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) }) + test.socket.zigbee:__expect_send({ mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) }) test.wait_for_events() test.mock_time.advance_time(50000) -- 21600 is the battery max interval @@ -175,6 +200,14 @@ test.register_coroutine_test( function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -253,6 +286,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua index 1b9676c9b6..da645dcc9f 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_sengled_motion.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -60,6 +61,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua index 922bc663c9..c0da6f813e 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_motion_iris.lua @@ -77,6 +77,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua index 4f063159be..c971d7d239 100644 --- a/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua +++ b/drivers/SmartThings/zigbee-motion-sensor/src/test/test_zigbee_plugin_motion_sensor.lua @@ -17,6 +17,7 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" --- @type st.zigbee.zcl.clusters.OccupancySensing local OccupancySensing = clusters.OccupancySensing +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local t_utils = require "integration_test.utils" @@ -86,6 +87,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-sound-sensor/src/init.lua b/drivers/SmartThings/zigbee-sound-sensor/src/init.lua index cf305ef133..fb972bd5b5 100644 --- a/drivers/SmartThings/zigbee-sound-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-sound-sensor/src/init.lua @@ -21,8 +21,14 @@ local zcl_clusters = require "st.zigbee.zcl.clusters" local PollControl = zcl_clusters.PollControl local IASZone = zcl_clusters.IASZone local PowerConfiguration = zcl_clusters.PowerConfiguration +local TemperatureMeasurement = zcl_clusters.TemperatureMeasurement local battery_defaults = require "st.zigbee.defaults.battery_defaults" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local CHECK_IN_INTERVAL = 6480 local LONG_POLL_INTERVAL = 1200 local SHORT_POLL_INTERVAL = 2 @@ -52,6 +58,29 @@ local ias_zone_status_change_handler = function(driver, device, zb_rx) generate_event_from_zone_status(driver, device, zb_rx.body.zcl_body.zone_status, zb_rx) end +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local do_configure = function(self, device) device_management.write_ias_cie_address(device, self.environment_info.hub_zigbee_eui) device:send(IASZone.server.commands.ZoneEnrollResponse(device, 0x00, 0x00)) -- ZoneEnroll Response should be called first in case of this device. @@ -67,6 +96,8 @@ end local added_handler = function(self, device) device:emit_event(capabilities.soundSensor.sound.not_detected()) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) end local zigbee_sound_sensor_driver_template = { @@ -79,6 +110,10 @@ local zigbee_sound_sensor_driver_template = { attr = { [IASZone.ID] = { [IASZone.attributes.ZoneStatus.ID] = ias_zone_status_attr_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } }, cluster = { diff --git a/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua b/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua index 90249669ba..673877b67c 100644 --- a/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua +++ b/drivers/SmartThings/zigbee-sound-sensor/src/test/test_zigbee_sound_sensor.lua @@ -139,6 +139,22 @@ test.register_message_test( direction = "send", message = mock_device:generate_test_message("main", capabilities.soundSensor.sound.not_detected()) }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", @@ -241,4 +257,41 @@ test.register_message_test( } ) +test.register_message_test( + "Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.run_registered_tests() diff --git a/drivers/SmartThings/zigbee-thermostat/src/init.lua b/drivers/SmartThings/zigbee-thermostat/src/init.lua index 6602c1c3db..da31da57d0 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/init.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/init.lua @@ -13,16 +13,17 @@ -- limitations under the License. -- Zigbee Driver utilities -local ZigbeeDriver = require "st.zigbee" -local device_management = require "st.zigbee.device_management" -local defaults = require "st.zigbee.defaults" -local utils = require "st.utils" +local ZigbeeDriver = require "st.zigbee" +local device_management = require "st.zigbee.device_management" +local defaults = require "st.zigbee.defaults" +local utils = require "st.utils" -- Zigbee Spec Utils local clusters = require "st.zigbee.zcl.clusters" local PowerConfiguration = clusters.PowerConfiguration local Thermostat = clusters.Thermostat local FanControl = clusters.FanControl +local TemperatureMeasurement = clusters.TemperatureMeasurement local FanMode = FanControl.attributes.FanMode local FanModeSequence = FanControl.attributes.FanModeSequence @@ -31,7 +32,7 @@ local ThermostatControlSequence = Thermostat.attributes.ControlSequenceOfOperati -- Capabilities local capabilities = require "st.capabilities" -local TemperatureMeasurement = capabilities.temperatureMeasurement +local Temperature = capabilities.temperatureMeasurement local ThermostatCoolingSetpoint = capabilities.thermostatCoolingSetpoint local ThermostatHeatingSetpoint = capabilities.thermostatHeatingSetpoint local ThermostatMode = capabilities.thermostatMode @@ -91,6 +92,12 @@ local SUPPORTED_THERMOSTAT_MODES = { ThermostatMode.thermostatMode.emergency_heat.NAME} } +-- TemperatureMeasurement cluster defaults +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local battery_voltage_handler = function(driver, device, battery_voltage) if (battery_voltage.value == 0) then -- this means we're plugged in device:emit_event(PowerSource.powerSource.mains()) @@ -197,6 +204,29 @@ local set_setpoint_factory = function(setpoint_attribute) end end +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local do_refresh = function(self, device) local attributes = { Thermostat.attributes.OccupiedCoolingSetpoint, @@ -223,12 +253,14 @@ local do_configure = function(self, device) end local device_added = function(self, device) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) do_refresh(self, device) end local zigbee_thermostat_driver = { supported_capabilities = { - TemperatureMeasurement, + Temperature, ThermostatCoolingSetpoint, ThermostatHeatingSetpoint, ThermostatMode, @@ -253,6 +285,10 @@ local zigbee_thermostat_driver = { [FanControl.ID] = { [FanControl.attributes.FanModeSequence.ID] = supported_fan_modes_handler, [FanControl.attributes.FanMode.ID] = thermostat_fan_mode_handler + }, + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } } }, diff --git a/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua b/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua index a02045a1a9..d80731888d 100644 --- a/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua +++ b/drivers/SmartThings/zigbee-thermostat/src/test/test_zigbee_thermostat.lua @@ -18,6 +18,7 @@ local clusters = require "st.zigbee.zcl.clusters" local PowerConfiguration = clusters.PowerConfiguration local Thermostat = clusters.Thermostat local FanControl = clusters.FanControl +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local t_utils = require "integration_test.utils" @@ -109,6 +110,43 @@ test.register_message_test( } ) +test.register_message_test( + "Temperature report should be handled (C) for the temperature cluster", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C) for the temperature cluster", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Heating setpoint reports are handled", { @@ -505,6 +543,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "zigbee", direction = "send", diff --git a/drivers/SmartThings/zigbee-vent/src/init.lua b/drivers/SmartThings/zigbee-vent/src/init.lua index bdd643d06f..0a5b7fb506 100644 --- a/drivers/SmartThings/zigbee-vent/src/init.lua +++ b/drivers/SmartThings/zigbee-vent/src/init.lua @@ -19,6 +19,11 @@ local defaults = require "st.zigbee.defaults" local clusters = require "st.zigbee.zcl.clusters" local cluster_base = require "st.zigbee.cluster_base" +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + local KEEN_PRESSURE_ATTRIBUTE = 0x0020 local KEEN_MFG_CODE = 0x115B @@ -58,10 +63,35 @@ local function switch_on_handler(driver, device, command) device:send(clusters.Level.commands.MoveToLevelWithOnOff(device, last_level, 0xFFFF)) end +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end + local function refresh_handler(driver, device, command) device:send(clusters.Level.attributes.CurrentLevel:read(device)) device:send(clusters.OnOff.attributes.OnOff:read(device)) device:send(clusters.TemperatureMeasurement.attributes.MeasuredValue:read(device)) + device:send(clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) + device:send(clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) device:send(clusters.PowerConfiguration.attributes.BatteryPercentageRemaining:read(device)) local pressure_read = cluster_base.read_manufacturer_specific_attribute(device, clusters.PressureMeasurement.ID, KEEN_PRESSURE_ATTRIBUTE, KEEN_MFG_CODE) @@ -102,6 +132,10 @@ local zigbee_vent_driver = { }, [clusters.Level.ID] = { [clusters.Level.attributes.CurrentLevel.ID] = level_report_handler + }, + [clusters.TemperatureMeasurement.ID] = { + [clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), } } }, diff --git a/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua b/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua index dcb1efcb7c..cedc74b9ec 100644 --- a/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua +++ b/drivers/SmartThings/zigbee-vent/src/test/test_zigbee_vent.lua @@ -17,6 +17,7 @@ local test = require "integration_test" local clusters = require "st.zigbee.zcl.clusters" local OnOff = clusters.OnOff local Level = clusters.Level +local TemperatureMeasurement = clusters.TemperatureMeasurement local capabilities = require "st.capabilities" local zigbee_test_utils = require "integration_test.zigbee_test_utils" local base64 = require "st.base64" @@ -112,6 +113,43 @@ test.register_coroutine_test( end ) +test.register_message_test( + "Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MeasuredValue:build_test_attr_report(mock_device, 2500) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperature({ value = 25.0, unit = "C"})) + } + } +) + +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "added lifecycle event should get initial state for device", { @@ -144,6 +182,22 @@ test.register_message_test( clusters.TemperatureMeasurement.attributes.MeasuredValue:read(mock_device) } }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + clusters.TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + clusters.TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, { channel = "zigbee", direction = "send", diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua index d7969a8e98..6ff290c337 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/init.lua @@ -18,6 +18,35 @@ local defaults = require "st.zigbee.defaults" local battery_defaults = require "st.zigbee.defaults.battery_defaults" local constants = require "st.zigbee.constants" local configurationMap = require "configurations" +local TemperatureMeasurement = (require "st.zigbee.zcl.clusters").TemperatureMeasurement + +local temperature_measurement_defaults = { + MIN_TEMP = "MIN_TEMP", + MAX_TEMP = "MAX_TEMP" +} + +local temperature_measurement_min_max_attr_handler = function(minOrMax) + return function(driver, device, value, zb_rx) + local raw_temp = value.value + local celc_temp = raw_temp / 100.0 + local temp_scale = "C" + + device:set_field(string.format("%s", minOrMax), celc_temp) + + local min = device:get_field(temperature_measurement_defaults.MIN_TEMP) + local max = device:get_field(temperature_measurement_defaults.MAX_TEMP) + + if min ~= nil and max ~= nil then + if min < max then + device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = temp_scale })) + device:set_field(temperature_measurement_defaults.MIN_TEMP, nil) + device:set_field(temperature_measurement_defaults.MAX_TEMP, nil) + else + device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max)) + end + end + end +end local function device_init(driver, device) local configuration = configurationMap.get_device_configuration(device) @@ -36,6 +65,11 @@ local function device_init(driver, device) end end +local function added_handler(self, device) + device:send(TemperatureMeasurement.attributes.MaxMeasuredValue:read(device)) + device:send(TemperatureMeasurement.attributes.MinMeasuredValue:read(device)) +end + local zigbee_water_driver_template = { supported_capabilities = { capabilities.waterSensor, @@ -43,8 +77,17 @@ local zigbee_water_driver_template = { capabilities.temperatureMeasurement, capabilities.battery, }, + zigbee_handlers = { + attr = { + [TemperatureMeasurement.ID] = { + [TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MIN_TEMP), + [TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temperature_measurement_min_max_attr_handler(temperature_measurement_defaults.MAX_TEMP), + } + } + }, lifecycle_handlers = { - init = device_init + init = device_init, + added = added_handler }, ias_zone_configuration_method = constants.IAS_ZONE_CONFIGURE_TYPE.AUTO_ENROLL_RESPONSE, sub_drivers = { diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua index 30258012d4..dec30eed40 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_centralite_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua index 4cae9883ca..a2fc7c3b45 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_frient_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua index 352841bdd4..05224a53fc 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_samjin_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua index e1e57db4fc..d4ad7bccff 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sengled_water_leak_sensor.lua @@ -19,6 +19,7 @@ local zigbee_test_utils = require "integration_test.zigbee_test_utils" local IASZone = clusters.IASZone local PowerConfiguration = clusters.PowerConfiguration +local TemperatureMeasurement = clusters.TemperatureMeasurement local IASCIEAddress = IASZone.attributes.IASCIEAddress local EnrollResponseCode = IASZone.types.EnrollResponseCode @@ -59,6 +60,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua index 33f6c28f24..3309db23f5 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_sinope_zigbee_water.lua @@ -161,6 +161,14 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) -- battery is 21600 for max reporting interval @@ -197,6 +205,14 @@ test.register_coroutine_test( function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -289,6 +305,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua index 5cf7801637..d3e624c29b 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_smartthings_water_leak_sensor.lua @@ -63,6 +63,14 @@ test.register_coroutine_test( "Configure should configure all necessary attributes", function() test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.socket.zigbee:__set_channel_ordering("relaxed") diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua index b202dd450c..c5f93506cf 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water.lua @@ -115,6 +115,33 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) + } + }, + { + channel = "zigbee", + direction = "receive", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) + } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_message_test( "Battery percentage report should be handled", { @@ -135,6 +162,14 @@ test.register_coroutine_test( "Health check should check all relevant attributes", function() test.socket.device_lifecycle:__queue_receive({mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.wait_for_events() test.mock_time.advance_time(50000) -- battery is 21600 for max reporting interval @@ -171,6 +206,14 @@ test.register_coroutine_test( function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -263,6 +306,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", diff --git a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua index ed03d10974..73f97cfcd4 100644 --- a/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua +++ b/drivers/SmartThings/zigbee-water-leak-sensor/src/test/test_zigbee_water_freeze.lua @@ -88,11 +88,40 @@ test.register_message_test( } ) +test.register_message_test( + "Minimum & Maximum Temperature report should be handled (C)", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MinMeasuredValue:build_test_attr_report(mock_device, 2000) } + }, + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, TemperatureMeasurement.attributes.MaxMeasuredValue:build_test_attr_report(mock_device, 3000) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = 20.00, maximum = 30.00 }, unit = "C" })) + } + } +) + test.register_coroutine_test( "Configure should configure all necessary attributes", function () test.socket.zigbee:__set_channel_ordering("relaxed") test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added"}) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + }) + test.socket.zigbee:__expect_send({ + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + }) test.socket.device_lifecycle:__queue_receive({ mock_device.id, "doConfigure"}) test.socket.zigbee:__expect_send({ mock_device.id, @@ -209,6 +238,22 @@ test.register_message_test( direction = "receive", message = {mock_device.id, "added"} }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MaxMeasuredValue:read(mock_device) + } + }, + { + channel = "zigbee", + direction = "send", + message = { + mock_device.id, + TemperatureMeasurement.attributes.MinMeasuredValue:read(mock_device) + } + }, { channel = "capability", direction = "receive", From 552722f66c0ef657cc31c2f634cd31cde8829aba Mon Sep 17 00:00:00 2001 From: Cooper Towns Date: Mon, 15 Jul 2024 09:53:52 -0500 Subject: [PATCH 07/18] Matter Switch: Add Nanoleaf Essentials Wifi Bulb fingerprint (#1504) --- .../matter-switch/fingerprints.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 38aa5d4c90..f4b86966ad 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -4,8 +4,8 @@ matterManufacturer: deviceLabel: THIRDREALITY Night Light vendorId: 0x1407 productId: 0x1088 - deviceProfileName: light-color-level-illuminance-motion-1000K-15000K - + deviceProfileName: light-color-level-illuminance-motion-1000K-15000K + #Eve - id: "Eve/Energy/US" deviceLabel: Eve Energy @@ -46,7 +46,7 @@ matterManufacturer: deviceLabel: Eve Light Switch vendorId: 0x130A productId: 0x005D - deviceProfileName: switch-binary + deviceProfileName: switch-binary #GE - id: "4921/177" @@ -73,7 +73,7 @@ matterManufacturer: deviceLabel: Cync Full Color 6 Inch Wafer vendorId: 0x1339 productId: 0x00AF - deviceProfileName: light-color-level-2000K-7000K + deviceProfileName: light-color-level-2000K-7000K - id: "4921/181" deviceLabel: Cync 6 Inch High Ceiling Wafer vendorId: 0x1339 @@ -133,12 +133,12 @@ matterManufacturer: deviceLabel: Cync Indoor Light Strip 16ft vendorId: 0x1339 productId: 0x006E - deviceProfileName: light-color-level-2000K-7000K + deviceProfileName: light-color-level-2000K-7000K - id: "4921/123" deviceLabel: Cync Indoor Light Strip 32ft vendorId: 0x1339 productId: 0x007B - deviceProfileName: light-color-level-2000K-7000K + deviceProfileName: light-color-level-2000K-7000K - id: "4921/111" deviceLabel: Cync Outdoor Plug vendorId: 0x1339 @@ -236,7 +236,12 @@ matterManufacturer: deviceLabel: Smart Holiday String Lights vendorId: 0x115A productId: 0x0047 - deviceProfileName: light-color-level-2700K-6500K + deviceProfileName: light-color-level-2700K-6500K + - id: "4442/75" + deviceLabel: Essentials Wifi A19-A60 Smart Bulb + vendorId: 0x115A + productId: 0x004B + deviceProfileName: light-color-level-2700K-6500K #SONOFF - id: "SONOFF MINIR4M" deviceLabel: Smart Plug-in Unit From 36ee8e21167424631a1f316c922402f81b302285 Mon Sep 17 00:00:00 2001 From: Cooper Towns Date: Mon, 15 Jul 2024 09:55:04 -0500 Subject: [PATCH 08/18] Matter Switch: new device Linkind Smart Light Bulb A21 RGBTW 1600lm (#1512) * Matter Switch: new device Linkind Smart Light Bulb A21 RGBTW 1600lm * add quotes around fingerprint id --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index f4b86966ad..12695571e8 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -322,6 +322,11 @@ matterManufacturer: vendorId: 0x1168 productId: 0x03F3 deviceProfileName: light-color-level-1800K-6500K + - id: "4456/1013" + deviceLabel: Matter Smart Light Bulb A21 RGBTW 1600lm + vendorId: 0x1168 + productId: 0x03F5 + deviceProfileName: light-color-level-1800K-6500K #WiZ - id: "WiZ A19" deviceLabel: WiZ A19 From fcd5083ddfc8934ec49b9f82ed703eb757d45719 Mon Sep 17 00:00:00 2001 From: zhongpei Ge <965159334@qq.com> Date: Mon, 15 Jul 2024 23:13:39 +0800 Subject: [PATCH 09/18] Add LeTianPai Presence Sensor Box (#1463) --- .../matter-sensor/fingerprints.yml | 6 +++++ ...otion-illuminance-temperature-humidity.yml | 23 +++++++++++++++++++ tools/localizations/cn.csv | 1 + 3 files changed, 30 insertions(+) create mode 100644 drivers/SmartThings/matter-sensor/profiles/motion-illuminance-temperature-humidity.yml diff --git a/drivers/SmartThings/matter-sensor/fingerprints.yml b/drivers/SmartThings/matter-sensor/fingerprints.yml index df21ef4c5f..5dc6c97089 100644 --- a/drivers/SmartThings/matter-sensor/fingerprints.yml +++ b/drivers/SmartThings/matter-sensor/fingerprints.yml @@ -54,6 +54,12 @@ matterManufacturer: vendorId: 0x141E productId: 0x0002 deviceProfileName: contact-battery + # LeTianpai + - id: "LeTianPai/Motion" + deviceLabel: LeTianPai Presence Sensor Box + vendorId: 0x142B + productId: 0x0002 + deviceProfileName: motion-illuminance-temperature-humidity matterGeneric: - id: "matter/contact/sensor" deviceLabel: Matter Contact Sensor diff --git a/drivers/SmartThings/matter-sensor/profiles/motion-illuminance-temperature-humidity.yml b/drivers/SmartThings/matter-sensor/profiles/motion-illuminance-temperature-humidity.yml new file mode 100644 index 0000000000..8ec14888a0 --- /dev/null +++ b/drivers/SmartThings/matter-sensor/profiles/motion-illuminance-temperature-humidity.yml @@ -0,0 +1,23 @@ +name: motion-illuminance-temperature-humidity +components: +- id: main + capabilities: + - id: motionSensor + version: 1 + - id: temperatureMeasurement + version: 1 + - id: relativeHumidityMeasurement + version: 1 + - id: illuminanceMeasurement + version: 1 + - id: firmwareUpdate + version: 1 + - id: refresh + version: 1 + categories: + - name: MotionSensor +preferences: + - preferenceId: tempOffset + explicit: true + - preferenceId: humidityOffset + explicit: true diff --git a/tools/localizations/cn.csv b/tools/localizations/cn.csv index 3000d765e1..093899a645 100644 --- a/tools/localizations/cn.csv +++ b/tools/localizations/cn.csv @@ -63,3 +63,4 @@ Aqara Wireless Mini Switch T1,Aqara 无线开关 T1 "Aqara Smart Wall Switch H1 EU (No Neutral, Double Rocker)",Aqara智能墙壁开关H1 EU (单火线双键版) "Aqara Single Switch Module T1 (No Neutral)",Aqara 单路控制器T1 (单火线版) "TOTEM Door Lock",TOTEM智能门锁 +"LeTianPai Presence Sensor Box",乐天派存在传感器Box \ No newline at end of file From 58c4755193670403e39ef92a143f5df0e21995a9 Mon Sep 17 00:00:00 2001 From: lelandblue <79465613+lelandblue@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:49:54 -0400 Subject: [PATCH 10/18] new-device-Cync-Full-Color-Deco (#1522) --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 12695571e8..1160a3e235 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -144,6 +144,11 @@ matterManufacturer: vendorId: 0x1339 productId: 0x006F deviceProfileName: plug-binary + - id: "4921/101" + deviceLabel: Cync Full Color Deco Candle Base + vendorId: 0x1339 + productId: 0x0065 + deviceProfileName: light-color-level-2000K-7000K #Legrand - id: "4129/3" deviceLabel: Smart Lights Smart Plug From 7b941ac7c01e0ae73796e810605070047c6f5d73 Mon Sep 17 00:00:00 2001 From: lelandblue <79465613+lelandblue@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:24:21 -0400 Subject: [PATCH 11/18] new-device-AiDot-Orein- OS0100411267 --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 1160a3e235..56d054b9d1 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -332,6 +332,11 @@ matterManufacturer: vendorId: 0x1168 productId: 0x03F5 deviceProfileName: light-color-level-1800K-6500K + - id: "4456/1007" + deviceLabel: Matter Smart Light Bulb A21 RGBTW 1600lm + vendorId: 0x1168 + productId: 0x03EF + deviceProfileName: light-color-level-1800K-6500K #WiZ - id: "WiZ A19" deviceLabel: WiZ A19 From 6bdc31a9f23c778fcd898fd2a10e95e9d9041655 Mon Sep 17 00:00:00 2001 From: lelandblue <79465613+lelandblue@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:09:16 -0400 Subject: [PATCH 12/18] Adding additional Fingerprint for Linkind device --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 56d054b9d1..8088e5d7ab 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -337,6 +337,11 @@ matterManufacturer: vendorId: 0x1168 productId: 0x03EF deviceProfileName: light-color-level-1800K-6500K + - id: "4456/1005" + deviceLabel: Matter Smart Light Bulb A19 RGBTW 1100lm + vendorId: 0x1168 + productId: 0x03ED + deviceProfileName: light-color-level-1800K-6500K #WiZ - id: "WiZ A19" deviceLabel: WiZ A19 From eda38f9b087210a9d551bf38238f6c6c8671e535 Mon Sep 17 00:00:00 2001 From: lelandblue <79465613+lelandblue@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:13:50 -0400 Subject: [PATCH 13/18] Adding additional fingerprint for the Oriein OS01006110 --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 8088e5d7ab..2f261cda00 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -342,6 +342,11 @@ matterManufacturer: vendorId: 0x1168 productId: 0x03ED deviceProfileName: light-color-level-1800K-6500K + - id: 4456/1006 + deviceLabel: Matter Smart Light Bulb A19 RGBTW 1100lm + vendorId: 0x1168 + productId: 0x03EE + deviceProfileName: light-color-level-1800K-6500K #WiZ - id: "WiZ A19" deviceLabel: WiZ A19 From 17db8e130692de0fed12d99574f6e9523125aa1e Mon Sep 17 00:00:00 2001 From: Cooper Towns Date: Thu, 11 Jul 2024 17:19:00 -0500 Subject: [PATCH 14/18] Matter Switch: new fingerprint for Cync Full Color A19 --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 2f261cda00..b7b930dcdf 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -144,6 +144,11 @@ matterManufacturer: vendorId: 0x1339 productId: 0x006F deviceProfileName: plug-binary + - id: "4921/21" + deviceLabel: Cync Full Color A19 + vendorId: 0x1339 + productId: 0x0015 + deviceProfileName: light-color-level-2000K-7000K - id: "4921/101" deviceLabel: Cync Full Color Deco Candle Base vendorId: 0x1339 From 2d76ad5b9a6847e29b3d2c4cf15d9e54df78e2c4 Mon Sep 17 00:00:00 2001 From: Alissa Dornbos <79465613+lelandblue@users.noreply.github.com> Date: Thu, 18 Jul 2024 09:56:27 -0400 Subject: [PATCH 15/18] new-devices-for-Cync-and-Winees --- .../SmartThings/matter-switch/fingerprints.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index b7b930dcdf..b3316a0011 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -154,6 +154,16 @@ matterManufacturer: vendorId: 0x1339 productId: 0x0065 deviceProfileName: light-color-level-2000K-7000K + - id: "4921/105" + deviceLabel: Cync Full Color A21 + vendorId: 0x1339 + productId: 0x0069 + deviceProfileName: light-color-level-2000K-7000K + - id: "4921/173" + deviceLabel: Cync Full Color BR30 + vendorId: 0x1339 + productId: 0x00AD + deviceProfileName: light-color-level-2000K-7000K #Legrand - id: "4129/3" deviceLabel: Smart Lights Smart Plug @@ -352,6 +362,11 @@ matterManufacturer: vendorId: 0x1168 productId: 0x03EE deviceProfileName: light-color-level-1800K-6500K + - id: "4456/1102" + deviceLabel: Matter Smart Plug + vendorId: 0x1168 + productId: 0x044E + deviceProfileName: plug-binary #WiZ - id: "WiZ A19" deviceLabel: WiZ A19 From 74020e067de63e891be203ec1224089d8f62eeb0 Mon Sep 17 00:00:00 2001 From: Alissa Dornbos <79465613+lelandblue@users.noreply.github.com> Date: Fri, 19 Jul 2024 08:57:04 -0400 Subject: [PATCH 16/18] Adding additional Fingerprint for Additional PR to add another recently opened WWST CERT request for a Cync Full Color A19, ModelNumber: CLEDA199CD1MS. vendorId: 0x1339 productId: 0x0015 I could not confirm the Matter Device Type ID --- drivers/SmartThings/matter-switch/fingerprints.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index b3316a0011..6a2d51eb8b 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -164,6 +164,11 @@ matterManufacturer: vendorId: 0x1339 productId: 0x00AD deviceProfileName: light-color-level-2000K-7000K + - id: 4921/21 + deviceLabel: Cync Full Color A19 + vendorId: 0x1339 + productId: 0x0015 + deviceProfileName: light-color-level-2000K-7000K #Legrand - id: "4129/3" deviceLabel: Smart Lights Smart Plug From 3b9d10d22ab990c033d03be6051d534eab14e58b Mon Sep 17 00:00:00 2001 From: Alissa Dornbos <79465613+lelandblue@users.noreply.github.com> Date: Fri, 19 Jul 2024 09:50:44 -0400 Subject: [PATCH 17/18] Fix a bad commit Removed a dupe fingerprint and added the following fingerprint. - id: 4921/107 deviceLabel: Cync Reveal Full Color A19 vendorId: 0x1339 productId: 0x006B deviceProfileName: light-color-level-2000K-7000K --- drivers/SmartThings/matter-switch/fingerprints.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 6a2d51eb8b..8780b10a41 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -164,11 +164,11 @@ matterManufacturer: vendorId: 0x1339 productId: 0x00AD deviceProfileName: light-color-level-2000K-7000K - - id: 4921/21 - deviceLabel: Cync Full Color A19 + - id: 4921/107 + deviceLabel: Cync Reveal Full Color A19 vendorId: 0x1339 - productId: 0x0015 - deviceProfileName: light-color-level-2000K-7000K + productId: 0x006B + deviceProfileName: light-color-level-2000K-7000K #Legrand - id: "4129/3" deviceLabel: Smart Lights Smart Plug From 545862c341fd0c71e490a11eede09bfc95471c8c Mon Sep 17 00:00:00 2001 From: Alissa Dornbos <79465613+lelandblue@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:14:35 -0400 Subject: [PATCH 18/18] Adding missed quotes around product ID --- drivers/SmartThings/matter-switch/fingerprints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/SmartThings/matter-switch/fingerprints.yml b/drivers/SmartThings/matter-switch/fingerprints.yml index 8780b10a41..926fbf5b53 100644 --- a/drivers/SmartThings/matter-switch/fingerprints.yml +++ b/drivers/SmartThings/matter-switch/fingerprints.yml @@ -164,7 +164,7 @@ matterManufacturer: vendorId: 0x1339 productId: 0x00AD deviceProfileName: light-color-level-2000K-7000K - - id: 4921/107 + - id: "4921/107" deviceLabel: Cync Reveal Full Color A19 vendorId: 0x1339 productId: 0x006B