Log redirected to console, dump of all available log to console when connecting to PLC
authorEdouard Tisserant
Tue, 29 Jan 2013 16:21:01 +1100
changeset 911 ffa24427396a
parent 910 f6d06bdd31e8
child 913 5d6a04abab3c
Log redirected to console, dump of all available log to console when connecting to PLC
ProjectController.py
runtime/PLCObject.py
targets/plc_debug.c
tests/logging/beremiz.xml
tests/logging/plc.xml
--- a/ProjectController.py	Thu Jan 24 17:44:44 2013 +1100
+++ b/ProjectController.py	Tue Jan 29 16:21:01 2013 +1100
@@ -113,7 +113,7 @@
         self.DebugThread = None
         self.debug_break = False
         self.previous_plcstate = None
-        self.previous_log_count = -1
+        self.previous_log_count = None
         # copy ConfNodeMethods so that it can be later customized
         self.StatusMethods = [dic.copy() for dic in self.StatusMethods]
 
@@ -1077,11 +1077,26 @@
         self._builder = None
         self.CompareLocalAndRemotePLC()
 
-    ############# Real PLC object access #############
+    def UpdatePLCLog(self, log_count):
+        if log_count and self.previous_log_count != log_count:
+            #self.logger.write("Now log count is "+repr(log_count)+"\n")
+            to_console = ['']
+            for msgidx in xrange(log_count-1, self.previous_log_count - 1 if self.previous_log_count is not None else 0,-1): 
+                msg = self._connector.GetLogMessage(msgidx)
+                if msg is not None :
+                    to_console.insert(0, '#' + repr(msgidx) + ": " + msg)
+                else:
+                    #self.logger.write(repr(msgidx) + " : GetLogMessage returned None\n")
+                    to_console.insert(0, 'No log before #'+repr(msgidx))
+                    break;
+            self.logger.write("\n".join(to_console))
+            self.previous_log_count = log_count
+
     def UpdateMethodsFromPLCStatus(self):
         status = None
         if self._connector is not None:
             status, log_count = self._connector.GetPLCstatus()
+            self.UpdatePLCLog(log_count)
         if status is None:
             self._connector = None
             status = "Disconnected"
@@ -1103,9 +1118,6 @@
                 self.ShowMethod(*args)
             self.previous_plcstate = status
             return True
-        if(self.previous_log_count != log_count):
-            self.logger.write("Now log count is %d"%log_count)
-            self.previous_log_count = log_count
         return False
     
     def PullPLCStatusProc(self, event):
--- a/runtime/PLCObject.py	Thu Jan 24 17:44:44 2013 +1100
+++ b/runtime/PLCObject.py	Tue Jan 29 16:21:01 2013 +1100
@@ -79,6 +79,23 @@
         if self.statuschange is not None:
             self.statuschange(self.PLCStatus)
 
+    def LogMessage(self, msg):
+        return self._LogMessage(msg, len(msg))
+
+
+    def GetLogCount(self):
+        if self._GetLogCount is not None :
+            return int(self._GetLogCount())
+
+    def GetLogMessage(self, msgid):
+        maxsz = len(self._log_read_buffer)-1
+        sz = self._GetLogMessage(msgid, self._log_read_buffer, maxsz)
+        if sz and sz <= maxsz:
+            self._log_read_buffer[sz] = '\x00'
+            return self._log_read_buffer.value
+        else :
+            return None
+
     def _GetMD5FileName(self):
         return os.path.join(self.workingdir, "lasttransferedPLC.md5")
 
@@ -149,6 +166,15 @@
             self._GetLogCount = self.PLClibraryHandle.GetLogCount
             self._GetLogCount.restype = ctypes.c_uint32
 
+            self._LogMessage = self.PLClibraryHandle.LogMessage
+            self._LogMessage.restype = ctypes.c_int
+            self._LogMessage.argtypes = [ctypes.c_char_p, ctypes.c_uint32]
+            
+            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_uint32, ctypes.c_char_p, ctypes.c_uint32]
+
             return True
         except:
             PLCprint(traceback.format_exc())
@@ -171,7 +197,9 @@
         self._suspendDebug = lambda x:-1
         self._resumeDebug = lambda:None
         self._PythonIterator = lambda:""
-        self._GetLogCount = lambda:-1 
+        self._GetLogCount = None 
+        self._LogMessage = lambda m,s:PLCprint("OFF LOG :"+m)
+        self._GetLogMessage = lambda i,b,s:None
         self.PLClibraryHandle = None
         # Unload library explicitely
         if getattr(self,"_PLClibraryHandle",None) is not None:
@@ -258,6 +286,7 @@
     
     def StartPLC(self):
         PLCprint("StartPLC")
+        self.LogMessage("Hello Log")
         if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped":
             c_argv = ctypes.c_char_p * len(self.argv)
             error = None
@@ -293,7 +322,7 @@
         return True
 
     def GetPLCstatus(self):
