connectors/WAMP/__init__.py
changeset 1475 de4ee16f7c6c
parent 1443 ff8a22d45c44
child 1571 486f94a8032c
equal deleted inserted replaced
1474:28e9d479aa65 1475:de4ee16f7c6c
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 #
       
     4 #Copyright (C) 2015: Edouard TISSERANT
       
     5 #
       
     6 #See COPYING file for copyrights details.
       
     7 #
       
     8 #This library is free software; you can redistribute it and/or
       
     9 #modify it under the terms of the GNU General Public
       
    10 #License as published by the Free Software Foundation; either
       
    11 #version 2.1 of the License, or (at your option) any later version.
       
    12 #
       
    13 #This library is distributed in the hope that it will be useful,
       
    14 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16 #General Public License for more details.
       
    17 #
       
    18 #You should have received a copy of the GNU General Public
       
    19 #License along with this library; if not, write to the Free Software
       
    20 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21 
       
    22 import sys, traceback, atexit
       
    23 #from twisted.python import log
       
    24 from twisted.internet import reactor, threads
       
    25 from autobahn.twisted import wamp
       
    26 from autobahn.twisted.websocket import WampWebSocketClientFactory, connectWS
       
    27 from autobahn.wamp import types
       
    28 from autobahn.wamp.exception import TransportLost
       
    29 from autobahn.wamp.serializer import MsgPackSerializer
       
    30 from threading import Thread, Event
       
    31 
       
    32 _WampSession = None
       
    33 _WampConnection = None
       
    34 _WampSessionEvent = Event()
       
    35 
       
    36 class WampSession(wamp.ApplicationSession):
       
    37     def onJoin(self, details):
       
    38         global _WampSession, _WampSessionEvent
       
    39         _WampSession = self
       
    40         _WampSessionEvent.set()
       
    41         print 'WAMP session joined for :', self.config.extra["ID"]
       
    42 
       
    43     def onLeave(self, details):
       
    44         global _WampSession, _WampSessionEvent
       
    45         _WampSessionEvent.clear()
       
    46         _WampSession = None
       
    47         print 'WAMP session left'
       
    48 
       
    49 PLCObjDefaults = { "StartPLC": False,
       
    50                    "GetTraceVariables" : ("Broken",None),
       
    51                    "GetPLCstatus" : ("Broken",None),
       
    52                    "RemoteExec" : (-1, "RemoteExec script failed!")}
       
    53 
       
    54 def WAMP_connector_factory(uri, confnodesroot):
       
    55     """
       
    56     WAMP://127.0.0.1:12345/path#realm#ID
       
    57     WAMPS://127.0.0.1:12345/path#realm#ID
       
    58     """
       
    59     servicetype, location = uri.split("://")
       
    60     urlpath, realm, ID = location.split('#')
       
    61     urlprefix = {"WAMP":"ws",
       
    62                  "WAMPS":"wss"}[servicetype]
       
    63     url = urlprefix+"://"+urlpath
       
    64 
       
    65     def RegisterWampClient():
       
    66 
       
    67         ## start logging to console
       
    68         # log.startLogging(sys.stdout)
       
    69 
       
    70         # create a WAMP application session factory
       
    71         component_config = types.ComponentConfig(
       
    72             realm = realm,
       
    73             extra = {"ID":ID})
       
    74         session_factory = wamp.ApplicationSessionFactory(
       
    75             config = component_config)
       
    76         session_factory.session = WampSession
       
    77 
       
    78         # create a WAMP-over-WebSocket transport client factory
       
    79         transport_factory = WampWebSocketClientFactory(
       
    80             session_factory,
       
    81             url = url,
       
    82             serializers = [MsgPackSerializer()],
       
    83             debug = False,
       
    84             debug_wamp = False)
       
    85 
       
    86         # start the client from a Twisted endpoint
       
    87         conn = connectWS(transport_factory)
       
    88         confnodesroot.logger.write(_("WAMP connecting to URL : %s\n")%url)
       
    89         return conn
       
    90 
       
    91     AddToDoBeforeQuit = confnodesroot.AppFrame.AddToDoBeforeQuit
       
    92     def ThreadProc():
       
    93         global _WampConnection
       
    94         _WampConnection = RegisterWampClient()
       
    95         AddToDoBeforeQuit(reactor.stop)
       
    96         reactor.run(installSignalHandlers=False)
       
    97 
       
    98     def WampSessionProcMapper(funcname):
       
    99         wampfuncname = '.'.join((ID,funcname))
       
   100         def catcher_func(*args,**kwargs):
       
   101             global _WampSession
       
   102             if _WampSession is not None :
       
   103                 try:
       
   104                     return threads.blockingCallFromThread(
       
   105                         reactor, _WampSession.call, wampfuncname,
       
   106                         *args,**kwargs)
       
   107                 except TransportLost, e:
       
   108                     confnodesroot.logger.write_error("Connection lost!\n")
       
   109                     confnodesroot._SetConnector(None)
       
   110                 except Exception,e:
       
   111                     errmess = traceback.format_exc()
       
   112                     confnodesroot.logger.write_error(errmess+"\n")
       
   113                     print errmess
       
   114                     #confnodesroot._SetConnector(None)
       
   115             return PLCObjDefaults.get(funcname)
       
   116         return catcher_func
       
   117 
       
   118     class WampPLCObjectProxy(object):
       
   119         def __init__(self):
       
   120             global _WampSessionEvent, _WampConnection
       
   121             if not reactor.running:
       
   122                 Thread(target=ThreadProc).start()
       
   123             else:
       
   124                 _WampConnection = threads.blockingCallFromThread(
       
   125                     reactor, RegisterWampClient)
       
   126             if not _WampSessionEvent.wait(5):
       
   127                 _WampConnection = stopConnecting()
       
   128                 raise Exception, _("WAMP connection timeout")
       
   129 
       
   130         def __del__(self):
       
   131             global _WampConnection
       
   132             _WampConnection.disconnect()
       
   133             #
       
   134             # reactor.stop()
       
   135 
       
   136         def __getattr__(self, attrName):
       
   137             member = self.__dict__.get(attrName, None)
       
   138             if member is None:
       
   139                 member = WampSessionProcMapper(attrName)
       
   140                 self.__dict__[attrName] = member
       
   141             return member
       
   142 
       
   143     # Try to get the proxy object
       
   144     try :
       
   145         return WampPLCObjectProxy()
       
   146     except Exception, msg:
       
   147         confnodesroot.logger.write_error(_("WAMP connection to '%s' failed.\n")%location)
       
   148         confnodesroot.logger.write_error(traceback.format_exc())
       
   149         return None
       
   150 
       
   151 
       
   152 
       
   153