ProjectController.py
changeset 978 3290eff761f1
parent 923 6ef6e0b3a908
child 985 cd8dadcef426
equal deleted inserted replaced
976:0ba3d9cd61e8 978:3290eff761f1
    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",