--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectors/LPC/LPCAppObject.py Thu Jun 03 12:57:28 2010 +0200
@@ -0,0 +1,157 @@
+#This file is part of Beremiz, a Integrated Development Environment for +#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. +#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD +#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 LPCAppProto import * +class LPCAppObject(LPCObject): + def connect(self,comport): + self.SerialConnection = LPCAppProto(comport,#number + self.HandleSerialTransaction(IDLETransaction()) + def HandleSerialTransaction(self, transaction): + if self.SerialConnection is not None: + self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction) + self.pluginsroot.logger.write_error(str(e)+"\n") + self.SerialConnection = None + self.PLCStatus = "Disconnected" + def StartPLC(self, debug=False): + self.HandleSerialTransaction(STARTTransaction()) + self.HandleSerialTransaction(STOPTransaction()) + def GetPLCstatus(self): + self.HandleSerialTransaction(RESETTransaction()) + self.HandleSerialTransaction(IDLETransaction()) + def MatchMD5(self, MD5): + data = self.HandleSerialTransaction(GET_PLCIDTransaction()) + print "PLCINFO",data[32:] + return data[:32] == MD5 + class IEC_STRING(ctypes.Structure): + Must be changed according to changes in iec_types.h + _fields_ = [("len", ctypes.c_uint8), + ("body", ctypes.c_char * 126)] + 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): + Call ctype imported function to append + these indexes to registred variables in PLC debugger + # keep a copy of requested idx + for idx,iectype,force in idxs: + idxstr = ctypes.string_at( + ctypes.c_uint32(length)),4) + c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) + forcedsizestr = chr(ctypes.sizeof(c_type)) + forcestr = ctypes.string_at( + pack_func(c_type,force)), + buff += idxstr + forced_type_size_str + forcestr + buff += idxstr + chr(0) + data = self.HandleSerialTransaction( + SET_TRACE_VARIABLETransaction(buff)) + def GetTraceVariables(self): + Return a list of variables, corresponding to the list of required idx + strbuf = self.HandleSerialTransaction( + GET_TRACE_VARIABLETransaction()) + if size > 0 and self.PLCStatus == "Started": + ctypes.c_char_p(strbuf[:4]), + ctypes.POINTER(ctypes.c_int)).contents + ctypes.c_char_p(strbuf[4:]), + 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) + PLCprint("Debug error - " + iectype + " not supported !") + PLCprint("Debug error - buffer too small !") + if offset and offset == size: + return self.PLCStatus, tick.value, res + PLCprint("Debug error - wrong buffer unpack !") + return self.PLCStatus, None, None --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectors/LPC/LPCAppProto.py Thu Jun 03 12:57:28 2010 +0200
@@ -0,0 +1,117 @@
+LPC_STATUS={0x01 : "Started", +class LPCAppProto(LPCProto): + def HandleTransaction(self, transaction): + self.TransactionLock.acquire() + transaction.SetPseudoFile(self.serialPort) + # send command, wait ack (timeout) + transaction.SendCommand() + current_plc_status = transaction.GetCommandAck() + if current_plc_status is not None: + res = transaction.ExchangeData() + raise LPCProtoError("LPC transaction error - controller did not answer as expected") + self.TransactionLock.release() + return LPC_STATUS.get(current_plc_status,"Broken"), res +class LPCAppTransaction: + def __init__(self, command, optdata = ""): + def SetPseudoFile(self, pseudofile): + self.pseudofile = pseudofile + self.pseudofile.write(chr(self.Command)) + def GetCommandAck(self): + res = self.pseudofile.read(2) + comm_status, current_plc_status = map(ord, res) + raise LPCProtoError("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 + 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) + buffer = lengthstr + self.OptData + return self.pseudofile.write(buffer) + 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): +class IDLETransaction(LPCAppTransaction): + LPCAppTransaction.__init__(self, 0x00) +class STARTTransaction(LPCAppTransaction): + LPCAppTransaction.__init__(self, 0x01) +class STOPTransaction(LPCAppTransaction): + LPCAppTransaction.__init__(self, 0x02) +class RESETTransaction(LPCAppTransaction): + LPCAppTransaction.__init__(self, 0x03) +class SET_TRACE_VARIABLETransaction(LPCAppTransaction): + def __init__(self, data): + LPCAppTransaction.__init__(self, 0x04, data) + ExchangeData = LPCAppTransaction.SendData +class GET_TRACE_VARIABLETransaction(LPCAppTransaction): + LPCAppTransaction.__init__(self, 0x05) + ExchangeData = LPCAppTransaction.GetData +class GET_PLCIDTransaction(LPCAppTransaction): + LPCAppTransaction.__init__(self, 0x07) + ExchangeData = LPCAppTransaction.GetData +if __name__ == "__main__": + TestConnection = LPCAppProto(6,115200,2) +# TestConnection.HandleTransaction(GET_PLCIDTransaction()) + TestConnection.HandleTransaction(STARTTransaction()) +# TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( +# "\x03\x00\x00\x00"*200)) +# TestConnection.HandleTransaction(STARTTransaction()) + TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction( + #status,res = TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction()) + #print "GOT : ", map(hex, map(ord, res)) + #TestConnection.HandleTransaction(STOPTransaction()) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectors/LPC/LPCBootObject.py Thu Jun 03 12:57:28 2010 +0200
@@ -0,0 +1,52 @@
+#This file is part of Beremiz, a Integrated Development Environment for +#programming IEC 61131-3 automates supporting plcopen standard and CanFestival. +#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD +#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 LPCBootProto import * +class LPCBootObject(LPCObject): + def __init__(self, pluginsroot, comportstr): + LPCObject.__init__(self, pluginsroot, comportstr) + self.successfully_transfered = False + def connect(self,comport): + self.SerialConnection = LPCBootProto(comport,#number + self.PLCStatus = "Stopped" + def NewPLC(self, md5sum, data, extrafiles): + self.successfully_transfered = self.HandleSerialTransaction(LOADTransaction(data)) + return successfully_transfered + def MatchMD5(self, MD5): + return self.successfully_transfered + def SetTraceVariablesList(self, idxs): + def GetTraceVariables(self): + return self.PLCStatus, None, None --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectors/LPC/LPCBootProto.py Thu Jun 03 12:57:28 2010 +0200
@@ -0,0 +1,34 @@
+class LPCBootProto(LPCProto): + def HandleTransaction(self, transaction): + self.TransactionLock.acquire() + transaction.SetPseudoFile(self.serialPort) + res = transaction.ExchangeData() + self.TransactionLock.release() +class LPCBootTransaction: + def __init__(self, optdata = ""): + def SetPseudoFile(self, pseudofile): + self.pseudofile = pseudofile + return self.pseudofile.write(self.OptData) == len(self.OptData) + def ExchangeData(self): +class LOADTransaction(LPCBootTransaction): + def __init__(self, data): + LPCBootTransaction.__init__(self, data) + ExchangeData = LPCBootTransaction.SendData --- a/connectors/LPC/LPCObject.py Thu Jun 03 12:56:21 2010 +0200
+++ b/connectors/LPC/LPCObject.py Thu Jun 03 12:57:28 2010 +0200
@@ -22,187 +22,51 @@
#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 ctypes, os, commands, types, sys
- def __init__(self,pluginsroot, location):
+ def __init__(self, pluginsroot, comportstr): self.PLCStatus = "Disconnected"
self.pluginsroot = pluginsroot
self.PLCprint = pluginsroot.logger.write
- self.UpdateLocation(location)
+ comport = int(comportstr[3:comportstr.index(':')]) - 1 + self.connect(comportstr) + self.pluginsroot.logger.write_error(str(e)+"\n") + self.SerialConnection = None + self.PLCStatus = "Disconnected" - def UpdateLocation(self, location):
- if len(location) == 5 and\
- location.startswith("COM") and \
- location[3].isdigit() and \
- self.StorageConnection = None
- comport = int(location[3]) - 1
- self.SerialConnection = LPCProto(comport,#number
- # This will update status
- self.HandleSerialTransaction(IDLETransaction())
- self.pluginsroot.logger.write_error(str(e)+"\n")
- self.SerialConnection = None
- self.PLCStatus = "Disconnected"
- elif len(location)==2 and \
- location[0].isalpha() and \
- self.SerialConnection = None
- if os.path.exists(location):
- self.StorageConnection = location
- self.PLCStatus = "Stopped"
- self.pluginsroot.logger.write_error("Drive "+
- self.StorageConnection = None
- self.PLCStatus = "Disconnected"
def HandleSerialTransaction(self, transaction):
if self.SerialConnection is not None:
self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
+ except LPCProtoError,e: self.pluginsroot.logger.write_error(str(e)+"\n")
self.SerialConnection = None
self.PLCStatus = "Disconnected"
def StartPLC(self, debug=False):
- self.HandleSerialTransaction(STARTTransaction())
+ raise LPCProtoError("Not implemented")
- self.HandleSerialTransaction(STOPTransaction())
+ raise LPCProtoError("Not implemented") - self.HandleSerialTransaction(IDLETransaction())
+ raise LPCProtoError("Not implemented") def NewPLC(self, md5sum, data, extrafiles):
- if os.path.exists(self.StorageConnection):
- firmwarepath = os.path.join(
- self.StorageConnection,
- if os.path.exists(firmwarepath ):
- os.unlink(firmwarepath)
- f = open(firmwarepath, "wb")
- self.StorageConnection = None
- self.PLCStatus = "Disconnected"
- self.pluginsroot.logger.write_error(
- "LPC transfer error : "+
+ raise LPCProtoError("Not implemented") - data = self.HandleSerialTransaction(GET_PLCIDTransaction())
- print "PLCINFO",data[32:]
- return data[:32] == MD5
- class IEC_STRING(ctypes.Structure):
- Must be changed according to changes in iec_types.h
- _fields_ = [("len", ctypes.c_uint8),
- ("body", ctypes.c_char * 126)]
- 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)),
+ raise LPCProtoError("Not implemented") def SetTraceVariablesList(self, idxs):
- Call ctype imported function to append
- these indexes to registred variables in PLC debugger
- # keep a copy of requested idx
- for idx,iectype,force in idxs:
- idxstr = ctypes.string_at(
- ctypes.c_uint32(length)),4)
- c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
- forcedsizestr = chr(ctypes.sizeof(c_type))
- forcestr = ctypes.string_at(
- pack_func(c_type,force)),
- buff += idxstr + forced_type_size_str + forcestr
- buff += idxstr + chr(0)
- data = self.HandleSerialTransaction(
- SET_TRACE_VARIABLETransaction(buff))
+ raise LPCProtoError("Not implemented") def GetTraceVariables(self):
- Return a list of variables, corresponding to the list of required idx
- strbuf = self.HandleSerialTransaction(
- GET_TRACE_VARIABLETransaction())
- if size > 0 and self.PLCStatus == "Started":
- ctypes.c_char_p(strbuf[:4]),
- ctypes.POINTER(ctypes.c_int)).contents
- ctypes.c_char_p(strbuf[4:]),
- 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)
- PLCprint("Debug error - " + iectype + " not supported !")
- PLCprint("Debug error - buffer too small !")
- if offset and offset == size:
- return self.PLCStatus, tick.value, res
- PLCprint("Debug error - wrong buffer unpack !")
- return self.PLCStatus, None, None
+ raise LPCProtoError("Not implemented") --- a/connectors/LPC/LPCProto.py Thu Jun 03 12:56:21 2010 +0200
+++ b/connectors/LPC/LPCProto.py Thu Jun 03 12:57:28 2010 +0200
@@ -1,19 +1,11 @@
from threading import Lock
-LPC_STATUS={0x01 : "Started",
-class LPCError(exceptions.Exception):
+class LPCProtoError(exceptions.Exception):
return "LPC communication error ! " + str(self.msg)
@@ -29,10 +21,17 @@
res = self._serialPort.read(cnt)
- print "Recv :", map(hex,map(ord,res))
+ print "Recv :", map(hex,map(ord,res[:16])), "[...]" + print "Recv :", map(hex,map(ord,res)) - print "Send :", map(hex,map(ord,str))
+ print "Send :", map(hex,map(ord,str[:16])), "[...]" + print "Send :", map(hex,map(ord,str)) self._serialPort.write(str)
@@ -40,109 +39,3 @@
- def HandleTransaction(self, transaction):
- self.TransactionLock.acquire()
- transaction.SetPseudoFile(self.serialPort)
- # send command, wait ack (timeout)
- transaction.SendCommand()
- current_plc_status = transaction.GetCommandAck()
- if current_plc_status is not None:
- res = transaction.ExchangeData()
- raise LPCError("LPC transaction error - controller did not answer as expected")
- self.TransactionLock.release()
- return LPC_STATUS.get(current_plc_status,"Broken"), res
- def __init__(self, command, optdata = ""):
- def SetPseudoFile(self, pseudofile):
- self.pseudofile = pseudofile
- self.pseudofile.write(chr(self.Command))
- def GetCommandAck(self):
- res = self.pseudofile.read(2)
- comm_status, current_plc_status = map(ord, res)
- 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
- 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)
- buffer = lengthstr + self.OptData
- return self.pseudofile.write(buffer)
- 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):
-class IDLETransaction(LPCTransaction):
- LPCTransaction.__init__(self, 0x00)
-class STARTTransaction(LPCTransaction):
- LPCTransaction.__init__(self, 0x01)
-class STOPTransaction(LPCTransaction):
- 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):
- LPCTransaction.__init__(self, 0x05)
- ExchangeData = LPCTransaction.GetData
-class GET_PLCIDTransaction(LPCTransaction):
- LPCTransaction.__init__(self, 0x07)
- ExchangeData = LPCTransaction.GetData
-if __name__ == "__main__":
- TestConnection = LPCProto(6,115200,2)
-# TestConnection.HandleTransaction(GET_PLCIDTransaction())
- TestConnection.HandleTransaction(STARTTransaction())
-# TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
-# "\x03\x00\x00\x00"*200))
-# TestConnection.HandleTransaction(STARTTransaction())
- TestConnection.HandleTransaction(SET_TRACE_VARIABLETransaction(
- #status,res = TestConnection.HandleTransaction(GET_TRACE_VARIABLETransaction())
- #print "GOT : ", map(hex, map(ord, res))
- #TestConnection.HandleTransaction(STOPTransaction())
--- a/connectors/LPC/__init__.py Thu Jun 03 12:56:21 2010 +0200
+++ b/connectors/LPC/__init__.py Thu Jun 03 12:57:28 2010 +0200
@@ -19,19 +19,17 @@
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-permanant_connector = None
def LPC_connector_factory(uri, pluginsroot):
This returns the connector to LPC style PLCobject
- from LPCObject import LPCObject
- global permanant_connector
servicetype, location = uri.split("://")
- if permanant_connector is None:
- permanant_connector = LPCObject(pluginsroot,location)
- permanant_connector.UpdateLocation(location)
- return permanant_connector
+ mode,comportstr = location.split('/') + if mode=="APPLICATION": + from LPCAppObject import LPCAppObject + return LPCAppObject(pluginsroot,comportstr) + elif mode=="BOOTLOADER": + from LPCBootObject import LPCBootObject + return LPCBootObject(pluginsroot,comportstr)