I have been racking my brain for a couple days, testing things back and forth trying to get labels in a child device to update programmatically instead of having to have another device type. I am using the ST_Anything program (https://community.smartthings.com/t/release-st-anything-v2-8-arduino-esp8266-esp32-to-st-via-thingshield-ethernet-or-wifi/) with a ESP32. I have a working sketch and got everything installed with no issues at all.
So here is what I’m trying to do. The child device right now is a simple contact sensor, open and closed (https://github.com/DanielOgorchock/ST_Anything/blob/master/devicetypes/ogiewon/child-contact-sensor.src/child-contact-sensor.groovy). I’m going to be using this for a garage heater (current sensor on its hot lead) so I want it to display “Running” or “Off”. Then I started thinking I would want to do the same with other things around my house, having a “On/Off” or “True/False”. More I thought about it the more I thought a custom device type with preferences would make the most sense. So I modified the default device and added a preferences section with two options, what to display when “open” and what to display when “closed”:
input(“openLabel”, “text”, title: “Label to display when Open”, defaultValue: “Open”, required: true, displayDuringSetup: true)
input(“closedLabel”, “text”, title: “Label to display when Closed”, defaultValue:“Closed”, required: true, displayDuringSetup: true)
However no matter what I did I could not get the labels to display in the MultiAttributeTile. I used the standard ‘{$openLabel}’ and every variation of it like so:
attributeState “open”, label:’{$openLabel}, icon:“st.contact.contact.open”, backgroundColor:"#e86d13"
attributeState “closed”, label:’{$closedLabel}, icon:“st.contact.contact.closed”, backgroundColor:"#00a0dc"
I kept getting the correct background color change but the text just said NULL. I would go back to the original code and put in "label: ‘${name}’ " and it would display OPEN or CLOSED like normal. After more reading I found something that said the metadata section can’t use the variables directly unless they were called from a function. I then found a post by @tslagle13 that seemed promising: https://community.smartthings.com/t/changing-properties-of-standardtiles-dynamically-based-on-other-state-variables/ . In that he called a function to determine backgroundColor in a tile and said that worked. Now that was on a stadard tile, I’m using a multi, but I didn’t think that would matter. So I tried the same for the label:
attributeState “open”, label:getLabelText(), icon:“st.contact.contact.open”, backgroundColor:"#e86d13"
attributeState “closed”, label:getLabelText(), icon:“st.contact.contact.closed”, backgroundColor:"#00a0dc"
along with a simple function:
def getLabelText(){
def myLabel = openLabel
if (device.currentState(“contact”) == “closed”){
myLabel = closedLabel
}
return myLabel
}
So it assigns the openLabel (Open or On or Running or Yes…whatever the user enters) then if the status is closed it switches to the closed label. The problem is two fold.
- I cannot figure out a value that returns when closed, I’ve tried dozens and none evaluate. The one above (device.currentState(“contact”) doesn’t compile…gives me a “java.lang.NullPointerException: Cannot invoke method currentState() on null object”.
- Even when I get something that compiles like ‘${name}’ which is what the label uses normally it still doesn’t evaluate and I’m still returning a empty string.
For testing I added some debug lines to the getLabelText() function and found that it doesn’t seem to actually get called on a status change. If I go into the device and hit the gear icon then hit Done it does run through it and I see my debug lines but on a normal status change it doesn’t. The odd thing about this is the background color changes so the tile is working…it’s just not calling the getLabelText() function at all.
Finally I tried setting state information like this:
def updated() {
log.debug(“Updated called…”)
state.myOpenLabel = openLabel
log.debug(“state.myOpenLabel set to $state.myOpenLabel”)
state.myClosedLabel = closedLabel
log.debug(“state.myClosedLabel set to $state.myClosedLabel”)
}
The state info did persist but I couldn’t find a way to use that within the tile label either.
So is this just how it is or is there a way I can programmatically change the labels? If I can then how? Or is it not working because its a child device and there needs to be more to it? I’m at a loss.
-Allan