-        return self.PLCStatus, self._GetLogCount()
+        return self.PLCStatus, self.GetLogCount()
     
     def NewPLC(self, md5sum, data, extrafiles):
         PLCprint("NewPLC (%s)"%md5sum)
@@ -414,10 +443,10 @@
                     self._FreeDebugData()
                 self.PLClibraryLock.release()
             if offset and offset == size.value:
-                return self.PLCStatus, self._GetLogCount(), tick.value, res
+                return self.PLCStatus, self.GetLogCount(), tick.value, res
             #elif size.value:
                 #PLCprint("Debug error - wrong buffer unpack ! %d != %d"%(offset, size.value))
-        return self.PLCStatus, self._GetLogCount(), None, []
+        return self.PLCStatus, self.GetLogCount(), None, []
 
     def RemoteExec(self, script, **kwargs):
         try:
--- a/targets/plc_debug.c	Thu Jan 24 17:44:44 2013 +1100
+++ b/targets/plc_debug.c	Tue Jan 29 16:21:01 2013 +1100
@@ -322,7 +322,7 @@
     if(buffpos + size < LOG_BUFFER_SIZE){
         memcpy(buf, &LogBuff[buffpos], size);
     }else{
-        uint32_t remaining = LOG_BUFFER_SIZE - buffpos - 1; 
+        uint32_t remaining = LOG_BUFFER_SIZE - buffpos; 
         memcpy(buf, &LogBuff[buffpos], remaining);
         memcpy(buf + remaining, LogBuff, size - remaining);
     }
