Skip to content

Commit 3a06809

Browse files
jterracebdracopre-commit-ci[bot]
authored
Add shortened common onvif namespace prefixes (#54)
* Add shortened common onvif namespace prefixes. This fixes some Tapo cameras that respond with a 500 error when receiving the ns0/ns1 namespace prefix with embedded xmlns definitions inside each element. A similar change was done upstream here: FalkTannhaeuser/python-onvif-zeep#46 for mvantellingen/python-zeep#870. I also updated the events example that was broken. * chore(pre-commit.ci): auto fixes * Update requirements.txt * fix examples --------- Co-authored-by: J. Nick Koston <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent e3b0d9c commit 3a06809

File tree

3 files changed

+98
-37
lines changed

3 files changed

+98
-37
lines changed

examples/events.py

Lines changed: 90 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,107 @@
11
"""Example to fetch pullpoint events."""
22

3+
from aiohttp import web
4+
import argparse
35
import asyncio
46
import datetime as dt
57
import logging
8+
import onvif
9+
import os.path
10+
import pprint
11+
import sys
612

13+
SUBSCRIPTION_TIME = dt.timedelta(minutes=1)
14+
WAIT_TIME = dt.timedelta(seconds=30)
715

8-
from onvif import ONVIFCamera
916

10-
logging.getLogger("zeep").setLevel(logging.DEBUG)
17+
def subscription_lost():
18+
print("subscription lost")
1119

1220

13-
async def run():
14-
mycam = ONVIFCamera(
15-
"192.168.3.10",
16-
80,
17-
"hass",
18-
"peek4boo",
19-
wsdl_dir="/home/jason/python-onvif-zeep-async/onvif/wsdl",
21+
async def post_handler(request):
22+
print(request)
23+
print(request.url)
24+
for k, v in request.headers.items():
25+
print(f"{k}: {v}")
26+
body = await request.content.read()
27+
print(body)
28+
return web.Response()
29+
30+
31+
async def run(args):
32+
mycam = onvif.ONVIFCamera(
33+
args.host,
34+
args.port,
35+
args.username,
36+
args.password,
37+
wsdl_dir=f"{os.path.dirname(onvif.__file__)}/wsdl/",
2038
)
2139
await mycam.update_xaddrs()
2240

23-
if not await mycam.create_pullpoint_subscription():
24-
print("PullPoint not supported")
25-
return
26-
27-
event_service = mycam.create_events_service()
28-
properties = await event_service.GetEventProperties()
29-
print(properties)
30-
capabilities = await event_service.GetServiceCapabilities()
31-
print(capabilities)
32-
33-
pullpoint = mycam.create_pullpoint_service()
34-
await pullpoint.SetSynchronizationPoint()
35-
req = pullpoint.create_type("PullMessages")
36-
req.MessageLimit = 100
37-
req.Timeout = dt.timedelta(seconds=30)
38-
messages = await pullpoint.PullMessages(req)
39-
print(messages)
40-
41-
subscription = mycam.create_subscription_service("PullPointSubscription")
42-
termination_time = (
43-
(dt.datetime.utcnow() + dt.timedelta(days=1))
44-
.isoformat(timespec="seconds")
45-
.replace("+00:00", "Z")
46-
)
47-
await subscription.Renew(termination_time)
48-
await subscription.Unsubscribe()
41+
capabilities = await mycam.get_capabilities()
42+
pprint.pprint(capabilities)
43+
44+
if args.notification:
45+
app = web.Application()
46+
app.add_routes([web.post("/", post_handler)])
47+
runner = web.AppRunner(app)
48+
await runner.setup()
49+
site = web.TCPSite(runner, args.notification_address, args.notification_port)
50+
await site.start()
51+
52+
receive_url = f"http://{args.notification_address}:{args.notification_port}/"
53+
manager = await mycam.create_notification_manager(
54+
receive_url,
55+
SUBSCRIPTION_TIME,
56+
subscription_lost,
57+
)
58+
await manager.set_synchronization_point()
59+
60+
print(f"waiting for messages at {receive_url}...")
61+
await asyncio.sleep(WAIT_TIME.total_seconds())
62+
63+
await manager.shutdown()
64+
await runner.cleanup()
65+
else:
66+
manager = await mycam.create_pullpoint_manager(
67+
SUBSCRIPTION_TIME, subscription_lost
68+
)
69+
await manager.set_synchronization_point()
70+
71+
pullpoint = manager.get_service()
72+
print("waiting for messages...")
73+
messages = await pullpoint.PullMessages(
74+
{
75+
"MessageLimit": 100,
76+
"Timeout": WAIT_TIME,
77+
}
78+
)
79+
print(messages)
80+
81+
await manager.shutdown()
82+
4983
await mycam.close()
5084

5185

52-
if __name__ == "__main__":
86+
def main():
87+
logging.getLogger("zeep").setLevel(logging.DEBUG)
88+
89+
parser = argparse.ArgumentParser(prog="EventTester")
90+
parser.add_argument("--host", default="192.168.3.10")
91+
parser.add_argument("--port", type=int, default=80)
92+
parser.add_argument("--username", default="hass")
93+
parser.add_argument("--password", default="peek4boo")
94+
parser.add_argument("--notification", action=argparse.BooleanOptionalAction)
95+
parser.add_argument("--notification_address")
96+
parser.add_argument("--notification_port", type=int, default=8976)
97+
98+
args = parser.parse_args(sys.argv[1:])
99+
if args.notification and args.notification_address is None:
100+
parser.error("--notification requires --notification_address")
101+
53102
loop = asyncio.get_event_loop()
54-
loop.run_until_complete(run())
103+
loop.run_until_complete(run(args))
104+
105+
106+
if __name__ == "__main__":
107+
main()

onvif/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ def _load_document() -> DocumentWithDeferredLoad:
127127
class ZeepAsyncClient(BaseZeepAsyncClient):
128128
"""Overwrite create_service method to be async."""
129129

130+
def __init__(self, *args, **kwargs):
131+
super().__init__(*args, **kwargs)
132+
self.set_ns_prefix("wsnt", "http://docs.oasis-open.org/wsn/b-2")
133+
self.set_ns_prefix("wsa", "http://www.w3.org/2005/08/addressing")
134+
130135
def create_service(self, binding_name, address):
131136
"""Create a new ServiceProxy for the given binding name and address.
132137
:param binding_name: The QName of the binding

requirements_dev.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Package
22
-r requirements.txt
33

4+
# Examples
5+
aiohttp==3.11.9
6+
47
# Dev
58
pytest==8.3.4
69
pytest-cov==6.0.0

0 commit comments

Comments
 (0)