WebCore Variables and Expressions Use Cases?

WebCore users - we need your help in understanding how you use one of the more advanced features in WebCore: variables and expressions.

From anonymized metadata analysis, it looks like about a third of WebCore users employ variables and expressions in some way as part of their pistons. This is clearly important functionality, but we don’t have context as to how it’s being used. We’d like to better understand that context so we can build core functionality to better serve your use cases.

If you’re willing to share, could you please post a 1-2 sentence synopsis of how you use variables and expressions and (if you’re comfortable doing it) an anonymized snapshot of those pistons?

Thanks in advance for your help in continuing to improve the platform!


I use a variable in a mailbox monitor. It prevents over-reporting of the mailbox opens and allows notification if the mail wasn’t picked up after delivery.

1 Like

The fact you’re asking has me worried. Please don’t put this on us. This is too much pressure.
Can’t you just incorporate webCoRE’s variables as is? Local and global variables? And Expressions? Sounds like you’re scrimping already.
If you can’t bring over local/global variables to replicate full parity, just do your best. As long as you do your best, nobody will complain. Or please ask Adrian. WebCoRE has infinite possibilities, it would be futile to list each case. I don’t envy your task, but many people are counting on you, best of luck :+1:

That’s why we’re asking - we want to understand WHY it’s important so that we don’t necessarily just replicate what’s already there when we could meet user needs in a more elegant or functional way. Thank you for the comment though :slight_smile:


Blake its pretty simple.

Store a value for later to act on. these are usually interpolated or calculated values that had little or nothing to do with the state of an existing device.

For instance. Lets go through this use case…

Washing Machine Notification:
(Dumb Washing machine connected to system with Zooz heavy duty Zwave outlet.)

When washing machine completes load, notify user until either acted upon (cancel is a valid action) or 5 notification cycles complete unanswered.

Washing machine is not ‘smart’ itself but is connected to the system using a metering plug. The plug accurately measures the load from the Washing machine and we have observed recurring values where we can be reasonably assured we can trap ‘running’ ‘spin’ and ‘idle’ DONE is to be considered IDLE after a period where the machine was ‘running’ for 5 or more minutes and is now idle.

