controls/DiscoveryPanel.py
changeset 2477 4866c01e7428
parent 2466 98d28d809488
child 2478 733d77bf0aa7
equal deleted inserted replaced
2476:1881d0ff5ae2 2477:4866c01e7428
    27 from __future__ import absolute_import
    27 from __future__ import absolute_import
    28 import socket
    28 import socket
    29 from six.moves import xrange
    29 from six.moves import xrange
    30 import wx
    30 import wx
    31 import wx.lib.mixins.listctrl as listmix
    31 import wx.lib.mixins.listctrl as listmix
    32 from zeroconf import ServiceBrowser, Zeroconf
    32 from zeroconf import ServiceBrowser, Zeroconf, get_all_addresses
    33 
    33 import netifaces
    34 
    34 
    35 service_type = '_PYRO._tcp.local.'
    35 service_type = '_Beremiz._tcp.local.'
    36 
    36 
    37 
    37 
    38 class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    38 class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    39     def __init__(self, parent, id, name, pos=wx.DefaultPosition,
    39     def __init__(self, parent, id, name, pos=wx.DefaultPosition,
    40                  size=wx.DefaultSize, style=0):
    40                  size=wx.DefaultSize, style=0):
    93     def _init_ctrls(self, prnt):
    93     def _init_ctrls(self, prnt):
    94         self.staticText1 = wx.StaticText(
    94         self.staticText1 = wx.StaticText(
    95             label=_('Services available:'), name='staticText1', parent=self,
    95             label=_('Services available:'), name='staticText1', parent=self,
    96             pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
    96             pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
    97 
    97 
    98         refreshID = wx.NewId()
       
    99         self.RefreshButton = wx.Button(
    98         self.RefreshButton = wx.Button(
   100             id=refreshID,
       
   101             label=_('Refresh'), name='RefreshButton', parent=self,
    99             label=_('Refresh'), name='RefreshButton', parent=self,
   102             pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
   100             pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
   103         self.Bind(wx.EVT_BUTTON, self.OnRefreshButton, id=refreshID)
   101         self.RefreshButton.Bind(wx.EVT_BUTTON, self.OnRefreshButton)
   104 
   102 
   105         self.ByIPCheck = wx.CheckBox(self, label=_("Use IP instead of Service Name"))
   103         self.ByIPCheck = wx.CheckBox(self, label=_("Use IP instead of Service Name"))
       
   104         self.ByIPCheck.SetValue(True)
   106 
   105 
   107         self._init_sizers()
   106         self._init_sizers()
   108         self.Fit()
   107         self.Fit()
   109 
   108 
   110     def __init__(self, parent):
   109     def __init__(self, parent):
   120         self.itemDataMap = {}
   119         self.itemDataMap = {}
   121         self.nextItemId = 0
   120         self.nextItemId = 0
   122 
   121 
   123         self.URI = None
   122         self.URI = None
   124         self.Browser = None
   123         self.Browser = None
   125 
   124         self.ZeroConfInstance = None
   126         self.ZeroConfInstance = Zeroconf()
   125 
   127         self.RefreshList()
   126         self.RefreshList()
   128         self.LatestSelection = None
   127         self.LatestSelection = None
   129 
   128 
       
   129         self.IfacesMonitorState = None
       
   130         self.IfacesMonitorTimer = wx.Timer(self)
       
   131         self.IfacesMonitorTimer.Start(2000)
       
   132         self.Bind(wx.EVT_TIMER, self.IfacesMonitor , self.IfacesMonitorTimer)
       
   133 
   130     def __del__(self):
   134     def __del__(self):
       
   135         self.IfacesMonitorTimer.Stop()
       
   136         self.Browser.cancel()
       
   137         self.ZeroConfInstance.close()
       
   138 
       
   139     def IfacesMonitor(self, event):
       
   140         NewState = get_all_addresses(socket.AF_INET)
       
   141 
       
   142         if self.IfacesMonitorState != NewState: 
       
   143             if self.IfacesMonitorState is not None:
       
   144                 # refresh only if a new address appeared
       
   145                 for addr in NewState:
       
   146                     if addr not in self.IfacesMonitorState:
       
   147                         self.RefreshList()
       
   148                         break
       
   149             self.IfacesMonitorState = NewState
       
   150         event.Skip()
       
   151 
       
   152     def RefreshList(self):
       
   153         self.ServicesList.DeleteAllItems()
   131         if self.Browser is not None:
   154         if self.Browser is not None:
   132             self.Browser.cancel()
   155             self.Browser.cancel()
   133         self.ZeroConfInstance.close()
   156         if self.ZeroConfInstance is not None:
   134 
   157             self.ZeroConfInstance.close()
   135     def RefreshList(self):
   158         self.ZeroConfInstance = Zeroconf()
   136         if self.Browser is not None:
       
   137             self.Browser.cancel()
       
   138         self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
   159         self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
   139 
   160 
   140     def OnRefreshButton(self, event):
   161     def OnRefreshButton(self, event):
   141         self.ServicesList.DeleteAllItems()
       
   142         self.RefreshList()
   162         self.RefreshList()
   143 
   163 
   144     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
   164     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
   145     def GetListCtrl(self):
   165     def GetListCtrl(self):
   146         return self.ServicesList
   166         return self.ServicesList
   165 #
   185 #
   166 #        self.URI = "%s://%s:%s"%(connect_type, connect_address, connect_port)
   186 #        self.URI = "%s://%s:%s"%(connect_type, connect_address, connect_port)
   167 
   187 
   168     def SetURI(self, idx):
   188     def SetURI(self, idx):
   169         self.LatestSelection = idx
   189         self.LatestSelection = idx
   170         svcname = self.getColumnText(idx, 0)
       
   171         connect_type = self.getColumnText(idx, 1)
       
   172         self.URI = str("%s://%s" % (connect_type, svcname + '.' + service_type))
       
   173 
   190 
   174     def GetURI(self):
   191     def GetURI(self):
   175         if self.LatestSelection is not None:
   192         if self.LatestSelection is not None:
   176             if self.ByIPCheck.IsChecked():
   193             if self.ByIPCheck.IsChecked():
   177                 self.URI = "%s://%s:%s" % tuple(
   194                 svcname, scheme, host, port = \
   178                     map(lambda col:self.getColumnText(self.LatestSelection, col),
   195                     map(lambda col:self.getColumnText(self.LatestSelection, col),
   179                         (1, 2, 3)))
   196                         range(4))
   180 
   197                 return ("%s://%s:%s#%s" % (scheme, host, port, svcname)) \
   181             return self.URI
   198                     if scheme[-1] == "S" \
       
   199                     else ("%s://%s:%s" % (scheme, host, port))
       
   200             else:
       
   201                 svcname = self.getColumnText(self.LatestSelection, 0)
       
   202                 connect_type = self.getColumnText(self.LatestSelection, 1)
       
   203                 return str("MDNS://%s" % svcname)
   182         return None
   204         return None
   183 
   205 
   184     def remove_service(self, zeroconf, _type, name):
   206     def remove_service(self, zeroconf, _type, name):
   185         wx.CallAfter(self._removeService, name)
   207         wx.CallAfter(self._removeService, name)
   186 
   208 
   208         '''
   230         '''
   209         called when a service with the desired type is discovered.
   231         called when a service with the desired type is discovered.
   210         '''
   232         '''
   211         info = self.ZeroConfInstance.get_service_info(_type, name)
   233         info = self.ZeroConfInstance.get_service_info(_type, name)
   212         svcname = name.split(".")[0]
   234         svcname = name.split(".")[0]
   213         typename = _type.split(".")[0][1:]
   235         typename = info.properties.get("protocol", None)
   214         ip = str(socket.inet_ntoa(info.address))
   236         ip = str(socket.inet_ntoa(info.address))
   215         port = info.port
   237         port = info.port
   216 
   238 
   217         num_items = self.ServicesList.GetItemCount()
   239         num_items = self.ServicesList.GetItemCount()
   218 
   240