ed@448: #!/usr/bin/env python ed@448: # -*- coding: utf-8 -*- ed@448: ed@448: #This file is part of Beremiz, a Integrated Development Environment for ed@448: #programming IEC 61131-3 automates supporting plcopen standard and CanFestival. ed@448: # ed@448: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD ed@448: # ed@448: #See COPYING file for copyrights details. ed@448: # ed@448: #This library is free software; you can redistribute it and/or ed@448: #modify it under the terms of the GNU General Public ed@448: #License as published by the Free Software Foundation; either ed@448: #version 2.1 of the License, or (at your option) any later version. ed@448: # ed@448: #This library is distributed in the hope that it will be useful, ed@448: #but WITHOUT ANY WARRANTY; without even the implied warranty of ed@448: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ed@448: #General Public License for more details. ed@448: # ed@448: #You should have received a copy of the GNU General Public ed@448: #License along with this library; if not, write to the Free Software ed@448: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ed@448: ed@448: from threading import Timer, Thread, Lock ed@448: import ctypes, os, commands, types, sys ed@448: import traceback edouard@453: from LPCProto import * ed@448: ed@448: class LPCObject(): ed@448: def __init__(self,pluginsroot): ed@448: self.PLCStatus = "Stopped" ed@448: self.pluginsroot = pluginsroot ed@448: self.PLCprint = pluginsroot.logger.write edouard@453: self.SerialConnection = None edouard@453: self._Idxs = [] edouard@453: edouard@453: def HandleSerialTransaction(self, transaction): edouard@453: if self.SerialConnection is None: edouard@453: try: edouard@453: self.SerialConnection = LPCProto(6,115200,2) edouard@453: except Exception,e: edouard@453: self.pluginsroot.logger.write_error(str(e)+"\n") edouard@453: self.SerialConnection = None edouard@453: return "Disconnected", res edouard@453: try: edouard@453: return self.SerialConnection.HandleTransaction(transaction) edouard@453: except LPCError,e: edouard@453: #pluginsroot.logger.write_error(traceback.format_exc()) edouard@453: self.pluginsroot.logger.write_error(str(e)+"\n") edouard@453: self.SerialConnection = None edouard@453: return "Disconnected", res edouard@453: ed@448: def StartPLC(self, debug=False): ed@448: PLCprint("StartPLC") edouard@453: self.HandleSerialTransaction(STARTTransaction()) ed@448: ed@448: def StopPLC(self): ed@448: PLCprint("StopPLC") edouard@453: self.HandleSerialTransaction(STOPTransaction()) ed@448: ed@448: def ForceReload(self): edouard@453: pass ed@448: ed@448: def GetPLCstatus(self): edouard@453: status,data = self.HandleSerialTransaction(IDLETransaction()) edouard@453: return status ed@448: ed@448: def NewPLC(self, md5sum, data, extrafiles): edouard@453: pass ed@448: ed@448: def MatchMD5(self, MD5): edouard@453: status,data = self.HandleSerialTransaction(PLCIDTransaction()) edouard@453: return data == MD5 ed@448: ed@448: def SetTraceVariablesList(self, idxs): edouard@453: self._Idxs = idxs[] edouard@453: status,data = self.HandleSerialTransaction( edouard@453: SET_TRACE_VARIABLETransaction( edouard@453: ''.join(map(chr,idx)))) ed@448: ed@448: class IEC_STRING(ctypes.Structure): ed@448: """ ed@448: Must be changed according to changes in iec_types.h ed@448: """ ed@448: _fields_ = [("len", ctypes.c_uint8), ed@448: ("body", ctypes.c_char * 127)] ed@448: ed@448: TypeTranslator = {"BOOL" : (ctypes.c_uint8, lambda x:x.value!=0), ed@448: "STEP" : (ctypes.c_uint8, lambda x:x.value), ed@448: "TRANSITION" : (ctypes.c_uint8, lambda x:x.value), ed@448: "ACTION" : (ctypes.c_uint8, lambda x:x.value), ed@448: "SINT" : (ctypes.c_int8, lambda x:x.value), ed@448: "USINT" : (ctypes.c_uint8, lambda x:x.value), ed@448: "BYTE" : (ctypes.c_uint8, lambda x:x.value), ed@448: "STRING" : (IEC_STRING, lambda x:x.body[:x.len]), ed@448: "INT" : (ctypes.c_int16, lambda x:x.value), ed@448: "UINT" : (ctypes.c_uint16, lambda x:x.value), ed@448: "WORD" : (ctypes.c_uint16, lambda x:x.value), ed@448: "WSTRING" : (None, None),#TODO ed@448: "DINT" : (ctypes.c_int32, lambda x:x.value), ed@448: "UDINT" : (ctypes.c_uint32, lambda x:x.value), ed@448: "DWORD" : (ctypes.c_uint32, lambda x:x.value), ed@448: "LINT" : (ctypes.c_int64, lambda x:x.value), ed@448: "ULINT" : (ctypes.c_uint64, lambda x:x.value), ed@448: "LWORD" : (ctypes.c_uint64, lambda x:x.value), ed@448: "REAL" : (ctypes.c_float, lambda x:x.value), ed@448: "LREAL" : (ctypes.c_double, lambda x:x.value), ed@448: } ed@448: ed@448: def GetTraceVariables(self): ed@448: """ ed@448: Return a list of variables, corresponding to the list of required idx ed@448: """ edouard@453: status,data = self.HandleSerialTransaction(GET_TRACE_VARIABLETransaction()) edouard@453: if data is not None: edouard@453: # transform serial string to real byte string in memory edouard@453: buffer = ctypes.c_char_p(data) edouard@453: # tick is first value in buffer edouard@453: tick = ctypes.cast(buffer,ctypes.POINTER(ctypes.c_uint32)).contents edouard@453: # variable data starts just after tick edouard@453: cursorp = ctypes.addressof(buffer) = ctypes.sizeof(ctypes.c_uint32) edouard@453: endp = offset + len(data) edouard@453: for idx, iectype in self._Idxs: edouard@453: cursor = ctypes.c_void_p(cursorp) edouard@453: c_type,unpack_func = self.TypeTranslator.get(iectype, (None,None)) edouard@453: if c_type is not None and cursorp < endp: edouard@453: res.append(unpack_func(ctypes.cast(cursor, edouard@453: ctypes.POINTER(c_type)).contents)) edouard@453: cursorp += ctypes.sizeof(c_type) edouard@453: else: edouard@453: PLCprint("Debug error !") edouard@453: break edouard@453: return self.PLCStatus, tick, res edouard@453: return self.PLCStatus, None, None ed@448: