Using global variables to trigger actions in a different piston


#1

1) Give a description of the problem
I have one piston that will set global variables (one after another) to boolean values. In another piston I use “wait for X to change to true”. The problem is that all the hardware actions that are tied to the global variables are in the same piston so I’m not sure if what I’m trying to do is possible? I have enabled parallelism and Async IF.

2) What is the expected behavior?
The expected behavior is that the hardware actions should fire but it doesn’t seem to be the case.

3) What is happening/not happening?
(PUT YOUR INFO HERE)

**4) Post a Green Snapshot of the piston!


5) Attach any logs (From ST IDE and by turning logging level to Full)
(PASTE YOUR LOGS HERE BETWEEN THE MARKS THEN HIGHLIGHT ALL OF THE LOGS SND CLICK ON THE </> ICON TO FORMAT THEM)

REMOVE BELOW AFTER READING
If a solution is found for your question then please mark the post as the solution.


#2

I have been using the same technique for a long time now. One piston to set a global flag and another piston to be triggered on flag changes. I just use simple if @global is “something” statements and it seems to work. Additionally I haven’t changed any default execution options for this to work.


#3

My scenario is a little different. I’m changing the value of two different global variables and the triggers for those are located within the same (but different) piston. From my understanding, this would mean that the piston containing the triggers would have to run twice and this should be possible if parallelism is on. I broke my pistons up in this way to reduce maintenance and to easily define actions but it’s proving to be problematic.


#4

Because both variables are not changing simultaneously, you’re going to run into issues with having the two triggers be “changes to.” You might want to look at “followed by” or just triggering off the second variable changing and using the first as a condition.

What are you trying to accomplish with your piston? I noticed that your contact sensor has some LOCK commands tied to it which seems a little strange to me. If you’re good…then don’t worry about explaining…but if you’re stuck on trying to implement a tough solution, you might want to try describing your ultimate goal and see if anyone on the forum might be able to come up with a little easier architecture for you. Because it seems very complicated to me.


#5

The idea I had here was to break everything up into “methods” or “functions” that I could just call from anywhere to avoid duplicate code. I’m a java developer so I’ve been thinking of pistons like “classes” and the different hardware actions that are triggered by global variables as “functions”. Is there a better way to do this? It seemed a bit convoluted to me.

I also noticed that my locks show up as contact sensors… why is this? Under “Available devices” in the webcore smartapp I have no contact sensors listed. My locks I have selected under “Electronic Locks”. Is it possible this is a bug?


#6

No, not a bug necessarily. As long as they work from the SmartThings app then everything should work fine. I would have just classified them differently if i was creating the DTH, that’s all.

What I meant by my question though was, big picture, what are you trying to accomplish? It seems to me like you’re trying to program your own SmartThings environment. Why are you doing everything through variables? Just do it! Have you ever seen the movie Spaceballs by Mel Brooks? “Why are you preparing? You’re always preparing! Just go!” That’s what I think of when I look at all this mess.
95a75be55b1aeccee3d779b3707127b6d838d279687c7e3b2bad5c4411688f1e

Webcore Pistons are set up so that you can subscribe to the events from a device across multiple pistons without interfering and they all fire at (roughly) the same time (baring processing irregularities). So, there really is no need to coordinate everything through the use of all these variables. How do you keep them all straight even? For example, when someone arrives, you set a variable and then in another when that changes you change a variable and then that variable unlocks your locks. You could save yourself a lot of time and worry if you just unlocked your locks when someone arrives. Do you see what I mean? You shorten everything from 3 functions down to 1.


#7

I don’t think this is a mess at all, it’s all separated into functions and the behavior is clearly defined (to me). I originally tried to just “do” stuff and it turned into a big huge mess and things just weren’t working as I wanted. My first piston designs were trying to set modes, unlock/lock doors, and adjust thermostats all in a single piston. Not only was it large but it was a nightmare to debug. My main goal right now is to mostly just automate my thermostats, locks, cameras, and a few switches based off presence. I work from home and the presence defines what mode the house is in. That in turn adjusts my thermostats and arms/disarms cameras. When my wife arrives, that changes the mode and thus what the thermostats are at, what switches are on, etc. It all works pretty great right now, just trying to get past this oddity which I could easily solve by just putting it into a different piston but wanted to see if anyone else had better ideas.


#8

I have never seen a piston with half as many variables. If you continue to use that architecture for all of your pistons I don’t know how that will affect your performance. Again, you can do all of the things you wanted to do with a single piston rather than setting multiple variables in multiple pistons. There’s a great resource on here with a ton of examples for every situation. Take a look at what others have done. You might change your mind about the approach you’re taking. But that’s just my advice.

As far as using the variables the way you have, two variables will never change at the same time unless they are changed by the same action in the same piston. Therefore, if you have two triggers for variables changing, that piston will never fire.

If A changes and If B changes will only be true if A and B are changed at the exact same time.

So, you have to used “Followed by” or different nomenclature.

If A changes and B IS would work instead.

