diff options
Diffstat (limited to 'netdisco/lms.py')
-rw-r--r-- | netdisco/lms.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/netdisco/lms.py b/netdisco/lms.py new file mode 100644 index 0000000..6026a86 --- /dev/null +++ b/netdisco/lms.py @@ -0,0 +1,78 @@ +"""Squeezebox/Logitech Media server discovery.""" +import socket + +from .const import ATTR_HOST, ATTR_PORT + +DISCOVERY_PORT = 3483 +DEFAULT_DISCOVERY_TIMEOUT = 2 + + +class LMS: + """Base class to discover Logitech Media servers.""" + + def __init__(self): + """Initialize the Logitech discovery.""" + self.entries = [] + self.last_scan = None + + def scan(self): + """Scan the network.""" + self.update() + + def all(self): + """Scan and return all found entries.""" + self.scan() + return list(self.entries) + + def update(self): + """Scan network for Logitech Media Servers.""" + lms_ip = '<broadcast>' + lms_port = DISCOVERY_PORT + lms_msg = b"eJSON\0" + lms_timeout = DEFAULT_DISCOVERY_TIMEOUT + + entries = [] + + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + sock.settimeout(lms_timeout) + sock.bind(('', 0)) + + try: + sock.sendto(lms_msg, (lms_ip, lms_port)) + + while True: + try: + data, server = sock.recvfrom(1024) + if data.startswith(b'E'): + # Full response is EJSON\xYYXXXX + # Where YY is length of port string (ie 4) + # And XXXX is the web interface port (ie 9000) + port = None + if data.startswith(b'JSON', 1): + length = data[5:6][0] + port = int(data[0-length:]) + entries.append({ + ATTR_HOST: server[0], + ATTR_PORT: port, + }) + except socket.timeout: + break + finally: + sock.close() + self.entries = entries + + +def main(): + """Test LMS discovery.""" + from pprint import pprint + + lms = LMS() + + pprint("Scanning for Logitech Media Servers...") + lms.update() + pprint(lms.entries) + + +if __name__ == "__main__": + main() |