diff --git a/drivers/SmartThings/matter-switch/src/sub_drivers/eve_energy/init.lua b/drivers/SmartThings/matter-switch/src/sub_drivers/eve_energy/init.lua index 6db532934c..1df33b19b0 100644 --- a/drivers/SmartThings/matter-switch/src/sub_drivers/eve_energy/init.lua +++ b/drivers/SmartThings/matter-switch/src/sub_drivers/eve_energy/init.lua @@ -8,9 +8,11 @@ local capabilities = require "st.capabilities" local clusters = require "st.matter.clusters" local cluster_base = require "st.matter.cluster_base" -local utils = require "st.utils" +local st_utils = require "st.utils" local data_types = require "st.matter.data_types" local device_lib = require "st.device" +local switch_utils = require "switch_utils.utils" +local fields = require "switch_utils.fields" local SWITCH_INITIALIZED = "__switch_intialized" local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map" @@ -37,9 +39,11 @@ local MINIMUM_ST_ENERGY_REPORT_INTERVAL = (15 * 60) -- 15 minutes, reported in s ------------------------------------------------------------------------------------- local function is_eve_energy_products(opts, driver, device) - -- this sub driver does not support child devices + -- this sub driver does NOT support child devices, and ONLY supports Eve devices + -- that do NOT support the Electrical Sensor device type if device.network_type == device_lib.NETWORK_TYPE_MATTER and - device.manufacturer_info.vendor_id == EVE_MANUFACTURER_ID then + device.manufacturer_info.vendor_id == EVE_MANUFACTURER_ID and + #switch_utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.ELECTRICAL_SENSOR) == 0 then return true end @@ -326,7 +330,7 @@ end local function watt_accumulated_attr_handler(driver, device, ib, zb_rx) if ib.data.value then local totalConsumptionRawValue = ib.data.value - local totalConsumptionWh = utils.round(1000 * totalConsumptionRawValue) + local totalConsumptionWh = st_utils.round(1000 * totalConsumptionRawValue) updateEnergyMeter(device, totalConsumptionWh) report_power_consumption_to_st_energy(device, totalConsumptionWh) end diff --git a/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua b/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua index 58310ef56b..1ebd114812 100644 --- a/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua +++ b/drivers/SmartThings/matter-switch/src/switch_handlers/attribute_handlers.lua @@ -294,13 +294,6 @@ end function AttributeHandlers.energy_imported_factory(is_cumulative_report) return function(driver, device, ib, response) - -- workaround: ignore devices supporting Eve's private energy cluster AND the ElectricalEnergyMeasurement cluster - local EVE_MANUFACTURER_ID, EVE_PRIVATE_CLUSTER_ID = 0x130A, 0x130AFC01 - local eve_private_energy_eps = device:get_endpoints(EVE_PRIVATE_CLUSTER_ID) - if device.manufacturer_info.vendor_id == EVE_MANUFACTURER_ID and #eve_private_energy_eps > 0 then - return - end - if is_cumulative_report then AttributeHandlers.cumul_energy_imported_handler(driver, device, ib, response) elseif device:get_field(fields.CUMULATIVE_REPORTS_NOT_SUPPORTED) then diff --git a/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua b/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua index c3d7faa4eb..f0ab1b0e9b 100644 --- a/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua +++ b/drivers/SmartThings/matter-switch/src/test/test_eve_energy.lua @@ -5,6 +5,7 @@ local test = require "integration_test" local capabilities = require "st.capabilities" local t_utils = require "integration_test.utils" local data_types = require "st.matter.data_types" +local fields = require "switch_utils.fields" local clusters = require "st.matter.clusters" local cluster_base = require "st.matter.cluster_base" @@ -53,6 +54,73 @@ local mock_device = test.mock_device.build_test_matter_device({ } }) +local mock_device_electrical_sensor = test.mock_device.build_test_matter_device({ + profile = t_utils.get_profile_definition("power-energy-powerConsumption.yml"), + manufacturer_info = { + vendor_id = 0x130A, + product_id = 0x0050, + }, + 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.OnOff.ID, + cluster_type = "SERVER", + cluster_revision = 1, + feature_map = 0, --u32 bitmap + }, + { + cluster_id = PRIVATE_CLUSTER_ID, + cluster_type = "SERVER", + cluster_revision = 1, + feature_map = 0, --u32 bitmap + } + }, + device_types = { + { device_type_id = 0x010A, device_type_revision = 1 } -- On/Off Plug + } + }, + { + endpoint_id = 2, + clusters = { + { + cluster_id = clusters.ElectricalEnergyMeasurement.ID, + cluster_type = "SERVER", + cluster_revision = 1, + feature_map = clusters.ElectricalEnergyMeasurement.types.Feature.CUMULATIVE_ENERGY, + } + }, + device_types = { + { device_type_id = fields.DEVICE_TYPE_ID.ELECTRICAL_SENSOR, device_type_revision = 1 } + } + } + } +}) + +local function test_init_electrical_sensor() + local cluster_subscribe_list = { + clusters.OnOff.attributes.OnOff, + clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyImported, + clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyImported, + } + local subscribe_request = cluster_subscribe_list[1]:subscribe(mock_device_electrical_sensor) + for i, cluster in ipairs(cluster_subscribe_list) do + subscribe_request:merge(cluster:subscribe(mock_device_electrical_sensor)) + end + test.socket.matter:__expect_send({ mock_device_electrical_sensor.id, subscribe_request }) + test.mock_device.add_test_device(mock_device_electrical_sensor) +end + local function test_init() local cluster_subscribe_list = { clusters.OnOff.attributes.OnOff, @@ -374,4 +442,94 @@ test.register_coroutine_test( } ) +local cumulative_report_val_19 = { + energy = 19000, + start_timestamp = 0, + end_timestamp = 0, + start_systime = 0, + end_systime = 0, + apparent_energy = 0, + reactive_energy = 0 +} + +local cumulative_report_val_29 = { + energy = 29000, + start_timestamp = 0, + end_timestamp = 0, + start_systime = 0, + end_systime = 0, + apparent_energy = 0, + reactive_energy = 0 +} + +local cumulative_report_val_39 = { + energy = 39000, + start_timestamp = 0, + end_timestamp = 0, + start_systime = 0, + end_systime = 0, + apparent_energy = 0, + reactive_energy = 0 +} + +test.register_coroutine_test( + "Cumulative Energy measurement should generate correct messages", + function() + local mock_device = mock_device_electrical_sensor + + test.mock_time.advance_time(901) -- move time 15 minutes past 0 (this can be assumed to be true in practice in all cases) + test.socket.matter:__queue_receive( + { + mock_device.id, + clusters.ElectricalEnergyMeasurement.server.attributes.CumulativeEnergyImported:build_test_report_data( + mock_device, 1, cumulative_report_val_19 + ) + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.energyMeter.energy({ value = 19.0, unit = "Wh" })) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.powerConsumptionReport.powerConsumption({ + start = "1970-01-01T00:00:00Z", + ["end"] = "1970-01-01T00:15:00Z", + deltaEnergy = 0.0, + energy = 19.0 + })) + ) + test.socket.matter:__queue_receive( + { + mock_device.id, + clusters.ElectricalEnergyMeasurement.server.attributes.CumulativeEnergyImported:build_test_report_data( + mock_device, 1, cumulative_report_val_29 + ) + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.energyMeter.energy({ value = 29.0, unit = "Wh" })) + ) + test.wait_for_events() + test.mock_time.advance_time(1500) + test.socket.matter:__queue_receive( + { + mock_device.id, + clusters.ElectricalEnergyMeasurement.server.attributes.CumulativeEnergyImported:build_test_report_data( + mock_device, 1, cumulative_report_val_39 + ) + } + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.energyMeter.energy({ value = 39.0, unit = "Wh" })) + ) + test.socket.capability:__expect_send( + mock_device:generate_test_message("main", capabilities.powerConsumptionReport.powerConsumption({ + start = "1970-01-01T00:15:01Z", + ["end"] = "1970-01-01T00:40:00Z", + deltaEnergy = 20.0, + energy = 39.0 + })) + ) + end, { test_init = test_init_electrical_sensor } +) + test.run_registered_tests()