If you put everything in IS language, then it treats it like a Trigger and a Condition.

If A IS and B IS will trigger if A or B changes and the other is in the state you specify. Make sense?


#9

Just an FYI; I’ve read that 'too many" global variables will degrade piston execution throughput. Now, as to whether you have “too many”, I really don’t know. I currently have (31) pistons and am using (14) global variables (so far). I use more local variables than that, but according to what I’ve read, they don’t have the same throughput degrading impact that global variables have.

Anyway, as I’m sure you know, when it comes to programming, there are many ways to arrive at the goal. I don’t recall others using the same methodology to the extent that you have, but that doesn’t mean yours isn’t the best way. To me, it appears you’re making it more difficult than needed, but I’m sure that anyone reading my code would think I’m an idiot :wink:

Anyway, I wanted to let you know about the potential ramifications of “excess” global variables - whatever that means.


#10

Yes this makes perfect sense. Is there a way to tie simple hardware actions to functions to avoid writing duplicate code though? This would also be super beneficial IMO.


#11

I have been splitting up a few pistons to accomplish that exact goal. I have a simple piston (with NO trigger) that contains a few lines of reusable code. Then, in any other piston, I can simply run that chuck of code by using this command:

temp

Just point it to your reusable code. The only downfall I have seen so far with this method is some variables have to be global, if they are going to be used back in the original piston.

Also, maybe someone could further explain the chain of events when executing other pistons. If I have a giant piston, and half way thru it, it Executes another piston, will it return back to the big piston to complete? Do the two pistons run simultaneously? Will global variables stored by the 2nd piston be available in the remaining part of the first piston?


#12

I already have a large mode setting piston that I call and it then evaluates who is home and changes the mode. I can use and call this from any where and it’s extremely useful IMO. Using global variables as flags has been the only way I’ve been able to split things up. Below is an example of my mode setting piston:


#13

What do you mean? Stop thinking of this as code. Your code is duplicating work. Think of it as a logic proof. Like I said, take a look at the example pistons here on the forum. Basically, map out all your triggers, conditions, restrictions you want to lead to a specific action and put them all in using the correct operators and grouping (Aka parens). You don’t have to create a function that gets called by other functions. You might have an action you only want to happen with a single set of triggers. Why would you draw that out into a function? When you’re defining the function, you could just Define the triggers as well. You’re trying to do what control correct? Simple, when someone arrives, unlock. You could add restrictions or other conditions but you add them into the same piston along with the trigger. It’s so much simpler than you’re making it.


#14

I’m not sure what you mean by this. I’m not saying that your method doesn’t have merit. I just don’t understand why the only way you can ‘split things up’ is via use of global variables. I use global variables and virtual switches as ‘flags’ too, but I use them to reduce ‘hard coding’ of values that I want accessibility to in multiple pistons. You seem to be writing new functions when (I think) they may already exist or can be written specifically with expressions in the piston that uses them. Again, many ways to skin a cat. I’m just curious about your method and the reasoning.


#15

I agree that trying to de-duplicate functional as in coding is admirable, but making a bullet proof state table for events and actions doesn’t always follow a linear programming model that does functions.

I have 3 global variables per room and split the events into pistons: programmatic events (timed, sunrise, sunset) , manual events (motion, button pushes) and scenes that execute the results of the events pistons with data passing using the global variables. Nothing is shared outside of these room groupings. Makes it easy to debug, all states are consolidated, and adapts well to remote switches and touch screens.


#16

I feel like I’m gonna take some flak for this but I’ve come up with a solution that seems to be working rather well. Right now it’s using hard-coded strings but if someone could suggest something better I’m all ears. Essentially what I’m doing is “priming” a piston for the hardware actions I want to take place and then I set a trigger to true which executes that piston. I currently only have 4 devices that I would manipulate through different location modes or automations, but it would require a global variable for each device you wish to control. This allows me to easily see what is happening with a single line of code. I’ve attached two pistons: my mode change piston which I’m currently using which locks doors, changes SMH status, etc., and then the hardware action piston itself.



#17

No flak. If it works for you, then it’s all good. We’re all learning from each other.

Let me ask this. You’re currently at four devices. If you have 70+ devices like me - or perhaps many more as a lot of users do, would your solution still be a viable and efficient option? Having a a separate piston to assign and keep track of values for every global variable/device you want to control would seem to get cumbersome pretty quick, but maybe I’m looking at it wrong.


#18

If global variables truly affect performance like you said, then I’m not sure if this would be viable. I have around 20 total devices if you count things like contact sensors and water sensors but I only have 3 that I need to actually control. You could definitely split them up into different groups, i.e. a “light switches” piston, a “cameras” piston, etc. I really just want good visibility into what is actually happening when I perform actions and this works great for me.


#19

All of that code is there to control the locking and unlocking of your lock? OMG…man, you are WAAAAAAYYYY over complicating things. This could have been accomplished with half as much code and you are going to get serious system performance issues with that many global variable. Do what ever you want but you’re making your own life a LOT harder than it has to be.