Comparing attribute to multiple text values

I’m migrating from webCoRE and trying to figure out how to write an old piston that checked if SmartWeather’s “weather” attribute was any of the following: “Rain, Light Rain, Thunderstorm, Rain Shower,Showers Near,Fog,Wintry Mix”

In an attempt to simplify things, I am creating a rule that will do the above comparison and store the result in a custom variable. I have selected Event Trigger, Device=SmartWeather, Attribute = weather, Operator = changes to, and then I have a line where I can type a string, but I’m not sure what the syntax is (if it is possible) to test for a match among an array of values.

1 Like

I would probably set the trigger up with a ‘changes and is not’ and use an arbitrary value (eg. a blank space) to effectively have the rule trigger any time the weather attribute changes.

In the flow, you could do one of the following:

  • Always copy the state to a variable (using Context Variables for best performance)
  • Use multiple IF conditions for each of your desired states
  • Use an expression to determine which states are saved to the variable

Multiple IF conditions is probably the easiest to understand, but requires the most clicks. Expressions are probably the most concise and give you the most control, but require writing the logic you want.

For example, an expression might be:

targetStates = ["Rain", "Light Rain", "Thunderstorm", "Rain Shower", "Showers Near", "Fog", "Wintry Mix"]
isTarget = contains(targetStates, $context.event.value)
isTarget ? $context.event.value : ""

I’ve broken it down into three lines to improve readability, but it’s basically checking if your current event value is included in the list you’re looking for and if so, it outputs that value otherwise it outputs a blank string (using a ternary operator condition ? trueOp : falseOp).

Of course, you’ll want to adjust the example as you see fit, but I wanted to give you crash course since you mentioned you’re coming from webCoRE. :slight_smile:

1 Like

Is there anyway to do a comparison without an exact match or case insensitive?

Can you share more details about your use-case? Maybe an example?

There’s a variety of different functions that might be helpful to you in the General Functions documentation:

Be sure to check the ‘Content Checks’ section and below as there’s a variety of functions for changing the case of a string like upper(input) and lower(input) that you could use to make your comparison case-insensitive.

And the various content check features like contains(input, searchTerm), indexOf(input, searchTerm), startsWith(input, searchTerm), endsWith(input, searchTerm) and equalText(left, right) might be helpful to you.

For example, imagine $myVariable is currently set to 'The Master Bedroom Light is On'. The following expression would lowercase the variable value, to make the check case-insensitive, and check to see if it contains the word ‘master bedroom’

contains(lower($myVariable), 'master bedroom')

Thanks Josh! I’m still in reading mode for Sharptools so been looking at a lot of topics. 2 more days to sign up :slight_smile: but so far so good…a bit of a learning curve.

My use case is similar to what’s in this thread and I was referencing the example you gave. I’m looking to pull data from open weather and store conditions in a variable. From there I want to check the variable if it contains rain and then perform some action.

For instance, if one of target states is lower case vs upper or can we use contains “rain” to cover “rain”, “light rain”, “moderate rain” etc.

targetStates = ["Rain", "Light Rain", "Thunderstorm", "Rain Shower", "Showers Near", "Fog", "Wintry Mix"]
isTarget = contains(targetStates, $context.event.value)
isTarget ? $context.event.value : ""

Edit**
During my quick testing, open weather returned “rain and snow” but I did not get a match by just trying to match “rain”
This is what I was playing around with.

targetStates = ["rain", "scattered clouds", "Light Rain", "Thunderstorm", "Rain Shower", "Showers Near", "Fog", "Wintry Mix"]
isTarget = contains(targetStates, $weatherAlert)
isTarget ? $weatherAlert : ""

I’m declaring $weatherAlert as {{$context.response.data.daily.1.weather.0.description}}

Thanks for the clarification. The example I mentioned above should work then. You can lowercase the input value and/or search term.

Keep in mind what the function is doing:

contains(input, searchTerm)
Returns true if an input contains a given searchTerm

In the original example, we are predefining a set of complete text matches for a provided search term. So the first input of contains() is an array of terms and we’re checking if the searchTerm provided in the second input exactly matches, case sensitive. In other words, we’re checking if the ‘weather’ attribute exactly matches one of the terms we were interested in.

If you wanted to check if the condition contained rain, you would likely want to flip the comparison around.

contains(lower($weatherAlert), 'rain')

So assuming your $weatherAlert was currently 'Light Rain', the above example would match it as your ‘searchTerm’ on the right is already defined as lower case and the lower() function would lowercase the $weatherAlert before doing the comparison.

image

When you’re just getting started, sometimes it’s helpful to open another tab with a blank rule with a single action that has an expression block in it just so you can manually evaluate simpler parts of an expression to better understand what they’re doing.

Side Note: I edited your post to add in the code blocks so it’s easier to read. You can highlight the block of text and tap the </> button in the toolbar before you submit your post to format it.

1 Like

Josh, thanks for the explanation! Your suggestion worked perfectly and I understand the example much better now.

Duly noted about formatting in future posts.

1 Like

Another thought, perhaps it is helpful.

There are a lot of different descriptions that can be returned. Depending on how you are using it, making an evaluation based on the ‘id’ may be more error proof.

To cover thunderstorm, drizzle, rain and snow, I’ve set mine based on based on weather id <=699, just to cover all of the various names.

Here is the list of codes:
https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2

Hope this helps.

2 Likes

That’s great! Thanks.