connectors/ZeroConfListener.py
changeset 4039 9ff455817691
equal deleted inserted replaced
4038:4b47b4ce0f12 4039:9ff455817691
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 # See COPYING file for copyrights details.
       
     5 
       
     6 import weakref
       
     7 from zeroconf import ServiceBrowser, Zeroconf, get_all_addresses
       
     8 import threading
       
     9 
       
    10 service_type = '_Beremiz._tcp.local.'
       
    11 
       
    12 class ZeroConfListenerClass:
       
    13     def __init__(self, dialog):
       
    14         self.dialog = weakref.ref(dialog)
       
    15 
       
    16         self.IfacesMonitorState = None
       
    17         self.IfacesMonitorTimer = None
       
    18         self.Browser = None
       
    19         self.ZeroConfInstance = None
       
    20         self.PublishedServices = set()
       
    21 
       
    22         self.start()
       
    23 
       
    24     def __del__(self):
       
    25         self.stop()
       
    26 
       
    27     def start(self):
       
    28         self.ZeroConfInstance = Zeroconf()
       
    29         self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
       
    30         # Start the ifaces_monitor timer thread
       
    31         self.IfacesMonitorTimer = threading.Timer(1.0, self.ifaces_monitor)
       
    32         self.IfacesMonitorTimer.start()
       
    33 
       
    34     def stop(self):
       
    35         if self.IfacesMonitorTimer is not None:
       
    36             self.IfacesMonitorTimer.cancel()
       
    37             self.IfacesMonitorTimer = None
       
    38 
       
    39         if self.Browser is not None:
       
    40             self.Browser.cancel()
       
    41             self.Browser = None
       
    42 
       
    43         if  self.ZeroConfInstance is not None:
       
    44             self.ZeroConfInstance.close()
       
    45             self.ZeroConfInstance = None
       
    46 
       
    47     def update_service(self, zeroconf, _type, name):
       
    48         self.remove_service(zeroconf, _type, name)
       
    49         self.add_service(zeroconf, _type, name)
       
    50 
       
    51     def add_service(self, zeroconf, _type, name):
       
    52         dialog = self.dialog()
       
    53         if not dialog:
       
    54             return
       
    55 
       
    56         info = self.ZeroConfInstance.get_service_info(_type, name)
       
    57         if info is None:
       
    58             return
       
    59 
       
    60         typename = info.properties.get(b"protocol", None).decode()
       
    61         ip = str(info.parsed_addresses()[0])
       
    62         port = info.port
       
    63         dialog.addService(typename, ip, port, name)
       
    64         self.PublishedServices.add(name)
       
    65 
       
    66     def remove_service(self, zeroconf, _type, name):
       
    67         dialog = self.dialog()
       
    68         if not dialog:
       
    69             return
       
    70         
       
    71         if name in self.PublishedServices:
       
    72             dialog.removeService(name)
       
    73             self.PublishedServices.discard(name)
       
    74 
       
    75     def ifaces_monitor(self):
       
    76         dialog = self.dialog()
       
    77         if not dialog:
       
    78             return
       
    79 
       
    80         NewState = get_all_addresses()
       
    81         OldState = self.IfacesMonitorState
       
    82         self.IfacesMonitorState = NewState
       
    83         do_restart = False
       
    84         
       
    85         if OldState is not None:
       
    86             # detect if a new address appeared
       
    87             for addr in NewState:
       
    88                 if addr not in OldState:
       
    89                     do_restart = True
       
    90                     break
       
    91                 else:
       
    92                     OldState.remove(addr)
       
    93             # detect if an address disappeared
       
    94             if len(OldState) > 0:
       
    95                 do_restart = True
       
    96 
       
    97             
       
    98         if do_restart:
       
    99             self.stop()
       
   100             
       
   101             while self.PublishedServices:
       
   102                 dialog.removeService(self.PublishedServices.pop())
       
   103         
       
   104             self.start()
       
   105         else:
       
   106             # Restart the ifaces_monitor timer thread
       
   107             self.IfacesMonitorTimer = threading.Timer(1.0, self.ifaces_monitor)
       
   108             self.IfacesMonitorTimer.start()