Skip to content

Commit 0298090

Browse files
Matter Camera: Remove trigger before zone (#2816)
The server will return `INVALID_IN_STATE` if `RemoveZone` is issued while there is an existing trigger for the given zone. The trigger should be removed first before attempting to remove the zone.
1 parent 6118ebf commit 0298090

2 files changed

Lines changed: 100 additions & 2 deletions

File tree

drivers/SmartThings/matter-switch/src/sub_drivers/camera/camera_handlers/capability_handlers.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,15 @@ end
259259

260260
function CameraCapabilityHandlers.handle_remove_zone(driver, device, cmd)
261261
local endpoint_id = device:component_to_endpoint(cmd.component)
262+
local triggers = device:get_latest_state(
263+
camera_fields.profile_components.main, capabilities.zoneManagement.ID, capabilities.zoneManagement.triggers.NAME
264+
) or {}
265+
for _, v in pairs(triggers) do
266+
if v.zoneId == cmd.args.zoneId then
267+
device:send(clusters.ZoneManagement.server.commands.RemoveTrigger(device, endpoint_id, cmd.args.zoneId))
268+
break
269+
end
270+
end
262271
device:send(clusters.ZoneManagement.server.commands.RemoveZone(device, endpoint_id, cmd.args.zoneId))
263272
end
264273

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

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,7 @@ test.register_coroutine_test(
15731573
test.socket.capability:__queue_receive({
15741574
mock_device.id,
15751575
{ capability = "zoneManagement", component = "main", command = "newZone", args = {
1576-
i .. " zone", {{value = {x = 0, y = 0}}, {value = {x = 1920, y = 1080}} }, i, "blue"
1576+
i .. " zone", {{value = {x = 0, y = 0}}, {value = {x = 1920, y = 1080}} }, i, "#FFFFFF"
15771577
}}
15781578
})
15791579
test.socket.matter:__expect_send({
@@ -1586,7 +1586,7 @@ test.register_coroutine_test(
15861586
clusters.ZoneManagement.types.TwoDCartesianVertexStruct({x = 0, y = 0}),
15871587
clusters.ZoneManagement.types.TwoDCartesianVertexStruct({x = 1920, y = 1080})
15881588
},
1589-
color = "blue"
1589+
color = "#FFFFFF"
15901590
}
15911591
)
15921592
)
@@ -1773,6 +1773,95 @@ test.register_coroutine_test(
17731773
end
17741774
)
17751775

1776+
test.register_coroutine_test(
1777+
"Removing a zone with an existing trigger should send RemoveTrigger followed by RemoveZone",
1778+
function()
1779+
update_device_profile()
1780+
test.wait_for_events()
1781+
1782+
-- Create a zone
1783+
test.socket.capability:__queue_receive({
1784+
mock_device.id,
1785+
{ capability = "zoneManagement", component = "main", command = "newZone", args = {
1786+
"motion zone", {{value = {x = 0, y = 0}}, {value = {x = 1920, y = 1080}}}, "motion", "#FFFFFF"
1787+
}}
1788+
})
1789+
test.socket.matter:__expect_send({
1790+
mock_device.id, clusters.ZoneManagement.server.commands.CreateTwoDCartesianZone(mock_device, CAMERA_EP,
1791+
clusters.ZoneManagement.types.TwoDCartesianZoneStruct({
1792+
name = "motion zone",
1793+
use = clusters.ZoneManagement.types.ZoneUseEnum.MOTION,
1794+
vertices = {
1795+
clusters.ZoneManagement.types.TwoDCartesianVertexStruct({x = 0, y = 0}),
1796+
clusters.ZoneManagement.types.TwoDCartesianVertexStruct({x = 1920, y = 1080})
1797+
},
1798+
color = "#FFFFFF"
1799+
})
1800+
)
1801+
})
1802+
1803+
-- Create a trigger
1804+
test.socket.capability:__queue_receive({
1805+
mock_device.id,
1806+
{ capability = "zoneManagement", component = "main", command = "createOrUpdateTrigger", args = {
1807+
1, 10, 3, 15, 3, 5
1808+
}}
1809+
})
1810+
test.socket.matter:__expect_send({
1811+
mock_device.id, clusters.ZoneManagement.server.commands.CreateOrUpdateTrigger(mock_device, CAMERA_EP, {
1812+
zone_id = 1,
1813+
initial_duration = 10,
1814+
augmentation_duration = 3,
1815+
max_duration = 15,
1816+
blind_duration = 3,
1817+
sensitivity = 5
1818+
})
1819+
})
1820+
1821+
-- Receive the Triggers attribute update from the device reflecting the new trigger
1822+
test.socket.matter:__queue_receive({
1823+
mock_device.id,
1824+
clusters.ZoneManagement.attributes.Triggers:build_test_report_data(
1825+
mock_device, CAMERA_EP, {
1826+
clusters.ZoneManagement.types.ZoneTriggerControlStruct({
1827+
zone_id = 1, initial_duration = 10, augmentation_duration = 3,
1828+
max_duration = 15, blind_duration = 3, sensitivity = 5
1829+
})
1830+
}
1831+
)
1832+
})
1833+
test.socket.capability:__expect_send(
1834+
mock_device:generate_test_message("main", capabilities.zoneManagement.triggers({{
1835+
zoneId = 1, initialDuration = 10, augmentationDuration = 3,
1836+
maxDuration = 15, blindDuration = 3, sensitivity = 5
1837+
}}))
1838+
)
1839+
test.wait_for_events()
1840+
1841+
-- Receive removeZone command: since a trigger exists for zone 1, RemoveTrigger is sent first, then RemoveZone
1842+
test.socket.capability:__queue_receive({
1843+
mock_device.id,
1844+
{ capability = "zoneManagement", component = "main", command = "removeZone", args = { 1 } }
1845+
})
1846+
test.socket.matter:__expect_send({
1847+
mock_device.id, clusters.ZoneManagement.server.commands.RemoveTrigger(mock_device, CAMERA_EP, 1)
1848+
})
1849+
test.socket.matter:__expect_send({
1850+
mock_device.id, clusters.ZoneManagement.server.commands.RemoveZone(mock_device, CAMERA_EP, 1)
1851+
})
1852+
test.wait_for_events()
1853+
1854+
-- Receive the updated Zones attribute from the device with the zone removed
1855+
test.socket.matter:__queue_receive({
1856+
mock_device.id,
1857+
clusters.ZoneManagement.attributes.Zones:build_test_report_data(mock_device, CAMERA_EP, {})
1858+
})
1859+
test.socket.capability:__expect_send(
1860+
mock_device:generate_test_message("main", capabilities.zoneManagement.zones({value = {}}))
1861+
)
1862+
end
1863+
)
1864+
17761865
test.register_coroutine_test(
17771866
"Stream management commands should send the appropriate commands",
17781867
function()

0 commit comments

Comments
 (0)