Skip to content

Commit 2d5cab2

Browse files
Add support for Irrigation System device type
This adds support for the Irrigation System device type, introduced with Matter 1.5.
1 parent aa630fa commit 2d5cab2

File tree

8 files changed

+481
-4
lines changed

8 files changed

+481
-4
lines changed

drivers/SmartThings/matter-switch/fingerprints.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3566,6 +3566,11 @@ matterGeneric:
35663566
deviceTypes:
35673567
- id: 0x0110 # Mounted Dimmable Load Control
35683568
deviceProfileName: switch-level
3569+
- id: "matter/irrigation-system"
3570+
deviceLabel: Matter Irrigation System
3571+
deviceTypes:
3572+
- id: 0x0040 # Irrigation System
3573+
deviceProfileName: irrigation-system
35693574
- id: "matter/water-valve"
35703575
deviceLabel: Matter Water Valve
35713576
deviceTypes:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: irrigation-system-level
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: valve
6+
version: 1
7+
- id: level
8+
version: 1
9+
config:
10+
values:
11+
- key: "level.value"
12+
range: [0, 100]
13+
- id: firmwareUpdate
14+
version: 1
15+
- id: refresh
16+
version: 1
17+
categories:
18+
- name: IrrigationSystem
19+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: irrigation-system
2+
components:
3+
- id: main
4+
capabilities:
5+
- id: valve
6+
version: 1
7+
- id: firmwareUpdate
8+
version: 1
9+
- id: refresh
10+
version: 1
11+
categories:
12+
- name: IrrigationSystem
13+

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function SwitchLifecycleHandlers.device_init(driver, device)
101101
end
102102
device:subscribe()
103103

104-
-- device energy reporting must be handled cumulatively, periodically, or by both simulatanously.
104+
-- device energy reporting must be handled cumulatively, periodically, or by both simultaneously.
105105
-- To ensure a single source of truth, we only handle a device's periodic reporting if cumulative reporting is not supported.
106106
if #embedded_cluster_utils.get_endpoints(device, clusters.ElectricalEnergyMeasurement.ID,
107107
{feature_bitmap = clusters.ElectricalEnergyMeasurement.types.Feature.CUMULATIVE_ENERGY}) > 0 then

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

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ end
1818
local DeviceConfiguration = {}
1919
local SwitchDeviceConfiguration = {}
2020
local ButtonDeviceConfiguration = {}
21+
local ValveDeviceConfiguration = {}
2122

2223
function SwitchDeviceConfiguration.assign_profile_for_onoff_ep(device, server_onoff_ep_id, is_child_device)
2324
local ep_info = switch_utils.get_endpoint_info(device, server_onoff_ep_id)
@@ -156,6 +157,48 @@ function ButtonDeviceConfiguration.configure_buttons(device)
156157
end
157158
end
158159

160+
function ValveDeviceConfiguration.assign_profile_for_valve_ep(device, valve_ep_id)
161+
local profile = "irrigation-system"
162+
163+
for _, ep in ipairs(device.endpoints) do
164+
if ep.endpoint_id == valve_ep_id then
165+
if switch_utils.find_cluster_on_ep(ep, clusters.ValveConfigurationAndControl.ID) then
166+
for _, cluster in ipairs(ep.clusters) do
167+
if cluster.cluster_id == clusters.ValveConfigurationAndControl.ID and
168+
cluster.feature_map and (cluster.feature_map & clusters.ValveConfigurationAndControl.types.Feature.LEVEL) ~= 0 then
169+
profile = profile .. "-level"
170+
break
171+
end
172+
end
173+
end
174+
break
175+
end
176+
end
177+
178+
return profile
179+
end
180+
181+
function ValveDeviceConfiguration.create_child_devices(driver, device, valve_ep_ids, default_endpoint_id)
182+
for device_num, ep_id in ipairs(valve_ep_ids) do
183+
local label_and_name = string.format("%s Valve %d", device.label, device_num)
184+
local child_profile = ValveDeviceConfiguration.assign_profile_for_valve_ep(device, ep_id)
185+
driver:try_create_device(
186+
{
187+
type = "EDGE_CHILD",
188+
label = label_and_name,
189+
profile = child_profile,
190+
parent_device_id = device.id,
191+
parent_assigned_child_key = string.format("%d", ep_id),
192+
vendor_provided_label = label_and_name
193+
}
194+
)
195+
end
196+
197+
-- Persist so that the find_child function is always set on each driver init.
198+
device:set_field(fields.IS_PARENT_CHILD_DEVICE, true, {persist = true})
199+
device:set_find_child(switch_utils.find_child)
200+
end
201+
159202

160203
-- [[ PROFILE MATCHING AND CONFIGURATIONS ]] --
161204

@@ -174,7 +217,40 @@ function DeviceConfiguration.match_profile(driver, device)
174217
local default_endpoint_id = switch_utils.find_default_endpoint(device)
175218
local updated_profile
176219

