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: