diff --git a/testApp/test.db b/testApp/test.db index ad4ac5b..86c4f91 100644 --- a/testApp/test.db +++ b/testApp/test.db @@ -30,3 +30,19 @@ record(longin, "$(P)async:cnt") { field(INP , "@test4") field(SCAN, "1 second") } + + +record(ao, "$(P):A-SP") { + field(DTYP, "Raw Python Device") + field(OUT , "@test5 hello none") +} + +record(ao, "$(P):B-SP") { + field(DTYP, "Raw Python Device") + field(OUT , "@test5 hello half") +} + +record(ai, "$(P):A-RB") { + field(DTYP, "Raw Python Device") + field(INP , "@test5 hello none") +} diff --git a/testApp/test4.py b/testApp/test4.py index f3a56a7..7287eec 100644 --- a/testApp/test4.py +++ b/testApp/test4.py @@ -14,7 +14,7 @@ class Counter(object): def process(self, rec, reason): if reason is AsyncComplete: rec.VAL = self.nextval - + else: self.nextval = rec.VAL+1 self.timer = threading.Timer(0.2, rec.asyncFinish, kwargs={'reason':AsyncComplete}) diff --git a/testApp/test5.py b/testApp/test5.py new file mode 100644 index 0000000..cc0ede6 --- /dev/null +++ b/testApp/test5.py @@ -0,0 +1,70 @@ + +import threading +from devsup.hooks import addHook +from devsup.util import Worker +from devsup.db import IOScanListThread + +#(forwardfn, reversefn) +_fns = { + 'none':(lambda x:x, lambda x:x), + 'half':(lambda x:x*2.0, lambda x:x/2.0), +} + +ReSync = object() + +instances = {} + +class UnitWorker(object): + def __init__(self, name): + super(UnitWorker,self).__init__() + self.name = name + self.scan = IOScanListThread() + self.scan.force = 0 + + self.worker = Worker() + + addHook('AfterIocRunning', self.worker.start) + addHook('AtIocExit', self.worker.join) + + def add(self, rec, unit, val): + self.worker.add(self.update, (rec, unit, val)) + + def update(self, rec, unit, val): + F, _ = _fns[unit] + V = F(val) + + values = {} + + for U,(F,R) in _fns.iteritems(): + values[U] = R(V) + + self.scan.interrupt(reason=values) + +class UnitSupport(object): + def __init__(self, rec, args): + worker, self.unit = args.split(None, 1) + try: + W = instances[worker] + except KeyError: + W = UnitWorker(worker) + instances[worker] = W + + self.worker = W + W.scan.add(rec) + + def detach(self, rec): + self.worker.scan.remove(rec) + + def process(self, rec, reason): + if reason is None: + self.worker.update(rec, self.unit, rec.VAL) + + else: + try: + rec.VAL = reason[self.unit] + rec.UDF = 0 + except: + rec.UDF = 1 + raise + +build = UnitSupport