[Resolved]Execute reusable section of code (subroutine) based on event/conditional/device state

conditions
execution
triggers
piston

#1

This may be a repeat question but I haven’t found any previous questions that deal with this specific question…so here goes

1) Give a description of the problem
based on a event, device state, or conditional execute a section of code within the same piston (without a parameter or return value - like a subroutine in BASIC) the return to the execution point in the piston.

2) What is the expected behavior?
I have a section of code that is only used by this piston but can be used by multiple conditions. An example would be:
if the outside temperature rises above the setpoint + 0.5 degrees AND $now is greater than lastToggle + toggleDelay(600 seconds) then turn off fan and run logging subroutine.

if the outside temperature lowers below the setpoint - 0.5 degrees AND $now is greater than lastToggle + toggleDelay(600 seconds) then turn on fan and run logging subroutine.

Same logging code but different conditionals. I’d prefer not to use the same code in multiple locations within the piston

3) What is happening/not happening?
Absolutely nothing - I have no idea how to implement this in webCoRE.

**4) Post a Green Snapshot of the piston

5) Attach logs after turning logging level to Full
Not applicable to this question - piston is operating as currently designed.


#2

The easy way with the least amount of conflict:

IF condition is X, then "Execute Piston-B"  \
IF condition is Y, then "Execute Piston-B"   (which logs & turns off fan)
IF condition is Z, then "Execute Piston-B"  /

There is no limit to how many pistons you can create. (I have 405 in my house at the moment) Many of them are bite size pistons that are called by other pistons. Advanced users can even call those subroutines via macros from a PC or commands from a phone etc.

It works quite well if it is planned out properly.


#3

You might want to check out this conversation:
https://community.webcore.co/t/finding-entry-in-list-or-collection-to-select-one-of-multiple-devices-to-control/12902
It has some really interesting options for calling pistons from other pistons including one piston calling another and then returning execution to a selected third piston. That may be way more than what you need right now though. For the most part, I’m doing exactly what WCMore describes above.
I also hate writing the same code in several places. It’s just asking for a mistake and it’s really annoying when you want to make a simple change.


#4

Thank you for the replies @qoheleth & @WCmore

Sooooo…being an long ago ex-VB programmer if I think of calling pistons like I would call subroutines and functions in VB I’m headed down the right track.

Which leads me to the subject of collection classes (yes, my mind works in mysterious ways), but that is another conversation entirely :slight_smile:


#5

It’s analogous. Although it’s more like a GOTO in terms of execution as there’s no way for execution to return. (If you call the calling piston, it will begin at it’s beginning.) The difference is that you can pass execution with parameters.


#6

Okay…I took a look at the reference you gave me. Didn’t seem to sink in - I had a head injury a few years back and can’t think like I did when I was programming any longer.

In webCoRE does the new piston continue in the current thread and terminate the calling thread or does the calling thread (piston) generate a completely new thread (piston) and both threads(pistons) continue? The calling piston from the point it created the new thread(piston) and the new thread(piston) from the beginning of the newly created piston. Or am I making this too complicated?

Theading always makes my head hurt - I think I’ll find some Tylenol now.


#7

Actually the calling thread continues. I usually place the call at the end of the calling piston so it’s kind of a moot point, but it’s true that execution is no so much passed as it’s forked and the two processes continue “simultaneously.”
There is an interesting conversation here


about some of the issues that parallelism can cause if you don’t pay attention to them.


#8

I agree with @qoheleth. Even though more than one piston can be in the process of execution simultaneously, it is important to remember that SmartThings can only send one command at a time. This means if you have two pistons running at the same moment, the commands sent can actually bounce back and forth between the two pistons.

IE:
Piston-A sends Command-1
Piston-B sends Command-1
Piston-A sends Command-2
Piston-A sends Command-3
Piston-B sends Command-2
Piston-A sends Command-4
Piston-B sends Command-3
etc...

