Skip to content

Commit

Permalink
fix: prefer given SimpleItem if available (#502)
Browse files Browse the repository at this point in the history
* fix: prefer given SimpleItem if available

starting with Axis OS 11.11, several SimpleItem entries are sent, which means that the existing method of determining the value fails

* test: add test for ObjectAnalytics under Axis OS 11.11+

---------

Co-authored-by: swoga <[email protected]>
  • Loading branch information
swoga and swoga authored Oct 21, 2024
1 parent dc5d93c commit 60b812a
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
11 changes: 8 additions & 3 deletions axis/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,17 @@ def traverse(


def extract_name_value(
data: dict[str, list[dict[str, str]] | dict[str, str]],
data: dict[str, list[dict[str, str]] | dict[str, str]], prefer: str | None = None
) -> tuple[str, str]:
"""Extract name and value from a simple item, take first dictionary if it is a list."""
item = data.get("SimpleItem", {})
if isinstance(item, list):
item = item[0]
if prefer is None:
item = item[0]
else:
item = next(
(item for item in item if item.get("@Name", "") == prefer), item[0]
)
return item.get("@Name", ""), item.get("@Value", "")
# return item.get("Name", ""), item.get("Value", "")

Expand Down Expand Up @@ -206,7 +211,7 @@ def _decode_from_bytes(cls, data: bytes) -> Self:

data_type = data_value = ""
if match := traverse(raw, DATA):
data_type, data_value = extract_name_value(match)
data_type, data_value = extract_name_value(match, "active")

return cls._decode_from_dict(
{
Expand Down
1 change: 1 addition & 0 deletions tests/event_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
MOTION_GUARD_INIT = b'<?xml version="1.0" encoding="UTF-8"?>\n<tt:MetadataStream xmlns:tt="http://www.onvif.org/ver10/schema">\n<tt:Event><wsnt:NotificationMessage xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tnsaxis="http://www.axis.com/2009/event/topics" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa5="http://www.w3.org/2005/08/addressing"><wsnt:Topic Dialect="http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple">tnsaxis:CameraApplicationPlatform/MotionGuard/Camera1ProfileANY</wsnt:Topic><wsnt:ProducerReference><wsa5:Address>uri://755cc9bb-cf3a-410b-bd1b-0ec97c6d6256/ProducerReference</wsa5:Address></wsnt:ProducerReference><wsnt:Message><tt:Message UtcTime="2020-09-04T21:01:36.676377Z" PropertyOperation="Initialized"><tt:Source></tt:Source><tt:Key></tt:Key><tt:Data><tt:SimpleItem Name="active" Value="0"/></tt:Data></tt:Message></wsnt:Message></wsnt:NotificationMessage></tt:Event></tt:MetadataStream>\n'

OBJECT_ANALYTICS_INIT = b'<?xml version="1.0" encoding="UTF-8"?>\n<tt:MetadataStream xmlns:tt="http://www.onvif.org/ver10/schema">\n<tt:Event><wsnt:NotificationMessage xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tnsaxis="http://www.axis.com/2009/event/topics" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa5="http://www.w3.org/2005/08/addressing"><wsnt:Topic Dialect="http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple">tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1</wsnt:Topic><wsnt:ProducerReference><wsa5:Address>uri://4b2daa4c-507e-482c-8ae0-2068b1c1d875/ProducerReference</wsa5:Address></wsnt:ProducerReference><wsnt:Message><tt:Message UtcTime="2020-09-04T21:44:04.840805Z" PropertyOperation="Initialized"><tt:Source></tt:Source><tt:Key></tt:Key><tt:Data><tt:SimpleItem Name="active" Value="0"/></tt:Data></tt:Message></wsnt:Message></wsnt:NotificationMessage></tt:Event></tt:MetadataStream>\n'
OBJECT_ANALYTICS_ANY_CHANGE = b'<?xml version="1.0" encoding="UTF-8"?>\n<tt:MetadataStream xmlns:tt="http://www.onvif.org/ver10/schema">\n<tt:Event>\n<wsnt:NotificationMessage xmlns:tns1="http://www.onvif.org/ver10/topics"\nxmlns:tnsaxis="http://www.axis.com/2009/event/topics"\nxmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"\nxmlns:wsa5="http://www.w3.org/2005/08/addressing">\n<wsnt:Topic Dialect="http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple">tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1</wsnt:Topic>\n<wsnt:ProducerReference>\n<wsa5:Address>uri://cfbf96f2-9dc7-437f-aa12-155aacbb0b8f/ProducerReference</wsa5:Address>\n</wsnt:ProducerReference>\n<wsnt:Message>\n<tt:Message UtcTime="2024-10-07T21:09:26.046851Z" PropertyOperation="Changed">\n<tt:Source></tt:Source>\n<tt:Key></tt:Key>\n<tt:Data>\n<tt:SimpleItem Name="classTypes" Value="human"/>\n<tt:SimpleItem Name="active" Value="1"/>\n<tt:SimpleItem Name="objectId" Value="234232"/>\n</tt:Data>\n</tt:Message>\n</wsnt:Message>\n</wsnt:NotificationMessage>\n</tt:Event>\n</tt:MetadataStream>\n'

PIR_INIT = b'<?xml version="1.0" encoding="UTF-8"?>\n<tt:MetadataStream xmlns:tt="http://www.onvif.org/ver10/schema">\n<tt:Event><wsnt:NotificationMessage xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tnsaxis="http://www.axis.com/2009/event/topics" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa5="http://www.w3.org/2005/08/addressing"><wsnt:Topic Dialect="http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple">tns1:Device/tnsaxis:Sensor/PIR</wsnt:Topic><wsnt:ProducerReference><wsa5:Address>uri://94fbe18e-0af8-40d2-8539-67b6ea550c6e/ProducerReference</wsa5:Address></wsnt:ProducerReference><wsnt:Message><tt:Message UtcTime="2019-03-12T23:48:26.371215Z" PropertyOperation="Initialized"><tt:Source><tt:SimpleItem Name="sensor" Value="0"/></tt:Source><tt:Key></tt:Key><tt:Data><tt:SimpleItem Name="state" Value="0"/></tt:Data></tt:Message></wsnt:Message></wsnt:NotificationMessage></tt:Event></tt:MetadataStream>\n'
PIR_CHANGE = b'<?xml version="1.0" encoding="UTF-8"?>\n<tt:MetadataStream xmlns:tt="http://www.onvif.org/ver10/schema">\n<tt:Event><wsnt:NotificationMessage xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tnsaxis="http://www.axis.com/2009/event/topics" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa5="http://www.w3.org/2005/08/addressing"><wsnt:Topic Dialect="http://docs.oasis-open.org/wsn/t-1/TopicExpression/Simple">tns1:Device/tnsaxis:Sensor/PIR</wsnt:Topic><wsnt:ProducerReference><wsa5:Address>uri://94fbe18e-0af8-40d2-8539-67b6ea550c6e/ProducerReference</wsa5:Address></wsnt:ProducerReference><wsnt:Message><tt:Message UtcTime="2019-03-12T23:48:28.425164Z" PropertyOperation="Changed"><tt:Source><tt:SimpleItem Name="sensor" Value="0"/></tt:Source><tt:Key></tt:Key><tt:Data><tt:SimpleItem Name="state" Value="1"/></tt:Data></tt:Message></wsnt:Message></wsnt:NotificationMessage></tt:Event></tt:MetadataStream>\n'
Expand Down
24 changes: 24 additions & 0 deletions tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
LIGHT_STATUS_INIT,
LOITERING_GUARD_INIT,
MOTION_GUARD_INIT,
OBJECT_ANALYTICS_ANY_CHANGE,
OBJECT_ANALYTICS_INIT,
PIR_CHANGE,
PIR_INIT,
Expand Down Expand Up @@ -133,6 +134,18 @@
"tripped": False,
},
),
(
OBJECT_ANALYTICS_ANY_CHANGE,
{
"topic": "tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1",
"source": "",
"source_idx": "Device1Scenario1",
"group": EventGroup.MOTION,
"type": "Object Analytics",
"state": "1",
"tripped": True,
},
),
(
PIR_INIT,
{
Expand Down Expand Up @@ -329,6 +342,17 @@ def test_create_event(input: bytes, expected: tuple) -> None:
"value": "1",
},
),
(
OBJECT_ANALYTICS_ANY_CHANGE,
{
"operation": "Changed",
"topic": "tnsaxis:CameraApplicationPlatform/ObjectAnalytics/Device1Scenario1",
"source": "",
"source_idx": "",
"type": "active",
"value": "1",
},
),
],
)
def test_parse_event_xml(input: bytes, expected: dict):
Expand Down

0 comments on commit 60b812a

Please sign in to comment.