From de2ee74d85d7ebdf705ab26747456f8e60cda24f Mon Sep 17 00:00:00 2001 From: kruger <kruger@astron.nl> Date: Thu, 8 Aug 2024 16:59:18 +0100 Subject: [PATCH] I2C flock added --- bin/apscttr | 2 +- bin/apsputr | 2 +- bin/unb2tr | 2 +- pypcc/i2cserv/i2cthread.py | 11 ++++++-- pypcc/pypcc.py | 6 +++- pypcc/simpleflock.py | 57 ++++++++++++++++++++++++++++++++++++++ scripts/get_all_pi.py | 11 ++++++++ 7 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 pypcc/simpleflock.py create mode 100644 scripts/get_all_pi.py diff --git a/bin/apscttr b/bin/apscttr index ed22f09..2030dca 100755 --- a/bin/apscttr +++ b/bin/apscttr @@ -1,2 +1,2 @@ #!/bin/bash -hwtr -p 4843 -c APSCTTR +hwtr -p 4843 -c APSCTTR --lockfile=/tmp/pypcc_i2c.lock diff --git a/bin/apsputr b/bin/apsputr index 5bb2b9a..4bba457 100755 --- a/bin/apsputr +++ b/bin/apsputr @@ -1,2 +1,2 @@ #!/bin/bash -hwtr -p 4842 -c APSPUTR +hwtr -p 4842 -c APSPUTR --lockfile=/tmp/pypcc_i2c.lock diff --git a/bin/unb2tr b/bin/unb2tr index 8ae634d..a64ae72 100755 --- a/bin/unb2tr +++ b/bin/unb2tr @@ -1,2 +1,2 @@ #!/bin/bash -hwtr -p 4841 -c UNB2TR +hwtr -p 4841 -c UNB2TR --lockfile=/tmp/pypcc_i2c.lock diff --git a/pypcc/i2cserv/i2cthread.py b/pypcc/i2cserv/i2cthread.py index fb1841d..0714c29 100644 --- a/pypcc/i2cserv/i2cthread.py +++ b/pypcc/i2cserv/i2cthread.py @@ -148,7 +148,11 @@ def I2Cserver(Qin,Qout,name,lock=None): # self.statevar.set_value("busy"); #print("SetVar",item)#,self.conf.variables[item.id]) if not(lock is None): - lock.acquire() + try: + lock.acquire() + except: + logging.error("I2C lock timeout!!") + #continue; # print('lock'); try: if (item.type==InstType.varSet): @@ -162,7 +166,10 @@ def I2Cserver(Qin,Qout,name,lock=None): else: print("OPCUA call not implemented!"); finally: if not(lock is None): - lock.release() + try: + lock.release() + except: + logging.error("I2C lock release error") # print('unlock'); # print("TODO: Set ready") logging.info("End i2c process "+name) diff --git a/pypcc/pypcc.py b/pypcc/pypcc.py index 8e795bc..d09e0d0 100755 --- a/pypcc/pypcc.py +++ b/pypcc/pypcc.py @@ -5,6 +5,7 @@ import signal import sys import threading import time +from pypcc.simpleflock import simpleflock parser = argparse.ArgumentParser() parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true") @@ -12,6 +13,7 @@ parser.add_argument("-t", "--test", help="Do not start OPC-UA server.", action=" parser.add_argument("-p", "--port", help="Port number to listen on [%(default)s].", type=int, default=4842) parser.add_argument("-l", "--loglevel", help="Log level [%(default)s].", type=str, choices=["DEBUG","INFO","WARNING","ERROR"], default="WARNING") parser.add_argument("--loghost", help="Logstash host to which to forward logs [%(default)s]",type=str, default='') +parser.add_argument("--lockfile", help="Lock while using I2C [%(default)s]",type=str, default='') parser.add_argument("-c", "--config", help="YAML config files, comma seperated [%(default)s]",type=str, default='RCU') args = parser.parse_args() @@ -50,7 +52,9 @@ if not(args.simulator): import multiprocessing as mp # lock=mp.Lock() #else: -lock=None; +#lock=None; +lock = None if args.lockfile=='' else simpleflock(args.lockfile,10) + #I2Cports=['UNB2','RCU','CLK'] #I2Cports=['RCU'] I2Cports=[x for x in args.config.split(',')] diff --git a/pypcc/simpleflock.py b/pypcc/simpleflock.py new file mode 100644 index 0000000..25e2e39 --- /dev/null +++ b/pypcc/simpleflock.py @@ -0,0 +1,57 @@ +from __future__ import print_function +import time +import os +import fcntl +import errno + +class simpleflock: + """Provides the simplest possible interface to flock-based file locking. Intended for use with the `with` syntax. It will create/truncate/delete the lock file as necessary.""" + + def __init__(self, path, timeout = None): + self._path = path + self._timeout = timeout +# self._fd = None + self._fd = os.open(self._path, os.O_CREAT) + def __del__(self): + os.close(self._fd) + self._fd = None + def acquire(self): + return self.__enter__() + def release(self): + return self.__exit__() + + def __enter__(self): + start_lock_search = time.time() + while True: + try: + fcntl.flock(self._fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + # Lock acquired! + return + except (OSError, IOError) as ex: + if ex.errno != errno.EAGAIN: # Resource temporarily unavailable + raise + elif self._timeout is not None and time.time() > (start_lock_search + self._timeout): + # Exceeded the user-specified timeout. + raise + + # TODO It would be nice to avoid an arbitrary sleep here, but spinning + # without a delay is also undesirable. + time.sleep(0.1) + + def __exit__(self, *args): + fcntl.flock(self._fd, fcntl.LOCK_UN) + + # Try to remove the lock file, but don't try too hard because it is + # unnecessary. This is mostly to help the user see whether a lock + # exists by examining the filesystem. +# try: +# os.unlink(self._path) +# except: +# pass + +if __name__ == "__main__": + print("Acquiring lock...") + with SimpleFlock("locktest", 2): + print("Lock acquired.") + time.sleep(3) + print("Lock released.") \ No newline at end of file diff --git a/scripts/get_all_pi.py b/scripts/get_all_pi.py new file mode 100644 index 0000000..d9098b5 --- /dev/null +++ b/scripts/get_all_pi.py @@ -0,0 +1,11 @@ +from test_common import * +from time import sleep +connect("opc.tcp://localhost:4899/") + + +names=get_all_variables() +for name in names: + att=get_value(name) + print(name,'=',att) + +disconnect(); -- GitLab