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