# HG changeset patch # User edouard # Date 1259936197 -3600 # Node ID 923d036dfa90ce23546b6783a08c767d34b912ff # Parent 2d0718a05cc7ede7be355115e0d56fab8e155178 LPC connector enhancements diff -r 2d0718a05cc7 -r 923d036dfa90 connectors/LPC/LPCObject.py --- a/connectors/LPC/LPCObject.py Fri Dec 04 15:15:57 2009 +0100 +++ b/connectors/LPC/LPCObject.py Fri Dec 04 15:16:37 2009 +0100 @@ -25,96 +25,59 @@ from threading import Timer, Thread, Lock import ctypes, os, commands, types, sys import traceback +from LPCProto import * class LPCObject(): - _Idxs = [] def __init__(self,pluginsroot): self.PLCStatus = "Stopped" self.pluginsroot = pluginsroot self.PLCprint = pluginsroot.logger.write - + self.SerialConnection = None + self._Idxs = [] + + def HandleSerialTransaction(self, transaction): + if self.SerialConnection is None: + try: + self.SerialConnection = LPCProto(6,115200,2) + except Exception,e: + self.pluginsroot.logger.write_error(str(e)+"\n") + self.SerialConnection = None + return "Disconnected", res + try: + return self.SerialConnection.HandleTransaction(transaction) + except LPCError,e: + #pluginsroot.logger.write_error(traceback.format_exc()) + self.pluginsroot.logger.write_error(str(e)+"\n") + self.SerialConnection = None + return "Disconnected", res + def StartPLC(self, debug=False): PLCprint("StartPLC") - if self.CurrentPLCFilename is not None: - self.PLCStatus = "Started" - self.PythonThread = Thread(target=self.PythonThreadProc, args=[debug]) - self.PythonThread.start() + self.HandleSerialTransaction(STARTTransaction()) def StopPLC(self): PLCprint("StopPLC") - if self.PLCStatus == "Started": - self._stopPLC() - return True - return False + self.HandleSerialTransaction(STOPTransaction()) def ForceReload(self): - # respawn python interpreter - Timer(0.1,self._Reload).start() - return True + pass def GetPLCstatus(self): - return self.PLCStatus + status,data = self.HandleSerialTransaction(IDLETransaction()) + return status def NewPLC(self, md5sum, data, extrafiles): - PLCprint("NewPLC (%s)"%md5sum) - if self.PLCStatus in ["Stopped", "Empty", "Broken"]: - NewFileName = md5sum + lib_ext - extra_files_log = os.path.join(self.workingdir,"extra_files.txt") - try: - os.remove(os.path.join(self.workingdir, - self.CurrentPLCFilename)) - for filename in file(extra_files_log, "r").readlines() + [extra_files_log]: - try: - os.remove(os.path.join(self.workingdir, filename.strip())) - except: - pass - except: - pass - - try: - # Create new PLC file - open(os.path.join(self.workingdir,NewFileName), - 'wb').write(data) - - # Store new PLC filename based on md5 key - open(self._GetMD5FileName(), "w").write(md5sum) - - # Then write the files - log = file(extra_files_log, "w") - for fname,fdata in extrafiles: - fpath = os.path.join(self.workingdir,fname) - open(fpath, "wb").write(fdata) - log.write(fname+'\n') - - # Store new PLC filename - self.CurrentPLCFilename = NewFileName - except: - PLCprint(traceback.format_exc()) - return False - if self.PLCStatus == "Empty": - self.PLCStatus = "Stopped" - return True - return False + pass def MatchMD5(self, MD5): - try: - last_md5 = open(self._GetMD5FileName(), "r").read() - return last_md5 == MD5 - except: - return False + status,data = self.HandleSerialTransaction(PLCIDTransaction()) + return data == MD5 def SetTraceVariablesList(self, idxs): - """ - Call ctype imported function to append - these indexes to registred variables in PLC debugger - """ - self._suspendDebug() - # keep a copy of requested idx - self._Idxs = idxs[:] - self._ResetDebugVariables() - for idx in idxs: - self._RegisterDebugVariable(idx) - self._resumeDebug() + self._Idxs = idxs[] + status,data = self.HandleSerialTransaction( + SET_TRACE_VARIABLETransaction( + ''.join(map(chr,idx)))) class IEC_STRING(ctypes.Structure): """ @@ -149,29 +112,25 @@ """ Return a list of variables, corresponding to the list of required idx """ - if self.PLCStatus == "Started": - self.PLClibraryLock.acquire() - tick = self._WaitDebugData() - #PLCprint("Debug tick : %d"%tick) - if tick == 2**32 - 1: - tick = -1 - res = None - else: - idx = ctypes.c_int() - typename = ctypes.c_char_p() - res = [] - - for given_idx in self._Idxs: - buffer=self._IterDebugData(ctypes.byref(idx), ctypes.byref(typename)) - c_type,unpack_func = self.TypeTranslator.get(typename.value, (None,None)) - if c_type is not None and given_idx == idx.value: - res.append(unpack_func(ctypes.cast(buffer, - ctypes.POINTER(c_type)).contents)) - else: - PLCprint("Debug error idx : %d, expected_idx %d, type : %s"%(idx.value, given_idx,typename.value)) - res.append(None) - self._FreeDebugData() - self.PLClibraryLock.release() - return tick, res - return -1, None + 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 + return self.PLCStatus, None, None diff -r 2d0718a05cc7 -r 923d036dfa90 connectors/LPC/LPCProto.py --- a/connectors/LPC/LPCProto.py Fri Dec 04 15:15:57 2009 +0100 +++ b/connectors/LPC/LPCProto.py Fri Dec 04 15:16:37 2009 +0100 @@ -1,16 +1,9 @@ import serial +import exceptions +import ctypes +import time from threading import Lock -LPC_CMDS=dict(IDLE = 0x00, - START = 0x01, - STOP = 0x02, - SET_TRACE_VARIABLE = 0x04, - GET_TRACE_VARIABLES = 0x05, - SET_FORCED_VARIABLE = 0x06, - GET_PLCID = 0x07) - -WAIT_DATA = 0x04 - LPC_STATUS=dict(STARTED = 0x01, STOPPED = 0x02, DEBUG = 0x03) @@ -26,13 +19,27 @@ class LPCProto: def __init__(self, port, rate, timeout): + # serialize access lock + self.TransactionLock = Lock() # open serial port - self.serialPort = serial.Serial( port, rate, timeout = timeout ) +# self.serialPort = serial.Serial( port, rate, timeout = timeout ) + # Debugging serial stuff + self._serialPort = serial.Serial( port, rate, timeout = timeout ) + class myser: + def read(self_,cnt): + res = self._serialPort.read(cnt) + print "Recv :", map(hex,map(ord,res)) + return res + def write(self_, str): + print "Send :", map(hex,map(ord,str)) + self._serialPort.write(str) + def flush(self_): + self._serialPort.flush() + self.serialPort = myser() + # start with empty self.serialPort.flush() # handshake - self.HandleTransaction(LPCTransaction("IDLE")) - # serialize access lock - self.TransactionLock = Lock() + self.HandleTransaction(IDLETransaction()) def HandleTransaction(self, transaction): self.TransactionLock.acquire() @@ -50,12 +57,12 @@ return current_plc_status, res class LPCTransaction: - def __init__(self, command, optdata): - self.Command = LPC_CMDS[command] - self.OptData = optdata[:] - self.serialPort = None + def __init__(self, command, optdata = ""): + self.Command = command + self.OptData = optdata + self.pseudofile = None - def SetPseudoFile(pseudofile): + def SetPseudoFile(self, pseudofile): self.pseudofile = pseudofile def SendCommand(self): @@ -63,26 +70,74 @@ self.pseudofile.write(chr(self.Command)) def GetCommandAck(self): - comm_status, current_plc_status = map(ord, self.pseudofile.read(2)) + res = self.pseudofile.read(2) + if len(res) == 2: + comm_status, current_plc_status = map(ord, res) + else: + raise LPCError("LPC transaction error - controller did not ack order") # LPC returns command itself as an ack for command if(comm_status == self.Command): return current_plc_status return None - def ExchangeData(self): - if self.Command & WAIT_DATA : - length = len(self.OptData) - # transform length into a byte string - # we presuppose endianess of LPC same as PC - lengthstr = ctypes.string_at(ctypes.pointer(ctypes.c_int(length)),4) - self.pseudofile.write(lengthstr + self.OptData) - - lengthstr = self.pseudofile.read(4) - # transform a byte string into length - length = ctypes.cast(ctypes.c_char_p(lengthstr), ctypes.POINTER(ctypes.c_int)).contents.value - return self.pseudofile.read(length) - return None - + def SendData(self): + length = len(self.OptData) + # transform length into a byte string + # we presuppose endianess of LPC same as PC + lengthstr = ctypes.string_at(ctypes.pointer(ctypes.c_int(length)),4) + self.pseudofile.write(lengthstr + self.OptData) + + def GetData(self): + lengthstr = self.pseudofile.read(4) + # transform a byte string into length + length = ctypes.cast(ctypes.c_char_p(lengthstr), ctypes.POINTER(ctypes.c_int)).contents.value + return self.pseudofile.read(length) + + def ExchangeData(self): + pass + +class IDLETransaction(LPCTransaction): + def __init__(self): + LPCTransaction.__init__(self, 0x00) + +class STARTTransaction(LPCTransaction): + def __init__(self): + LPCTransaction.__init__(self, 0x01) + +class STOPTransaction(LPCTransaction): + def __init__(self): + LPCTransaction.__init__(self, 0x02) + +class SET_TRACE_VARIABLETransaction(LPCTransaction): + def __init__(self, data): + LPCTransaction.__init__(self, 0x04, data) + ExchangeData = LPCTransaction.SendData + +class GET_TRACE_VARIABLETransaction(LPCTransaction): + def __init__(self): + LPCTransaction.__init__(self, 0x05) + ExchangeData = LPCTransaction.GetData + +class SET_FORCED_VARIABLETransaction(LPCTransaction): + def __init__(self, data): + LPCTransaction.__init__(self, 0x06, data) + ExchangeData = LPCTransaction.SendData + +class GET_PLCIDTransaction(LPCTransaction): + def __init__(self): + LPCTransaction.__init__(self, 0x07) + ExchangeData = LPCTransaction.GetData + if __name__ == "__main__": - TestConnection = LPCProto() - \ No newline at end of file + TestConnection = LPCProto(6,115200,2) + #TestConnection.HandleTransaction(GET_PLCIDTransaction()) + TestConnection.HandleTransaction(STARTTransaction()) + TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( + "\x03\x00\x00\x00")) + TestConnection.HandleTransaction(STARTTransaction()) + while True: + time.sleep(0.5) + TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( + "\x01\x00\x00\x00"*31)) + #print map(hex,map(ord,TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction()))) + #TestConnection.HandleTransaction(STOPTransaction())