Skip to content

Commit eb50abd

Browse files
Support Soil Sensor device type
1 parent 1ecc63b commit eb50abd

File tree

9 files changed

+378
-6
lines changed

9 files changed

+378
-6
lines changed

drivers/SmartThings/matter-sensor/fingerprints.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,8 @@ matterGeneric:
350350
deviceTypes:
351351
- id: 0x0306 # Flow Sensor
352352
deviceProfileName: flow-battery
353+
- id: "matter/soil/sensor"
354+
deviceLabel: Matter Soil Sensor
355+
deviceTypes:
356+
- id: 0x0045 # Soil Sensor
357+
deviceProfileName: humidity
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
local cluster_base = require "st.matter.cluster_base"
2+
local SoilMeasurementServerAttributes = require "embedded_clusters.SoilMeasurement.server.attributes"
3+
4+
local SoilMeasurement = {}
5+
6+
SoilMeasurement.ID = 0x0430
7+
SoilMeasurement.NAME = "SoilMeasurement"
8+
SoilMeasurement.server = {}
9+
SoilMeasurement.client = {}
10+
SoilMeasurement.server.attributes = SoilMeasurementServerAttributes:set_parent_cluster(SoilMeasurement)
11+
12+
function SoilMeasurement:get_attribute_by_id(attr_id)
13+
local attr_id_map = {
14+
[0x0000] = "SoilMoistureMeasurementLimits",
15+
[0x0001] = "SoilMoistureMeasuredValue",
16+
[0xFFF9] = "AcceptedCommandList",
17+
[0xFFFB] = "AttributeList",
18+
}
19+
local attr_name = attr_id_map[attr_id]
20+
if attr_name ~= nil then
21+
return self.attributes[attr_name]
22+
end
23+
return nil
24+
end
25+
26+
SoilMeasurement.attribute_direction_map = {
27+
["SoilMoistureMeasurementLimits"] = "server",
28+
["SoilMoistureMeasuredValue"] = "server",
29+
["AcceptedCommandList"] = "server",
30+
["AttributeList"] = "server",
31+
}
32+
33+
local attribute_helper_mt = {}
34+
attribute_helper_mt.__index = function(self, key)
35+
local direction = SoilMeasurement.attribute_direction_map[key]
36+
if direction == nil then
37+
error(string.format("Referenced unknown attribute %s on cluster %s", key, SoilMeasurement.NAME))
38+
end
39+
return SoilMeasurement[direction].attributes[key]
40+
end
41+
SoilMeasurement.attributes = {}
42+
setmetatable(SoilMeasurement.attributes, attribute_helper_mt)
43+
44+
setmetatable(SoilMeasurement, {__index = cluster_base})
45+
46+
return SoilMeasurement
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 AcceptedCommandList = {
6+
ID = 0xFFF9,
7+
NAME = "AcceptedCommandList",
8+
base_type = require "st.matter.data_types.Array",
9+
element_type = require "st.matter.data_types.Uint32",
10+
}
11+
12+
function AcceptedCommandList: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, AcceptedCommandList.element_type)
15+
end
16+
end
17+
18+
function AcceptedCommandList:new_value(...)
19+
local o = self.base_type(table.unpack({...}))
20+
21+
return o
22+
end
23+
24+
function AcceptedCommandList: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 AcceptedCommandList: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 AcceptedCommandList:set_parent_cluster(cluster)
45+
self._cluster = cluster
46+
return self
47+
end
48+
49+
function AcceptedCommandList: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 AcceptedCommandList:deserialize(tlv_buf)
68+
local data = TLVParser.decode_tlv(tlv_buf)
69+
70+
return data
71+
end
72+
73+
setmetatable(AcceptedCommandList, {__call = AcceptedCommandList.new_value, __index = AcceptedCommandList.base_type})
74+
return AcceptedCommandList
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 AttributeList = {
6+
ID = 0xFFFB,
7+
NAME = "AttributeList",
8+
base_type = require "st.matter.data_types.Array",
9+
element_type = require "st.matter.data_types.Uint32",
10+
}
11+
12+
function AttributeList: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, AttributeList.element_type)
15+
end
16+
end
17+
18+
function AttributeList:new_value(...)
19+
local o = self.base_type(table.unpack({...}))
20+
21+
return o
22+
end
23+
24+
function AttributeList: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 AttributeList: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 AttributeList:set_parent_cluster(cluster)
45+
self._cluster = cluster
46+
return self
47+
end
48+
49+
function AttributeList: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 AttributeList:deserialize(tlv_buf)
68+
local data = TLVParser.decode_tlv(tlv_buf)
69+
70+
return data
71+
end
72+
73+
setmetatable(AttributeList, {__call = AttributeList.new_value, __index = AttributeList.base_type})
74+
return AttributeList
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 SoilMoistureMeasuredValue = {
6+
ID = 0x0001,
7+
NAME = "SoilMoistureMeasuredValue",
8+
base_type = require "st.matter.data_types.Uint8",
9+
}
10+
11+
function SoilMoistureMeasuredValue:new_value(...)
12+
local o = self.base_type(table.unpack({...}))
13+
14+
return o
15+
end
16+
17+
function SoilMoistureMeasuredValue:read(device, endpoint_id)
18+
return cluster_base.read(
19+
device,
20+
endpoint_id,
21+
self._cluster.ID,
22+
self.ID,
23+
nil
24+
)
25+
end
26+
27+
function SoilMoistureMeasuredValue:subscribe(device, endpoint_id)
28+
return cluster_base.subscribe(
29+
device,
30+
endpoint_id,
31+
self._cluster.ID,
32+
self.ID,
33+
nil
34+
)
35+
end
36+
37+
function SoilMoistureMeasuredValue:set_parent_cluster(cluster)
38+
self._cluster = cluster
39+
return self
40+
end
41+
42+
function SoilMoistureMeasuredValue:build_test_report_data(
43+
device,
44+
endpoint_id,
45+
value,
46+
status
47+
)
48+
local data = data_types.validate_or_build_type(value, self.base_type)
49+
50+
return cluster_base.build_test_report_data(
51+
device,
52+
endpoint_id,
53+
self._cluster.ID,
54+
self.ID,
55+
data,
56+
status
57+
)
58+
end
59+
60+
function SoilMoistureMeasuredValue:deserialize(tlv_buf)
61+
local data = TLVParser.decode_tlv(tlv_buf)
62+
63+
return data
64+
end
65+
66+
setmetatable(SoilMoistureMeasuredValue, {__call = SoilMoistureMeasuredValue.new_value, __index = SoilMoistureMeasuredValue.base_type})
67+
return SoilMoistureMeasuredValue
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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 SoilMoistureMeasurementLimits = {
6+
ID = 0x0000,
7+
NAME = "SoilMoistureMeasurementLimits",
8+
base_type = require "st.matter.clusters.Global.types.MeasurementAccuracyStruct",
9+
}
10+
11+
function SoilMoistureMeasurementLimits:new_value(...)
12+
local o = self.base_type(table.unpack({...}))
13+
self:augment_type(o)
14+
return o
15+
end
16+
17+
function SoilMoistureMeasurementLimits:read(device, endpoint_id)
18+
return cluster_base.read(
19+
device,
20+
endpoint_id,
21+
self._cluster.ID,
22+
self.ID,
23+
nil
24+
)
25+
end
26+
27+
function SoilMoistureMeasurementLimits:subscribe(device, endpoint_id)
28+
return cluster_base.subscribe(
29+
device,
30+
endpoint_id,
31+
self._cluster.ID,
32+
self.ID,
33+
nil
34+
)
35+
end
36+
37+
function SoilMoistureMeasurementLimits:set_parent_cluster(cluster)
38+
self._cluster = cluster
39+
return self
40+
end
41+
42+
function SoilMoistureMeasurementLimits:build_test_report_data(
43+
device,
44+
endpoint_id,
45+
value,
46+
status
47+
)
48+
local data = data_types.validate_or_build_type(value, self.base_type)
49+
self:augment_type(data)
50+
return cluster_base.build_test_report_data(
51+
device,
52+
endpoint_id,
53+
self._cluster.ID,
54+
self.ID,
55+
data,
56+
status
57+
)
58+
end
59+
60+
function SoilMoistureMeasurementLimits:deserialize(tlv_buf)
61+
local data = TLVParser.decode_tlv(tlv_buf)
62+
self:augment_type(data)
63+
return data
64+
end
65+
66+
setmetatable(SoilMoistureMeasurementLimits, {__call = SoilMoistureMeasurementLimits.new_value, __index = SoilMoistureMeasurementLimits.base_type})
67+
return SoilMoistureMeasurementLimits
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
local attr_mt = {}
2+
attr_mt.__index = function(self, key)
3+
local req_loc = string.format("embedded_clusters.SoilMeasurement.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 SoilMeasurementServerAttributes = {}
11+
12+
function SoilMeasurementServerAttributes:set_parent_cluster(cluster)
13+
self._cluster = cluster
14+
return self
15+
end
16+
17+
setmetatable(SoilMeasurementServerAttributes, attr_mt)
18+
19+
return SoilMeasurementServerAttributes

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ if not pcall(function(cluster) return clusters[cluster] end,
1616
clusters.PressureMeasurement = require "embedded_clusters.PressureMeasurement"
1717
end
1818

19+
-- This can be removed once LuaLibs supports the SoilMeasurement cluster
20+
if not pcall(function(cluster) return clusters[cluster] end,
21+
"SoilMeasurement") then
22+
clusters.SoilMeasurement = require "embedded_clusters.SoilMeasurement"
23+
end
24+
1925
-- Include driver-side definitions when lua libs api version is < 10
2026
if version.api < 10 then
2127
clusters.AirQuality = require "embedded_clusters.AirQuality"
@@ -117,6 +123,9 @@ local matter_driver_template = {
117123
[clusters.RelativeHumidityMeasurement.ID] = {
118124
[clusters.RelativeHumidityMeasurement.attributes.MeasuredValue.ID] = attribute_handlers.humidity_measured_value_handler
119125
},
126+
[clusters.SoilMeasurement.ID] = {
127+
[clusters.SoilMeasurement.attributes.SoilMoistureMeasuredValue.ID] = attribute_handlers.soil_moisture_measured_value_handler
128+
},
120129
[clusters.TemperatureMeasurement.ID] = {
121130
[clusters.TemperatureMeasurement.attributes.MeasuredValue.ID] = attribute_handlers.temperature_measured_value_handler,
122131
[clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = attribute_handlers.temperature_measured_value_bounds_factory(fields.TEMP_MIN),
@@ -164,7 +173,8 @@ local matter_driver_template = {
164173
clusters.BooleanState.attributes.StateValue,
165174
},
166175
[capabilities.relativeHumidityMeasurement.ID] = {
167-
clusters.RelativeHumidityMeasurement.attributes.MeasuredValue
176+
clusters.RelativeHumidityMeasurement.attributes.MeasuredValue,
177+
clusters.SoilMeasurement.attributes.SoilMoistureMeasuredValue
168178
},
169179
[capabilities.temperatureAlarm.ID] = {
170180
clusters.BooleanState.attributes.StateValue,

0 commit comments

Comments
 (0)