Just to add some thought to the decision making behind keeping the hardware task reference and the vale state inside the Action engine...
When we put together an application that control multiple, possibley unrelated vavles using DO fucntions we can benefit from abtracting the details of "What" and "How" of the interface into functions that make sense in the context of the application.
It can be very tedious thinking "I have to turn on the main valvle but keep the other valves of so I set this bit and keep another bit off and use this hardware ref to make it happen."
I perfer to stay high-level and define what I want to do with the hardware and decide how I want to identify the parts involved.
So like others have stated, states like;
In the case of "Open" and Close I will pass a parameter that indicates what I want to operate on.
Go Safe will act on all of the valves with no parameter required.
The above talks what the interface to the AE should be. The next aspect to concider is "encapulation" or wrapping up all of the details so that we can stay high-level in the use of the AE. Encapsulation happens when we put inforamtin in the storage elements of the AE (I now use Feedback nodes instead of Shift Registers). In the case above there are two things that we can store internally to the AE to prevent other processes from not using it correctly.
1) Task reference - Keeping it in the AE protect any other process from doing the wrong thing to it.
2) The valve states - Again protected inside the AE so that there is no chance of assorted code threads doing the wrong thing at the wrong time.
The example code I included in the third post of my Action Engine Nugget (found here) can offer some ideas for an Action Engine to control valves.
Thank you for letting me chime in!