--- a/connectors/PYRO/__init__.py Thu Feb 05 23:32:31 2015 +0100
+++ b/connectors/PYRO/__init__.py Sun Feb 08 16:50:54 2015 +0100
@@ -37,7 +37,7 @@
This returns the connector to Pyro style PLCobject
- confnodesroot.logger.write(_("Connecting to URI : %s\n")%uri)
+ confnodesroot.logger.write(_("PYRO connecting to URI : %s\n")%uri) servicetype, location = uri.split("://")
if location.find(service_type) != -1:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectors/WAMP/__init__.py Sun Feb 08 16:50:54 2015 +0100
@@ -0,0 +1,146 @@
+#Copyright (C) 2015: Edouard TISSERANT +#See COPYING file for copyrights details. +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public +#License as published by the Free Software Foundation; either +#version 2.1 of the License, or (at your option) any later version. +#This library is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +#General Public License for more details. +#You should have received a copy of the GNU General Public +#License along with this library; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#from twisted.python import log +from twisted.internet import reactor, threads +from autobahn.twisted import wamp +from autobahn.twisted.websocket import WampWebSocketClientFactory, connectWS +from autobahn.wamp import types +from autobahn.wamp.exception import TransportLost +from autobahn.wamp.serializer import MsgPackSerializer +from threading import Thread, Event +_WampSessionEvent = Event() +class WampSession(wamp.ApplicationSession): + def onJoin(self, details): + _WampSessionEvent.set() + print 'WAMP session joined for :', self.config.extra["ID"] + def onLeave(self, details): + _WampSessionEvent.clear() + print 'WAMP session left' +PLCObjDefaults = { "StartPLC": False, + "GetTraceVariables" : ("Broken",None), + "GetPLCstatus" : ("Broken",None), + "RemoteExec" : (-1, "RemoteExec script failed!")} +def WAMP_connector_factory(uri, confnodesroot): + WAMP://127.0.0.1:12345/path#realm#ID + WAMPS://127.0.0.1:12345/path#realm#ID + global _WampSession, _ReactorThread, _WampSessionEvent + servicetype, location = uri.split("://") + urlpath, realm, ID = location.split('#') + urlprefix = {"WAMP":"ws", + "WAMPS":"wss"}[servicetype] + url = urlprefix+"://"+urlpath + def RegisterWampClient(): + ## start logging to console + # log.startLogging(sys.stdout) + # create a WAMP application session factory + component_config = types.ComponentConfig( + session_factory = wamp.ApplicationSessionFactory( + config = component_config) + session_factory.session = WampSession + # create a WAMP-over-WebSocket transport client factory + transport_factory = WampWebSocketClientFactory( + serializers = [MsgPackSerializer()], + # start the client from a Twisted endpoint + conn = connectWS(transport_factory) + confnodesroot.logger.write(_("WAMP connecting to URL : %s\n")%url) + def WampSessionProcMapper(funcname): + def catcher_func(*args,**kwargs): + if _WampSession is not None : + return threads.blockingCallFromThread( + reactor, _WampSession.call, funcname, + except TransportLost, e: + confnodesroot.logger.write_error("Connection lost!\n") + confnodesroot._SetConnector(None) + errmess = traceback.format_exc() + confnodesroot.logger.write_error(errmess+"\n") + #confnodesroot._SetConnector(None) + return PLCObjDefaults.get(funcname) + class WampPLCObjectProxy(object): + if not reactor.running: + self.connection = RegisterWampClient() + reactor.run(installSignalHandlers=False) + Thread(target=ThreadProc).start() + self.connection = threads.blockingCallFromThread( + reactor, RegisterWampClient) + if not _WampSessionEvent.wait(5): + self.connection.stopConnecting() + raise Exception, _("WAMP connection timeout") + self.connection.disconnect() + def __getattr__(self, attrName): + member = self.__dict__.get(attrName, None) + member = WampSessionProcMapper(attrName) + self.__dict__[attrName] = member + # Try to get the proxy object + return WampPLCObjectProxy() + confnodesroot.logger.write_error(_("WAMP connection to '%s' failed.\n")%location) + confnodesroot.logger.write_error(traceback.format_exc()) --- a/connectors/__init__.py Thu Feb 05 23:32:31 2015 +0100
+++ b/connectors/__init__.py Sun Feb 08 16:50:54 2015 +0100
@@ -30,9 +30,9 @@
def _GetLocalConnectorClassFactory(name):
return lambda:getattr(__import__(name,globals(),locals()), name + "_connector_factory")
-connectors = {name:_GetLocalConnectorClassFactory(name)
- for name in listdir(_base_path)
- if path.isdir(path.join(_base_path, name))
+connectors = {name:_GetLocalConnectorClassFactory(name) + for name in listdir(_base_path) + if path.isdir(path.join(_base_path, name)) and not name.startswith("__")}
def ConnectorFactory(uri, confnodesroot):
@@ -40,15 +40,23 @@
Return a connector corresponding to the URI
or None if cannot connect to URI
- servicetype = uri.split("://")[0]
- if servicetype in connectors:
- # import module according to uri type
- connectorclass = connectors[servicetype]()
- elif servicetype == "LOCAL":
- from PYRO import PYRO_connector_factory as connectorclass
- runtime_port = confnodesroot.AppFrame.StartLocalRuntime(taskbaricon=True)
+ servicetype = uri.split("://")[0].upper() + if servicetype == "LOCAL": + # Local is special case + # pyro connection to local runtime + # started on demand, listening on random port + runtime_port = confnodesroot.AppFrame.StartLocalRuntime( uri="PYRO://127.0.0.1:"+str(runtime_port)
+ elif servicetype in connectors: + elif servicetype[-1]=='S' and servicetype[:-1] in connectors: + servicetype = servicetype[:-1]
+ # import module according to uri type + connectorclass = connectors[servicetype]() return connectorclass(uri, confnodesroot)
--- a/runtime/PLCObject.py Thu Feb 05 23:32:31 2015 +0100
+++ b/runtime/PLCObject.py Sun Feb 08 16:50:54 2015 +0100
@@ -447,7 +447,8 @@
last_md5 = open(self._GetMD5FileName(), "r").read()
def SetTraceVariablesList(self, idxs):
@@ -534,7 +535,7 @@
- def RemoteExec(self, script, **kwargs):
+ def RemoteExec(self, script, *kwargs): --- a/runtime/WampClient.py Thu Feb 05 23:32:31 2015 +0100
+++ b/runtime/WampClient.py Sun Feb 08 16:50:54 2015 +0100
@@ -2,38 +2,59 @@
-from twisted.python import log
-from twisted.internet import reactor, ssl
+#from twisted.python import log from autobahn.twisted import wamp
from autobahn.twisted.websocket import WampWebSocketClientFactory, connectWS
+from twisted.internet.defer import inlineCallbacks from autobahn.wamp import types
+from autobahn.wamp.serializer import MsgPackSerializer +ExposedCalls = ["StartPLC", + "SetTraceVariablesList", + def Callee(*args,**kwargs): + return getattr(_PySrv.plcobj, name)(*args,**kwargs) class WampSession(wamp.ApplicationSession):
def onJoin(self, details):
print 'WAMP session joined by :', self.config.extra["ID"]
+ for name in ExposedCalls: + reg = yield self.register(MakeCallee(name), name) def onLeave(self, details):
print 'WAMP session left'
def RegisterWampClient(wampconf):
WSClientConf = json.load(open(wampconf))
- ## TODO log to PLC console instead
- ## 0) start logging to console
- log.startLogging(sys.stdout)
+ ## start logging to console + # log.startLogging(sys.stdout) - ## 1) create a WAMP application session factory
+ # create a WAMP application session factory component_config = types.ComponentConfig(
realm = WSClientConf["realm"],
extra = {"ID":WSClientConf["ID"]})
@@ -41,27 +62,17 @@
config = component_config)
session_factory.session = WampSession
- ## TODO select optimum serializer for passing session lists
- ## optional: use specific set of serializers
- #from autobahn.wamp.serializer import *
- ##serializers.append(JsonSerializer(batched = True))
- ##serializers.append(MsgPackSerializer(batched = True))
- #serializers.append(JsonSerializer())
- ##serializers.append(MsgPackSerializer())
- ## 2) create a WAMP-over-WebSocket transport client factory
+ # create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(
url = WSClientConf["url"],
- serializers = serializers,
+ serializers = [MsgPackSerializer()], - ## 3) start the client from a Twisted endpoint
+ # start the client from a Twisted endpoint conn = connectWS(transport_factory)
- print "WAMP clien connecting to :",WSClientConf["url"]
+ print "WAMP client connecting to :",WSClientConf["url"] --- a/tests/wamp/.crossbar/config.json Thu Feb 05 23:32:31 2015 +0100
+++ b/tests/wamp/.crossbar/config.json Sun Feb 08 16:50:54 2015 +0100
@@ -34,7 +34,8 @@
- "url": "ws://127.0.0.1:8888/"
+ "url": "ws://127.0.0.1:8888/", + "serializers" : ["msgpack"] --- a/tests/wamp/beremiz.xml Thu Feb 05 23:32:31 2015 +0100
+++ b/tests/wamp/beremiz.xml Sun Feb 08 16:50:54 2015 +0100
@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
-<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="PYRO://127.0.0.1:3000">
+<BeremizRoot xmlns:xsd="http://www.w3.org/2001/XMLSchema" URI_location="WAMP://127.0.0.1:8888#Automation#wamptest"> --- a/tests/wamp/plc.xml Thu Feb 05 23:32:31 2015 +0100
+++ b/tests/wamp/plc.xml Sun Feb 08 16:50:54 2015 +0100
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.plcopen.org/xml/tc6_0201">
<fileHeader companyName="Beremiz" productName="Beremiz" productVersion="1" creationDateTime="2015-02-05T11:44:55" contentDescription=" "/>
- <contentHeader name="WAMPTest" modificationDateTime="2015-02-05T13:45:38">
+ <contentHeader name="WAMPTest" modificationDateTime="2015-02-07T22:25:01">