You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

88 lines
2.4 KiB

"""Provide service that scans the network in intervals."""
import logging
import threading
import time
from collections import defaultdict
from .discovery import NetworkDiscovery
DEFAULT_INTERVAL = 300 # seconds
_LOGGER = logging.getLogger(__name__)
class DiscoveryService(threading.Thread):
"""Service that will scan the network for devices each `interval` seconds.
Add listeners to the service to be notified of new services found.
"""
def __init__(self, interval=DEFAULT_INTERVAL):
"""Initialize the discovery."""
super(DiscoveryService, self).__init__()
# Scanning interval
self.interval = interval
# Listeners for new services
self.listeners = []
# To track when we have to stop
self._stop = threading.Event()
# Tell Python not to wait till this thread exits
self.daemon = True
# The discovery object
self.discovery = None
# Dict to keep track of found services. We do not want to
# broadcast the same found service twice.
self._found = defaultdict(list)
def add_listener(self, listener):
"""Add a listener for new services."""
self.listeners.append(listener)
def stop(self):
"""Stop the service."""
self._stop.set()
def run(self):
"""Start the discovery service."""
self.discovery = NetworkDiscovery()
while True:
self._scan()
seconds_since_scan = 0
while seconds_since_scan < self.interval:
if self._stop.is_set():
return
time.sleep(1)
seconds_since_scan += 1
def _scan(self):
"""Scan for new devices."""
_LOGGER.info("Scanning")
self.discovery.scan()
for disc in self.discovery.discover():
for service in self.discovery.get_info(disc):
self._service_found(disc, service)
self.discovery.stop()
def _service_found(self, disc, service):
"""Tell listeners a service was found."""
if service not in self._found[disc]:
self._found[disc].append(service)
for listener in self.listeners:
try:
listener(disc, service)
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
"Error calling listener")