blob: 3cfb6b1e0585a31e2d4337df789bc000d7d9c6fc (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
"""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")
|