diff --git a/examples/events.py b/examples/events.py index e71968f..420060c 100644 --- a/examples/events.py +++ b/examples/events.py @@ -1,54 +1,107 @@ """Example to fetch pullpoint events.""" +from aiohttp import web +import argparse import asyncio import datetime as dt import logging +import onvif +import os.path +import pprint +import sys +SUBSCRIPTION_TIME = dt.timedelta(minutes=1) +WAIT_TIME = dt.timedelta(seconds=30) -from onvif import ONVIFCamera -logging.getLogger("zeep").setLevel(logging.DEBUG) +def subscription_lost(): + print("subscription lost") -async def run(): - mycam = ONVIFCamera( - "192.168.3.10", - 80, - "hass", - "peek4boo", - wsdl_dir="/home/jason/python-onvif-zeep-async/onvif/wsdl", +async def post_handler(request): + print(request) + print(request.url) + for k, v in request.headers.items(): + print(f"{k}: {v}") + body = await request.content.read() + print(body) + return web.Response() + + +async def run(args): + mycam = onvif.ONVIFCamera( + args.host, + args.port, + args.username, + args.password, + wsdl_dir=f"{os.path.dirname(onvif.__file__)}/wsdl/", ) await mycam.update_xaddrs() - if not await mycam.create_pullpoint_subscription(): - print("PullPoint not supported") - return - - event_service = mycam.create_events_service() - properties = await event_service.GetEventProperties() - print(properties) - capabilities = await event_service.GetServiceCapabilities() - print(capabilities) - - pullpoint = mycam.create_pullpoint_service() - await pullpoint.SetSynchronizationPoint() - req = pullpoint.create_type("PullMessages") - req.MessageLimit = 100 - req.Timeout = dt.timedelta(seconds=30) - messages = await pullpoint.PullMessages(req) - print(messages) - - subscription = mycam.create_subscription_service("PullPointSubscription") - termination_time = ( - (dt.datetime.utcnow() + dt.timedelta(days=1)) - .isoformat(timespec="seconds") - .replace("+00:00", "Z") - ) - await subscription.Renew(termination_time) - await subscription.Unsubscribe() + capabilities = await mycam.get_capabilities() + pprint.pprint(capabilities) + + if args.notification: + app = web.Application() + app.add_routes([web.post("/", post_handler)]) + runner = web.AppRunner(app) + await runner.setup() + site = web.TCPSite(runner, args.notification_address, args.notification_port) + await site.start() + + receive_url = f"http://{args.notification_address}:{args.notification_port}/" + manager = await mycam.create_notification_manager( + receive_url, + SUBSCRIPTION_TIME, + subscription_lost, + ) + await manager.set_synchronization_point() + + print(f"waiting for messages at {receive_url}...") + await asyncio.sleep(WAIT_TIME.total_seconds()) + + await manager.shutdown() + await runner.cleanup() + else: + manager = await mycam.create_pullpoint_manager( + SUBSCRIPTION_TIME, subscription_lost + ) + await manager.set_synchronization_point() + + pullpoint = manager.get_service() + print("waiting for messages...") + messages = await pullpoint.PullMessages( + { + "MessageLimit": 100, + "Timeout": WAIT_TIME, + } + ) + print(messages) + + await manager.shutdown() + await mycam.close() -if __name__ == "__main__": +def main(): + logging.getLogger("zeep").setLevel(logging.DEBUG) + + parser = argparse.ArgumentParser(prog="EventTester") + parser.add_argument("--host", default="192.168.3.10") + parser.add_argument("--port", type=int, default=80) + parser.add_argument("--username", default="hass") + parser.add_argument("--password", default="peek4boo") + parser.add_argument("--notification", action=argparse.BooleanOptionalAction) + parser.add_argument("--notification_address") + parser.add_argument("--notification_port", type=int, default=8976) + + args = parser.parse_args(sys.argv[1:]) + if args.notification and args.notification_address is None: + parser.error("--notification requires --notification_address") + loop = asyncio.get_event_loop() - loop.run_until_complete(run()) + loop.run_until_complete(run(args)) + + +if __name__ == "__main__": + main() diff --git a/onvif/client.py b/onvif/client.py index 59b1c1a..916e368 100644 --- a/onvif/client.py +++ b/onvif/client.py @@ -127,6 +127,11 @@ def _load_document() -> DocumentWithDeferredLoad: class ZeepAsyncClient(BaseZeepAsyncClient): """Overwrite create_service method to be async.""" + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.set_ns_prefix("wsnt", "http://docs.oasis-open.org/wsn/b-2") + self.set_ns_prefix("wsa", "http://www.w3.org/2005/08/addressing") + def create_service(self, binding_name, address): """Create a new ServiceProxy for the given binding name and address. :param binding_name: The QName of the binding diff --git a/requirements_dev.txt b/requirements_dev.txt index eaa59b5..09e4845 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,6 +1,9 @@ # Package -r requirements.txt +# Examples +aiohttp==3.11.9 + # Dev pytest==8.3.4 pytest-cov==6.0.0