So for this we would need to capture a value for current state. (remember the plug doesn’t do this so we’re reading values and calculating a flag based on that value - lets create a string (local) variable and store RUNNING, SPIN, IDLE, OFF, and UNKNOWN (This could also be an integer, but I like self documenting code)

I need to capture the ‘DONE’ condition, so I need a temp variable to store ‘last’ state and compare to current. (another local same type as above) and if it meets the criteria I want, I need to set ANOTHER flag in this case, lets do bIsDone as a local Boolean

So now we can trap the is Done flag. We announce. To what? under what conditions? When Echo Speaks was a thing, I had a second piston constantly capturing the ‘last used’ echo in my system and Stuffing a global variable of type DEVICE with the device object of the last spoken to Echo. BTW - Echo Speaks shouldn’t be the barometer if this IS necessary - it just is - we need a way to store a device or group of devices for later processing, this could be speakers, presence objects, lamps, switches, etc. Doesn’t matter. It facilitates creating a program that behaves conditionally depending on what devices are fed to it.

Also do we even Announce? For this I had global variables tQuietHoursStart, and tQuietHoursEnd, with the start and stop times for all general announcements. These were both type DateTime that stored a 24 hr time. Any announcement went through a piston that accepted the announcement text as input - String, a type of announcement (general or urgent, as string were the most common) as well as an optional Device as the speaker target. Depending on the combination of these inputs it would route the announcement to the right speaker and if it were quiet hours and not urgent it wouldn’t notify at all and instead route the message to the system’s history.

I need a loop that does the notify, check response thing- another boolean possibly two depending on how complex the check is, local context. I also need a counter for this loop to limit after 4 retries… Integer, local.

So in just this ONE example I need, Boolean, Integer, String, Device and DateTime in BOTH local and global contexts. I also need advanced comparison and branching.

BTW - THIS is why you guys are seeing so many v-switches popping up and why the v-switch creator is so important right now. Without a way to store state flags, guess what becomes state flag storage? (Unfortunately most people don’t realize they’re also bumping themselves against various system limits by doing this)

Without it you can’t do anything beyond a basic motion light. Even those are iffy without the ability to run locally - big improvement when you finally get the ability to do a delayed check in local processing…

Ady knows all this - just go ask him. :slight_smile:


Assuming @ady264 still works for st

1 Like

I use variables most often to store a string for use in a notification. here’s some examples.

This is a piston for automatically closing our garage door for various reasons. Instead of repeating a lot of the logic in separate automations, it’s one big piston with 3 reasons for closing the garage: darkness, rain or temperature. The reason is stored in a varable and put in the notification.

This is my wasting energy alert piston. One variable for storing the list of offending devices and another with the HVAC state

This is my rain alert if we have windows open. Similar to above, list of offending devices is stored to a variable and sent in the notification

Lastly, my dog light automation one uses a boolean variable to determine when to turn the light off after the door is opened the second time to let the dog in. I could probably use a virtual switch for this, but variable is better in this case since i’ll never need to manually change it and it doesn’t count towards the 200 device limit :smirk:


I love expressions. An example is for ceiling fans…

I have a piston that runs between set days each year using an expression. When the date is between that set range - the piston runs, if not in the date range - it does not run.

And I use cases for the temperature range of my thermostat such as:

  • 77 and above
  • 75-76
  • 73-74
  • 71 and below

In each of those cases, I have it look at whether the AC is on/off (expressions),if it off - run at the set speed, if AC is on, adjust the speed of the ceiling fan down a bit and when ac switches off, it returns to the normal set speed.

So for when the temperature is 77 above… I have it set high speed for when AC is off and medium high for when AC is on. Each case for temperature uses different speeds that I find comfortable in my house.


+1 to what @Automated_House put forth regarding notifications. I use variables in my notifications as well, such as to identify which garage door, which leak sensor, etc . . .

1 Like

I’m not a WebCore user (partially as I learned it was going away, not long after I started with ST), but I’d like you to consider one use case, I’d love to have in the future automations. To my knowledge there is no out of the box way to run a slow speed fully adjustable control feedback loop. For instance, daylighting control would read a daylight sensor output and then adjust the lighting dimmer input value accordingly to maintain a constant light level. Generally, this would entail having the inputs and outputs (which already exist in ST), as well as an algorithm that would calculate the dimming level between a minimum and maximum value. In the simplest form, this could be a linear equation with a slope and an intercept, along with the min and max values that would be output.

1 Like

Similar to others, I use variables in my last remaining piston to put friendlier names in notifications.

Unrelated to variables… This is also a use case that I don’t think Automations (sorry, Routines now) can’t cover - different actions for specific door unlock codes. I think Routines can only be triggered been on the lock unlocking, not which code is used?


I’ll also mention that I’ve moved some of my use cases for webcore over to Home Assistant. It’s more complicated, but just as (if not more) powerful than webcore. Honestly, I’ll probably move this piston to Home Assistant before long as I honestly doubt that SmartThings will preserve the ability to replicate this after Groovy is shut down.

Similar to others here, I use variables and expressions all of the time. I mainly use them for notifications to my phone, through Echo devices, etc. But I frequently use expressions for debugging/error messages when testing pistons.

This is my away at night light randomizer. It will choose random lights to toggle at random intervals.

I am aware that there is an option in Labs but it does not randomize the lights or the time like this. I feel this piston simulates someone being home more effectively than the Labs option.

I’ve had two or three false starts at responding to this thread. The problem I have is that I stopped using webCoRE months back, in favour of using the Rules API. Although I have never used webCoRE for complex pistons, I consider that I have a good understanding of how it all plumbs together. So when I look at what there is in the Rules API so far, the most I can see the Rules API and webCoRE have in common is an end goal. I just don’t see a migration path as things are just being done differently, and in my opinion more elegantly.

I also see a lot of really complex pistons in webCoRE and I just see stuff that could be written a whole lot easier in a SmartApp. Yes, a SmartApp wouldn’t offer local execution but nor does webCoRE. Just because webCoRE could be made to do something, it doesn’t mean it should have. Just because webCoRE could do something, it doesn’t mean the same mistake should be made twice. We need a line, and webCoRE blurred the line.

So the last thing I’d want to see is too much attention being paid to what webCoRE could do and how it did it. I want to see the elegant and functional solutions.

So what do I actually want for the Rules API? Well I certainly want to be able to define device aliases as the code is very repetitive. YAML anchors and aliases are almost there but there isn’t an obvious way to batch them at the top of the file. Is that the same as variables? Not really no. More like constants.

Do I want local variables? Yes please. Do I want them to end up like webCoRE ones? I hope not. I just want them to last for the life of a rule execution. Mostly I am interested in customising notifications.

Do I want global variables? Yes. Do I want them like webCoRE ones? No, because I think they should be truly global entities accessible via the API. If I want to set a variable in a SmartApp and read it in a Rule then why not? Indeed I should be able to read and set variables in the mobile app.

Do I want expressions? Yes, please. I particularly want to be able to process JSON. Should it be exclusively a feature of Rules? Nope, that’s another entity to me.


Here’s one of my few remaining Webcore pistons.

We use this to detect and count motion of my MIL around the house. It then sends a message twice a day with the accumulated data. This was created to ease my wife and SIL worries and let them check for MIL moving about.

We used to use it full time before she moved in with us. Now it checks when she’s the only person home.

Just thought I would share as it uses expression, sends messages, and uses variables all in 1 piston.

1 Like

Bathroom fan piston - Quick selection for timer adjustments

Storing data received in $args from external HTTP requests (from iOS shortcuts, CCTV software etc):

Storing global variables and also converting them to local variables, so that they can be used in POST requests (this could be streamlined, just allow global variables to be used in POST).
This example is for sending SMS messages in the UK using Twilio, without having to enter my phone number / Twilio security credentials in every piston - Without global variables I would have to update 20+ pistons should my credentials change…

Converting system variables to local variables, so that they can be used as arguments when triggering another piston (could be streamlined also):

Boolean variables are very handy and often replace the need for virtual switches in ST. They can help to pause / delay automations, prevent looping notifications, record that an action was taken for the day etc:

I use device variables in tonnes of pistons, where a device needs to be referenced in several places throughout the piston. That way if I need to change or add devices to the automation, I only have to change the variable, not scroll through the whole thing hunting for each instance.

I am currently using Hubitat as nothing has been said about replacing webCoRE on ST in a long time, but if webCoRE were to be recreated in its entirety I may return… please just replicate it as is… does not need to be elegant, this normally just means stripped out functionality.

We want the same local, global and system variables as currently provided by webCoRE.

Also, please don’t forget Expressions, Functions & Weather. I make regular use of these.


I also want to add that I do miss some of the system type variables such as the $current Event… family and, perhaps more on topic, variables that save matches.

I don’t care how it is achieved, but if I do an ‘any’ match with a list of devices I would like to know how many devices and which ones matched and be able to use that information later.