connectors/LPC/LPCObject.py
changeset 545 627e5c636a4f
parent 525 e43bc748d1fe
child 556 1ad4e7f1e89e
equal deleted inserted replaced
544:064165a5276a 545:627e5c636a4f
    20 #
    20 #
    21 #You should have received a copy of the GNU General Public
    21 #You should have received a copy of the GNU General Public
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 import ctypes, os, commands, types, sys
       
    26 from LPCProto import *
    25 from LPCProto import *
    27 
    26 
    28 class LPCObject():
    27 class LPCObject():
    29     def __init__(self,pluginsroot, location):
    28     def __init__(self, pluginsroot, comportstr):
    30         self.PLCStatus = "Disconnected"
    29         self.PLCStatus = "Disconnected"
    31         self.pluginsroot = pluginsroot
    30         self.pluginsroot = pluginsroot
    32         self.PLCprint = pluginsroot.logger.write
    31         self.PLCprint = pluginsroot.logger.write
    33         self._Idxs = []
    32         self._Idxs = []
    34         self.UpdateLocation(location)
    33         comport = int(comportstr[3:comportstr.index(':')]) - 1
       
    34         try:
       
    35             self.connect(comportstr)
       
    36         except Exception,e:
       
    37             self.pluginsroot.logger.write_error(str(e)+"\n")
       
    38             self.SerialConnection = None
       
    39             self.PLCStatus = "Disconnected"
    35 
    40 
    36     def UpdateLocation(self, location):
       
    37         # Is that a comport ?
       
    38         if len(location) == 5 and\
       
    39            location.startswith("COM") and \
       
    40            location[3].isdigit() and \
       
    41            location[4]==":" :
       
    42             self.StorageConnection = None
       
    43             try:
       
    44                 comport = int(location[3]) - 1
       
    45                 self.SerialConnection = LPCProto(comport,#number
       
    46                                                  115200, #speed
       
    47                                                  2)      #timeout
       
    48                 # This will update status
       
    49                 self.HandleSerialTransaction(IDLETransaction())
       
    50             except Exception,e:
       
    51                 self.pluginsroot.logger.write_error(str(e)+"\n")
       
    52                 self.SerialConnection = None
       
    53                 self.PLCStatus = "Disconnected"
       
    54         # or a drive unit ?
       
    55         elif len(location)==2 and \
       
    56              location[0].isalpha() and \
       
    57              location[1] == ':' :
       
    58             self.SerialConnection = None
       
    59             if os.path.exists(location):
       
    60                 self.StorageConnection = location
       
    61                 self.PLCStatus = "Stopped"
       
    62             else:
       
    63                 self.pluginsroot.logger.write_error("Drive "+
       
    64                                                     location+
       
    65                                                     " do not exist !\n")
       
    66                 self.StorageConnection = None
       
    67                 self.PLCStatus = "Disconnected"
       
    68         
       
    69     def HandleSerialTransaction(self, transaction):
    41     def HandleSerialTransaction(self, transaction):
    70         if self.SerialConnection is not None:
    42         if self.SerialConnection is not None:
    71             try:
    43             try:
    72                 self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
    44                 self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
    73                 return res
    45                 return res
    74             except LPCError,e:
    46             except LPCProtoError,e:
    75                 self.pluginsroot.logger.write_error(str(e)+"\n")
    47                 self.pluginsroot.logger.write_error(str(e)+"\n")
    76                 self.SerialConnection = None
    48                 self.SerialConnection = None
    77                 self.PLCStatus = "Disconnected"
    49                 self.PLCStatus = "Disconnected"
    78                 return None
    50                 return None
    79 
    51         
    80     def StartPLC(self, debug=False):
    52     def StartPLC(self, debug=False):
    81         PLCprint("StartPLC")
    53         raise LPCProtoError("Not implemented")
    82         self.HandleSerialTransaction(STARTTransaction())
       
    83             
    54             
    84     def StopPLC(self):
    55     def StopPLC(self):
    85         PLCprint("StopPLC")
    56         raise LPCProtoError("Not implemented")
    86         self.HandleSerialTransaction(STOPTransaction())
       
    87 
       
    88     def ForceReload(self):
       
    89         pass
       
    90 
    57 
    91     def GetPLCstatus(self):
    58     def GetPLCstatus(self):
    92         self.HandleSerialTransaction(IDLETransaction())
    59         raise LPCProtoError("Not implemented")
    93         return self.PLCStatus
       
    94     
    60     
    95     def NewPLC(self, md5sum, data, extrafiles):
    61     def NewPLC(self, md5sum, data, extrafiles):
    96         if os.path.exists(self.StorageConnection):
    62         raise LPCProtoError("Not implemented")
    97             firmwarepath = os.path.join(
       
    98                     self.StorageConnection, 
       
    99                     "firmware.bin")
       
   100             try:
       
   101                 if os.path.exists(firmwarepath ):
       
   102                     os.unlink(firmwarepath)
       
   103                 f = open(firmwarepath, "wb")
       
   104                 f.write(data)
       
   105                 f.close()
       
   106                 return True
       
   107             except LPCError,e:
       
   108                 self.StorageConnection = None
       
   109                 self.PLCStatus = "Disconnected"
       
   110                 self.pluginsroot.logger.write_error(
       
   111                                     "LPC transfer error : "+
       
   112                                     str(e)+"\n")
       
   113 
    63 
   114     def MatchMD5(self, MD5):
    64     def MatchMD5(self, MD5):
   115         data = self.HandleSerialTransaction(GET_PLCIDTransaction())
    65         raise LPCProtoError("Not implemented")
   116         print "PLCINFO",data[32:]
       
   117         return data[:32] == MD5
       
   118 
       
   119     class IEC_STRING(ctypes.Structure):
       
   120         """
       
   121         Must be changed according to changes in iec_types.h
       
   122         """
       
   123         _fields_ = [("len", ctypes.c_uint8),
       
   124                     ("body", ctypes.c_char * 126)] 
       
   125     
       
   126     TypeTranslator = {"BOOL" :       (ctypes.c_uint8,  lambda x:x.value!=0,     lambda t,x:t(x)),
       
   127                       "STEP" :       (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
   128                       "TRANSITION" : (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
   129                       "ACTION" :     (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
   130                       "SINT" :       (ctypes.c_int8,   lambda x:x.value,        lambda t,x:t(x)),
       
   131                       "USINT" :      (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
   132                       "BYTE" :       (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
   133                       "STRING" :     (IEC_STRING,      lambda x:x.body[:x.len], lambda t,x:t(len(x),x)),
       
   134                       "INT" :        (ctypes.c_int16,  lambda x:x.value,        lambda t,x:t(x)),
       
   135                       "UINT" :       (ctypes.c_uint16, lambda x:x.value,        lambda t,x:t(x)),
       
   136                       "WORD" :       (ctypes.c_uint16, lambda x:x.value,        lambda t,x:t(x)),
       
   137                       "WSTRING" :    (None,            None,                    None),#TODO
       
   138                       "DINT" :       (ctypes.c_int32,  lambda x:x.value,        lambda t,x:t(x)),
       
   139                       "UDINT" :      (ctypes.c_uint32, lambda x:x.value,        lambda t,x:t(x)),
       
   140                       "DWORD" :      (ctypes.c_uint32, lambda x:x.value,        lambda t,x:t(x)),
       
   141                       "LINT" :       (ctypes.c_int64,  lambda x:x.value,        lambda t,x:t(x)),
       
   142                       "ULINT" :      (ctypes.c_uint64, lambda x:x.value,        lambda t,x:t(x)),
       
   143                       "LWORD" :      (ctypes.c_uint64, lambda x:x.value,        lambda t,x:t(x)),
       
   144                       "REAL" :       (ctypes.c_float,  lambda x:x.value,        lambda t,x:t(x)),
       
   145                       "LREAL" :      (ctypes.c_double, lambda x:x.value,        lambda t,x:t(x)),
       
   146                       } 
       
   147 
    66 
   148     def SetTraceVariablesList(self, idxs):
    67     def SetTraceVariablesList(self, idxs):
   149         """
    68         raise LPCProtoError("Not implemented")
   150         Call ctype imported function to append 
       
   151         these indexes to registred variables in PLC debugger
       
   152         """
       
   153         if idxs:
       
   154             buff = ""
       
   155             # keep a copy of requested idx
       
   156             self._Idxs = idxs[:]
       
   157             for idx,iectype,force in idxs:
       
   158                 idxstr = ctypes.string_at(
       
   159                           ctypes.pointer(
       
   160                            ctypes.c_uint32(length)),4)
       
   161                 if force !=None:
       
   162                     c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
       
   163                     forcedsizestr = chr(ctypes.sizeof(c_type))
       
   164                     forcestr = ctypes.string_at(
       
   165                                 ctypes.pointer(
       
   166                                  pack_func(c_type,force)),
       
   167                                  forced_type_size)
       
   168                     buff += idxstr + forced_type_size_str + forcestr
       
   169                 else:
       
   170                     buff += idxstr + chr(0)
       
   171             data = self.HandleSerialTransaction(
       
   172                    SET_TRACE_VARIABLETransaction(buff))
       
   173         else:
       
   174             self._Idxs =  []
       
   175 
    69 
   176     def GetTraceVariables(self):
    70     def GetTraceVariables(self):
   177         """
    71         raise LPCProtoError("Not implemented")
   178         Return a list of variables, corresponding to the list of required idx
       
   179         """
       
   180         offset = 0
       
   181         strbuf = self.HandleSerialTransaction(
       
   182                                      GET_TRACE_VARIABLETransaction())
       
   183         size = len(strbuf) - 4
       
   184         if size > 0 and self.PLCStatus == "Started":
       
   185             tick = ctypes.cast(
       
   186                     ctypes.c_char_p(strbuf[:4]),
       
   187                     ctypes.POINTER(ctypes.c_int)).contents
       
   188             buffer = ctypes.cast(
       
   189                       ctypes.c_char_p(strbuf[4:]),
       
   190                       ctypes.c_void_p)
       
   191             for idx, iectype, forced in self._Idxs:
       
   192                 cursor = ctypes.c_void_p(buffer.value + offset)
       
   193                 c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
       
   194                 if c_type is not None and offset < size:
       
   195                     res.append(unpack_func(ctypes.cast(cursor,
       
   196                                                        ctypes.POINTER(c_type)).contents))
       
   197                     offset += ctypes.sizeof(c_type)
       
   198                 else:
       
   199                     if c_type is None:
       
   200                         PLCprint("Debug error - " + iectype + " not supported !")
       
   201                     if offset >= size:
       
   202                         PLCprint("Debug error - buffer too small !")
       
   203                     break
       
   204             if offset and offset == size:
       
   205                 return self.PLCStatus, tick.value, res
       
   206             PLCprint("Debug error - wrong buffer unpack !")
       
   207         return self.PLCStatus, None, None
       
   208 
    72