# HG changeset patch # User Laurent Bessard # Date 1360110061 -3600 # Node ID 2323981f5d410c47281d3119aef8c67cf82ff864 # Parent 6ef6e0b3a908b0ec8f2eb693a21ed456dd8f4a91# Parent 5f9dd88a605b66a83f7d4efd135f51f28ad78362 Merged diff -r 5f9dd88a605b -r 2323981f5d41 ProjectController.py --- a/ProjectController.py Wed Feb 06 01:18:56 2013 +0100 +++ b/ProjectController.py Wed Feb 06 01:21:01 2013 +0100 @@ -1078,10 +1078,10 @@ def UpdatePLCLog(self, log_count): if log_count : + to_console = [] for level, count, prev in zip(xrange(LogLevelsCount), log_count,self.previous_log_count): if count is not None and prev != count: # XXX replace dump to console with dedicated log panel. - to_console = [''] dump_end = max( # request message sent after the last one we already got prev - 1 if prev is not None else -1, count - 100) # 100 is purely arbitrary number @@ -1089,20 +1089,31 @@ # depending on how user navigate in the panel # and only ask for last one in follow mode for msgidx in xrange(count-1, dump_end,-1): - msg = self._connector.GetLogMessage(level, msgidx) - if msg is not None : - to_console.insert(0, LogLevels[level]+ ':#' + repr(msgidx) + ": " + msg) + answer = self._connector.GetLogMessage(level, msgidx) + if answer is not None : + msg, tick, tv_sec, tv_nsec = answer + to_console.insert(0,( + (tv_sec, tv_nsec), + '%d|%s.%9.9d|%s(%s)'%( + int(tick), + str(datetime.fromtimestamp(tv_sec)), + tv_nsec, + msg, + LogLevels[level]))) else: - to_console.insert(0, LogLevels[level]+ ': No log before #'+repr(msgidx)) break; - self.logger.write("\n".join(to_console)) self.previous_log_count[level] = count + if to_console: + to_console.sort() + self.logger.write("\n".join(zip(*to_console)[1]+('',))) def UpdateMethodsFromPLCStatus(self): status = None if self._connector is not None: - status, log_count = self._connector.GetPLCstatus() - self.UpdatePLCLog(log_count) + PLCstatus = self._connector.GetPLCstatus() + if PLCstatus is not None: + status, log_count = PLCstatus + self.UpdatePLCLog(log_count) if status is None: self._connector = None status = "Disconnected" @@ -1122,10 +1133,10 @@ ("_Disconnect", False)], }.get(status,[]): self.ShowMethod(*args) - self.previous_plcstate = status {"Broken": self.logger.write_error, None: lambda x: None}.get( - status, self.logger.write)(_("PLC is %s\n")%_(status)) + status, self.logger.write)(_("PLC state is \"%s\"\n")%_(status)) + self.previous_plcstate = status if self.AppFrame is not None: self.AppFrame.RefreshStatusToolBar() @@ -1363,7 +1374,7 @@ wx.CallAfter(self.UpdateMethodsFromPLCStatus) def _Connect(self): - # don't accept re-connetion is already connected + # don't accept re-connetion if already connected if self._connector is not None: self.logger.write_error(_("Already connected. Please disconnect\n")) return @@ -1428,17 +1439,18 @@ status = _(self.previous_plcstate) else: status = "" - self.logger.write(_("PLC is %s\n")%status) + + #self.logger.write(_("PLC is %s\n")%status) # Start the status Timer self.StatusTimer.Start(milliseconds=500, oneShot=False) - if self.previous_plcstate=="Started": + if self.previous_plcstate in ["Started","Stopped"]: if self.DebugAvailable() and self.GetIECProgramsAndVariables(): - self.logger.write(_("Debug connect matching running PLC\n")) + self.logger.write(_("Debugger ready\n")) self._connect_debug() else: - self.logger.write_warning(_("Debug do not match PLC - stop/transfert/start to re-enable\n")) + self.logger.write_warning(_("Debug does not match PLC - stop/transfert/start to re-enable\n")) def CompareLocalAndRemotePLC(self): if self._connector is None: diff -r 5f9dd88a605b -r 2323981f5d41 connectors/PYRO/__init__.py --- a/connectors/PYRO/__init__.py Wed Feb 06 01:18:56 2013 +0100 +++ b/connectors/PYRO/__init__.py Wed Feb 06 01:21:01 2013 +0100 @@ -88,7 +88,7 @@ # Check connection is effective. # lambda is for getattr of GetPLCstatus to happen inside catcher - if PyroCatcher(lambda:RemotePLCObjectProxy.GetPLCstatus())() == None: + if PyroCatcher(lambda:RemotePLCObjectProxy.GetPLCstatus())() is None: confnodesroot.logger.write_error(_("Cannot get PLC status - connection failed.\n")) return None @@ -144,7 +144,7 @@ def _PyroGetPLCstatus(self): return RemotePLCObjectProxy.GetPLCstatus() - GetPLCstatus = PyroCatcher(_PyroGetPLCstatus, ("Broken",-1)) + GetPLCstatus = PyroCatcher(_PyroGetPLCstatus, ("Broken",None)) def _PyroRemoteExec(self, script, **kwargs): return RemotePLCObjectProxy.RemoteExec(script, **kwargs) diff -r 5f9dd88a605b -r 2323981f5d41 runtime/PLCObject.py --- a/runtime/PLCObject.py Wed Feb 06 01:18:56 2013 +0100 +++ b/runtime/PLCObject.py Wed Feb 06 01:21:01 2013 +0100 @@ -97,14 +97,21 @@ return 1; def GetLogMessage(self, level, msgid): + tick = ctypes.c_uint32() + tv_sec = ctypes.c_uint32() + tv_nsec = ctypes.c_uint32() if self._GetLogMessage is not None: maxsz = len(self._log_read_buffer)-1 - sz = self._GetLogMessage(level, msgid, self._log_read_buffer, maxsz) + sz = self._GetLogMessage(level, msgid, + self._log_read_buffer, maxsz, + ctypes.byref(tick), + ctypes.byref(tv_sec), + ctypes.byref(tv_nsec)) if sz and sz <= maxsz: self._log_read_buffer[sz] = '\x00' - return self._log_read_buffer.value + return self._log_read_buffer.value,tick.value,tv_sec.value,tv_nsec.value elif self._loading_error is not None and level==0: - return self._loading_error + return self._loading_error,0,0,0 return None def _GetMD5FileName(self): @@ -185,7 +192,7 @@ self._log_read_buffer = ctypes.create_string_buffer(1<<14) #16K self._GetLogMessage = self.PLClibraryHandle.GetLogMessage self._GetLogMessage.restype = ctypes.c_uint32 - self._GetLogMessage.argtypes = [ctypes.c_uint8, ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32] + self._GetLogMessage.argtypes = [ctypes.c_uint8, ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32)] self._loading_error = None return True diff -r 5f9dd88a605b -r 2323981f5d41 targets/plc_debug.c --- a/targets/plc_debug.c Wed Feb 06 01:18:56 2013 +0100 +++ b/targets/plc_debug.c Wed Feb 06 01:21:01 2013 +0100 @@ -310,7 +310,7 @@ #define LOG_CRITICAL 0 #define LOG_WARNING 1 #define LOG_INFO 2 -#define LOG_DEBUG 4 +#define LOG_DEBUG 3 #define LOG_BUFFER_SIZE (1<<14) /*16Ko*/ #define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1) @@ -343,8 +343,8 @@ typedef struct { uint32_t msgidx; uint32_t msgsize; - /*XXX tick*/ - /*XXX RTC*/ + unsigned long tick; + IEC_TIME time; } mTail; /* Log cursor : 64b @@ -357,12 +357,17 @@ int LogMessage(uint8_t level, char* buf, uint32_t size){ if(size < LOG_BUFFER_SIZE - sizeof(mTail)){ uint32_t buffpos; + uint64_t new_cursor, old_cursor; + mTail tail; + tail.msgsize = size; + tail.tick = __tick; + PLC_GetTime(&tail.time); + /* We cannot increment both msg index and string pointer in a single atomic operation but we can detect having been interrupted. So we can try with atomic compare and swap in a loop until operation succeeds non interrupted */ - uint64_t new_cursor, old_cursor; do{ old_cursor = LogCursor[level]; buffpos = (uint32_t)old_cursor; @@ -372,9 +377,6 @@ }while(!__sync_bool_compare_and_swap(&LogCursor[level],old_cursor,new_cursor)); copy_to_log(level, buffpos, buf, size); - tail.msgsize = size; - /*XXX tick*/ - /*XXX RTC*/ copy_to_log(level, (buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); return 1; /* Success */ @@ -390,7 +392,7 @@ } /* Return message size and content */ -uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size){ +uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size, uint32_t* tick, uint32_t* tv_sec, uint32_t* tv_nsec){ uint64_t cursor = LogCursor[level]; if(cursor){ /* seach cursor */ @@ -409,8 +411,12 @@ if(tail.msgidx == msgidx){ uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; - uint32_t totalsize = tail.msgsize; /*sizeof(mTail);*/ - copy_from_log(level, sbuffpos, buf, totalsize > max_size ? max_size : totalsize); + uint32_t totalsize = tail.msgsize; + *tick = tail.tick; + *tv_sec = tail.time.tv_sec; + *tv_nsec = tail.time.tv_nsec; + copy_from_log(level, sbuffpos, buf, + totalsize > max_size ? max_size : totalsize); return totalsize; } }