@@ -387,27 +387,24 @@
 uint32_t GetLogMessage(uint32_t msgidx, char* buf, uint32_t max_size){
     uint64_t cursor = LogCursor;
     if(cursor){
-        /* feeding cursor values */
-        uint32_t curbuffpos = (uint32_t)cursor;
-        uint32_t curmsgidx = (cursor >> 32);
-
         /* seach cursor */
-        uint32_t stailpos = (curbuffpos - sizeof(mTail)) & LOG_BUFFER_MASK; 
+        uint32_t stailpos = (uint32_t)cursor; 
         uint32_t smsgidx;
         mTail tail;
-        tail.msgidx = curmsgidx;
+        tail.msgidx = cursor >> 32;
+        tail.msgsize = 0;
 
         /* Message search loop */
         do {
             smsgidx = tail.msgidx;
+            stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK;
             copy_from_log(stailpos, &tail, sizeof(mTail));
-            stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK;
-        }while(tail.msgidx == smsgidx - 1 && tail.msgidx > msgidx);
+        }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx));
 
         if(tail.msgidx == msgidx){
             uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; 
-            uint32_t totalsize = tail.msgsize + sizeof(mTail);
-            copy_from_log(stailpos, &tail, totalsize > max_size ? max_size : totalsize);
+            uint32_t totalsize = tail.msgsize; /*sizeof(mTail);*/
+            copy_from_log(sbuffpos, buf, totalsize > max_size ? max_size : totalsize);
             return totalsize;
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/logging/beremiz.xml	Tue Jan 29 16:21:01 2013 +1100
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<BeremizRoot URI_location="PYRO://127.0.0.1:3000">
+  <TargetType/>
+</BeremizRoot>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/logging/plc.xml	Tue Jan 29 16:21:01 2013 +1100
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.plcopen.org/xml/tc6.xsd"
+         xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns:xhtml="http://www.w3.org/1999/xhtml">
+  <fileHeader companyName="Unknown"
+              productName="Unnamed"
+              productVersion="1"
+              creationDateTime="2013-01-29T14:01:00"/>
+  <contentHeader name="Unnamed"
+                 modificationDateTime="2013-01-29T15:56:10">
+    <coordinateInfo>
+      <fbd>
+        <scaling x="0" y="0"/>
+      </fbd>
+      <ld>
+        <scaling x="0" y="0"/>
+      </ld>
+      <sfc>
+        <scaling x="0" y="0"/>
+      </sfc>
+    </coordinateInfo>
+  </contentHeader>
+  <types>
+    <dataTypes/>
+    <pous>
+      <pou name="LOGGER" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="TRIG">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="MSG">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <localVars>
+            <variable name="TRIG0">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[IF TRIG AND NOT TRIG0 THEN
+{{
+ LogMessage(GetFbVar(MSG, .body),GetFbVar(MSG, .len));
+}}
+END_IF;
+TRIG0:=TRIG;
+]]>
+          </ST>
+        </body>
+      </pou>
+      <pou name="program0" pouType="program">
+        <interface>
+          <localVars>
+            <variable name="LOGGER0">
+              <type>
+                <derived name="LOGGER"/>
+              </type>
+            </variable>
+            <variable name="beat">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="count">
+              <type>
+                <INT/>
+              </type>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <FBD>
+            <block localId="1" width="65" height="71" typeName="LOGGER" instanceName="LOGGER0">
+              <position x="1008" y="64"/>
+              <inputVariables>
+                <variable formalParameter="TRIG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="32"/>
+                    <connection refLocalId="3" formalParameter="OUT">
+                      <position x="1008" y="96"/>
+                      <position x="640" y="96"/>
+                      <position x="640" y="94"/>
+                      <position x="272" y="94"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="MSG">
+                  <connectionPointIn>
+                    <relPosition x="0" y="57"/>
+                    <connection refLocalId="8" formalParameter="OUT">
+                      <position x="1008" y="121"/>
+                      <position x="970" y="121"/>
+                      <position x="970" y="204"/>
+                      <position x="935" y="204"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables/>
+            </block>
+            <inVariable localId="2" height="27" width="85">
+              <position x="732" y="188"/>
+              <connectionPointOut>
+                <relPosition x="85" y="13"/>
+              </connectionPointOut>
+              <expression>'Moooooo'</expression>
+            </inVariable>
+            <block localId="3" width="59" height="40" typeName="NOT">
+              <position x="213" y="64"/>
+              <inputVariables>
+                <variable formalParameter="IN">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="4">
+                      <position x="213" y="94"/>
+                      <position x="179" y="94"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="59" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inOutVariable localId="4" height="27" width="41">
+              <position x="138" y="81"/>
+              <connectionPointIn>
+                <relPosition x="0" y="13"/>
+                <connection refLocalId="3" formalParameter="OUT">
+                  <position x="138" y="94"/>
+                  <position x="123" y="94"/>
+                  <position x="123" y="124"/>
+                  <position x="282" y="124"/>
+                  <position x="282" y="94"/>
+                  <position x="272" y="94"/>
+                </connection>
+              </connectionPointIn>
+              <connectionPointOut>
+                <relPosition x="41" y="13"/>
+              </connectionPointOut>
+              <expression>beat</expression>
+            </inOutVariable>
+            <block localId="5" width="68" height="80" typeName="ADD">
+              <position x="482" y="209"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="35"/>
+                    <connection refLocalId="10" formalParameter="OUT">
+                      <position x="482" y="244"/>
+                      <position x="459" y="244"/>
+                      <position x="459" y="230"/>
+                      <position x="449" y="230"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="65"/>
+                    <connection refLocalId="6">
+                      <position x="482" y="274"/>
+                      <position x="397" y="274"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="68" y="35"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <inOutVariable localId="6" height="27" width="48">
+              <position x="349" y="261"/>
+              <connectionPointIn>
+                <relPosition x="0" y="13"/>
+                <connection refLocalId="5" formalParameter="OUT">
+                  <position x="349" y="274"/>
+                  <position x="339" y="274"/>
+                  <position x="339" y="306"/>
+                  <position x="563" y="306"/>
+                  <position x="563" y="244"/>
+                  <position x="550" y="244"/>
+                </connection>
+              </connectionPointIn>
+              <connectionPointOut>
+                <relPosition x="48" y="13"/>
+              </connectionPointOut>
+              <expression>count</expression>
+            </inOutVariable>
+            <block localId="8" width="67" height="60" typeName="CONCAT">
+              <position x="868" y="174"/>
+              <inputVariables>
+                <variable formalParameter="IN1">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="2">
+                      <position x="868" y="204"/>
+                      <position x="843" y="204"/>
+                      <position x="843" y="201"/>
+                      <position x="817" y="201"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+                <variable formalParameter="IN2">
+                  <connectionPointIn>
+                    <relPosition x="0" y="50"/>
+                    <connection refLocalId="9" formalParameter="OUT">
+                      <position x="868" y="224"/>
+                      <position x="765" y="224"/>
+                      <position x="765" y="232"/>
+                      <position x="712" y="232"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="67" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="9" width="116" height="40" typeName="INT_TO_STRING">
+              <position x="596" y="202"/>
+              <inputVariables>
+                <variable formalParameter="IN">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="5" formalParameter="OUT">
+                      <position x="596" y="232"/>
+                      <position x="573" y="232"/>
+                      <position x="573" y="244"/>
+                      <position x="550" y="244"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="116" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+            <block localId="10" width="105" height="40" typeName="BOOL_TO_INT">
+              <position x="344" y="200"/>
+              <inputVariables>
+                <variable formalParameter="IN" edge="rising">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="3" formalParameter="OUT">
+                      <position x="344" y="230"/>
+                      <position x="242" y="230"/>
+                      <position x="242" y="163"/>
+                      <position x="282" y="163"/>
+                      <position x="282" y="94"/>
+                      <position x="272" y="94"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="105" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
+          </FBD>
+        </body>
+      </pou>
+    </pous>
+  </types>
+  <instances>
+    <configurations>
+      <configuration name="config">
+        <resource name="resource1">
+          <task name="blob" interval="T#1ms" priority="0">
+            <pouInstance name="blub" typeName="program0"/>
+          </task>
+        </resource>
+      </configuration>
+    </configurations>
+  </instances>
+</project>