Skip to content

Commit 428476c

Browse files
committed
add embedded PowerTopology handling
1 parent 3b02007 commit 428476c

File tree

9 files changed

+314
-0
lines changed

9 files changed

+314
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
local cluster_base = require "st.matter.cluster_base"
2+
local PowerTopologyServerAttributes = require "embedded_clusters.PowerTopology.server.attributes"
3+
local PowerTopologyTypes = require "embedded_clusters.PowerTopology.types"
4+
5+
local PowerTopology = {}
6+
7+
PowerTopology.ID = 0x009C
8+
PowerTopology.NAME = "PowerTopology"
9+
PowerTopology.server = {}
10+
PowerTopology.client = {}
11+
PowerTopology.server.attributes = PowerTopologyServerAttributes:set_parent_cluster(PowerTopology)
12+
PowerTopology.types = PowerTopologyTypes
13+
14+
function PowerTopology:get_attribute_by_id(attr_id)
15+
local attr_id_map = {
16+
[0x0000] = "AvailableEndpoints",
17+
[0x0001] = "ActiveEndpoints",
18+
[0xFFF9] = "AcceptedCommandList",
19+
[0xFFFA] = "EventList",
20+
[0xFFFB] = "AttributeList",
21+
}
22+
local attr_name = attr_id_map[attr_id]
23+
if attr_name ~= nil then
24+
return self.attributes[attr_name]
25+
end
26+
return nil
27+
end
28+
29+
function PowerTopology:get_server_command_by_id(command_id)
30+
local server_id_map = {
31+
}
32+
if server_id_map[command_id] ~= nil then
33+
return self.server.commands[server_id_map[command_id]]
34+
end
35+
return nil
36+
end
37+
38+
39+
PowerTopology.attribute_direction_map = {
40+
["AvailableEndpoints"] = "server",
41+
["ActiveEndpoints"] = "server",
42+
["AcceptedCommandList"] = "server",
43+
["EventList"] = "server",
44+
["AttributeList"] = "server",
45+
}
46+
47+
PowerTopology.command_direction_map = {
48+
}
49+
50+
PowerTopology.FeatureMap = PowerTopology.types.Feature
51+
52+
function PowerTopology.are_features_supported(feature, feature_map)
53+
if (PowerTopology.FeatureMap.bits_are_valid(feature)) then
54+
return (feature & feature_map) == feature
55+
end
56+
return false
57+
end
58+
59+
local attribute_helper_mt = {}
60+
attribute_helper_mt.__index = function(self, key)
61+
local direction = PowerTopology.attribute_direction_map[key]
62+
if direction == nil then
63+
error(string.format("Referenced unknown attribute %s on cluster %s", key, PowerTopology.NAME))
64+
end
65+
return PowerTopology[direction].attributes[key]
66+
end
67+
PowerTopology.attributes = {}
68+
setmetatable(PowerTopology.attributes, attribute_helper_mt)
69+
70+
setmetatable(PowerTopology, {__index = cluster_base})
71+
72+
return PowerTopology
73+
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
local cluster_base = require "st.matter.cluster_base"
2+
local data_types = require "st.matter.data_types"
3+
local TLVParser = require "st.matter.TLV.TLVParser"
4+
5+
local AvailableEndpoints = {
6+
ID = 0x0000,
7+
NAME = "AvailableEndpoints",
8+
base_type = require "st.matter.data_types.Array",
9+
element_type = require "st.matter.data_types.Uint16",
10+
}
11+
12+
function AvailableEndpoints:augment_type(data_type_obj)
13+
for i, v in ipairs(data_type_obj.elements) do
14+
data_type_obj.elements[i] = data_types.validate_or_build_type(v, AvailableEndpoints.element_type)
15+
end
16+
end
17+
18+
function AvailableEndpoints:new_value(...)
19+
local o = self.base_type(table.unpack({...}))
20+
21+
return o
22+
end
23+
24+
function AvailableEndpoints:read(device, endpoint_id)
25+
return cluster_base.read(
26+
device,
27+
endpoint_id,
28+
self._cluster.ID,
29+
self.ID,
30+
nil
31+
)
32+
end
33+
34+
function AvailableEndpoints:subscribe(device, endpoint_id)
35+
return cluster_base.subscribe(
36+
device,
37+
endpoint_id,
38+
self._cluster.ID,
39+
self.ID,
40+
nil
41+
)
42+
end
43+
44+
function AvailableEndpoints:set_parent_cluster(cluster)
45+
self._cluster = cluster
46+
return self
47+
end
48+
49+
function AvailableEndpoints:build_test_report_data(
50+
device,
51+
endpoint_id,
52+
value,
53+
status
54+
)
55+
local data = data_types.validate_or_build_type(value, self.base_type)
56+
57+
return cluster_base.build_test_report_data(
58+
device,
59+
endpoint_id,
60+
self._cluster.ID,
61+
self.ID,
62+
data,
63+
status
64+
)
65+
end
66+
67+
function AvailableEndpoints:deserialize(tlv_buf)
68+
local data = TLVParser.decode_tlv(tlv_buf)
69+
70+
return data
71+
end
72+
73+
setmetatable(AvailableEndpoints, {__call = AvailableEndpoints.new_value, __index = AvailableEndpoints.base_type})
74+
return AvailableEndpoints
75+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
local attr_mt = {}
2+
attr_mt.__index = function(self, key)
3+
local req_loc = string.format("embedded_clusters.PowerTopology.server.attributes.%s", key)
4+
local raw_def = require(req_loc)
5+
local cluster = rawget(self, "_cluster")
6+
raw_def:set_parent_cluster(cluster)
7+
return raw_def
8+
end
9+
10+
local PowerTopologyServerAttributes = {}
11+
12+
function PowerTopologyServerAttributes:set_parent_cluster(cluster)
13+
self._cluster = cluster
14+
return self
15+
end
16+
17+
setmetatable(PowerTopologyServerAttributes, attr_mt)
18+
19+
return PowerTopologyServerAttributes
20+
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
local data_types = require "st.matter.data_types"
2+
local UintABC = require "st.matter.data_types.base_defs.UintABC"
3+
4+
local Feature = {}
5+
local new_mt = UintABC.new_mt({NAME = "Feature", ID = data_types.name_to_id_map["Uint32"]}, 4)
6+
7+
Feature.BASE_MASK = 0xFFFF
8+
Feature.NODE_TOPOLOGY = 0x0001
9+
Feature.TREE_TOPOLOGY = 0x0002
10+
Feature.SET_TOPOLOGY = 0x0004
11+
Feature.DYNAMIC_POWER_FLOW = 0x0008
12+
13+
Feature.mask_fields = {
14+
BASE_MASK = 0xFFFF,
15+
NODE_TOPOLOGY = 0x0001,
16+
TREE_TOPOLOGY = 0x0002,
17+
SET_TOPOLOGY = 0x0004,
18+
DYNAMIC_POWER_FLOW = 0x0008,
19+
}
20+
21+
Feature.is_node_topology_set = function(self)
22+
return (self.value & self.NODE_TOPOLOGY) ~= 0
23+
end
24+
25+
Feature.set_node_topology = function(self)
26+
if self.value ~= nil then
27+
self.value = self.value | self.NODE_TOPOLOGY
28+
else
29+
self.value = self.NODE_TOPOLOGY
30+
end
31+
end
32+
33+
Feature.unset_node_topology = function(self)
34+
self.value = self.value & (~self.NODE_TOPOLOGY & self.BASE_MASK)
35+
end
36+
Feature.is_tree_topology_set = function(self)
37+
return (self.value & self.TREE_TOPOLOGY) ~= 0
38+
end
39+
40+
Feature.set_tree_topology = function(self)
41+
if self.value ~= nil then
42+
self.value = self.value | self.TREE_TOPOLOGY
43+
else
44+
self.value = self.TREE_TOPOLOGY
45+
end
46+
end
47+
48+
Feature.unset_tree_topology = function(self)
49+
self.value = self.value & (~self.TREE_TOPOLOGY & self.BASE_MASK)
50+
end
51+
Feature.is_set_topology_set = function(self)
52+
return (self.value & self.SET_TOPOLOGY) ~= 0
53+
end
54+
55+
Feature.set_set_topology = function(self)
56+
if self.value ~= nil then
57+
self.value = self.value | self.SET_TOPOLOGY
58+
else
59+
self.value = self.SET_TOPOLOGY
60+
end
61+
end
62+
63+
Feature.unset_set_topology = function(self)
64+
self.value = self.value & (~self.SET_TOPOLOGY & self.BASE_MASK)
65+
end
66+
Feature.is_dynamic_power_flow_set = function(self)
67+
return (self.value & self.DYNAMIC_POWER_FLOW) ~= 0
68+
end
69+
70+
Feature.set_dynamic_power_flow = function(self)
71+
if self.value ~= nil then
72+
self.value = self.value | self.DYNAMIC_POWER_FLOW
73+
else
74+
self.value = self.DYNAMIC_POWER_FLOW
75+
end
76+
end
77+
78+
Feature.unset_dynamic_power_flow = function(self)
79+
self.value = self.value & (~self.DYNAMIC_POWER_FLOW & self.BASE_MASK)
80+
end
81+
82+
function Feature.bits_are_valid(feature)
83+
local max =
84+
Feature.NODE_TOPOLOGY |
85+
Feature.TREE_TOPOLOGY |
86+
Feature.SET_TOPOLOGY |
87+
Feature.DYNAMIC_POWER_FLOW
88+
if (feature <= max) and (feature >= 1) then
89+
return true
90+
else
91+
return false
92+
end
93+
end
94+
95+
Feature.mask_methods = {
96+
is_node_topology_set = Feature.is_node_topology_set,
97+
set_node_topology = Feature.set_node_topology,
98+
unset_node_topology = Feature.unset_node_topology,
99+
is_tree_topology_set = Feature.is_tree_topology_set,
100+
set_tree_topology = Feature.set_tree_topology,
101+
unset_tree_topology = Feature.unset_tree_topology,
102+
is_set_topology_set = Feature.is_set_topology_set,
103+
set_set_topology = Feature.set_set_topology,
104+
unset_set_topology = Feature.unset_set_topology,
105+
is_dynamic_power_flow_set = Feature.is_dynamic_power_flow_set,
106+
set_dynamic_power_flow = Feature.set_dynamic_power_flow,
107+
unset_dynamic_power_flow = Feature.unset_dynamic_power_flow,
108+
}
109+
110+
Feature.augment_type = function(cls, val)
111+
setmetatable(val, new_mt)
112+
end
113+
114+
setmetatable(Feature, new_mt)
115+
116+
return Feature
117+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
local types_mt = {}
2+
types_mt.__index = function(self, key)
3+
return require("embedded_clusters.PowerTopology.types." .. key)
4+
end
5+
6+
local PowerTopologyTypes = {}
7+
8+
setmetatable(PowerTopologyTypes, types_mt)
9+
10+
return PowerTopologyTypes
11+

