General improvements on the Zeroconf plugin and backend

This commit is contained in:
Fabio Manganiello 2021-03-03 19:19:56 +01:00
parent e43147e6a3
commit 210cefc1a4
2 changed files with 36 additions and 10 deletions

View file

@ -10,7 +10,7 @@ import threading
import time
from threading import Thread
from typing import Optional
from typing import Optional, Dict
from platypush.bus import Bus
from platypush.config import Config
@ -313,9 +313,31 @@ class Backend(Thread, EventGenerator):
s.close()
return addr
def register_service(self, port: Optional[int] = None, name: Optional[str] = None, udp: bool = False):
def register_service(self,
port: Optional[int] = None,
name: Optional[str] = None,
srv_type: Optional[str] = None,
srv_name: Optional[str] = None,
udp: bool = False,
properties: Optional[Dict] = None):
"""
Initialize the Zeroconf service configuration for this backend.
:param port: Service listen port (default: the backend ``port`` attribute if available, or ``None``).
:param name: Service short name (default: backend name).
:param srv_type: Service type (default: ``_platypush-{name}._{proto}.local.``).
:param srv_name: Full service name (default: ``{hostname or device_id}.{type}``).
:param udp: Set to True if this is a UDP service.
:param properties: Extra properties to be passed on the service. Default:
.. code-block:: json
{
"name": "Platypush",
"vendor": "Platypush",
"version": "{platypush_version}"
}
"""
try:
from zeroconf import ServiceInfo, Zeroconf
@ -329,11 +351,12 @@ class Backend(Thread, EventGenerator):
'name': 'Platypush',
'vendor': 'Platypush',
'version': __version__,
**(properties or {}),
}
name = name or re.sub(r'Backend$', '', self.__class__.__name__).lower()
srv_type = '_platypush-{name}._{proto}.local.'.format(name=name, proto='udp' if udp else 'tcp')
srv_name = '{host}.{type}'.format(host=self.device_id, type=srv_type)
srv_type = srv_type or '_platypush-{name}._{proto}.local.'.format(name=name, proto='udp' if udp else 'tcp')
srv_name = srv_name or '{host}.{type}'.format(host=self.device_id, type=srv_type)
if port:
srv_port = port

View file

@ -1,14 +1,14 @@
import queue
import socket
import time
from typing import List, Dict, Any, Optional
from typing import List, Dict, Any, Optional, Union
import zeroconf
from zeroconf import Zeroconf, ServiceInfo, ServiceBrowser
from platypush.context import get_bus
from platypush.message.event.zeroconf import ZeroconfServiceAddedEvent, ZeroconfServiceRemovedEvent, \
ZeroconfServiceUpdatedEvent, ZeroconfEvent
ZeroconfServiceUpdatedEvent
from platypush.plugins import Plugin, action
@ -82,11 +82,11 @@ class ZeroconfPlugin(Plugin):
return list(zeroconf.ZeroconfServiceTypes.find(timeout=timeout))
@action
def discover_service(self, service: str, timeout: Optional[int] = 5) -> Dict[str, Any]:
def discover_service(self, service: Union[str, list], timeout: Optional[int] = 5) -> Dict[str, Any]:
"""
Find all the services matching the specified type.
:param service: Service type (e.g. ``_http._tcp.local.``).
:param service: Service type (e.g. ``_http._tcp.local.``) or list of service types.
:param timeout: Browser timeout in seconds (default: 5). Specify None for no timeout - in such case the
discovery will loop forever and generate events upon service changes.
:return: A ``service_type -> [service_names]`` mapping. Example:
@ -121,11 +121,13 @@ class ZeroconfPlugin(Plugin):
evt_queue = queue.Queue()
zc = Zeroconf()
listener = ZeroconfListener(evt_queue=evt_queue)
browser = ServiceBrowser(zc, service, listener)
discovery_start = time.time()
services = {}
browser = None
try:
browser = ServiceBrowser(zc, service, listener)
while timeout and time.time() - discovery_start < timeout:
to = discovery_start + timeout - time.time() if timeout else None
try:
@ -145,7 +147,8 @@ class ZeroconfPlugin(Plugin):
if not services:
self.logger.warning('No such service discovered: {}'.format(service))
finally:
browser.cancel()
if browser:
browser.cancel()
zc.close()
self._discovery_in_progress = False