Now, PYRO:// locations also accept MDNS service names
authorEdouard Tisserant
Sat, 09 Jun 2012 00:08:34 +0200
changeset 763 c1104099c151
parent 762 aaacc83aa86b
child 768 fe47069f214c
Now, PYRO:// locations also accept MDNS service names
ProjectController.py
connectors/PYRO/__init__.py
connectors/__init__.py
runtime/ServicePublisher.py
tests/python/beremiz.xml
tests/python/plc.xml
util/discovery.py
--- a/ProjectController.py	Fri Jun 08 12:39:37 2012 +0200
+++ b/ProjectController.py	Sat Jun 09 00:08:34 2012 +0200
@@ -1271,6 +1271,8 @@
                 uri = dialog.GetURI()
                 dialog.Destroy()
             except:
+                self.logger.write_error(_("Local service discovery failed !\n"))
+                self.logger.write_error(traceback.format_exc())
                 uri = None
             
             # Nothing choosed or cancel button
--- a/connectors/PYRO/__init__.py	Fri Jun 08 12:39:37 2012 +0200
+++ b/connectors/PYRO/__init__.py	Sat Jun 09 00:08:34 2012 +0200
@@ -24,6 +24,8 @@
 import traceback
 from time import sleep
 import copy
+import socket
+service_type = '_PYRO._tcp.local.'
 
 # this module attribute contains a list of DNS-SD (Zeroconf) service types
 # supported by this connector confnode.
@@ -38,12 +40,27 @@
     confnodesroot.logger.write(_("Connecting to URI : %s\n")%uri)
 
     servicetype, location = uri.split("://")
+    if location.find(service_type) != -1:
+        try :
+            from util.Zeroconf import Zeroconf
+            r = Zeroconf()
+            i=r.getServiceInfo(service_type, location)
+            ip = str(socket.inet_ntoa(i.getAddress()))
+            port = str(i.getPort())
+            newlocation = ip+':'+port
+            confnodesroot.logger.write(_("'%s' is located at %s\n")%(location, newlocation))
+            location = newlocation
+            r.close()
+        except Exception, msg:
+            confnodesroot.logger.write_error(_("MDNS resolution failure for '%s'\n")%location)
+            confnodesroot.logger.write_error(traceback.format_exc())
+            return None
     
     # Try to get the proxy object
     try :
         RemotePLCObjectProxy = pyro.getAttrProxyForURI("PYROLOC://"+location+"/PLCObject")
     except Exception, msg:
-        confnodesroot.logger.write_error(_("Wrong URI, please check it !\n"))
+        confnodesroot.logger.write_error(_("Connection to '%s' failed.\n")%location)
         confnodesroot.logger.write_error(traceback.format_exc())
         return None
 
--- a/connectors/__init__.py	Fri Jun 08 12:39:37 2012 +0200
+++ b/connectors/__init__.py	Sat Jun 09 00:08:34 2012 +0200
@@ -27,9 +27,6 @@
 _base_path = path.split(__file__)[0]
 
 
-# a dict from a DNS-SD service type to a connector module that support it
-dnssd_connectors = {"_PYRO._tcp.local.":"PYRO"}
-
 def _GetLocalConnectorClassFactory(name):
     return lambda:getattr(__import__(name,globals(),locals()), name + "_connector_factory")
 
--- a/runtime/ServicePublisher.py	Fri Jun 08 12:39:37 2012 +0200
+++ b/runtime/ServicePublisher.py	Sat Jun 09 00:08:34 2012 +0200
@@ -25,11 +25,11 @@
 import socket, threading
 from util import Zeroconf
 
+service_type = '_PYRO._tcp.local.'
+
 class ServicePublisher():
     def __init__(self):
         # type: fully qualified service type name
-        self.service_type = '_PYRO._tcp.local.'
-        # properties: dictionary of properties (or a string holding the bytes for the text field)
         self.serviceproperties = {'description':'Beremiz remote PLC'}
         
         self.name = None
@@ -48,7 +48,7 @@
 
     def _RegisterService(self, name, ip, port):
         # name: fully qualified service name
