--- 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:
--- 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)
--- 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
--- 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;
}
}