177-
if #embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID) > 0 then
220+
local is_irrigation_system = false
221+
for _, ep in ipairs(device.endpoints) do
222+
for _, dt in ipairs(ep.device_types) do
223+
if dt.device_type_id == fields.DEVICE_TYPE_ID.IRRIGATION_SYSTEM then
224+
is_irrigation_system = true
225+
break
226+
end
227+
end
228+
end
229+
230+
local valve_ep_ids = device:get_endpoints(clusters.ValveConfigurationAndControl.ID)
231+
232+
if is_irrigation_system then
233+
updated_profile = "irrigation-system"
234+
table.sort(valve_ep_ids)
235+
for _, ep in ipairs(device.endpoints) do
236+
if ep.endpoint_id == valve_ep_ids[1] then
237+
if switch_utils.find_cluster_on_ep(ep, clusters.ValveConfigurationAndControl.ID) then
238+
for _, cluster in ipairs(ep.clusters) do
239+
if cluster.cluster_id == clusters.ValveConfigurationAndControl.ID and
240+
cluster.feature_map and (cluster.feature_map & clusters.ValveConfigurationAndControl.types.Feature.LEVEL) ~= 0 then
241+
updated_profile = updated_profile .. "-level"
242+
break
243+
end
244+
end
245+
end
246+
break
247+
end
248+
end
249+
if #valve_ep_ids > 1 then
250+
table.remove(valve_ep_ids, 1) -- the first valve ep is accounted for in the main irrigation system profile
251+
ValveDeviceConfiguration.create_child_devices(driver, device, valve_ep_ids, default_endpoint_id)
252+
end
253+
elseif #valve_ep_ids > 0 then
178254
updated_profile = "water-valve"
179255
if #embedded_cluster_utils.get_endpoints(device, clusters.ValveConfigurationAndControl.ID,
180256
{feature_bitmap = clusters.ValveConfigurationAndControl.types.Feature.LEVEL}) > 0 then
@@ -221,5 +297,6 @@ end
221297
return {
222298
DeviceCfg = DeviceConfiguration,
223299
SwitchCfg = SwitchDeviceConfiguration,
224-
ButtonCfg = ButtonDeviceConfiguration
300+
ButtonCfg = ButtonDeviceConfiguration,
301+
ValveCfg = ValveDeviceConfiguration
225302
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ SwitchFields.DEVICE_TYPE_ID = {
4343
DOORBELL = 0x0143,
4444
ELECTRICAL_SENSOR = 0x0510,
4545
GENERIC_SWITCH = 0x000F,
46+
IRRIGATION_SYSTEM = 0x0040,
4647
MOUNTED_ON_OFF_CONTROL = 0x010F,
4748
MOUNTED_DIMMABLE_LOAD_CONTROL = 0x0110,
4849
ON_OFF_PLUG_IN_UNIT = 0x010A,
50+
WATER_VALVE = 0x0042,
4951
LIGHT = {
5052
ON_OFF = 0x0100,
5153
DIMMABLE = 0x0101,
@@ -148,7 +150,7 @@ SwitchFields.switch_category_vendor_overrides = {
148150
SwitchFields.ELECTRICAL_SENSOR_EPS = "__electrical_sensor_eps"
149151

150152
--- used in tandem with an EP ID. Stores the required electrical tags "-power", "-energy-powerConsumption", etc.
151-
--- for an Electrical Sensor EP with a "primary" endpoint, used during device profling.
153+
--- for an Electrical Sensor EP with a "primary" endpoint, used during device profiling.
152154
SwitchFields.ELECTRICAL_TAGS = "__electrical_tags"
153155

154156
SwitchFields.profiling_data = {
@@ -299,6 +301,10 @@ SwitchFields.device_type_attribute_map = {
299301
clusters.ElectricalPowerMeasurement.attributes.ActivePower,
300302
clusters.ElectricalEnergyMeasurement.attributes.CumulativeEnergyImported,
301303
clusters.ElectricalEnergyMeasurement.attributes.PeriodicEnergyImported
304+
},
305+
[SwitchFields.DEVICE_TYPE_ID.WATER_VALVE] = {
306+
clusters.ValveConfigurationAndControl.attributes.CurrentState,
307+
clusters.ValveConfigurationAndControl.attributes.CurrentLevel
302308
}
303309
}
304310

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ function utils.find_default_endpoint(device)
187187
end
188188
end
189189

190+
local water_valve_eps = utils.get_endpoints_by_device_type(device, fields.DEVICE_TYPE_ID.WATER_VALVE)
191+
if #water_valve_eps > 0 then
192+
return get_first_non_zero_endpoint(water_valve_eps)
193+
end
194+
190195
device.log.warn(string.format("Did not find default endpoint, will use endpoint %d instead", device.MATTER_DEFAULT_ENDPOINT))
191196
return device.MATTER_DEFAULT_ENDPOINT
192197
end

0 commit comments

Comments
 (0)