-        self.service_name = 'Beremiz_%s.%s'%(name,self.service_type)
+        self.service_name = 'Beremiz_%s.%s'%(name,service_type)
         self.name = name
         self.port = port
 
@@ -61,7 +61,7 @@
         self.ip_32b = socket.inet_aton(ip)
 
         self.server.registerService(
-             Zeroconf.ServiceInfo(self.service_type,
+             Zeroconf.ServiceInfo(service_type,
                                   self.service_name,
                                   self.ip_32b,
                                   self.port,
@@ -73,7 +73,7 @@
             self.retrytimer.cancel()
 
         self.server.unregisterService(
-                                      Zeroconf.ServiceInfo(self.service_type, 
+                                      Zeroconf.ServiceInfo(service_type, 
                                                            self.service_name, 
                                                            self.ip_32b, 
                                                            self.port, 
--- a/tests/python/beremiz.xml	Fri Jun 08 12:39:37 2012 +0200
+++ b/tests/python/beremiz.xml	Sat Jun 09 00:08:34 2012 +0200
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<BeremizRoot URI_location="LOCAL://">
+<BeremizRoot>
   <TargetType/>
 </BeremizRoot>
--- a/tests/python/plc.xml	Fri Jun 08 12:39:37 2012 +0200
+++ b/tests/python/plc.xml	Sat Jun 09 00:08:34 2012 +0200
@@ -8,7 +8,7 @@
               productVersion="0.0"
               creationDateTime="2008-12-14T16:21:19"/>
   <contentHeader name="Beremiz Python Support Tests"
-                 modificationDateTime="2012-05-20T18:14:50">
+                 modificationDateTime="2012-06-08T23:11:45">
     <coordinateInfo>
       <pageSize x="1024" y="1024"/>
       <fbd>
--- a/util/discovery.py	Fri Jun 08 12:39:37 2012 +0200
+++ b/util/discovery.py	Sat Jun 09 00:08:34 2012 +0200
@@ -28,6 +28,8 @@
 
 import connectors
 
+service_type = '_PYRO._tcp.local.'
+
 class AutoWidthListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
     def __init__(self, parent, id, name, pos=wx.DefaultPosition,
                  size=wx.DefaultSize, style=0):
@@ -36,8 +38,8 @@
 
 [ID_DISCOVERYDIALOG, ID_DISCOVERYDIALOGSTATICTEXT1, 
  ID_DISCOVERYDIALOGSERVICESLIST, ID_DISCOVERYDIALOGREFRESHBUTTON, 
- ID_DISCOVERYDIALOGLOCALBUTTON, 
-] = [wx.NewId() for _init_ctrls in range(5)]
+ ID_DISCOVERYDIALOGLOCALBUTTON, ID_DISCOVERYDIALOGIPBUTTON, 
+] = [wx.NewId() for _init_ctrls in range(6)]
 
 class DiscoveryDialog(wx.Dialog, listmix.ColumnSorterMixin):
     
@@ -53,6 +55,7 @@
     def _init_coll_ButtonGridSizer_Items(self, parent):
         parent.AddWindow(self.RefreshButton, 0, border=0, flag=0)
         parent.AddWindow(self.LocalButton, 0, border=0, flag=0)
+        parent.AddWindow(self.IpButton, 0, border=0, flag=0)
         parent.AddSizer(self.ButtonSizer, 0, border=0, flag=0)
         
     def _init_coll_ButtonGridSizer_Growables(self, parent):
@@ -62,7 +65,7 @@
     
     def _init_sizers(self):
         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=10)
-        self.ButtonGridSizer = wx.FlexGridSizer(cols=3, hgap=5, rows=1, vgap=0)
+        self.ButtonGridSizer = wx.FlexGridSizer(cols=4, hgap=5, rows=1, vgap=0)
         
         self._init_coll_MainSizer_Items(self.MainSizer)
         self._init_coll_MainSizer_Growables(self.MainSizer)
@@ -107,6 +110,11 @@
               label=_('Local'), name='LocalButton', parent=self,
               pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
         self.Bind(wx.EVT_BUTTON, self.OnLocalButton, id=ID_DISCOVERYDIALOGLOCALBUTTON)
+
+        self.IpButton = wx.Button(id=ID_DISCOVERYDIALOGIPBUTTON,
+              label=_('Add IP'), name='IpButton', parent=self,
+              pos=wx.Point(0, 0), size=wx.DefaultSize, style=0)
+        self.Bind(wx.EVT_BUTTON, self.OnIpButton, id=ID_DISCOVERYDIALOGIPBUTTON)
         
         self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTER)
         
@@ -119,23 +127,19 @@
         self.nextItemId = 0
         
         self.URI = None
-        self.Browsers = []
+        self.Browser = None
         
         self.ZeroConfInstance = Zeroconf()
         self.RefreshList()
+        self.LatestSelection=None
         
     def __del__(self):
-        for browser in self.Browsers:
-            browser.cancel()
+        if self.Browser is not None : self.Browser.cancel()
         self.ZeroConfInstance.close()
         
     def RefreshList(self):
-        for browser in self.Browsers:
-            browser.cancel()
-        
-        self.Browsers = []
-        for t in connectors.dnssd_connectors.keys():
-            self.Browsers.append(ServiceBrowser(self.ZeroConfInstance, t, self))
+        if self.Browser is not None : self.Browser.cancel()
+        self.Browser = ServiceBrowser(self.ZeroConfInstance, service_type, self)
 
     def OnRefreshButton(self, event):
         self.ServicesList.DeleteAllItems()
@@ -146,6 +150,13 @@
         self.EndModal(wx.ID_OK)
         event.Skip()
 
+    def OnIpButton(self, event):
+        if self.LatestSelection is not None:
+            l = lambda col : self.getColumnText(self.LatestSelection,col)
+            self.URI = "%s://%s:%s"%tuple(map(l,(1,2,3)))
+            self.EndModal(wx.ID_OK)
+        event.Skip()
+
     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
     def GetListCtrl(self):
         return self.ServicesList
@@ -163,17 +174,23 @@
         self.EndModal(wx.ID_OK)
         event.Skip()
 
+#    def SetURI(self, idx):
+#        connect_type = self.getColumnText(idx, 1)
+#        connect_address = self.getColumnText(idx, 2)
+#        connect_port = self.getColumnText(idx, 3)
+#        
+#        self.URI = "%s://%s:%s"%(connect_type, connect_address, connect_port)
+
     def SetURI(self, idx):
+        self.LatestSelection = idx
+        svcname = self.getColumnText(idx, 0) 
         connect_type = self.getColumnText(idx, 1)
-        connect_address = self.getColumnText(idx, 2)
-        connect_port = self.getColumnText(idx, 3)
-        
-        self.URI = "%s://%s:%s"%(connect_type, connect_address, connect_port)
-
+        self.URI = "%s://%s"%(connect_type, svcname + '.' + service_type)
+        
     def GetURI(self):
         return self.URI
         
-    def removeService(self, zeroconf, type, name):
+    def removeService(self, zeroconf, _type, name):
         wx.CallAfter(self._removeService, name)
 
 
@@ -194,17 +211,17 @@
                 self.ServicesList.DeleteItem(idx)
                 break
         
-    def addService(self, zeroconf, type, name):
-        wx.CallAfter(self._addService, type, name)
-
-    def _addService(self, type, name):
+    def addService(self, zeroconf, _type, name):
+        wx.CallAfter(self._addService, _type, name)
+
+    def _addService(self, _type, name):
         '''
         called when a service with the desired type is discovered.
         '''
-        info = self.ZeroConfInstance.getServiceInfo(type, name)
+        info = self.ZeroConfInstance.getServiceInfo(_type, name)
 
         svcname  = name.split(".")[0]
-        typename = type.split(".")[0][1:]
+        typename = _type.split(".")[0][1:]
         ip       = str(socket.inet_ntoa(info.getAddress()))
         port     = info.getPort()