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 |