From 7542e4b46209f57f337e79b716e58929f41e2bb1 Mon Sep 17 00:00:00 2001 From: Steven Green Date: Fri, 26 Jul 2024 14:18:59 -0700 Subject: [PATCH 1/5] CHAD-13655 Add emulated reset implementation This emulated reset behavior is defined in the defaults, but some sub-drivers overwrote the defaults without including it. --- .../zigbee-power-meter/src/ezex/init.lua | 6 ++-- .../zigbee-switch/src/aqara/init.lua | 18 ++++++----- .../zigbee-switch/src/aqara/version/init.lua | 9 +++++- .../zigbee-switch/src/ezex/init.lua | 31 ++++--------------- .../zigbee-switch/src/robb/init.lua | 27 ++++++---------- .../test/test_robb_smarrt_2-wire_dimmer.lua | 17 ++++++++++ .../init.lua | 7 ++--- 7 files changed, 55 insertions(+), 60 deletions(-) diff --git a/drivers/SmartThings/zigbee-power-meter/src/ezex/init.lua b/drivers/SmartThings/zigbee-power-meter/src/ezex/init.lua index 0792abec16..0b85da97c7 100644 --- a/drivers/SmartThings/zigbee-power-meter/src/ezex/init.lua +++ b/drivers/SmartThings/zigbee-power-meter/src/ezex/init.lua @@ -16,6 +16,7 @@ local capabilities = require "st.capabilities" local constants = require "st.zigbee.constants" local clusters = require "st.zigbee.zcl.clusters" local SimpleMetering = clusters.SimpleMetering +local energy_meter_defaults = require "st.zigbee.defaults.energyMeter_defaults" local ZIGBEE_POWER_METER_FINGERPRINTS = { { model = "E240-KR080Z0-HA" } @@ -63,10 +64,7 @@ local function energy_meter_handler(driver, device, value, zb_rx) end device:emit_event(capabilities.powerConsumptionReport.powerConsumption({energy = raw_value_watts, deltaEnergy = delta_energy })) -- the unit of these values should be 'Wh' - local multiplier = device:get_field(constants.SIMPLE_METERING_MULTIPLIER_KEY) or 1 - local divisor = device:get_field(constants.SIMPLE_METERING_DIVISOR_KEY) or 1000000 - local converted_value = raw_value_miliwatts * multiplier/divisor -- unit: kWh - device:emit_event(capabilities.energyMeter.energy({value = converted_value, unit = "kWh"})) + energy_meter_defaults.energy_meter_handler(driver, device, value, zb_rx) end local ezex_power_meter_handler = { diff --git a/drivers/SmartThings/zigbee-switch/src/aqara/init.lua b/drivers/SmartThings/zigbee-switch/src/aqara/init.lua index d833c510c3..09464322b5 100644 --- a/drivers/SmartThings/zigbee-switch/src/aqara/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/aqara/init.lua @@ -162,9 +162,16 @@ local function wireless_switch_handler(driver, device, value, zb_rx) end end -local function energy_meter_power_consumption_report(device, raw_value) +local function energy_meter_power_consumption_report(driver, device, value, zb_rx) + local raw_value = value.value -- energy meter - device:emit_event(capabilities.energyMeter.energy({ value = raw_value, unit = "Wh" })) + local offset = device:get_field(constants.ENERGY_METER_OFFSET) or 0 + if raw_value < offset then + --- somehow our value has gone below the offset, so we'll reset the offset, since the device seems to have + offset = 0 + device:set_field(constants.ENERGY_METER_OFFSET, offset, {persist = true}) + end + device:emit_event(capabilities.energyMeter.energy({ value = raw_value - offset, unit = "Wh" })) -- report interval local current_time = os.time() @@ -191,11 +198,6 @@ local function power_meter_handler(driver, device, value, zb_rx) device:emit_event(capabilities.powerMeter.power({ value = raw_value, unit = "W" })) end -local function energy_meter_handler(driver, device, value, zb_rx) - local raw_value = value.value -- 'Wh' - energy_meter_power_consumption_report(device, raw_value) -end - local function do_refresh(self, device) device:send(OnOff.attributes.OnOff:read(device)) if (device:supports_capability_by_id(capabilities.powerMeter.ID)) then @@ -255,7 +257,7 @@ local aqara_switch_handler = { [ElectricalMeasurement.attributes.ActivePower.ID] = power_meter_handler }, [SimpleMetering.ID] = { - [SimpleMetering.attributes.CurrentSummationDelivered.ID] = energy_meter_handler + [SimpleMetering.attributes.CurrentSummationDelivered.ID] = energy_meter_power_consumption_report }, [WIRELESS_SWITCH_CLUSTER_ID] = { [WIRELESS_SWITCH_ATTRIBUTE_ID] = wireless_switch_handler diff --git a/drivers/SmartThings/zigbee-switch/src/aqara/version/init.lua b/drivers/SmartThings/zigbee-switch/src/aqara/version/init.lua index 1e80c23ea0..d3611738d3 100644 --- a/drivers/SmartThings/zigbee-switch/src/aqara/version/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/aqara/version/init.lua @@ -1,5 +1,6 @@ local capabilities = require "st.capabilities" local clusters = require "st.zigbee.zcl.clusters" +local constants = require "st.zigbee.constants" local OnOff = clusters.OnOff local AnalogInput = clusters.AnalogInput @@ -22,7 +23,13 @@ end local function energy_meter_power_consumption_report(device, raw_value) -- energy meter - device:emit_event(capabilities.energyMeter.energy({ value = raw_value, unit = "Wh" })) + local offset = device:get_field(constants.ENERGY_METER_OFFSET) or 0 + if raw_value < offset then + --- somehow our value has gone below the offset, so we'll reset the offset, since the device seems to have + offset = 0 + device:set_field(constants.ENERGY_METER_OFFSET, offset, {persist = true}) + end + device:emit_event(capabilities.energyMeter.energy({ value = raw_value - offset, unit = "Wh" })) -- report interval local current_time = os.time() diff --git a/drivers/SmartThings/zigbee-switch/src/ezex/init.lua b/drivers/SmartThings/zigbee-switch/src/ezex/init.lua index 29ed8c8778..406d51ccd7 100644 --- a/drivers/SmartThings/zigbee-switch/src/ezex/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/ezex/init.lua @@ -12,11 +12,7 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -local zcl_clusters = require "st.zigbee.zcl.clusters" -local capabilities = require "st.capabilities" - -local SimpleMetering = zcl_clusters.SimpleMetering -local ElectricalMeasurement = zcl_clusters.ElectricalMeasurement +local zigbee_constants = require "st.zigbee.constants" local ZIGBEE_METERING_SWITCH_FINGERPRINTS = { { model = "E240-KR116Z-HA" } @@ -33,30 +29,15 @@ local is_zigbee_ezex_switch = function(opts, driver, device) return false end -local function energy_meter_handler(driver, device, value, zb_rx) - local raw_value = value.value - raw_value = raw_value / 1000000 - device:emit_event(capabilities.energyMeter.energy({value = raw_value, unit = "kWh" })) -end - -local function power_meter_handler(driver, device, value, zb_rx) - local raw_value = value.value - raw_value = raw_value / 1000 - device:emit_event(capabilities.powerMeter.power({value = raw_value, unit = "W" })) +local do_init = function(self, device) + device:set_field(zigbee_constants.SIMPLE_METERING_DIVISOR_KEY, 1000000, {persist = true}) + device:set_field(zigbee_constants.ELECTRICAL_MEASUREMENT_DIVISOR_KEY, 1000, {persist = true}) end local ezex_switch_handler = { NAME = "ezex switch handler", - zigbee_handlers = { - attr = { - [SimpleMetering.ID] = { - [SimpleMetering.attributes.InstantaneousDemand.ID] = power_meter_handler, - [SimpleMetering.attributes.CurrentSummationDelivered.ID] = energy_meter_handler - }, - [ElectricalMeasurement.ID] = { - [ElectricalMeasurement.attributes.ActivePower.ID] = power_meter_handler - } - } + lifecycle_handlers = { + init = do_init }, can_handle = is_zigbee_ezex_switch } diff --git a/drivers/SmartThings/zigbee-switch/src/robb/init.lua b/drivers/SmartThings/zigbee-switch/src/robb/init.lua index 8aaf62f69e..c00488ee30 100644 --- a/drivers/SmartThings/zigbee-switch/src/robb/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/robb/init.lua @@ -12,13 +12,10 @@ -- See the License for the specific language governing permissions and -- limitations under the License. +local constants = require "st.zigbee.constants" local zcl_clusters = require "st.zigbee.zcl.clusters" local capabilities = require "st.capabilities" - -local constants = require "st.zigbee.constants" - local SimpleMetering = zcl_clusters.SimpleMetering -local ElectricalMeasurement = zcl_clusters.ElectricalMeasurement local ROBB_DIMMER_FINGERPRINTS = { { mfr = "ROBB smarrt", model = "ROB_200-011-0" }, @@ -35,19 +32,16 @@ local function is_robb_dimmer(opts, driver, device) return false end -local function energy_meter_handler(driver, device, value, zb_rx) - local raw_value = value.value - local multiplier = device:get_field(constants.SIMPLE_METERING_MULTIPLIER_KEY) or 1 - local divisor = device:get_field(constants.SIMPLE_METERING_DIVISOR_KEY) or 1000000 - - raw_value = raw_value * multiplier / divisor - device:emit_event(capabilities.energyMeter.energy({ value = raw_value, unit = "kWh" })) +local do_init = function(driver, device) + device:set_field(constants.SIMPLE_METERING_DIVISOR_KEY, 1000000, {persist = true}) + device:set_field(constants.ELECTRICAL_MEASUREMENT_DIVISOR_KEY, 10, {persist = true}) end + local function power_meter_handler(driver, device, value, zb_rx) local raw_value = value.value local multiplier = device:get_field(constants.ELECTRICAL_MEASUREMENT_MULTIPLIER_KEY) or 1 - local divisor = device:get_field(constants.ELECTRICAL_MEASUREMENT_DIVISOR_KEY) or 10 + local divisor = 10 raw_value = raw_value * multiplier / divisor device:emit_event(capabilities.powerMeter.power({ value = raw_value, unit = "W" })) @@ -58,14 +52,13 @@ local robb_dimmer_handler = { zigbee_handlers = { attr = { [SimpleMetering.ID] = { - [SimpleMetering.attributes.InstantaneousDemand.ID] = power_meter_handler, - [SimpleMetering.attributes.CurrentSummationDelivered.ID] = energy_meter_handler - }, - [ElectricalMeasurement.ID] = { - [ElectricalMeasurement.attributes.ActivePower.ID] = power_meter_handler + [SimpleMetering.attributes.InstantaneousDemand.ID] = power_meter_handler } } }, + lifecycle_handlers = { + init = do_init + }, can_handle = is_robb_dimmer } diff --git a/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua b/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua index 39f8a49f74..fa099fb1ef 100644 --- a/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua +++ b/drivers/SmartThings/zigbee-switch/src/test/test_robb_smarrt_2-wire_dimmer.lua @@ -94,6 +94,23 @@ test.register_message_test( } ) +test.register_message_test( + "Handle Power meter", + { + { + channel = "zigbee", + direction = "receive", + message = { mock_device.id, + SimpleMetering.attributes.InstantaneousDemand:build_test_attr_report(mock_device, 90) } + }, + { + channel = "capability", + direction = "send", + message = mock_device:generate_test_message("main", capabilities.powerMeter.power({ value = 9.0, unit = "W" })) + } + } +) + test.register_message_test( "Handle Energy meter", { diff --git a/drivers/SmartThings/zigbee-switch/src/zigbee-metering-plug-power-consumption-report/init.lua b/drivers/SmartThings/zigbee-switch/src/zigbee-metering-plug-power-consumption-report/init.lua index 45ff40d958..4234fd36ab 100644 --- a/drivers/SmartThings/zigbee-switch/src/zigbee-metering-plug-power-consumption-report/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/zigbee-metering-plug-power-consumption-report/init.lua @@ -14,16 +14,13 @@ local clusters = require "st.zigbee.zcl.clusters" local capabilities = require "st.capabilities" -local constants = require "st.zigbee.constants" local zigbee_constants = require "st.zigbee.constants" +local energy_meter_defaults = require "st.zigbee.defaults.energyMeter_defaults" local SimpleMetering = clusters.SimpleMetering local function energy_meter_handler(driver, device, value, zb_rx) local raw_value = value.value - local multiplier = device:get_field(constants.SIMPLE_METERING_MULTIPLIER_KEY) or 1 - local divisor = device:get_field(constants.SIMPLE_METERING_DIVISOR_KEY) or 1000 - local converted_value = raw_value * multiplier/divisor local delta_energy = 0.0 local current_power_consumption = device:get_latest_state("main", capabilities.powerConsumptionReport.ID, capabilities.powerConsumptionReport.powerConsumption.NAME) @@ -32,7 +29,7 @@ local function energy_meter_handler(driver, device, value, zb_rx) end device:emit_event(capabilities.powerConsumptionReport.powerConsumption({energy = raw_value, deltaEnergy = delta_energy })) -- the unit of these values should be 'Wh' - device:emit_event(capabilities.energyMeter.energy({value = converted_value, unit = "kWh"})) + energy_meter_defaults.energy_meter_handler(driver, device, value, zb_rx) end local do_configure = function(self, device) From 4e5aef576e26d0351a8cce5a599fb9110c2babdb Mon Sep 17 00:00:00 2001 From: HunsupJung <59987061+HunsupJung@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:11:24 +0900 Subject: [PATCH 2/5] Add device configuration for supporting Routine (#1458) Signed-off-by: Hunsup Jung --- .../matter-appliance/profiles/dishwasher-tn-tl.yml | 7 +++---- .../matter-appliance/profiles/dishwasher-tn.yml | 7 +++---- .../matter-appliance/profiles/dishwasher.yml | 3 +++ .../matter-appliance/profiles/laundry-washer-tl.yml | 3 +++ .../profiles/laundry-washer-tn-tl.yml | 7 +++---- .../matter-appliance/profiles/laundry-washer-tn.yml | 7 +++---- .../matter-appliance/profiles/laundry-washer.yml | 3 +++ .../profiles/refrigerator-freezer-tl.yml | 3 +++ .../profiles/refrigerator-freezer-tn-tl.yml | 7 +++---- .../profiles/refrigerator-freezer-tn.yml | 11 +++-------- .../profiles/refrigerator-freezer.yml | 11 +++-------- drivers/SmartThings/matter-rvc/profiles/rvc.yml | 3 +++ drivers/SmartThings/matter-rvc/src/init.lua | 11 ++++++++--- 13 files changed, 44 insertions(+), 39 deletions(-) diff --git a/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn-tl.yml b/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn-tl.yml index 0cbbb5ae54..de82f0cd79 100644 --- a/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn-tl.yml +++ b/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn-tl.yml @@ -6,10 +6,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: temperatureLevel version: 1 - id: mode @@ -28,3 +24,6 @@ components: version: 1 categories: - name: Dishwasher +metadata: + mnmn: SmartThingsEdge + vid: generic-dishwasher diff --git a/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn.yml b/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn.yml index 5d8deadbfa..bf94068115 100644 --- a/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn.yml +++ b/drivers/SmartThings/matter-appliance/profiles/dishwasher-tn.yml @@ -6,10 +6,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: mode version: 1 - id: waterFlowAlarm @@ -26,3 +22,6 @@ components: version: 1 categories: - name: Dishwasher +metadata: + mnmn: SmartThingsEdge + vid: generic-dishwasher diff --git a/drivers/SmartThings/matter-appliance/profiles/dishwasher.yml b/drivers/SmartThings/matter-appliance/profiles/dishwasher.yml index cd047df321..5028869055 100644 --- a/drivers/SmartThings/matter-appliance/profiles/dishwasher.yml +++ b/drivers/SmartThings/matter-appliance/profiles/dishwasher.yml @@ -20,3 +20,6 @@ components: version: 1 categories: - name: Dishwasher +metadata: + mnmn: SmartThingsEdge + vid: generic-dishwasher diff --git a/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tl.yml b/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tl.yml index 4c3da072b6..259c4b37fb 100644 --- a/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tl.yml +++ b/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tl.yml @@ -20,3 +20,6 @@ components: version: 1 categories: - name: Washer +metadata: + mnmn: SmartThingsEdge + vid: generic-laundry-washer diff --git a/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn-tl.yml b/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn-tl.yml index 9b7e01c2fc..ae1525bef8 100644 --- a/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn-tl.yml +++ b/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn-tl.yml @@ -10,10 +10,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: operationalState version: 1 - id: temperatureLevel @@ -26,3 +22,6 @@ components: version: 1 categories: - name: Washer +metadata: + mnmn: SmartThingsEdge + vid: generic-laundry-washer diff --git a/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn.yml b/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn.yml index 26a89a3a23..44bf29dd6a 100644 --- a/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn.yml +++ b/drivers/SmartThings/matter-appliance/profiles/laundry-washer-tn.yml @@ -10,10 +10,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: operationalState version: 1 - id: laundryWasherSpinSpeed @@ -24,3 +20,6 @@ components: version: 1 categories: - name: Washer +metadata: + mnmn: SmartThingsEdge + vid: generic-laundry-washer diff --git a/drivers/SmartThings/matter-appliance/profiles/laundry-washer.yml b/drivers/SmartThings/matter-appliance/profiles/laundry-washer.yml index dd508477dc..62b69cfbe6 100644 --- a/drivers/SmartThings/matter-appliance/profiles/laundry-washer.yml +++ b/drivers/SmartThings/matter-appliance/profiles/laundry-washer.yml @@ -18,3 +18,6 @@ components: version: 1 categories: - name: Washer +metadata: + mnmn: SmartThingsEdge + vid: generic-laundry-washer diff --git a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tl.yml b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tl.yml index 48845a5d75..a3a503ac04 100644 --- a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tl.yml +++ b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tl.yml @@ -35,3 +35,6 @@ components: version: 1 categories: - name: Refrigerator +metadata: + mnmn: SmartThingsEdge + vid: generic-refrigerator diff --git a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn-tl.yml b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn-tl.yml index 0c35cef481..be761c666d 100644 --- a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn-tl.yml +++ b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn-tl.yml @@ -20,10 +20,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: temperatureMeasurement version: 1 categories: @@ -39,3 +35,6 @@ components: version: 1 categories: - name: Refrigerator +metadata: + mnmn: SmartThingsEdge + vid: generic-refrigerator diff --git a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn.yml b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn.yml index bfaf5b4f0b..37c3bdfbb3 100644 --- a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn.yml +++ b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer-tn.yml @@ -20,10 +20,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: temperatureMeasurement version: 1 categories: @@ -35,11 +31,10 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: temperatureMeasurement version: 1 categories: - name: Refrigerator +metadata: + mnmn: SmartThingsEdge + vid: generic-refrigerator diff --git a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer.yml b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer.yml index e9b1ba3491..0cf1949ef5 100644 --- a/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer.yml +++ b/drivers/SmartThings/matter-appliance/profiles/refrigerator-freezer.yml @@ -20,10 +20,6 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: temperatureLevel version: 1 - id: temperatureMeasurement @@ -37,13 +33,12 @@ components: version: 1 - id: temperatureSetpoint version: 1 - config: - values: - - key: "temperatureSetpoint.value" - range: [ 0, 100 ] - id: temperatureLevel version: 1 - id: temperatureMeasurement version: 1 categories: - name: Refrigerator +metadata: + mnmn: SmartThingsEdge + vid: generic-refrigerator diff --git a/drivers/SmartThings/matter-rvc/profiles/rvc.yml b/drivers/SmartThings/matter-rvc/profiles/rvc.yml index c05987ace7..0b41b86dfa 100644 --- a/drivers/SmartThings/matter-rvc/profiles/rvc.yml +++ b/drivers/SmartThings/matter-rvc/profiles/rvc.yml @@ -25,3 +25,6 @@ components: version: 1 categories: - name: RobotCleaner +metadata: + mnmn: SmartThingsEdge + vid: generic-rvc diff --git a/drivers/SmartThings/matter-rvc/src/init.lua b/drivers/SmartThings/matter-rvc/src/init.lua index cd7d9f928f..1cf28bfb98 100644 --- a/drivers/SmartThings/matter-rvc/src/init.lua +++ b/drivers/SmartThings/matter-rvc/src/init.lua @@ -155,13 +155,16 @@ local function rvc_run_mode_supported_mode_attr_handler(driver, device, ib, resp break end end - local labels_of_supported_modes = get_labels_of_supported_modes_filter_by_current_mode(device, + local labels_of_supported_arguments = get_labels_of_supported_modes_filter_by_current_mode(device, RVC_RUN_MODE_SUPPORTED_MODES, clusters.RvcRunMode.types.ModeTag.IDLE, current_mode ) + local labels_of_supported_modes = get_field_labels_of_supported_modes(device, RVC_RUN_MODE_SUPPORTED_MODES) local component = device.profile.components["runMode"] - local event = capabilities.mode.supportedModes(labels_of_supported_modes, {visibility = {displayed = false}}) + local event = capabilities.mode.supportedArguments(labels_of_supported_arguments, {visibility = {displayed = false}}) + device:emit_component_event(component, event) + event = capabilities.mode.supportedModes(labels_of_supported_modes, {visibility = {displayed = false}}) device:emit_component_event(component, event) end @@ -214,7 +217,9 @@ local function rvc_clean_mode_supported_mode_attr_handler(driver, device, ib, re local labels_of_supported_modes = get_field_labels_of_supported_modes(device, RVC_CLEAN_MODE_SUPPORTED_MODES) local component = device.profile.components["cleanMode"] - local event = capabilities.mode.supportedModes(labels_of_supported_modes, {visibility = {displayed = false}}) + local event = capabilities.mode.supportedArguments(labels_of_supported_modes, {visibility = {displayed = false}}) + device:emit_component_event(component, event) + event = capabilities.mode.supportedModes(labels_of_supported_modes, {visibility = {displayed = false}}) device:emit_component_event(component, event) end From e3ce14d3ea8fb3ab5f310f5a17fa528d5e7026c6 Mon Sep 17 00:00:00 2001 From: HunsupJung <59987061+HunsupJung@users.noreply.github.com> Date: Mon, 5 Aug 2024 21:11:44 +0900 Subject: [PATCH 3/5] Fix an issue that temperature level can't be controlled (#1500) Signed-off-by: Hunsup Jung --- .../src/matter-refrigerator/init.lua | 101 ++++++++++++------ 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/drivers/SmartThings/matter-appliance/src/matter-refrigerator/init.lua b/drivers/SmartThings/matter-appliance/src/matter-refrigerator/init.lua index ba7db0326a..b0ffa57d31 100644 --- a/drivers/SmartThings/matter-appliance/src/matter-refrigerator/init.lua +++ b/drivers/SmartThings/matter-appliance/src/matter-refrigerator/init.lua @@ -35,7 +35,7 @@ local setpoint_limit_device_field = { } local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map" -local SUPPORTED_TEMPERATURE_LEVEL = "__supported_temperature_levels" +local SUPPORTED_TEMPERATURE_LEVELS_MAP = "__supported_temperature_levels_map" local SUPPORTED_REFRIGERATOR_TCC_MODES_MAP = "__supported_refrigerator_tcc_modes_map" local function endpoint_to_component(device, ep) @@ -96,15 +96,43 @@ local function is_matter_refrigerator(opts, driver, device) return false end -local function temperature_setpoint_attr_handler(driver, device, ib, response) - local tn_eps = embedded_cluster_utils.get_endpoints(device, clusters.TemperatureControl.ID, {feature_bitmap = clusters.TemperatureControl.types.Feature.TEMPERATURE_NUMBER}) +local function supports_temperature_level_endpoint(device, endpoint) + local feature = clusters.TemperatureControl.types.Feature.TEMPERATURE_LEVEL + local tl_eps = embedded_cluster_utils.get_endpoints(device, clusters.TemperatureControl.ID, {feature_bitmap = feature}) + if #tl_eps == 0 then + device.log.warn_with({ hub_logs = true }, string.format("Device does not support TEMPERATURE_LEVEL feature")) + return false + end + for i, eps in ipairs(tl_eps) do + if eps == endpoint then + return true + end + end + device.log.warn_with({ hub_logs = true }, string.format("Endpoint(%d) does not support TEMPERATURE_LEVEL feature", endpoint)) + return false +end + +local function supports_temperature_number_endpoint(device, endpoint) + local feature = clusters.TemperatureControl.types.Feature.TEMPERATURE_NUMBER + local tn_eps = embedded_cluster_utils.get_endpoints(device, clusters.TemperatureControl.ID, {feature_bitmap = feature}) if #tn_eps == 0 then device.log.warn_with({ hub_logs = true }, string.format("Device does not support TEMPERATURE_NUMBER feature")) - return + return false end - device.log.info_with({ hub_logs = true }, - string.format("temperature_setpoint_attr_handler: %d", ib.data.value)) + for i, eps in ipairs(tn_eps) do + if eps == endpoint then + return true + end + end + device.log.warn_with({ hub_logs = true }, string.format("Endpoint(%d) does not support TEMPERATURE_NUMBER feature", endpoint)) + return false +end +local function temperature_setpoint_attr_handler(driver, device, ib, response) + if not supports_temperature_number_endpoint(device, ib.endpoint_id) then + return + end + device.log.info(string.format("temperature_setpoint_attr_handler: %d", ib.data.value)) local min_field = string.format("%s-%d", setpoint_limit_device_field.MIN_TEMP, ib.endpoint_id) local max_field = string.format("%s-%d", setpoint_limit_device_field.MAX_TEMP, ib.endpoint_id) local min = device:get_field(min_field) or 0 @@ -122,9 +150,7 @@ end local function setpoint_limit_handler(limit_field) return function(driver, device, ib, response) - local tn_eps = embedded_cluster_utils.get_endpoints(device,clusters.TemperatureControl.ID, {feature_bitmap = clusters.TemperatureControl.types.Feature.TEMPERATURE_NUMBER}) - if #tn_eps == 0 then - device.log.warn_with({ hub_logs = true }, string.format("Device does not support TEMPERATURE_NUMBER feature")) + if not supports_temperature_number_endpoint(device, ib.endpoint_id) then return end local field = string.format("%s-%d", limit_field, ib.endpoint_id) @@ -135,17 +161,17 @@ local function setpoint_limit_handler(limit_field) end local function selected_temperature_level_attr_handler(driver, device, ib, response) - local tl_eps = embedded_cluster_utils.get_endpoints(device,clusters.TemperatureControl.ID, {feature_bitmap = clusters.TemperatureControl.types.Feature.TEMPERATURE_LEVEL}) - if #tl_eps == 0 then - device.log.warn_with({ hub_logs = true }, string.format("Device does not support TEMPERATURE_LEVEL feature")) + if not supports_temperature_level_endpoint(device, ib.endpoint_id) then return end - device.log.info_with({ hub_logs = true }, - string.format("selected_temperature_level_attr_handler: %s", ib.data.value)) - local temperatureLevel = ib.data.value - local supportedTemperatureLevels = device:get_field(SUPPORTED_TEMPERATURE_LEVEL) + local supportedTemperatureLevelsMap = device:get_field(SUPPORTED_TEMPERATURE_LEVELS_MAP) + if not supportedTemperatureLevelsMap then + return + end + local supportedTemperatureLevels = supportedTemperatureLevelsMap[ib.endpoint_id] for i, tempLevel in ipairs(supportedTemperatureLevels) do + device.log.info(string.format("selected_temperature_level_attr_handler: %d, %s", i, tempLevel)) if i - 1 == temperatureLevel then device:emit_event_for_endpoint(ib.endpoint_id, capabilities.temperatureLevel.temperatureLevel(tempLevel)) break @@ -154,18 +180,23 @@ local function selected_temperature_level_attr_handler(driver, device, ib, respo end local function supported_temperature_levels_attr_handler(driver, device, ib, response) - local tl_eps = embedded_cluster_utils.get_endpoints(device,clusters.TemperatureControl.ID, {feature_bitmap = clusters.TemperatureControl.types.Feature.TEMPERATURE_LEVEL}) - if #tl_eps == 0 then - device.log.warn_with({ hub_logs = true }, string.format("Device does not support TEMPERATURE_LEVEL feature")) + if not supports_temperature_level_endpoint(device, ib.endpoint_id) then return end + local supportedTemperatureLevelsMap = device:get_field(SUPPORTED_TEMPERATURE_LEVELS_MAP) or {} local supportedTemperatureLevels = {} for _, tempLevel in ipairs(ib.data.elements) do - log.info_with({ hub_logs = true }, - string.format("supported_temperature_levels_attr_handler: %s", tempLevel.value)) + device.log.info(string.format("supported_temperature_levels_attr_handler: %s", tempLevel.value)) table.insert(supportedTemperatureLevels, tempLevel.value) end - device:set_field(SUPPORTED_TEMPERATURE_LEVEL, supportedTemperatureLevels, { persist = true }) + for ep = 1, ib.endpoint_id - 1 do + if not supportedTemperatureLevelsMap[ep] then + device.log.info(string.format("supportedTemperatureLevelsMap[%d] is nil", ep)) + supportedTemperatureLevelsMap[ep] = {"Nothing"} + end + end + supportedTemperatureLevelsMap[ib.endpoint_id] = supportedTemperatureLevels + device:set_field(SUPPORTED_TEMPERATURE_LEVELS_MAP, supportedTemperatureLevelsMap, { persist = true }) local event = capabilities.temperatureLevel.supportedTemperatureLevels(supportedTemperatureLevels, {visibility = {displayed = false}}) device:emit_event_for_endpoint(ib.endpoint_id, event) end @@ -224,9 +255,7 @@ end -- Capability Handlers -- local function handle_refrigerator_tcc_mode(driver, device, cmd) - device.log.info_with({ hub_logs = true }, - string.format("handle_refrigerator_tcc_mode mode: %s", cmd.args.mode)) - + device.log.info(string.format("handle_refrigerator_tcc_mode mode: %s", cmd.args.mode)) local ep = component_to_endpoint(device, cmd.component) local supportedRefrigeratorTccModesMap = device:get_field(SUPPORTED_REFRIGERATOR_TCC_MODES_MAP) local supportedRefrigeratorTccModes = supportedRefrigeratorTccModesMap[ep] or {} @@ -239,13 +268,11 @@ local function handle_refrigerator_tcc_mode(driver, device, cmd) end local function handle_temperature_setpoint(driver, device, cmd) - local tn_eps = embedded_cluster_utils.get_endpoints(device,clusters.TemperatureControl.ID, {feature_bitmap = clusters.TemperatureControl.types.Feature.TEMPERATURE_NUMBER}) - if #tn_eps == 0 then - device.log.warn_with({ hub_logs = true }, string.format("Device does not support TEMPERATURE_NUMBER feature")) + local ep = component_to_endpoint(device, cmd.component) + if not supports_temperature_number_endpoint(device, ep) then return end - device.log.info_with({ hub_logs = true }, - string.format("handle_temperature_setpoint: %s", cmd.args.setpoint)) + device.log.info(string.format("handle_temperature_setpoint: %s", cmd.args.setpoint)) local value = cmd.args.setpoint local _, temp_setpoint = device:get_latest_state( @@ -253,7 +280,6 @@ local function handle_temperature_setpoint(driver, device, cmd) capabilities.temperatureSetpoint.temperatureSetpoint.NAME, 0, { value = 0, unit = "C" } ) - local ep = component_to_endpoint(device, cmd.component) local min_field = string.format("%s-%d", setpoint_limit_device_field.MIN_TEMP, ep) local max_field = string.format("%s-%d", setpoint_limit_device_field.MAX_TEMP, ep) local min = device:get_field(min_field) or 0 @@ -273,10 +299,15 @@ end local function handle_temperature_level(driver, device, cmd) local ep = component_to_endpoint(device, cmd.component) - device.log.info_with({ hub_logs = true }, - string.format("handle_temperature_level: %s(%d)", cmd.args.temperatureLevel, ep)) - - local supportedTemperatureLevels = device:get_field(SUPPORTED_TEMPERATURE_LEVEL) + device.log.info(string.format("handle_temperature_level: %s(%d)", cmd.args.temperatureLevel, ep)) + if not supports_temperature_level_endpoint(device, ep) then + return + end + local supportedTemperatureLevelsMap = device:get_field(SUPPORTED_TEMPERATURE_LEVELS_MAP) + if not supportedTemperatureLevelsMap then + return + end + local supportedTemperatureLevels = supportedTemperatureLevelsMap[ep] for i, tempLevel in ipairs(supportedTemperatureLevels) do if cmd.args.temperatureLevel == tempLevel then device:send(clusters.TemperatureControl.commands.SetTemperature(device, ep, nil, i - 1)) From 76433b2c4ee22c7f14299dd07ce121bc307f7f3f Mon Sep 17 00:00:00 2001 From: lelandblue <79465613+lelandblue@users.noreply.github.com> Date: Mon, 15 Jul 2024 08:56:05 -0400 Subject: [PATCH 4/5] new-device-Eve-MTR-Thermo --- drivers/SmartThings/matter-thermostat/fingerprints.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/SmartThings/matter-thermostat/fingerprints.yml b/drivers/SmartThings/matter-thermostat/fingerprints.yml index 6bae370321..fec18a21b9 100644 --- a/drivers/SmartThings/matter-thermostat/fingerprints.yml +++ b/drivers/SmartThings/matter-thermostat/fingerprints.yml @@ -10,6 +10,13 @@ matterManufacturer: vendorId: 0x1396 productId: 0x0043A deviceProfileName: air-purifier-hepa +#Eve + - id: "4874/79" + deviceLabel: Eve Thermo + vendorId: 0x130A + productId: 0x004F + deviceProfileName: thermostat-heating-only-nostate + matterGeneric: - id: "matter/hvac/heatcool" From f7e537de099fdc3c4b07990453112cb3d1b62390 Mon Sep 17 00:00:00 2001 From: cjswedes Date: Wed, 31 Jul 2024 11:04:32 -0500 Subject: [PATCH 5/5] Enable native handlers for drivers that can use them only switch and switchLevel capabilities will be supported for Matter, Zigbee, and Z-Wave devices in the 0.54.x firmware. Using this functionality give a huge latency improvement for handling these capability commands which is important when a driver is handling several commands all at once (i.e. a routine is triggered that toggles a bunch of switches) --- drivers/SmartThings/matter-switch/src/init.lua | 9 +++++++++ drivers/SmartThings/zigbee-switch/src/init.lua | 2 +- drivers/SmartThings/zwave-bulb/src/init.lua | 2 +- drivers/SmartThings/zwave-switch/src/init.lua | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/SmartThings/matter-switch/src/init.lua b/drivers/SmartThings/matter-switch/src/init.lua index c588c3dbef..7876c61732 100644 --- a/drivers/SmartThings/matter-switch/src/init.lua +++ b/drivers/SmartThings/matter-switch/src/init.lua @@ -250,6 +250,9 @@ local function device_removed(driver, device) end local function handle_switch_on(driver, device, cmd) + if type(device.register_native_capability_cmd_handler) == "function" then + device:register_native_capability_cmd_handler(cmd.capability, cmd.command) + end local endpoint_id = device:component_to_endpoint(cmd.component) --TODO use OnWithRecallGlobalScene for devices with the LT feature local req = clusters.OnOff.server.commands.On(device, endpoint_id) @@ -257,12 +260,18 @@ local function handle_switch_on(driver, device, cmd) end local function handle_switch_off(driver, device, cmd) + if type(device.register_native_capability_cmd_handler) == "function" then + device:register_native_capability_cmd_handler(cmd.capability, cmd.command) + end local endpoint_id = device:component_to_endpoint(cmd.component) local req = clusters.OnOff.server.commands.Off(device, endpoint_id) device:send(req) end local function handle_set_level(driver, device, cmd) + if type(device.register_native_capability_cmd_handler) == "function" then + device:register_native_capability_cmd_handler(cmd.capability, cmd.command) + end local endpoint_id = device:component_to_endpoint(cmd.component) local level = math.floor(cmd.args.level/100.0 * 254) local req = clusters.LevelControl.server.commands.MoveToLevelWithOnOff(device, endpoint_id, level, cmd.args.rate or 0, 0 ,0) diff --git a/drivers/SmartThings/zigbee-switch/src/init.lua b/drivers/SmartThings/zigbee-switch/src/init.lua index d26da471fc..bd31c191bd 100644 --- a/drivers/SmartThings/zigbee-switch/src/init.lua +++ b/drivers/SmartThings/zigbee-switch/src/init.lua @@ -127,6 +127,6 @@ local zigbee_switch_driver_template = { } defaults.register_for_default_handlers(zigbee_switch_driver_template, - zigbee_switch_driver_template.supported_capabilities) + zigbee_switch_driver_template.supported_capabilities, {native_capability_cmds_enabled = true}) local zigbee_switch = ZigbeeDriver("zigbee_switch", zigbee_switch_driver_template) zigbee_switch:run() diff --git a/drivers/SmartThings/zwave-bulb/src/init.lua b/drivers/SmartThings/zwave-bulb/src/init.lua index 581f6ca466..62079594fa 100644 --- a/drivers/SmartThings/zwave-bulb/src/init.lua +++ b/drivers/SmartThings/zwave-bulb/src/init.lua @@ -37,7 +37,7 @@ local driver_template = { }, } -defaults.register_for_default_handlers(driver_template, driver_template.supported_capabilities) +defaults.register_for_default_handlers(driver_template, driver_template.supported_capabilities, {native_capability_cmds_enabled = true}) --- @type st.zwave.Driver local bulb = ZwaveDriver("zwave_bulb", driver_template) bulb:run() diff --git a/drivers/SmartThings/zwave-switch/src/init.lua b/drivers/SmartThings/zwave-switch/src/init.lua index ca73631808..4274c3cc97 100644 --- a/drivers/SmartThings/zwave-switch/src/init.lua +++ b/drivers/SmartThings/zwave-switch/src/init.lua @@ -172,7 +172,7 @@ local driver_template = { } } -defaults.register_for_default_handlers(driver_template, driver_template.supported_capabilities) +defaults.register_for_default_handlers(driver_template, driver_template.supported_capabilities, {native_capability_cmds_enabled = true}) --- @type st.zwave.Driver local switch = ZwaveDriver("zwave_switch", driver_template) switch:run()