LPC connector - one step further
authoredouard
Thu, 10 Dec 2009 14:57:27 +0100
changeset 502 5343ae43f6d0
parent 501 d7bf56b036a8
child 503 4c0cd5e54e1b
LPC connector - one step further
connectors/LPC/LPCObject.py
connectors/LPC/LPCProto.py
connectors/LPC/__init__.py
targets/LPC/plc_LPC_main.c
targets/plc_debug.c
--- a/connectors/LPC/LPCObject.py	Thu Dec 10 12:31:42 2009 +0100
+++ b/connectors/LPC/LPCObject.py	Thu Dec 10 14:57:27 2009 +0100
@@ -33,6 +33,7 @@
         self.pluginsroot = pluginsroot
         self.PLCprint = pluginsroot.logger.write
         self.SerialConnection = None
+        self.StorageConnection = None
         self._Idxs = []
         
     def HandleSerialTransaction(self, transaction):
@@ -72,65 +73,101 @@
     def MatchMD5(self, MD5):
         status,data = self.HandleSerialTransaction(PLCIDTransaction())
         return data == MD5
-    
-    def SetTraceVariablesList(self, idxs):
-        self._Idxs = idxs[]
-        status,data = self.HandleSerialTransaction(
-               SET_TRACE_VARIABLETransaction(
-                     ''.join(map(chr,idx))))
 
     class IEC_STRING(ctypes.Structure):
         """
         Must be changed according to changes in iec_types.h
         """
         _fields_ = [("len", ctypes.c_uint8),
-                    ("body", ctypes.c_char * 127)] 
+                    ("body", ctypes.c_char * 126)] 
     
