CLI: poll runtime log and output new entries to stdout. wxPython4
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Wed, 05 Oct 2022 20:25:58 +0200
branchwxPython4
changeset 3619 f75b11506fb2
parent 3618 f08b59f7c00a
child 3620 1cf21430ed4a
CLI: poll runtime log and output new entries to stdout.
CLIController.py
--- a/CLIController.py	Wed Oct 05 20:15:28 2022 +0200
+++ b/CLIController.py	Wed Oct 05 20:25:58 2022 +0200
@@ -4,6 +4,8 @@
 import os
 import sys
 from functools import wraps
+from threading import Timer
+from datetime import datetime
 
 import click
 
@@ -11,6 +13,8 @@
 
 from ProjectController import ProjectController
 from LocalRuntimeMixin import LocalRuntimeMixin
+from runtime.loglevels import LogLevelsCount, LogLevels
+
 
 class Log:
 
@@ -74,6 +78,64 @@
         log = Log()
         LocalRuntimeMixin.__init__(self, log, use_gui=False)
         ProjectController.__init__(self, None, log)
+        self.CLIStatusTimer = None
+        self.KillCLIStatusTimer = False
+
+
+    def StartCLIStatusTimer(self):
+        if self.CLIStatusTimer is not None:
+            return
+        self.CLIStatusTimer = Timer(0.5, self.CLIStatusTimerProc)
+        self.KillCLIStatusTimer = False
+        self.CLIStatusTimer.start()
+
+    def StopCLIStatusTimer(self):
+        if self.CLIStatusTimer is None:
+            return
+        self.KillCLIStatusTimer = True
+        self.CLIStatusTimer.cancel()
+        self.CLIStatusTimer = None
+
+    def CLIStatusTimerProc(self):
+        self.CLIStatusTimer = None
+        if not self.KillCLIStatusTimer:
+            self.PullPLCStatusProc(None)
+            self.StartCLIStatusTimer()
+
+    def _SetConnector(self, connector, update_status=True):
+        self._connector = connector
+        self.previous_log_count = [None]*LogLevelsCount
+        if connector is not None:
+            self.StartCLIStatusTimer()
+        else:
+            self.StopCLIStatusTimer()
+            if update_status:
+                self.UpdateMethodsFromPLCStatus()
+
+    def UpdatePLCLog(self, log_count):
+        connector = self._connector
+        new_messages = []
+        if connector:
+            for level, count, prev in zip(
+                xrange(LogLevelsCount), log_count, self.previous_log_count):
+                if count is not None and prev != count:
+                    if prev is None:
+                        dump_end = max(-1, count - 10)
+                    else:
+                        dump_end = prev - 1
+                    for msgidx in range(count-1, dump_end, -1):
+                        message = connector.GetLogMessage(level, msgidx)
+                        if message is not None:
+                            msg, _tick, tv_sec, tv_nsec = message
+                            date = datetime.utcfromtimestamp(tv_sec + tv_nsec * 1e-9)
+                            txt = "%s at %s: %s\n" % (LogLevels[level], date.isoformat(' '), msg)
+                            new_messages.append((date,txt))
+                        else:
+                            break
+                self.previous_log_count[level] = count
+            new_messages.sort()
+            for date, txt in new_messages:
+                self.logger.write(txt)
 
     def check_and_load_project(self):
         if not os.path.isdir(self.session.project_home):