Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,31 @@ EnergyMeasurementStruct.field_defs = {
is_optional = true,
data_type = require "st.matter.data_types.Uint64",
},
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also need to make these updates in matter-thermostat and matter-energy where this is also defined via an embedded cluster definition?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it matters in those drivers. 1. Nobody is using them 2. Even if they were, there'd be no real side effects of the coroutine error for them

name = "apparent_energy",
field_id = 5,
is_nullable = false,
is_optional = true,
data_type = require "st.matter.data_types.Int64",
},
{
name = "reactive_energy",
field_id = 6,
is_nullable = false,
is_optional = true,
data_type = require "st.matter.data_types.Int64",
},
}

EnergyMeasurementStruct.init = function(cls, tbl)
local o = {}
o.elements = {}
o.num_elements = 0
setmetatable(o, new_mt)
for idx, field_def in ipairs(cls.field_defs) do
for _idx, field_def in ipairs(cls.field_defs) do
if (not field_def.is_optional and not field_def.is_nullable) and not tbl[field_def.name] then
error("Missing non optional or non_nullable field: " .. field_def.name)
else
elseif not (field_def.is_optional and tbl[field_def.name] == nil) then
o.elements[field_def.name] = data_types.validate_or_build_type(tbl[field_def.name], field_def.data_type, field_def.name)
o.elements[field_def.name].field_id = field_def.field_id
o.num_elements = o.num_elements + 1
Expand All @@ -71,19 +85,19 @@ new_mt.__index.serialize = EnergyMeasurementStruct.serialize
EnergyMeasurementStruct.augment_type = function(self, val)
local elems = {}
local num_elements = 0
for _, v in pairs(val.elements) do
for _, v in pairs(val.elements or {}) do
for _, field_def in ipairs(self.field_defs) do
if field_def.field_id == v.field_id and
field_def.is_nullable and
(v.value == nil and v.elements == nil) then
elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name)
num_elements = num_elements + 1
elseif field_def.field_id == v.field_id and not
(field_def.is_optional and v.value == nil) then
(field_def.is_optional and v.value == nil and v.elements == nil) then
elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name)
num_elements = num_elements + 1
if field_def.element_type ~= nil then
for i, e in ipairs(elems[field_def.name].elements) do
for i, e in ipairs(elems[field_def.name].elements or {}) do
elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type)
end
end
Expand Down
5 changes: 5 additions & 0 deletions drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ if version.api < 16 then
clusters.Descriptor = require "embedded_clusters.Descriptor"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local SwitchLifecycleHandlers = {}

function SwitchLifecycleHandlers.device_added(driver, device)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ if version.api < 11 then
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local AttributeHandlers = {}

-- [[ ON OFF CLUSTER ATTRIBUTES ]] --
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ if version.api < 11 then
clusters.ValveConfigurationAndControl = require "embedded_clusters.ValveConfigurationAndControl"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local DeviceConfiguration = {}
local ChildConfiguration = {}
local SwitchDeviceConfiguration = {}
Expand Down Expand Up @@ -87,7 +92,9 @@ function SwitchDeviceConfiguration.assign_profile_for_onoff_ep(device, server_on
local generic_profile = fields.device_type_profile_map[primary_dt_id]

local static_electrical_tags = switch_utils.get_field_for_endpoint(device, fields.ELECTRICAL_TAGS, server_onoff_ep_id)
if static_electrical_tags ~= nil then
if type(static_electrical_tags) == "string" then
-- if no associated profile is found for the device type and static electrical tags are available, use "plug-binary" as a fallback
generic_profile = generic_profile or "plug-binary"
-- profiles like 'light-binary' and 'plug-binary' should drop the '-binary' and become 'light-power', 'plug-energy-powerConsumption', etc.
generic_profile = string.gsub(generic_profile, "-binary", "") .. static_electrical_tags
end
Expand Down
20 changes: 16 additions & 4 deletions drivers/SmartThings/matter-switch/src/switch_utils/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ if version.api < 16 then
clusters.Descriptor = require "embedded_clusters.Descriptor"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local utils = {}

function utils.tbl_contains(array, value)
Expand Down Expand Up @@ -545,16 +550,14 @@ function utils.subscribe(device)
devices_seen[checked_device.id] = true -- only loop through any device once
end
end
-- The refresh capability command handler in the lua libs uses this key to determine which attributes to read. Note
-- that only attributes_seen needs to be saved here, and not events_seen, since the refresh handler only checks
-- attributes and not events.
device:set_field(fields.SUBSCRIBED_ATTRIBUTES_KEY, attributes_seen)

-- If the type of battery support has not yet been determined, add the PowerSource AttributeList to the list of
-- subscribed attributes in order to determine which if any battery capability should be used.
if device:get_field(fields.profiling_data.BATTERY_SUPPORT) == nil then
local ib = im.InteractionInfoBlock(nil, clusters.PowerSource.ID, clusters.PowerSource.attributes.AttributeList.ID)
subscribe_request:with_info_block(ib)
attributes_seen[clusters.PowerSource.ID] = attributes_seen[clusters.PowerSource.ID] or {}
attributes_seen[clusters.PowerSource.ID][clusters.PowerSource.attributes.AttributeList.ID] = ib
end

-- If the power topology of the device has not yet been determined, add the AvailableEndpoints (for SET topology)
Expand All @@ -566,12 +569,21 @@ function utils.subscribe(device)
if clusters.PowerTopology.are_features_supported(clusters.PowerTopology.types.Feature.SET_TOPOLOGY, endpoint_power_topology_cluster.feature_map or 0) then
local ib = im.InteractionInfoBlock(nil, clusters.PowerTopology.ID, clusters.PowerTopology.attributes.AvailableEndpoints.ID)
subscribe_request:with_info_block(ib)
attributes_seen[clusters.PowerTopology.ID] = attributes_seen[clusters.PowerTopology.ID] or {}
attributes_seen[clusters.PowerTopology.ID][clusters.PowerTopology.attributes.AvailableEndpoints.ID] = ib
elseif clusters.PowerTopology.are_features_supported(clusters.PowerTopology.types.Feature.TREE_TOPOLOGY, endpoint_power_topology_cluster.feature_map or 0) then
local ib = im.InteractionInfoBlock(nil, clusters.Descriptor.ID, clusters.Descriptor.attributes.PartsList.ID)
subscribe_request:with_info_block(ib)
attributes_seen[clusters.Descriptor.ID] = attributes_seen[clusters.Descriptor.ID] or {}
attributes_seen[clusters.Descriptor.ID][clusters.Descriptor.attributes.PartsList.ID] = ib
end
end

-- The refresh capability command handler in the lua libs uses this key to determine which attributes to read. Note
-- that only attributes_seen needs to be saved here, and not events_seen, since the refresh handler only checks
-- attributes and not events.
device:set_field(fields.SUBSCRIBED_ATTRIBUTES_KEY, attributes_seen)

if #subscribe_request.info_blocks > 0 then
device:send(subscribe_request)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ if version.api < 11 then
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local aqara_parent_ep = 4
local aqara_child1_ep = 1
local aqara_child2_ep = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ if version.api < 11 then
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local mock_device = test.mock_device.build_test_matter_device({
profile = t_utils.get_profile_definition("plug-level-power-energy-powerConsumption.yml"),
manufacturer_info = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ if version.api < 16 then
clusters.Descriptor = require "embedded_clusters.Descriptor"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local mock_device = test.mock_device.build_test_matter_device({
profile = t_utils.get_profile_definition("plug-level-power-energy-powerConsumption.yml"),
manufacturer_info = {
Expand Down
Loading