-    TypeTranslator = {"BOOL" :       (ctypes.c_uint8, lambda x:x.value!=0),
-                      "STEP" :       (ctypes.c_uint8, lambda x:x.value),
-                      "TRANSITION" : (ctypes.c_uint8, lambda x:x.value),
-                      "ACTION" :     (ctypes.c_uint8, lambda x:x.value),
-                      "SINT" :       (ctypes.c_int8, lambda x:x.value),
-                      "USINT" :      (ctypes.c_uint8, lambda x:x.value),
-                      "BYTE" :       (ctypes.c_uint8, lambda x:x.value),
-                      "STRING" :     (IEC_STRING, lambda x:x.body[:x.len]),
-                      "INT" :        (ctypes.c_int16, lambda x:x.value),
-                      "UINT" :       (ctypes.c_uint16, lambda x:x.value),
-                      "WORD" :       (ctypes.c_uint16, lambda x:x.value),
-                      "WSTRING" :    (None, None),#TODO
-                      "DINT" :       (ctypes.c_int32, lambda x:x.value),
-                      "UDINT" :      (ctypes.c_uint32, lambda x:x.value),
-                      "DWORD" :      (ctypes.c_uint32, lambda x:x.value),
-                      "LINT" :       (ctypes.c_int64, lambda x:x.value),
-                      "ULINT" :      (ctypes.c_uint64, lambda x:x.value),
-                      "LWORD" :      (ctypes.c_uint64, lambda x:x.value),
-                      "REAL" :       (ctypes.c_float, lambda x:x.value),
-                      "LREAL" :      (ctypes.c_double, lambda x:x.value),
+    TypeTranslator = {"BOOL" :       (ctypes.c_uint8,  lambda x:x.value!=0,     lambda t,x:t(x)),
+                      "STEP" :       (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
+                      "TRANSITION" : (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
+                      "ACTION" :     (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
+                      "SINT" :       (ctypes.c_int8,   lambda x:x.value,        lambda t,x:t(x)),
+                      "USINT" :      (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
+                      "BYTE" :       (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
+                      "STRING" :     (IEC_STRING,      lambda x:x.body[:x.len], lambda t,x:t(len(x),x)),
+                      "INT" :        (ctypes.c_int16,  lambda x:x.value,        lambda t,x:t(x)),
+                      "UINT" :       (ctypes.c_uint16, lambda x:x.value,        lambda t,x:t(x)),
+                      "WORD" :       (ctypes.c_uint16, lambda x:x.value,        lambda t,x:t(x)),
+                      "WSTRING" :    (None,            None,                    None),#TODO
+                      "DINT" :       (ctypes.c_int32,  lambda x:x.value,        lambda t,x:t(x)),
+                      "UDINT" :      (ctypes.c_uint32, lambda x:x.value,        lambda t,x:t(x)),
+                      "DWORD" :      (ctypes.c_uint32, lambda x:x.value,        lambda t,x:t(x)),
+                      "LINT" :       (ctypes.c_int64,  lambda x:x.value,        lambda t,x:t(x)),
+                      "ULINT" :      (ctypes.c_uint64, lambda x:x.value,        lambda t,x:t(x)),
+                      "LWORD" :      (ctypes.c_uint64, lambda x:x.value,        lambda t,x:t(x)),
+                      "REAL" :       (ctypes.c_float,  lambda x:x.value,        lambda t,x:t(x)),
+                      "LREAL" :      (ctypes.c_double, lambda x:x.value,        lambda t,x:t(x)),
                       } 
-                           
+
+    def SetTraceVariablesList(self, idxs):
+        self._Idxs = idxs[:]
+        status,data = self.HandleSerialTransaction(
+               SET_TRACE_VARIABLETransaction(
+                     ''.join(map(chr,idx))))
+
+    def SetTraceVariablesList(self, idxs):
+        """
+        Call ctype imported function to append 
+        these indexes to registred variables in PLC debugger
+        """
+        if idxs:
+            buff = ""
+            # keep a copy of requested idx
+            self._Idxs = idxs[:]
+            for idx,iectype,force in idxs:
+                idxstr = ctypes.string_at(
+                          ctypes.pointer(
+                           ctypes.c_uint32(length)),4)
+                if force !=None:
+                    c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
+                    forcedsizestr = chr(ctypes.sizeof(c_type))
+                    forcestr = ctypes.string_at(
+                                ctypes.pointer(
+                                 pack_func(c_type,force)),
+                                 forced_type_size)
+                    buff += idxstr + forced_type_size_str + forcestr
+                else:
+                    buff += idxstr + chr(0)
+            status,data = self.HandleSerialTransaction(
+                   SET_TRACE_VARIABLETransaction(buff))
+        else:
+            self._Idxs =  []
+
     def GetTraceVariables(self):
         """
         Return a list of variables, corresponding to the list of required idx
         """
-        status,data = self.HandleSerialTransaction(GET_TRACE_VARIABLETransaction())
-        if data is not None:
-            # transform serial string to real byte string in memory 
-            buffer = ctypes.c_char_p(data)
-            # tick is first value in buffer
-            tick = ctypes.cast(buffer,ctypes.POINTER(ctypes.c_uint32)).contents
-            # variable data starts just after tick 
-            cursorp = ctypes.addressof(buffer) = ctypes.sizeof(ctypes.c_uint32)
-            endp = offset + len(data)
-            for idx, iectype in self._Idxs:
-                cursor = ctypes.c_void_p(cursorp)
-                c_type,unpack_func = self.TypeTranslator.get(iectype, (None,None))
-                if c_type is not None and cursorp < endp:
-                    res.append(unpack_func(ctypes.cast(cursor,
-                                                       ctypes.POINTER(c_type)).contents))
-                    cursorp += ctypes.sizeof(c_type) 
-                else:
-                    PLCprint("Debug error !")
-                        break
-            return self.PLCStatus, tick, res
+        if self.PLCStatus == "Started":
+            res=[]
+            tick = ctypes.c_uint32()
+            size = ctypes.c_uint32()
+            buffer = ctypes.c_void_p()
+            offset = 0
+            if self.PLClibraryLock.acquire(False) and \
+               self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 :
+                if size.value:
+                    for idx, iectype, forced in self._Idxs:
+                        cursor = ctypes.c_void_p(buffer.value + offset)
+                        c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
+                        if c_type is not None and offset < size:
+                            res.append(unpack_func(ctypes.cast(cursor,
+                                                               ctypes.POINTER(c_type)).contents))
+                            offset += ctypes.sizeof(c_type)
+                        else:
+                            if c_type is None:
+                                PLCprint("Debug error - " + iectype + " not supported !")
+                            if offset >= size:
+                                PLCprint("Debug error - buffer too small !")
+                            break
+                self._FreeDebugData()
+                self.PLClibraryLock.release()
+            if offset and offset == size.value:
+                return self.PLCStatus, tick.value, res
+            elif size.value:
+                PLCprint("Debug error - wrong buffer unpack !")
         return self.PLCStatus, None, None
 
--- a/connectors/LPC/LPCProto.py	Thu Dec 10 12:31:42 2009 +0100
+++ b/connectors/LPC/LPCProto.py	Thu Dec 10 14:57:27 2009 +0100
@@ -150,9 +150,12 @@
 #    TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
 #           "\x03\x00\x00\x00"*200))
 #    TestConnection.HandleTransaction(STARTTransaction())
-    while True:
-        #time.sleep(0.5)
-        TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
-           "\x01\x00\x00\x00"*200))
-   #print map(hex,map(ord,TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction())))
+    TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
+       "\x05\x00\x00\x00"+
+       "\x01\x00\x00\x00"+
+       "\x04"+
+       "\x01\x02\x02\x04"))
+    #status,res = TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction())
+    #print len(res)
+    #print "GOT : ", map(hex, map(ord, res))
     #TestConnection.HandleTransaction(STOPTransaction())
--- a/connectors/LPC/__init__.py	Thu Dec 10 12:31:42 2009 +0100
+++ b/connectors/LPC/__init__.py	Thu Dec 10 14:57:27 2009 +0100
@@ -19,6 +19,7 @@
 #License along with this library; if not, write to the Free Software
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 import traceback
+import LPCObject
 
 
 def LPC_connector_factory(uri, pluginsroot):
@@ -26,62 +27,6 @@
     This returns the connector to LPC style PLCobject
     """
     pluginsroot.logger.write(_("Connecting to URI : %s\n")%uri)
-
-    servicetype, location = uri.split("://")
-    
-    # Try to get the proxy object
-    try :
-        # TODO: Open Serial Port
-        RemotePLCObjectProxy = LPCObject(pluginsroot) # LPC_PLCObject_Proxy
-    except Exception, msg:
-        pluginsroot.logger.write_error(_("Couldn't connect !\n"))
-        pluginsroot.logger.write_error(traceback.format_exc())
-        return None
-
-    def LPCCatcher(func, default=None):
-        """
-        A function that catch a pyserial exceptions, write error to logger
-        and return defaul value when it happen
-        """
-        def catcher_func(*args,**kwargs):
-            try:
-                return func(*args,**kwargs)
-            except Exception,e:
-                #pluginsroot.logger.write_error(traceback.format_exc())
-                pluginsroot.logger.write_error(str(e)+"\n")
-                pluginsroot._connector = None
-                return default
-        return catcher_func
-
-    # Check connection is effective. 
-    # lambda is for getattr of GetPLCstatus to happen inside catcher
-    if LPCCatcher(lambda:RemotePLCObjectProxy.GetPLCstatus())() == None:
-        pluginsroot.logger.write_error(_("Cannot get PLC status - connection failed.\n"))
-        return None
-
-
-    class LPCProxy:
-        """
-        A Serial proxy class to handle Beremiz Pyro interface specific behavior.
-        And to put LPC exception catcher in between caller and pyro proxy
-        """
-        def _LPCGetTraceVariables(self):
-            return self.RemotePLCObjectProxy.GetTraceVariables()
-        GetTraceVariables = LPCCatcher(_LPCGetTraceVariables,("Broken",None,None))
-
-        def _LPCGetPLCstatus(self):
-            return RemotePLCObjectProxy.GetPLCstatus()
-        GetPLCstatus = LPCCatcher(_LPCGetPLCstatus, "Broken")
-        
-        def __getattr__(self, attrName):
-            member = self.__dict__.get(attrName, None)
-            if member is None:
-                def my_local_func(*args,**kwargs):
-                    return RemotePLCObjectProxy.__getattr__(attrName)(*args,**kwargs)
-                member = LPCCatcher(my_local_func, None)
-                self.__dict__[attrName] = member
-            return member
-
-    return LPCProxy()
+    return LPCObject()
     
 
--- a/targets/LPC/plc_LPC_main.c	Thu Dec 10 12:31:42 2009 +0100
+++ b/targets/LPC/plc_LPC_main.c	Thu Dec 10 14:57:27 2009 +0100
@@ -34,7 +34,7 @@
 
 int TryEnterDebugSection(void)
 {
-    return 0;
+    return __DEBUG;
 }
 
 void LeaveDebugSection(void)
@@ -48,49 +48,29 @@
 }
 
 extern unsigned long __tick;
+int _DebugDataAvailable = 0;
 /* from plc_debugger.c */
 int WaitDebugData(unsigned long *tick)
 {
     *tick = __tick;
-    return 0;
+    return _DebugDataAvailable;
 }
 
 /* Called by PLC thread when debug_publish finished
  * This is supposed to unlock debugger thread in WaitDebugData*/
 void InitiateDebugTransfer(void)
 {
+    _DebugDataAvailable = 1;
 }
 
-void suspendDebug(void)
+void suspendDebug(int disable)
 {
+    __DEBUG = !disable;
 }
 
 void resumeDebug(void)
 {
-}
-
-/* from plc_python.c */
-int WaitPythonCommands(void)
-{
-    return 0;
-}
-
-/* Called by PLC thread on each new python command*/
-void UnBlockPythonCommands(void)
-{
-}
-
-int TryLockPython(void)
-{
-	return 0;
-}
-
-void UnLockPython(void)
-{
-}
-
-void LockPython(void)
-{
+    __DEBUG = 1;
 }
 
 void Retain(unsigned int offset, unsigned int count, void *p)
--- a/targets/plc_debug.c	Thu Dec 10 12:31:42 2009 +0100
+++ b/targets/plc_debug.c	Thu Dec 10 14:57:27 2009 +0100
@@ -279,8 +279,10 @@
 /* Wait until debug data ready and return pointer to it */
 int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){
     int res = WaitDebugData(tick);
-    *size = buffer_cursor - debug_buffer;
-    *buffer = debug_buffer;
+    if(res){
+        *size = buffer_cursor - debug_buffer;
+        *buffer = debug_buffer;
+    }
     return res;
 }