From 124b9a3c2966d4c4c672bae86ea01b8978c36a23 Mon Sep 17 00:00:00 2001
From: kruger <kruger@astron.nl>
Date: Mon, 14 Aug 2023 14:13:24 +0200
Subject: [PATCH] I2C reset 1st version

---
 pypcc/opcuaserv/i2client.py   |  4 +++
 pypcc/opcuaserv/yamlreader.py | 23 ++++++++------
 pypcc/pypcc.py                | 58 ++++++++++++++++++++++++++++-------
 3 files changed, 65 insertions(+), 20 deletions(-)

diff --git a/pypcc/opcuaserv/i2client.py b/pypcc/opcuaserv/i2client.py
index 680f0f0..7aaabac 100644
--- a/pypcc/opcuaserv/i2client.py
+++ b/pypcc/opcuaserv/i2client.py
@@ -19,6 +19,10 @@ class i2client():
 #        self.thread1.join();
 #        os.close(self.Output)
 #        self.Input.close()
+    def restart(self):
+        self.stop()
+        self.Qin=Queue()
+        self.Qout=Queue()
 
     def readvar(self,id1,mask=[]):
         Data=OPCUAset(id1,InstType.varRead,[],mask.copy())
diff --git a/pypcc/opcuaserv/yamlreader.py b/pypcc/opcuaserv/yamlreader.py
index f4debf2..43bb376 100644
--- a/pypcc/opcuaserv/yamlreader.py
+++ b/pypcc/opcuaserv/yamlreader.py
@@ -134,8 +134,8 @@ class yamlreader(yamlconfig):
         self.statusid=self.getvarid(self.basename+"_translator_busy");
         self.monitorvarid=self.getvarid(self.basename+"_monitor_rate");
         self.statusOPC=None
-        self.lastSend=time.localtime()
-        self.lastRecv=time.localtime()
+        self.lastSend=time.time()
+        self.lastRecv=time.time()
 
     def SetBusy(self):
         if self.statusid is None: return
@@ -149,7 +149,7 @@ class yamlreader(yamlconfig):
         if var1 is None: var1=v.get('OPCW',None)
         if var1 is None:
            logging.warn("OPC variable not found!!");
-           return;
+           return False;
         data3=var1.get_value();
         return data3
 
@@ -225,8 +225,9 @@ class yamlreader(yamlconfig):
         logging.debug("Method called!"+v['name'])
         mask=v.get('maskOPC',None);
         mask=mask.get_value() if (mask!=None) else [];
+        if not(self.GetBusy()): self.lastRecv=time.time()
         self.SetBusy()
-        self.lastSend=time.localtime()
+        self.lastSend=time.time()
         self.server.callmethod(id1,mask) 
 
     def CallInit(self):
@@ -250,8 +251,9 @@ class yamlreader(yamlconfig):
         data2,mask=var2byte(v,data)
         logging.info(str(("setvar ",v['name'],data2,mask)));
         if data2 is None: return 
+        if not(self.GetBusy()): self.lastRecv=time.time()
         self.SetBusy()
-        self.lastSend=time.localtime()
+        self.lastSend=time.time()
         self.server.setvar(id1,data2,mask) 
 
     def getvar(self):
@@ -262,7 +264,7 @@ class yamlreader(yamlconfig):
 #           try:
             item=self.server.readdata()
             if item is None: break;
-            self.lastRecv=time.localtime()
+            self.lastRecv=time.time()
             id1,data,mask=item; 
             logging.debug(str(("**getvar",id1,data,mask)));
             if len(data)==0: continue;
@@ -296,7 +298,7 @@ class yamlreader(yamlconfig):
         if len(data3)==1: data3=data3[0];
         var1.set_value(data3,datatype);
     def watchdog(self):
-        print(self.lastRecv,self.lastSend,self.lastSend-self.lastRecv)
+#        print(self.lastRecv,self.lastSend,self.lastSend-self.lastRecv)
         return  self.lastSend-self.lastRecv; 
     def Monitor(self):
         if self.monitorvar is None: return
