diff options
Diffstat (limited to 'netdisco/tellstick.py')
-rw-r--r-- | netdisco/tellstick.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/netdisco/tellstick.py b/netdisco/tellstick.py new file mode 100644 index 0000000..24cf243 --- /dev/null +++ b/netdisco/tellstick.py @@ -0,0 +1,72 @@ +"""Tellstick device discovery.""" +import socket +from datetime import timedelta +import logging + + +DISCOVERY_PORT = 30303 +DISCOVERY_ADDRESS = '<broadcast>' +DISCOVERY_PAYLOAD = b"D" +DISCOVERY_TIMEOUT = timedelta(seconds=2) + + +class Tellstick: + """Base class to discover Tellstick devices.""" + + def __init__(self): + """Initialize the Tellstick discovery.""" + self.entries = [] + + def scan(self): + """Scan the network.""" + self.update() + + def all(self): + """Scan and return all found entries.""" + self.scan() + return self.entries + + def update(self): + """Scan network for Tellstick devices.""" + entries = [] + + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.settimeout(DISCOVERY_TIMEOUT.seconds) + sock.sendto(DISCOVERY_PAYLOAD, (DISCOVERY_ADDRESS, DISCOVERY_PORT)) + + while True: + try: + data, (address, _) = sock.recvfrom(1024) + entry = data.decode("ascii").split(":") + # expecting product, mac, activation code, version + if len(entry) != 4: + continue + entry = (address,) + tuple(entry) + entries.append(entry) + + except socket.timeout: + break + except UnicodeDecodeError: + # Catch invalid responses + logging.getLogger(__name__).debug( + 'Ignoring invalid unicode response from %s', address) + continue + + self.entries = entries + + sock.close() + + +def main(): + """Test Tellstick discovery.""" + from pprint import pprint + tellstick = Tellstick() + pprint("Scanning for Tellstick devices..") + tellstick.update() + pprint(tellstick.entries) + + +if __name__ == "__main__": + main() |