Skip to content

Commit

Permalink
Change use of the EnergyExported attribute to EnergyImported in matte…
Browse files Browse the repository at this point in the history
…r switch (#1830)
  • Loading branch information
hcarter-775 authored Jan 4, 2025
1 parent aebfa31 commit f4cefe9
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ local cluster_base = require "st.matter.cluster_base"
local data_types = require "st.matter.data_types"
local TLVParser = require "st.matter.TLV.TLVParser"

local CumulativeEnergyExported = {
ID = 0x0002,
NAME = "CumulativeEnergyExported",
local CumulativeEnergyImported = {
ID = 0x0001,
NAME = "CumulativeEnergyImported",
base_type = require "ElectricalEnergyMeasurement.types.EnergyMeasurementStruct",
}

function CumulativeEnergyExported:new_value(...)
function CumulativeEnergyImported:new_value(...)
local o = self.base_type(table.unpack({...}))
self:augment_type(o)
return o
end

function CumulativeEnergyExported:read(device, endpoint_id)
function CumulativeEnergyImported:read(device, endpoint_id)
return cluster_base.read(
device,
endpoint_id,
Expand All @@ -24,7 +24,7 @@ function CumulativeEnergyExported:read(device, endpoint_id)
)
end

function CumulativeEnergyExported:subscribe(device, endpoint_id)
function CumulativeEnergyImported:subscribe(device, endpoint_id)
return cluster_base.subscribe(
device,
endpoint_id,
Expand All @@ -34,12 +34,12 @@ function CumulativeEnergyExported:subscribe(device, endpoint_id)
)
end

function CumulativeEnergyExported:set_parent_cluster(cluster)
function CumulativeEnergyImported:set_parent_cluster(cluster)
self._cluster = cluster
return self
end

function CumulativeEnergyExported:build_test_report_data(
function CumulativeEnergyImported:build_test_report_data(
device,
endpoint_id,
value,
Expand All @@ -57,12 +57,12 @@ function CumulativeEnergyExported:build_test_report_data(
)
end

function CumulativeEnergyExported:deserialize(tlv_buf)
function CumulativeEnergyImported:deserialize(tlv_buf)
local data = TLVParser.decode_tlv(tlv_buf)
self:augment_type(data)
return data
end

setmetatable(CumulativeEnergyExported, {__call = CumulativeEnergyExported.new_value, __index = CumulativeEnergyExported.base_type})
return CumulativeEnergyExported
setmetatable(CumulativeEnergyImported, {__call = CumulativeEnergyImported.new_value, __index = CumulativeEnergyImported.base_type})
return CumulativeEnergyImported

Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ local cluster_base = require "st.matter.cluster_base"
local data_types = require "st.matter.data_types"
local TLVParser = require "st.matter.TLV.TLVParser"

local PeriodicEnergyExported = {
ID = 0x0004,
NAME = "PeriodicEnergyExported",
local PeriodicEnergyImported = {
ID = 0x0003,
NAME = "PeriodicEnergyImported",
base_type = require "ElectricalEnergyMeasurement.types.EnergyMeasurementStruct",
}

function PeriodicEnergyExported:new_value(...)
function PeriodicEnergyImported:new_value(...)
local o = self.base_type(table.unpack({...}))
self:augment_type(o)
return o
end

function PeriodicEnergyExported:read(device, endpoint_id)
function PeriodicEnergyImported:read(device, endpoint_id)
return cluster_base.read(
device,
endpoint_id,
Expand All @@ -24,7 +24,7 @@ function PeriodicEnergyExported:read(device, endpoint_id)
)
end

function PeriodicEnergyExported:subscribe(device, endpoint_id)
function PeriodicEnergyImported:subscribe(device, endpoint_id)
return cluster_base.subscribe(
device,
endpoint_id,
Expand All @@ -34,12 +34,12 @@ function PeriodicEnergyExported:subscribe(device, endpoint_id)
)
end

function PeriodicEnergyExported:set_parent_cluster(cluster)
function PeriodicEnergyImported:set_parent_cluster(cluster)
self._cluster = cluster
return self
end

function PeriodicEnergyExported:build_test_report_data(
function PeriodicEnergyImported:build_test_report_data(
device,
endpoint_id,
value,
Expand All @@ -57,12 +57,12 @@ function PeriodicEnergyExported:build_test_report_data(
)
end

function PeriodicEnergyExported:deserialize(tlv_buf)
function PeriodicEnergyImported:deserialize(tlv_buf)
local data = TLVParser.decode_tlv(tlv_buf)
self:augment_type(data)
return data
end

setmetatable(PeriodicEnergyExported, {__call = PeriodicEnergyExported.new_value, __index = PeriodicEnergyExported.base_type})
return PeriodicEnergyExported
setmetatable(PeriodicEnergyImported, {__call = PeriodicEnergyImported.new_value, __index = PeriodicEnergyImported.base_type})
return PeriodicEnergyImported

84 changes: 42 additions & 42 deletions drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ local child_device_profile_overrides = {
local detect_matter_thing

local CUMULATIVE_REPORTS_NOT_SUPPORTED = "__cumulative_reports_not_supported"
local FIRST_EXPORT_REPORT_TIMESTAMP = "__first_export_report_timestamp"
local EXPORT_POLL_TIMER_SETTING_ATTEMPTED = "__export_poll_timer_setting_attempted"
local EXPORT_REPORT_TIMEOUT = "__export_report_timeout"
local TOTAL_EXPORTED_ENERGY = "__total_exported_energy"
local LAST_EXPORTED_REPORT_TIMESTAMP = "__last_exported_report_timestamp"
local RECURRING_EXPORT_REPORT_POLL_TIMER = "__recurring_export_report_poll_timer"
local FIRST_IMPORT_REPORT_TIMESTAMP = "__first_import_report_timestamp"
local IMPORT_POLL_TIMER_SETTING_ATTEMPTED = "__import_poll_timer_setting_attempted"
local IMPORT_REPORT_TIMEOUT = "__import_report_timeout"
local TOTAL_IMPORTED_ENERGY = "__total_imported_energy"
local LAST_IMPORTED_REPORT_TIMESTAMP = "__last_imported_report_timestamp"
local RECURRING_IMPORT_REPORT_POLL_TIMER = "__recurring_import_report_poll_timer"
local MINIMUM_ST_ENERGY_REPORT_INTERVAL = (15 * 60) -- 15 minutes, reported in seconds
local SUBSCRIPTION_REPORT_OCCURRED = "__subscription_report_occurred"
local CONVERSION_CONST_MILLIWATT_TO_WATT = 1000 -- A milliwatt is 1/1000th of a watt
Expand All @@ -183,44 +183,44 @@ local function iso8061Timestamp(time)
return os.date("!%Y-%m-%dT%H:%M:%SZ", time)
end

local function delete_export_poll_schedule(device)
local export_poll_timer = device:get_field(RECURRING_EXPORT_REPORT_POLL_TIMER)
if export_poll_timer then
device.thread:cancel_timer(export_poll_timer)
device:set_field(RECURRING_EXPORT_REPORT_POLL_TIMER, nil)
device:set_field(EXPORT_POLL_TIMER_SETTING_ATTEMPTED, nil)
local function delete_import_poll_schedule(device)
local import_poll_timer = device:get_field(RECURRING_IMPORT_REPORT_POLL_TIMER)
if import_poll_timer then
device.thread:cancel_timer(import_poll_timer)
device:set_field(RECURRING_IMPORT_REPORT_POLL_TIMER, nil)
device:set_field(IMPORT_POLL_TIMER_SETTING_ATTEMPTED, nil)
end
end

local function send_export_poll_report(device, latest_total_exported_energy_wh)
local function send_import_poll_report(device, latest_total_imported_energy_wh)
local current_time = os.time()
local last_time = device:get_field(LAST_EXPORTED_REPORT_TIMESTAMP) or 0
device:set_field(LAST_EXPORTED_REPORT_TIMESTAMP, current_time, { persist = true })
local last_time = device:get_field(LAST_IMPORTED_REPORT_TIMESTAMP) or 0
device:set_field(LAST_IMPORTED_REPORT_TIMESTAMP, current_time, { persist = true })

-- Calculate the energy delta between reports
local energy_delta_wh = 0.0
local previous_exported_report = device:get_latest_state("main", capabilities.powerConsumptionReport.ID,
local previous_imported_report = device:get_latest_state("main", capabilities.powerConsumptionReport.ID,
capabilities.powerConsumptionReport.powerConsumption.NAME)
if previous_exported_report and previous_exported_report.energy then
energy_delta_wh = math.max(latest_total_exported_energy_wh - previous_exported_report.energy, 0.0)
if previous_imported_report and previous_imported_report.energy then
energy_delta_wh = math.max(latest_total_imported_energy_wh - previous_imported_report.energy, 0.0)
end

-- Report the energy consumed during the time interval. The unit of these values should be 'Wh'
device:emit_event(capabilities.powerConsumptionReport.powerConsumption({
start = iso8061Timestamp(last_time),
["end"] = iso8061Timestamp(current_time - 1),
deltaEnergy = energy_delta_wh,
energy = latest_total_exported_energy_wh
energy = latest_total_imported_energy_wh
}))
end

local function create_poll_report_schedule(device)
local export_timer = device.thread:call_on_schedule(
device:get_field(EXPORT_REPORT_TIMEOUT),
send_export_poll_report(device, device:get_field(TOTAL_EXPORTED_ENERGY)),
"polling_export_report_schedule_timer"
local import_timer = device.thread:call_on_schedule(
device:get_field(IMPORT_REPORT_TIMEOUT),
send_import_poll_report(device, device:get_field(TOTAL_IMPORTED_ENERGY)),
"polling_import_report_schedule_timer"
)
device:set_field(RECURRING_EXPORT_REPORT_POLL_TIMER, export_timer)
device:set_field(RECURRING_IMPORT_REPORT_POLL_TIMER, import_timer)
end

local function set_poll_report_timer_and_schedule(device, is_cumulative_report)
Expand All @@ -234,18 +234,18 @@ local function set_poll_report_timer_and_schedule(device, is_cumulative_report)
return
elseif not device:get_field(SUBSCRIPTION_REPORT_OCCURRED) then
device:set_field(SUBSCRIPTION_REPORT_OCCURRED, true)
elseif not device:get_field(FIRST_EXPORT_REPORT_TIMESTAMP) then
device:set_field(FIRST_EXPORT_REPORT_TIMESTAMP, os.time())
elseif not device:get_field(FIRST_IMPORT_REPORT_TIMESTAMP) then
device:set_field(FIRST_IMPORT_REPORT_TIMESTAMP, os.time())
else
local first_timestamp = device:get_field(FIRST_EXPORT_REPORT_TIMESTAMP)
local first_timestamp = device:get_field(FIRST_IMPORT_REPORT_TIMESTAMP)
local second_timestamp = os.time()
local report_interval_secs = second_timestamp - first_timestamp
device:set_field(EXPORT_REPORT_TIMEOUT, math.max(report_interval_secs, MINIMUM_ST_ENERGY_REPORT_INTERVAL))
device:set_field(IMPORT_REPORT_TIMEOUT, math.max(report_interval_secs, MINIMUM_ST_ENERGY_REPORT_INTERVAL))
-- the poll schedule is only needed for devices that support powerConsumption
if device:supports_capability(capabilities.powerConsumptionReport) then
create_poll_report_schedule(device)
end
device:set_field(EXPORT_POLL_TIMER_SETTING_ATTEMPTED, true)
device:set_field(IMPORT_POLL_TIMER_SETTING_ATTEMPTED, true)
end
end

Expand Down Expand Up @@ -700,7 +700,7 @@ end

local function device_removed(driver, device)
log.info("device removed")
delete_export_poll_schedule(device)
delete_import_poll_schedule(device)
end

local function handle_switch_on(driver, device, cmd)
Expand Down Expand Up @@ -979,33 +979,33 @@ local function occupancy_attr_handler(driver, device, ib, response)
device:emit_event(ib.data.value == 0x01 and capabilities.motionSensor.motion.active() or capabilities.motionSensor.motion.inactive())
end

local function cumul_energy_exported_handler(driver, device, ib, response)
local function cumul_energy_imported_handler(driver, device, ib, response)
if ib.data.elements.energy then
local watt_hour_value = ib.data.elements.energy.value / CONVERSION_CONST_MILLIWATT_TO_WATT
device:set_field(TOTAL_EXPORTED_ENERGY, watt_hour_value)
device:set_field(TOTAL_IMPORTED_ENERGY, watt_hour_value)
device:emit_event(capabilities.energyMeter.energy({ value = watt_hour_value, unit = "Wh" }))
end
end

local function per_energy_exported_handler(driver, device, ib, response)
local function per_energy_imported_handler(driver, device, ib, response)
if ib.data.elements.energy then
local watt_hour_value = ib.data.elements.energy.value / CONVERSION_CONST_MILLIWATT_TO_WATT
local latest_energy_report = device:get_field(TOTAL_EXPORTED_ENERGY) or 0
local latest_energy_report = device:get_field(TOTAL_IMPORTED_ENERGY) or 0
local summed_energy_report = latest_energy_report + watt_hour_value
device:set_field(TOTAL_EXPORTED_ENERGY, summed_energy_report)
device:set_field(TOTAL_IMPORTED_ENERGY, summed_energy_report)
device:emit_event(capabilities.energyMeter.energy({ value = summed_energy_report, unit = "Wh" }))
end
end

local function energy_report_handler_factory(is_cumulative_report)
return function(driver, device, ib, response)
if not device:get_field(EXPORT_POLL_TIMER_SETTING_ATTEMPTED) then
if not device:get_field(IMPORT_POLL_TIMER_SETTING_ATTEMPTED) then
set_poll_report_timer_and_schedule(device, is_cumulative_report)
end
if is_cumulative_report then
cumul_energy_exported_handler(driver, device, ib, response)
cumul_energy_imported_handler(driver, device, ib, response)
elseif device:get_field(CUMULATIVE_REPORTS_NOT_SUPPORTED) then
per_energy_exported_handler(driver, device, ib, response)
per_energy_imported_handler(driver, device, ib, response)
end
end
end
Expand Down Expand Up @@ -1174,8 +1174,8 @@ local matter_driver_template = {
[clusters.ElectricalPowerMeasurement.attributes.ActivePower.ID] = active_power_handler,
},
[clusters.ElectricalEnergyMeasurement.ID] = {
[clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyExported.ID] = energy_report_handler_factory(true),
[clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyExported.ID] = energy_report_handler_factory(false),
[clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyImported.ID] = energy_report_handler_factory(true),
[clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyImported.ID] = energy_report_handler_factory(false),
},
[clusters.ValveConfigurationAndControl.ID] = {
[clusters.ValveConfigurationAndControl.attributes.CurrentState.ID] = valve_state_attr_handler,
Expand Down Expand Up @@ -1234,8 +1234,8 @@ local matter_driver_template = {
clusters.PowerSource.attributes.BatPercentRemaining,
},
[capabilities.energyMeter.ID] = {
clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyExported,
clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyExported
clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyImported,
clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyImported
},
[capabilities.powerMeter.ID] = {
clusters.ElectricalPowerMeasurement.attributes.ActivePower
Expand Down
Loading

0 comments on commit f4cefe9

Please sign in to comment.