connectors/LPC/LPCAppObject.py
changeset 545 627e5c636a4f
child 548 1428fd553988
equal deleted inserted replaced
544:064165a5276a 545:627e5c636a4f
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of Beremiz, a Integrated Development Environment for
       
     5 #programming IEC 61131-3 automates supporting plcopen standard and CanFestival. 
       
     6 #
       
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    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
       
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    24 
       
    25 import ctypes
       
    26 from LPCAppProto import *
       
    27 from LPCObject import *
       
    28 
       
    29 class LPCAppObject(LPCObject):
       
    30     def connect(self,comport):
       
    31         self.SerialConnection = LPCAppProto(comport,#number
       
    32                                          115200, #speed
       
    33                                          2)      #timeout
       
    34         self.HandleSerialTransaction(IDLETransaction())
       
    35         
       
    36     def HandleSerialTransaction(self, transaction):
       
    37         if self.SerialConnection is not None:
       
    38             try:
       
    39                 self.PLCStatus, res = self.SerialConnection.HandleTransaction(transaction)
       
    40                 return res
       
    41             except LPCError,e:
       
    42                 self.pluginsroot.logger.write_error(str(e)+"\n")
       
    43                 self.SerialConnection = None
       
    44                 self.PLCStatus = "Disconnected"
       
    45                 return None
       
    46 
       
    47     def StartPLC(self, debug=False):
       
    48         PLCprint("StartPLC")
       
    49         self.HandleSerialTransaction(STARTTransaction())
       
    50             
       
    51     def StopPLC(self):
       
    52         PLCprint("StopPLC")
       
    53         self.HandleSerialTransaction(STOPTransaction())
       
    54 
       
    55     def GetPLCstatus(self):
       
    56         self.HandleSerialTransaction(RESETTransaction())
       
    57         return self.PLCStatus
       
    58 
       
    59     def ResetPLC(self):
       
    60         self.HandleSerialTransaction(IDLETransaction())
       
    61         return self.PLCStatus
       
    62 
       
    63     def MatchMD5(self, MD5):
       
    64         data = self.HandleSerialTransaction(GET_PLCIDTransaction())
       
    65         print "PLCINFO",data[32:]
       
    66         return data[:32] == MD5
       
    67 
       
    68     class IEC_STRING(ctypes.Structure):
       
    69         """
       
    70         Must be changed according to changes in iec_types.h
       
    71         """
       
    72         _fields_ = [("len", ctypes.c_uint8),
       
    73                     ("body", ctypes.c_char * 126)] 
       
    74     
       
    75     TypeTranslator = {"BOOL" :       (ctypes.c_uint8,  lambda x:x.value!=0,     lambda t,x:t(x)),
       
    76                       "STEP" :       (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
    77                       "TRANSITION" : (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
    78                       "ACTION" :     (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
    79                       "SINT" :       (ctypes.c_int8,   lambda x:x.value,        lambda t,x:t(x)),
       
    80                       "USINT" :      (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
    81                       "BYTE" :       (ctypes.c_uint8,  lambda x:x.value,        lambda t,x:t(x)),
       
    82                       "STRING" :     (IEC_STRING,      lambda x:x.body[:x.len], lambda t,x:t(len(x),x)),
       
    83                       "INT" :        (ctypes.c_int16,  lambda x:x.value,        lambda t,x:t(x)),
       
    84                       "UINT" :       (ctypes.c_uint16, lambda x:x.value,        lambda t,x:t(x)),
       
    85                       "WORD" :       (ctypes.c_uint16, lambda x:x.value,        lambda t,x:t(x)),
       
    86                       "WSTRING" :    (None,            None,                    None),#TODO
       
    87                       "DINT" :       (ctypes.c_int32,  lambda x:x.value,        lambda t,x:t(x)),
       
    88                       "UDINT" :      (ctypes.c_uint32, lambda x:x.value,        lambda t,x:t(x)),
       
    89                       "DWORD" :      (ctypes.c_uint32, lambda x:x.value,        lambda t,x:t(x)),
       
    90                       "LINT" :       (ctypes.c_int64,  lambda x:x.value,        lambda t,x:t(x)),
       
    91                       "ULINT" :      (ctypes.c_uint64, lambda x:x.value,        lambda t,x:t(x)),
       
    92                       "LWORD" :      (ctypes.c_uint64, lambda x:x.value,        lambda t,x:t(x)),
       
    93                       "REAL" :       (ctypes.c_float,  lambda x:x.value,        lambda t,x:t(x)),
       
    94                       "LREAL" :      (ctypes.c_double, lambda x:x.value,        lambda t,x:t(x)),
       
    95                       } 
       
    96 
       
    97     def SetTraceVariablesList(self, idxs):
       
    98         """
       
    99         Call ctype imported function to append 
       
   100         these indexes to registred variables in PLC debugger
       
   101         """
       
   102         if idxs:
       
   103             buff = ""
       
   104             # keep a copy of requested idx
       
   105             self._Idxs = idxs[:]
       
   106             for idx,iectype,force in idxs:
       
   107                 idxstr = ctypes.string_at(
       
   108                           ctypes.pointer(
       
   109                            ctypes.c_uint32(length)),4)
       
   110                 if force !=None:
       
   111                     c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
       
   112                     forcedsizestr = chr(ctypes.sizeof(c_type))
       
   113                     forcestr = ctypes.string_at(
       
   114                                 ctypes.pointer(
       
   115                                  pack_func(c_type,force)),
       
   116                                  forced_type_size)
       
   117                     buff += idxstr + forced_type_size_str + forcestr
       
   118                 else:
       
   119                     buff += idxstr + chr(0)
       
   120             data = self.HandleSerialTransaction(
       
   121                    SET_TRACE_VARIABLETransaction(buff))
       
   122         else:
       
   123             self._Idxs =  []
       
   124 
       
   125     def GetTraceVariables(self):
       
   126         """
       
   127         Return a list of variables, corresponding to the list of required idx
       
   128         """
       
   129         offset = 0
       
   130         strbuf = self.HandleSerialTransaction(
       
   131                                      GET_TRACE_VARIABLETransaction())
       
   132         size = len(strbuf) - 4
       
   133         if size > 0 and self.PLCStatus == "Started":
       
   134             tick = ctypes.cast(
       
   135                     ctypes.c_char_p(strbuf[:4]),
       
   136                     ctypes.POINTER(ctypes.c_int)).contents
       
   137             buffer = ctypes.cast(
       
   138                       ctypes.c_char_p(strbuf[4:]),
       
   139                       ctypes.c_void_p)
       
   140             for idx, iectype, forced in self._Idxs:
       
   141                 cursor = ctypes.c_void_p(buffer.value + offset)
       
   142                 c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None))
       
   143                 if c_type is not None and offset < size:
       
   144                     res.append(unpack_func(ctypes.cast(cursor,
       
   145                                                        ctypes.POINTER(c_type)).contents))
       
   146                     offset += ctypes.sizeof(c_type)
       
   147                 else:
       
   148                     if c_type is None:
       
   149                         PLCprint("Debug error - " + iectype + " not supported !")
       
   150                     if offset >= size:
       
   151                         PLCprint("Debug error - buffer too small !")
       
   152                     break
       
   153             if offset and offset == size:
       
   154                 return self.PLCStatus, tick.value, res
       
   155             PLCprint("Debug error - wrong buffer unpack !")
       
   156         return self.PLCStatus, None, None
       
   157