Merged
authorLaurent Bessard
Wed, 06 Feb 2013 01:21:01 +0100
changeset 926 2323981f5d41
parent 923 6ef6e0b3a908 (diff)
parent 925 5f9dd88a605b (current diff)
child 927 bd3e5b65e8be
Merged
--- 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;
         }
     }