@@ -307,16 +309,19 @@ class yamlreader(yamlconfig):
         while self.timecount>=T1:
           if self.GetBusy():
               logging.info("Busy, try monitor again in 1s")
+              self.lastSend=time.time()
               self.timecount=T1-10; #busy, so try again in 1s
               return
           if not(self.statusOPC is None) and self.statusOPC.get_value(): return;
-          if self.server.QoutLength()>0: return;
+          if self.server.QoutLength()>0: 
+             self.lastSend=time.time()
+             return;
           v=self.conf['variables'][self.monitorvarcnt];
           if v.get('monitor'):
                mask=(v['maskOPC'].get_value() if v.get('maskOPC') else [])
 #               print("monitor",v['name'],mask)
 #               self.SetBusy()
-               self.lastSend=time.localtime()
+               self.lastRecv=time.time()
                self.server.readvar(self.monitorvarcnt,mask=mask)
           self.monitorvarcnt+=1;
           if self.monitorvarcnt>=len(self.conf['variables']): 
diff --git a/pypcc/pypcc.py b/pypcc/pypcc.py
index ba4cecb..5dffde8 100755
--- a/pypcc/pypcc.py
+++ b/pypcc/pypcc.py
@@ -48,9 +48,9 @@ logging.info("Start I2C processes")
 if not(args.simulator):
   logging.info("Make I2C lock")   
   import multiprocessing as mp
-  lock=mp.Lock()
-else:
-  lock=None;
+#  lock=mp.Lock()
+#else:
+lock=None;
 #I2Cports=['UNB2','RCU','CLK']
 #I2Cports=['RCU']
 I2Cports=[x for x in args.config.split(',')]
@@ -90,7 +90,40 @@ if False:
    opcuaserv.server.stop()
    exit()
 
- 
+def stop_process(thread):
+  thread.join(10)
+  if thread.exitcode is None:
+    logging.warning("Kill thread")
+    thread.kill()
+    thread.join(1)
+  if thread.exitcode is None:
+    logging.warning("Terminate thread")
+    thread.terminate() 
+  return thread.exitcode
+
+def restart_I2C(i):
+              logging.warning("Restarting I2C process!")
+              RCU_I2C=I2Cclients[i];
+              RCU_I2C.restart() #make new Queues
+              stop_process(I2C_process[i])
+
+              logging.getLogger().setLevel(args.loglevel)
+              logging.info("Start new I2C process")
+              thread1=i2cthread.start(*RCU_I2C.GetInfo(),lock=lock) #Start a new I2C process
+              I2C_process[i]=thread1
+
+              RCU_conf=configs[i]
+              logging.info("Wait for I2C thread")
+              I2C_threads[i].join()
+              logging.info("Start new I2C thread")
+              RCU_conf.CallInit()
+              thread2=threading.Thread(target=RCU_conf.getvar) #start new I2C thread
+              thread2.start()
+              I2C_threads[i]=thread2
+
+              RCU_conf.lastRecv=time.time()
+              logging.getLogger().setLevel("WARNING")
+#cnt=0
 try:
  while RunTimer:
     if not(args.test): 
@@ -102,13 +135,14 @@ try:
     if not(args.simulator) and not(args.test):  
         for i,c in enumerate(configs):
            timeout=c.watchdog()
+           if timeout>10:
+                 print(i,timeout)
            if timeout>60:
-              logging.warning("Restarting I2C process!")
-              I2C_process[i].terminate()
-              RCU_I2C=I2Cclients[i];
-              thread1=i2cthread.start(*RCU_I2C.GetInfo(),lock=lock) #Start a new I2C process
-              I2C_process[i]=thread1
-              configs[i].CallInit()
+               restart_I2C(i)
+#    cnt+=1;
+#    if cnt==60*10*2: 
+#      print("****** restart test *****")
+#      restart_I2C(0)
           
 finally:
    if not(args.test):
@@ -118,5 +152,7 @@ finally:
 logging.info("Stop threads")
 for i2c in I2Cclients:
     i2c.stop()
-for thread1 in threads:
+for thread1 in I2C_process:
+    stop_process(thread1)
+for thread1 in I2C_threads:
     thread1.join()
-- 
GitLab