Start a piston from another piston?


#1

I’m having a simple issue. I have a piston (BUTTONS) that has many “if button X is pressed, set up/down variable and execute MOTOR piston” actions. Then the MOTOR piston has many IFs that run actions depending on devices status and variables.

I tried this before with boolean variables for starting the MOTOR piston and also virtual switches, but they always get stuck at some point (task does not complete, variable stays true, piston doesn’t start again until I manually set the variable to false) so I want to try this “execute piston” method.
But in the MOTOR piston, when I get all the actions in the first level of the piston (there are many IFs) these IFs start running when the variables or devices change (variables that are not supposed to start actions when changed, they only store info for this piston to use when it is executed).

I only want the piston to run from the start to the end if it is executed by the BUTTONS piston. If I had a big IF, like “IF virtual switch turns on”, then the rest of the IFs inside this big IF don’t run unless the first IF is true.

Is there any way to make the IFs only work as filters and never run the piston by their own?

Thanks,
Rodrigo


#2

We would need at least a green shot of both of your pistons to help you.


#3

You may need to disable event subscriptions if you only want it to execute when called from another piston. As @Pantheon said, we need to see the piston to help more.


#4

This is the BUTTONS piston. We’re talking starting at line 35. blinds_id sets the blind that is to be controlled and blinds_dir sets if the button that was pressed was 1 (up) 2 (middle) or 3 (down).
There are 6 positions set in the MOTOR piston, button 1 toggles between 100 and 80%, button 2 toggles between 60 and 40% and button 3 between 20 and 0%.

This is the previous MOTOR piston, which doesn’t work because the IFs execute the piston multiple times in a loop sometimes.

And this is a working MOTOR piston, which I ended up doing, seems to work fine, but I had to think extra carefully the restrictions. In the previous one, I would set the IF action, and then the ELSE would do whatever happens if ELSE (which is what I want to happen, I want each button to react differently depending on the blinds current position. In this new one, I had to replicate the ELSE actions with restrictions too.
Even though this one works, I’d prefer to have a simpler piston like the previous one so it’s easier to edit if I ever want to change the way it operates.

Thanks,
Rodrigo


#5

I will dig into these and get back to you.


#6

Not sure it if is me, but your BUTTONS greenshot did not capture the entire piston. It cut off the bottom.


#7

Just a quick look, with bfwy, could you just disable event subscriptions?


#8

Yep, tried to take the screenshot again and the same happens, anyway that’s the last IF in the piston, it ends there.

How do I do this? :slight_smile:

Thanks,
Rodrigo


#9
  1. Edit your Motor 1 piston.
  2. Click on the name of the piston at the top. That will give you this…
  3. Click the cog at the lower right. That will give you this…
  4. Click “Event subcriptions” and select Disabled.
  5. Save the piston.
  6. Run the piston to see if it works as you have edited it (without the IF looping you described).

#10

Once you do this, you should notice that you no longer have orange lightning bolts in the left margin of your piston. All of the triggers for that piston should be removed and MOTOR 1 should only be executed by a call from BUTTONS.


#11

Thank you very much! That’s exactly what I wanted :smiley:


#12

Hi everyone!

So… I’m having a new problem here: since I disabled the event subscriptions, sometimes when I press a button the action is sent but to the previous blind that was used, so I press a button in one room and the blinds open in another room. Then I press the same button again and it sends the command to the right room.

This never happened before. Many times I would press a button and nothing happened so I had to press it again (and it still happens sometimes).

Is there any way for the piston to “refresh” all the variables and devices data before starting? I believe the piston is going “too fast” and reading old data.

This is my current piston:

Thanks,
R.


#13

When a piston starts up it takes a copy of the global variables. It then works with that copy. When it exits it writes back any changes it has made.

If you are setting a global variable and then executing a piston that needs to read that global variable, you are depending on the calling piston exiting and updating the global variable before the called piston reaches the point where it reads them. So it is a race condition really. If there is very little going on between the call to the piston and the end of the calling piston you may find you get away with it more often than not, but you simply can’t rely on it.

Do you particularly need to use global variables? Could you call the pistons with arguments instead?


#14

Okay, I’ll have to learn how to use arguments… :slight_smile:

Thanks,
R.


#15

I’ve been trying to read about this but got lost in the way, so I wanted to try two simple pistons, one that is activated by a button and executes another piston setting an argument:

And the second piston that is executed by the first one and sends the value from that argument in a push notification.

Clearly I’m not doing this right. Do I need to convert the data from the argument back to a variable and send the push notification with the content from the variable?

Thanks,
R.


#16

I think you just need to remove the ‘$’ before rail or add a statement in your define section like

integer myValue=($args.rsill)


#17

Okay, needed to remove the $ and enable it to store in messages, now it worked. Thanks!


#18

Thanks @orangebucket and @guxdude, I just changed both my BUTTONS and MOTOR piston’s global variables to arguments and the system works better. By enabling the logs, I compared them and the whole run time of both pistons together came down from 850 to 775ms aprox, but one thing I noticed (which is clearly not 75ms) is that the whole action happens faster. It would take 5 to 7 seconds for the motors to start and now it just takes around 3-4 :smiley:


#19

Now I have a new doubt!

I want to apply this same logic to other two switch/motor pistons, but there’s a difference. In the pistons I already changed, I only needed to send one command after each button was pressed.
In these other pistons I’m talking about now, I have switches that stay ON while the task is being executed and they turn OFF after it is done, but they can be manually turned OFF at the middle of the process and this will cancel the task and prevent it from finishing.
This is done through a global ON/OFF (boolean) variable, the SWITCHES piston sets the arguments as global variables and then sets the ON/OFF variable to TRUE. The MOTORS piston is executed by an IF that reacts to the ON/OFF variable, and if the switch is manually turned OFF, then the ON/OFF variable turns FALSE and the IF stops the task.

If I remove the global variables and switch to the “execute piston with arguments” format, I don’t know how I would stop the piston from finishing its task. Is there any other (better, faster, more fluid) way of canceling a piston’s action half way?

Thanks :slight_smile:
R.

Edit (thoughts): Does executing a piston while it is already running cancel the current actions? If so, I could use a boolean argument at the motor piston’s IF intstead of a variable, if the piston is executed with false argument it does nothing.