As ST now has official support for the FP2 I’m trying to set a rule for when a zone gets triggered, but SharpTools doesnt see any zones, it just gives me a JSON thing, do I have write some code for when a zone has motion?
What other attributes are available for the FP2?
It looks like the zoneState
is some sort of special attribute format – as you mentioned, it looks like it’s potentially reporting some sort of JSON value.
I would recommend adding that attribute as a Hero Attribute to a dashboard or as a Trigger to a rule and then monitor the attribute values as they change to see what it reports. Then you can monitor it manually by:
- Open your SharpTools User Page
- Tap the
...
next to the location in question - Scroll down and tap the device in question
- Monitor the Attribute Values section
Note: The device + attribute must be added to a dashboard or rule trigger for it to receive status updates.
@josh I am having trouble getting if conditions based on the attribute value to match. I have copy/pasted from the Attribute Values from the User Page, Location, Device as you mentioned above into my rules and it’s not matching the if condition and moving to else instead.
Any tips you can suggest? I also have the device and attribute shown on a dashboard and those update accordingly when I enter either of the 2 zones defined by my sensor.
The attribute for my 2 detection zones shows as follows:
[ { “id”: “1”, “name”: “Master Shower”, “state”: “not present” }, { “id”: “2”, “name”: “Master Bathtub”, “state”: “not present” } ]
I want to match that exactly to turn off my exhaust fan, but the if condition match is failing despite copy/pasting that into the JSON field.
Does the device driver also create those zones as child devices? I thought I read something about that when I did a quick search a few days ago.
If not, I would consider setting up a rule that listens for any change in the attribute, then use an expression to parse out the JSON and store each zone as a true/false variable.
Then you can use those variables to directly react to the zone statuses changing as needed.
They are not child devices.
I’ll dig into the method you described.
@josh Can you give an example of parsing the JSON of the device attribute value? I read through the expressions and functions examples, but I’m not seeing how to tell the expression to search the value of the device attribute for a specific string to allow me to set the variable.
If it’s a raw object passed across from SmartThings, you would access the object properties similar to JSON notation with any language:
object.property
object[index]
So in the case of the context variable for the event value:
$context.event.value.someProperty
$context.event.value[0]
So maybe something like:
equalText($context.event.value[0].state, "present")
—-
That still looks above my ability. For my use case, I don’t need status of both zones, just if one is active or neither is active, so setting a text variable to the trigger context variable and using that text variable to set true/false variables, I was able to get it to work.
A glitch in this setup. Somehow, the sensor attributes 1 and 2 swapped positions in the value field, so it was never matching to allow the my fan that is triggered by this setup to turn off. I was able to get it working by setting the text string to the swapped format, but needs some ideas how to make this more robust to tolerate the attribute text for the 2 zones getting swapped around.
I read through your above messages again, Josh, but I’m failing to see how to get that setup in a rule in my clicking around trying to see how to possibly use that the way the rules are structured. I’m probably missing something obvious . If you had an example of a rule doing this operation “equalText()”, I can probably sort it out.
The JSON approach with an Expression I mentioned above would be the best way to do this.
In reading through the example you provided, it sounds like you get a value similar to the following whenever the zoneState
attribute changes. This is just a formatted version from the rule condition you shared:
[
{
"id": "1",
"name": "Master Shower",
"state": "not present"
},
{
"id": "2",
"name": "Master Bathtub",
"state": "not present"
}
]
But based on your latest comment, it sounds like the “Master Shower” entry with the id
of 1 sometimes is in the first position and sometimes it’s swapped with “Master Bathtub” and in the second position. Is that right?
Example Snippet
In that case, the overall concept I mentioned still applies, but it would need to be a bit more fancy to handle the position changing. You could use something like the following to grab the “Master Shower” state by its unique id:
items = parseJson($AqaraPresenceText) #// converts the string back into an object
shower = filter(items, x.id == 1)[0] #//Filter the list to just the item with the specific id and return that single matching item
equalText(shower.state, "present") #// return true if the state is 'present', otherwise false
How This Works
I included comments next to each line above, but here’s a breakdown:
-
Takes the
$AqaraPresenceText
and converts it from text back into an object (list) and stores that initems
items = parseJson($AqaraPresenceText)
items
is an expression local variable, meaning that it only exists during the context of this Expression execution- This step makes it so we can filter on the list of items
-
Filter the list of items to just the item that has an
id
of 1. And since the filtered list only has our matching item, we grab that first item.filteredItems = filter(items, x.id == 1) shower = filteredItems[0]
- Sometimes it’s easier to think about it logically like two difference steps similar to immediately above.
- First we filter the list to just the items we are interested in
filter()
, then we pick that first item from the listfilteredItems[0]
. - For a refresher, check the post I quoted above as it explains the concept of lists and objects.
-
Return a
true
/false
based on if thestate
of our selected item is exactly “present”equalText(shower.state, "present")
The beauty of this approach is we can have a single rule that runs whenever the zoneState
updates that sets all of our desired variables in rule. We then immediately have variables indicating if motion is active in the shower and if motion is active in the bathtub.
Full(ish) Example
Here’s an example of what this whole thing would look like.
Of course in my example, I don’t have a real Aqara FP2, so I’m simulating your example by using a $AqaraPresenceText
variable… this is roughly equivalent to the existing rule screenshot you shared:
- Trigger: Master Bath Presence & Light - zoneState updates
- Flow: Set
$ShowerBathPresenceText
value using$context.event.value
value
Then it just needs a Set Variable action for each motion/presence status that we want to record. So I created one for the Bathtub and one for the Shower from your example.
As noted above, this single rule takes care of recording both the Bathtub and Shower motion status. It will set each variable to true
if the relevant item’s state is present
, otherwise it’s false
.
Expression Snippets
Here’s the expression snippets in text format for your reference and ease of copying:
Bathtub (id: 2)
items = parseJson($AqaraPresenceText) #// converts the string back into an object
bath = filter(items, x.id == 2)[0] #// Filter the list to just the item with the specific id and return that single matching item
equalText(bath.state, "present") #// return true if the state is 'present', otherwise false
Shower (id: 1)
items = parseJson($AqaraPresenceText) #// converts the string back into an object
shower = filter(items, x.id == 1)[0] #// Filter the list to just the item with the specific id and return that single matching item
equalText(shower.state, "present") #// return true if the state is 'present', otherwise false
You might have noticed that the expression are functionally the same. The only thing that matters is making sure to update the
id
value.The usage of
shower
vsbath
as the expression variable doesn’t actually matter since it is only used during function execution. You could just as easily used a generic name likeitem
in both examples.
Appreciate this! When I have some time this weekend I’ll dig through it and update my rules accordingly!
Found some time tonight to mess with it and was able to get it all setup and working! Thanks so much for your help! This will make this sensor even more powerful! For some reason in Smartthings, you can’t set a single routines based on the status of more than one zone.