83 |
83 |
84 def __init__(self, frame, logger): |
84 def __init__(self, frame, logger): |
85 PLCControler.__init__(self) |
85 PLCControler.__init__(self) |
86 |
86 |
87 self.MandatoryParams = None |
87 self.MandatoryParams = None |
88 self.SetAppFrame(frame, logger) |
|
89 self._builder = None |
88 self._builder = None |
90 self._connector = None |
89 self._connector = None |
|
90 self.SetAppFrame(frame, logger) |
91 |
91 |
92 self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+(".exe" if wx.Platform == '__WXMSW__' else "")) |
92 self.iec2c_path = os.path.join(base_folder, "matiec", "iec2c"+(".exe" if wx.Platform == '__WXMSW__' else "")) |
93 self.ieclib_path = os.path.join(base_folder, "matiec", "lib") |
93 self.ieclib_path = os.path.join(base_folder, "matiec", "lib") |
94 |
94 |
95 # Setup debug information |
95 # Setup debug information |
111 self.ProjectPath = None |
111 self.ProjectPath = None |
112 self._setBuildPath(None) |
112 self._setBuildPath(None) |
113 self.DebugThread = None |
113 self.DebugThread = None |
114 self.debug_break = False |
114 self.debug_break = False |
115 self.previous_plcstate = None |
115 self.previous_plcstate = None |
116 self.previous_log_count = [None]*LogLevelsCount |
|
117 # copy ConfNodeMethods so that it can be later customized |
116 # copy ConfNodeMethods so that it can be later customized |
118 self.StatusMethods = [dic.copy() for dic in self.StatusMethods] |
117 self.StatusMethods = [dic.copy() for dic in self.StatusMethods] |
119 |
118 |
120 def LoadLibraries(self): |
119 def LoadLibraries(self): |
121 self.Libraries = [] |
120 self.Libraries = [] |
135 self.AppFrame = frame |
134 self.AppFrame = frame |
136 self.logger = logger |
135 self.logger = logger |
137 self.StatusTimer = None |
136 self.StatusTimer = None |
138 |
137 |
139 if frame is not None: |
138 if frame is not None: |
|
139 frame.LogViewer.SetLogSource(self._connector) |
|
140 |
140 # Timer to pull PLC status |
141 # Timer to pull PLC status |
141 ID_STATUSTIMER = wx.NewId() |
142 ID_STATUSTIMER = wx.NewId() |
142 self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER) |
143 self.StatusTimer = wx.Timer(self.AppFrame, ID_STATUSTIMER) |
143 self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer) |
144 self.AppFrame.Bind(wx.EVT_TIMER, self.PullPLCStatusProc, self.StatusTimer) |
144 |
145 |
279 Load a project contained in a folder |
280 Load a project contained in a folder |
280 @param ProjectPath: path of the project folder |
281 @param ProjectPath: path of the project folder |
281 """ |
282 """ |
282 if os.path.basename(ProjectPath) == "": |
283 if os.path.basename(ProjectPath) == "": |
283 ProjectPath = os.path.dirname(ProjectPath) |
284 ProjectPath = os.path.dirname(ProjectPath) |
284 # Verify that project contains a PLCOpen program |
285 # Verify that project contains a PLCOpen program |
285 plc_file = os.path.join(ProjectPath, "plc.xml") |
286 plc_file = os.path.join(ProjectPath, "plc.xml") |
286 if not os.path.isfile(plc_file): |
287 if not os.path.isfile(plc_file): |
287 return _("Chosen folder doesn't contain a program. It's not a valid project!") |
288 return _("Chosen folder doesn't contain a program. It's not a valid project!") |
288 # Load PLCOpen file |
289 # Load PLCOpen file |
289 result = self.OpenXMLFile(plc_file) |
290 result = self.OpenXMLFile(plc_file) |
1075 # kill the builder |
1076 # kill the builder |
1076 self._builder = None |
1077 self._builder = None |
1077 self.CompareLocalAndRemotePLC() |
1078 self.CompareLocalAndRemotePLC() |
1078 |
1079 |
1079 def UpdatePLCLog(self, log_count): |
1080 def UpdatePLCLog(self, log_count): |
1080 if log_count : |
1081 if log_count: |
1081 to_console = [] |
1082 if self.AppFrame is not None: |
1082 for level, count, prev in zip(xrange(LogLevelsCount), log_count,self.previous_log_count): |
1083 self.AppFrame.LogViewer.SetLogCounters(log_count) |
1083 if count is not None and prev != count: |
1084 |
1084 # XXX replace dump to console with dedicated log panel. |
|
1085 dump_end = max( # request message sent after the last one we already got |
|
1086 prev - 1 if prev is not None else -1, |
|
1087 count - 100) # 100 is purely arbitrary number |
|
1088 # dedicated panel should only ask for a small range, |
|
1089 # depending on how user navigate in the panel |
|
1090 # and only ask for last one in follow mode |
|
1091 for msgidx in xrange(count-1, dump_end,-1): |
|
1092 answer = self._connector.GetLogMessage(level, msgidx) |
|
1093 if answer is not None : |
|
1094 msg, tick, tv_sec, tv_nsec = answer |
|
1095 to_console.insert(0,( |
|
1096 (tv_sec, tv_nsec), |
|
1097 '%d|%s.%9.9d|%s(%s)'%( |
|
1098 int(tick), |
|
1099 str(datetime.fromtimestamp(tv_sec)), |
|
1100 tv_nsec, |
|
1101 msg, |
|
1102 LogLevels[level]))) |
|
1103 else: |
|
1104 break; |
|
1105 self.previous_log_count[level] = count |
|
1106 if to_console: |
|
1107 to_console.sort() |
|
1108 self.logger.write("\n".join(zip(*to_console)[1]+('',))) |
|
1109 |
|
1110 def UpdateMethodsFromPLCStatus(self): |
1085 def UpdateMethodsFromPLCStatus(self): |
1111 status = None |
1086 status = None |
1112 if self._connector is not None: |
1087 if self._connector is not None: |
1113 PLCstatus = self._connector.GetPLCstatus() |
1088 PLCstatus = self._connector.GetPLCstatus() |
1114 if PLCstatus is not None: |
1089 if PLCstatus is not None: |
1115 status, log_count = PLCstatus |
1090 status, log_count = PLCstatus |
1116 self.UpdatePLCLog(log_count) |
1091 self.UpdatePLCLog(log_count) |
1117 if status is None: |
1092 if status is None: |
1118 self._connector = None |
1093 self._SetConnector(None) |
1119 status = "Disconnected" |
1094 status = "Disconnected" |
1120 if(self.previous_plcstate != status): |
1095 if(self.previous_plcstate != status): |
1121 for args in { |
1096 for args in { |
1122 "Started" : [("_Run", False), |
1097 "Started" : [("_Run", False), |
1123 ("_Stop", True)], |
1098 ("_Stop", True)], |
1301 if(Trace): |
1276 if(Trace): |
1302 plc_status, debug_tick, debug_vars = Trace |
1277 plc_status, debug_tick, debug_vars = Trace |
1303 else: |
1278 else: |
1304 plc_status = None |
1279 plc_status = None |
1305 debug_getvar_retry += 1 |
1280 debug_getvar_retry += 1 |
|
1281 #print [dict.keys() for IECPath, (dict, log, status, fvalue) in self.IECdebug_datas.items()] |
1306 if plc_status == "Started": |
1282 if plc_status == "Started": |
1307 self.IECdebug_lock.acquire() |
1283 self.IECdebug_lock.acquire() |
1308 if len(debug_vars) == len(self.TracedIECPath): |
1284 if len(debug_vars) == len(self.TracedIECPath): |
1309 if debug_getvar_retry > DEBUG_RETRIES_WARN: |
1285 if debug_getvar_retry > DEBUG_RETRIES_WARN: |
1310 self.logger.write(_("... debugger recovered\n")) |
1286 self.logger.write(_("... debugger recovered\n")) |
1339 self.logger.write(_("Debugger stopped.\n")) |
1315 self.logger.write(_("Debugger stopped.\n")) |
1340 self.DebugThread = None |
1316 self.DebugThread = None |
1341 |
1317 |
1342 def _connect_debug(self): |
1318 def _connect_debug(self): |
1343 self.previous_plcstate = None |
1319 self.previous_plcstate = None |
1344 self.previous_log_count = [None]*LogLevelsCount |
|
1345 if self.AppFrame: |
1320 if self.AppFrame: |
1346 self.AppFrame.ResetGraphicViewers() |
1321 self.AppFrame.ResetGraphicViewers() |
1347 self.RegisterDebugVarToConnector() |
1322 self.RegisterDebugVarToConnector() |
1348 if self.DebugThread is None: |
1323 if self.DebugThread is None: |
1349 self.DebugThread = Thread(target=self.DebugThreadProc) |
1324 self.DebugThread = Thread(target=self.DebugThreadProc) |
1371 # debugthread should die on his own |
1346 # debugthread should die on his own |
1372 #self.KillDebugThread() |
1347 #self.KillDebugThread() |
1373 |
1348 |
1374 wx.CallAfter(self.UpdateMethodsFromPLCStatus) |
1349 wx.CallAfter(self.UpdateMethodsFromPLCStatus) |
1375 |
1350 |
|
1351 def _SetConnector(self, connector): |
|
1352 self._connector = connector |
|
1353 if self.AppFrame is not None: |
|
1354 self.AppFrame.LogViewer.SetLogSource(connector) |
|
1355 |
1376 def _Connect(self): |
1356 def _Connect(self): |
1377 # don't accept re-connetion if already connected |
1357 # don't accept re-connetion if already connected |
1378 if self._connector is not None: |
1358 if self._connector is not None: |
1379 self.logger.write_error(_("Already connected. Please disconnect\n")) |
1359 self.logger.write_error(_("Already connected. Please disconnect\n")) |
1380 return |
1360 return |
1415 self.AppFrame.RefreshEditMenu() |
1395 self.AppFrame.RefreshEditMenu() |
1416 self.AppFrame.RefreshPageTitles() |
1396 self.AppFrame.RefreshPageTitles() |
1417 |
1397 |
1418 # Get connector from uri |
1398 # Get connector from uri |
1419 try: |
1399 try: |
1420 self._connector = connectors.ConnectorFactory(uri, self) |
1400 self._SetConnector(connectors.ConnectorFactory(uri, self)) |
1421 except Exception, msg: |
1401 except Exception, msg: |
1422 self.logger.write_error(_("Exception while connecting %s!\n")%uri) |
1402 self.logger.write_error(_("Exception while connecting %s!\n")%uri) |
1423 self.logger.write_error(traceback.format_exc()) |
1403 self.logger.write_error(traceback.format_exc()) |
1424 |
1404 |
1425 # Did connection success ? |
1405 # Did connection success ? |
1475 # _("Cannot compare latest build to target. Please build.\n")) |
1455 # _("Cannot compare latest build to target. Please build.\n")) |
1476 self.EnableMethod("_Transfer", False) |
1456 self.EnableMethod("_Transfer", False) |
1477 |
1457 |
1478 |
1458 |
1479 def _Disconnect(self): |
1459 def _Disconnect(self): |
1480 self._connector = None |
1460 self._SetConnector(None) |
1481 self.StatusTimer.Stop() |
1461 self.StatusTimer.Stop() |
1482 wx.CallAfter(self.UpdateMethodsFromPLCStatus) |
1462 wx.CallAfter(self.UpdateMethodsFromPLCStatus) |
1483 |
1463 |
1484 def _Transfer(self): |
1464 def _Transfer(self): |
1485 # Get the last build PLC's |
1465 # Get the last build PLC's |
1519 self.logger.write(_("Transfer completed successfully.\n")) |
1499 self.logger.write(_("Transfer completed successfully.\n")) |
1520 else: |
1500 else: |
1521 self.logger.write_error(_("Transfer failed\n")) |
1501 self.logger.write_error(_("Transfer failed\n")) |
1522 else: |
1502 else: |
1523 self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n")) |
1503 self.logger.write_error(_("No PLC to transfer (did build succeed ?)\n")) |
1524 |
|
1525 self.previous_log_count = [None]*LogLevelsCount |
|
1526 |
1504 |
1527 wx.CallAfter(self.UpdateMethodsFromPLCStatus) |
1505 wx.CallAfter(self.UpdateMethodsFromPLCStatus) |
1528 |
1506 |
1529 StatusMethods = [ |
1507 StatusMethods = [ |
1530 {"bitmap" : "Build", |
1508 {"bitmap" : "Build", |