Whenever I program pistons, I always try to code them in such a way that only one of them is executing at any given moment. (IE: I call Piston-B at the very end of Piston-A, not in the middle) I do this because if SmartThings is trying to do too much in any given moment, there is a chance that some commands will be lost in the ethers, and may not reach the device. If I need more commands sent after Piston-B, I might make the last line to call Piston-C to wrap it up.


#9

This is excellent advice for programming pistons. Trying to trace though a set of “simultaneously” running pistons can be no end of frustrating.


#10

Thanks for the additional info @WCmore & @qoheleth .

In my community travels I ran across another interesting question where it was mentioned that you should try to only have one trigger per piston if possible. Between this thread and that thread https://community.webcore.co/t/piston-fails-to-compare-proper-time/12448/6 it sounds like webCoRE functions best with a single task per piston if possible.

That being the case does anyone have a naming convention or other method of keeping track of exactly what this proliferation of pistons do? I’ve started using groups for some high level grouping (like Presence Detection - Release, SLMC - Release, SLMC - Development, etc). SLMC (for those who hate/love acronyms = Security Light Motion Control).

Should I be looking at adding a convention something like this…

SLMC - Front Porch for a specific device

…which then leads me to something like this for the operation…

SLMC - Front Porch Light - Master
SLMC - Front Porch Light - General
SLMC - Front Porch Light - Turn On
SLMC - Front Porch Light- Turn Off

…which then continues on for the the trigger device. or stimulus (or lack of)…

SLMC - Front Porch Light - Turn On - Ring Front Porch Motion Active
SLMC - Front Porch Light - Turn On - Blink East Walkway Camera Active
SLMC - Front Porch Light - Turn Off - Ring Front Porch Motion Inactive
SLMC - Front Porch Light - Turn Off - Blink East Walkway Camera Inactive

…which then leaves me with trigger/stimulus modifiers…

SLMC - Front Porch Light - Ring Front Porch Motion Active - Quiet Hours
SLMC - Front Porch Light - Ring Front Porch Motion Active - Emergency Mode

My inkling is that trigger/stimulus modifiers can stay in the individual and use a if or switch statement to test values and decide on the proper response.

For those (if anyone even really cares) that want to know Emergency Mode forces the front porch light on, changes it to red, then flashes the bulb every 15 seconds, day or night, to help first responders find the right door. I live in an apartment and only my front door has a August Smart Lock that unlocks during Emergency Mode, not the back door.

Quiet mode would be for something like that light shines in the neighbors bedroom window and annoys the. So in the interest of avoiding conflict we agree that the light won’t come on between the hours of midnight and 0500 unless I am coming home or it was manually triggered.

For some reason I’m still struggling with this. I haven’t had this much trouble understanding a programming concept since 1999 when I was trying to understand how to build a collection class in Visual Basic 6.

For those that can’t remember programming in 1999 or didn’t have the dubious honor of coding in VB6, there wasn’t a collection class like there is now. You had to build the collection class using variable properties and collections by hand.


#11

Using dozens of tasks (commands) and/or conditions in the same piston is OK… I just try to limit the lightning bolts (triggers) to one or less in each piston. It is not always possible, but it is always my goal.


WebCoRE might have a lot of similarities with other programming languages, but much of it is unique, or approaches things quite differently, due to the nature of SmartHome technology.

I think that when learning webCoRE, (temporarily) forgetting all you know about coding can actually be helpful. (a sort of Tabula Rasa)


#12

I"ve approached it in a similar way. Basically, I had to learn never to assume that webCoRE operates the same way as ______, There seems to be about a 50/50 probability that knowing code will help or confuse you :slight_smile:
Knowing coding can help on sussing out what a While does. Being familiar with multi-threaded or multi-processed environments helps in understanding some aspects of execution, but webCoRE’s particular aspects of triggers and start-at-the-top execution have to be held in forefront.