connectors/PYRO/__init__.py
author etisserant
Wed, 20 Aug 2008 00:11:40 +0200
changeset 203 cb9901076a21
child 218 71fddab24be9
permissions -rwxr-xr-x
Added concepts :
- connector class (for PLC control, debug and flashing abstraction).
- builder class (C toolchain abstraction)

Added features :
- Pyro based connector.
- ctypes loader, load PLC shared object and run it
- ctypes based debugger embryo (not tested)
- gcc builder

Broken:
- Win32 runtime
- Most tests
203
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     1
#!/usr/bin/env python
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     2
# -*- coding: utf-8 -*-
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     3
#
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     4
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     5
#
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     6
#See COPYING file for copyrights details.
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     7
#
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     8
#This library is free software; you can redistribute it and/or
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
     9
#modify it under the terms of the GNU General Public
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    10
#License as published by the Free Software Foundation; either
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    11
#version 2.1 of the License, or (at your option) any later version.
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    12
#
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    13
#This library is distributed in the hope that it will be useful,
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    14
#but WITHOUT ANY WARRANTY; without even the implied warranty of
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    15
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    16
#General Public License for more details.
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    17
#
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    18
#You should have received a copy of the GNU General Public
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    19
#License along with this library; if not, write to the Free Software
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    20
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    21
import Pyro.core as pyro
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    22
from Pyro.errors import PyroError
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    23
import traceback
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    24
from time import sleep
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    25
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    26
def PYRO_connector_factory(uri, pluginsroot):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    27
    """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    28
    This returns the connector to Pyro style PLCobject
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    29
    """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    30
    pluginsroot.logger.write("Connecting to URI : %s\n"%uri)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    31
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    32
    servicetype, location = uri.split("://")
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    33
    
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    34
    # Try to get the proxy object
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    35
    try :
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    36
        RemotePLCObjectProxy = pyro.getAttrProxyForURI("PYROLOC://"+location+"/PLCObject")
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    37
    except Exception, msg:
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    38
        pluginsroot.logger.write_error("Wrong URI, please check it !\n")
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    39
        pluginsroot.logger.write_error(traceback.format_exc())
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    40
        return None
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    41
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    42
    def PyroCatcher(func, default=None):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    43
        """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    44
        A function that catch a pyro exceptions, write error to logger
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    45
        and return defaul value when it happen
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    46
        """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    47
        def cather_func(*args,**kwargs):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    48
            try:
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    49
                return func(*args,**kwargs)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    50
            except PyroError,e:
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    51
                #pluginsroot.logger.write_error(traceback.format_exc())
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    52
                pluginsroot.logger.write_error(str(e))
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    53
                pluginsroot._Disconnect()
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    54
                return default
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    55
        return cather_func
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    56
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    57
    # Check connection is effective. 
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    58
    # lambda is for getattr of GetPLCstatus to happen inside catcher
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    59
    if PyroCatcher(lambda:RemotePLCObjectProxy.GetPLCstatus())() == None:
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    60
        pluginsroot.logger.write_error("Cannot get PLC status - connection failed.\n")
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    61
        return None
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    62
        
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    63
    class PyroProxyProxy:
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    64
        """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    65
        A proxy proxy class to handle Beremiz Pyro interface specific behavior.
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    66
        And to put pyro exception catcher in between caller and pyro proxy
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    67
        """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    68
        def GetPyroProxy(self):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    69
            """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    70
            This func returns the real Pyro Proxy.
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    71
            Use this if you musn't keep reference to it.
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    72
            """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    73
            return RemotePLCObjectProxy
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    74
        
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    75
        def __getattr__(self, attrName):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    76
            if not self.__dict__.has_key(attrName):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    77
                if attrName=="StartPLC":
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    78
                    def _StartPLC():
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    79
                        """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    80
                        pluginsroot._connector.GetPyroProxy() is used 
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    81
                        rather than RemotePLCObjectProxy because
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    82
                        object is recreated meanwhile, 
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    83
                        so we must not keep ref to it here
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    84
                        """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    85
                        if pluginsroot._connector.GetPyroProxy().GetPLCstatus() == "Dirty":
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    86
                            """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    87
                            Some bad libs with static symbols may polute PLC
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    88
                            ask runtime to suicide and come back again
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    89
                            """
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    90
                            pluginsroot.logger.write("Force runtime reload\n")
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    91
                            pluginsroot._connector.GetPyroProxy().ForceReload()
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    92
                            pluginsroot._Disconnect()
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    93
                            # let remote PLC time to resurect.(freeze app)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    94
                            sleep(0.5)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    95
                            pluginsroot._Connect()
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    96
                        return pluginsroot._connector.GetPyroProxy().StartPLC()
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    97
                    member = PyroCatcher(_StartPLC, False)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    98
                else:
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
    99
                    def my_local_func(*args,**kwargs):
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   100
                        return RemotePLCObjectProxy.__getattr__(attrName)(*args,**kwargs)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   101
                    member = PyroCatcher(my_local_func, None)
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   102
                self.__dict__[attrName] = member
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   103
            return self.__dict__[attrName]
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   104
    return PyroProxyProxy()
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   105
    
cb9901076a21 Added concepts :
etisserant
parents:
diff changeset
   106