diff --git a/bin/apscttr b/bin/apscttr index ed22f09e2b5709789ef08208d0f799c9da4dd30d..2030dca05c1416d5aede6c8742446f23894aba11 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 5bb2b9a4aaca61b347850584a2d703879bfff207..4bba457517a3e7d8c074cd1401f981097fa90a40 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 8ae634d581d0f708fe249466bacf2aa0dd80ef20..a64ae7297a8fc8389d74f13001a91d12fd0457d5 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 fb1841dd37d91badd138f08701aa87e04aedeb9d..0714c291372c4033832d6e6b63778fa88269b367 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 8e795bc6488c38466cf684cc3d6c16f8a52ea2c9..d09e0d0389be0798dc17508b1620cb49fb6400a0 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 0000000000000000000000000000000000000000..25e2e39f0aa82851f72e2100ae39ea4f31604d55 --- /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 0000000000000000000000000000000000000000..d9098b58813341355be22731f8dee3b6d2739c94 --- /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();