discovery: Make discovery more robust and faster

This migrates toward a simplified listener interface so that commands can do
their work more efficiently.

Change-Id: I5e6fd7bcd6fa511b8af116d6efe3f72ef0aed0d5
diff --git a/mdt/devices.py b/mdt/devices.py
index 8d67056..0d8c1c0 100644
--- a/mdt/devices.py
+++ b/mdt/devices.py
@@ -11,20 +11,20 @@
         print('Devices found:')
         discoveries = self.discoverer.discoveries
         for host, address in discoveries.items():
-            print('%s\t\t%s' % (host, address))
+            print('{0}\t\t({1})'.format(host, address))
 
 class DevicesWaitCommand:
     def __init__(self):
-        self.discoverer = Discoverer()
+        self.found_devices = False
+        self.discoverer = Discoverer(self)
+
+    def add_device(self, hostname, address):
+        self.found_devices = True
+        self.hostname = hostname
+        self.address = address
 
     def run(self, args):
         print('Waiting for device...')
-        found_device = False
-        while True:
-            sleep(1)
-            discoveries = self.discoverer.discoveries
-            if discoveries:
-                break
-        print('Devices found:')
-        for host, address in self.discoverer.discoveries.items():
-            print('%s\t\t%s' % (host, address))
+        while not self.found_devices:
+            sleep(0.1)
+        print('Device found: {0} ({1})'.format(self.hostname, self.address))
diff --git a/mdt/discoverer.py b/mdt/discoverer.py
index b4664c6..78d5255 100644
--- a/mdt/discoverer.py
+++ b/mdt/discoverer.py
@@ -4,9 +4,10 @@
 import socket
 
 class Discoverer:
-    def __init__(self):
+    def __init__(self, listener = None):
         self.zeroconf = Zeroconf()
         self.discoveries = {}
+        self.listener = listener
         browser = ServiceBrowser(self.zeroconf, "_google_mdt._tcp.local.", self)
 
     def add_service(self, zeroconf, type, name):
@@ -15,7 +16,11 @@
             hostname = info.server.split('.')[0]
             address = socket.inet_ntoa(cast(bytes, info.address))
             self.discoveries[hostname] = address
+            if self.listener and hasattr(self.listener, "add_device"):
+                self.listener.add_device(hostname, address)
 
     def remove_service(self, zeroconf, type, name):
         info = self.zeroconf.get_service_info(type, name)
+        if self.listener and hasattr(self.listener, "remove_device"):
+            self.listener.remove_device(info.server, self.discoveries[info.server])
         del(self.discoveries[info.server])