# Trigger Transaction Group on Multiple Triggers: Mutually Exclusive Booleans

**URL:** <https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254>\
**Category:** Ignition\
**Tags:** ignition81\
**Created:** [January 21, 2022, 4:40pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254 "2022-01-21T16:40:43Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [January 21, 2022, 4:40pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/1 "2022-01-21T16:40:43Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 21, 2022, 4:59pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/2 "2022-01-21T16:59:26Z")

</div>

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

```auto
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.

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [January 21, 2022, 5:15pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/3 "2022-01-21T17:15:57Z")

</div>

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.

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

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 21, 2022, 5:25pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/4 "2022-01-21T17:25:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Kraenbring](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@Kraenbring](https://forum.inductiveautomation.com/u/Kraenbring)\
**Post date:** [December 24, 2025, 3:10pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/5 "2025-12-24T15:10:11Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 24, 2025, 3:57pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/6 "2025-12-24T15:57:03Z")

</div>

> [@Kraenbring](#):
>
> do a simple combination trick

See the `binEnc()` expression function.

---

<div class="post-metadata">

**Author:** ![Kraenbring](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@Kraenbring](https://forum.inductiveautomation.com/u/Kraenbring)\
**Post date:** [December 26, 2025, 2:43pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/7 "2025-12-26T14:43:44Z")

</div>

I did say “simple”. 🙂 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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 26, 2025, 3:33pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/8 "2025-12-26T15:33:29Z")

</div>

> [@Kraenbring](#):
>
> Add/Multiply would be less ‘expensive’ than a function too.

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

---

<div class="post-metadata">

**Author:** ![Chris\_Bingham](https://avatars.discourse-cdn.com/v4/letter/c/e5b9ba/32.png) [@Chris\_Bingham](https://forum.inductiveautomation.com/u/Chris_Bingham)\
**Post date:** [December 29, 2025, 4:32am UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/9 "2025-12-29T04:32:46Z")

</div>

> [@Kraenbring](#):
>
> Then just look for any change of value.

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`.

---

<div class="post-metadata">

**Author:** ![Kraenbring](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@Kraenbring](https://forum.inductiveautomation.com/u/Kraenbring)\
**Post date:** [December 29, 2025, 8:19pm UTC](https://forum.inductiveautomation.com/t/trigger-transaction-group-on-multiple-triggers-mutually-exclusive-booleans/55254/10 "2025-12-29T20:19:50Z")

</div>

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).