drivers/SmartThings/matter-switch/src/generic_handlers/attribute_handlers.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ local color_utils = require "utils.color_utils"
2525
local cfg = require "utils.device_configuration"
2626
local device_cfg = cfg.DeviceCfg
2727

28+
-- Include driver-side definitions when lua libs api version is < 11
29+
if version.api < 11 then
30+
clusters.ElectricalEnergyMeasurement.ID = 0x0091
31+
clusters.ElectricalPowerMeasurement.ID = 0x0090
32+
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
33+
end
34+
35+
2836
local AttributeHandlers = {}
2937

3038
-- [[ ON OFF CLUSTER ATTRIBUTES ]] --

drivers/SmartThings/matter-switch/src/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ local capability_handlers = require "generic_handlers.capability_handlers"
3434
if version.api < 11 then
3535
clusters.ElectricalEnergyMeasurement = require "embedded_clusters.ElectricalEnergyMeasurement"
3636
clusters.ElectricalPowerMeasurement = require "embedded_clusters.ElectricalPowerMeasurement"
37+
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
3738
clusters.ValveConfigurationAndControl = require "embedded_clusters.ValveConfigurationAndControl"
3839
end
3940

drivers/SmartThings/matter-switch/src/test/test_electrical_sensor.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ local version = require "version"
2222
if version.api < 11 then
2323
clusters.ElectricalEnergyMeasurement = require "embedded_clusters.ElectricalEnergyMeasurement"
2424
clusters.ElectricalPowerMeasurement = require "embedded_clusters.ElectricalPowerMeasurement"
25+
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
2526
end
2627

2728
local mock_device = test.mock_device.build_test_matter_device({

drivers/SmartThings/matter-switch/src/utils/switch_utils.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,19 @@
1414

1515
local fields = require "utils.switch_fields"
1616
local st_utils = require "st.utils"
17+
local version = require "version"
1718
local clusters = require "st.matter.clusters"
1819
local capabilities = require "st.capabilities"
1920
local im = require "st.matter.interaction_model"
2021
local log = require "log"
2122

23+
-- Include driver-side definitions when lua libs api version is < 11
24+
if version.api < 11 then
25+
clusters.ElectricalEnergyMeasurement.ID = 0x0091
26+
clusters.ElectricalPowerMeasurement.ID = 0x0090
27+
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
28+
end
29+
2230
local utils = {}
2331

2432
function utils.tbl_contains(array, value)

0 commit comments

Comments
 (0)