Trigger Transaction Group on Multiple Triggers: Mutually Exclusive Booleans

I can’t quite get my head around this transaction group trigger. I have three Boolean tags that I want to trigger on when any of them go low. I’ve tried many permutations with binEnc(), masks, shifts, and boolean logic, but I can’t get a single expression to reflect the correct trigger events. I’m wondering if this is possible.

One problem is if one Boolean is already low and one of the other tags goes low, there is no trigger because the first tag was already low. I could set this up with 3 separate transaction groups, but all of the tags to log are the same so it would be redundant.

I would use my objectScript function in a run-always expression item:

objectScript("any(state.get('B0', False) and not args[0], state.get('B1', False) and not args[1], state.get('B2', False))\n"
+ "state['B0'] = args[0]\n"
+ "state['B1'] = args[1]\n"
+ "state['B2'] = args[2]", {path/to/boolean0}, {path/to/boolean1}, {path/to/boolean2})

It can take a multi-line script if you provide new-lines in the string. The first line must be the expression to return. Remaining lines are regular jython.

The above will pulse true if any boolean transitions to false, but not on first execution.

1 Like

Hmm, pretty slick. This got me to thinking more about functions instead of pure Boolean logic, and I came up with this that does work. Not sure about first execution yet.

(hasChanged({[.]Bool 1}) && !{[.]Bool 1}) ||
(hasChanged({[.]Bool 2}) && !{[.]Bool 2}) ||
(hasChanged({[.]Bool 3}) && !{[.]Bool 3}) 
1 Like

My only beef against the hasChanged function is that there is a tiny race condition window between evaluating each boolean for hasChanged and then evaluating it again for the && operation. My approach evaluates the arguments once then applies the change detection logic.

1 Like

Treat the bools like ints and you can do a simple combination trick: (Bool1*100)+(Bool2*10)+(Bool3*1) Then just look for any change of value.

See the binEnc() expression function.

I did say “simple”. :slight_smile: Add/Multiply would be less ‘expensive’ than a function too. Plus it works on small-ish non-boolean numbers as well. I’ll use it when there tiny ints (like a status of 0-5) and I need to see a change across multiple. Judging from the first post, i’m wondering if they were using the bitEnum instead of bitEnc.

No, they aren't. Not in the expression language. binEnc() is a single operation that is easily extended to more bits.

1 Like

This method alone might produce some false negatives. For example, a transition of one bit from True --> False while another bit is already False might cause the transaction to be missed...as the OP mentioned.

Any solution to this problem requires a comparison of each bool's previous value in order to capture the transition of any tag from True --> False.

well, each bit is in a different position in the number (1’s, 10’s, 100’s, etc) so any change results in a unique number ( 000,001,010,110,101, etc). if you have two bits that happen to change at the exact same time, you could only get one transition triggered, but that might be sufficient for what comes next in your logic. If you want to know which bit changed, then I agree that you’d need the previous value to compare to. We use that method for some words we use for alarm bits, to know which bits are coming in and out, by comparing to the previous value (in our case that saved previous word and the comparison are all done on the database side).