How to show a dynamic label in my device handler?

I wrote this device handler to interact with MPD linux music daemon.
One of the fields is the track name which the music player is currently playing.
Here is the definition I used:

valueTile(“file”, “device.status”, width: 3, height: 1, decoration: “flat”) {
state (“name”, label:‘${currentValue}’)
}

Then in the parse method I sendevent to update this field.

It does not work for me.
How to fix it?

I think you are mixing state and values.

I use both in my DTH (https://github.com/philippeportesppo/Honeywell_HPA250B_SmartThings/blob/master/honeywell-hpa250b.groovy) but I update them differently depending I want to update a state or a value.

For value, I have this tile definition:

standardTile("timer", "device.timer", width: 2, height: 2, canChangeIcon: false, canChangeBackground: false, decoration: "flat") {
    state ("default", label: 'Timer: ${currentValue}h', backgroundColor:"#ffffff")
}

Then in my parse:

def parse(description) {
    def events = []
    def descMap = parseDescriptionAsMap(description)
    log.debug descMap
    def body = new String(descMap["body"].decodeBase64())
    log.debug body
    def slurper = new JsonSlurper()
    def result = slurper.parseText(body)
....
    events << createEvent(name: "timer",     	value: "${result.hpa250b.timer}", isStateChanged:true)   

    return events
}

If you really want to manage states, here is one:

standardTile("light", "device.light", width: 2, height: 2, canChangeIcon: false, canChangeBackground: false,decoration: "flat",) {
    state ("light_off", label:'Off', action:"light_on", icon:"st.Lighting.light13", backgroundColor:"#ffffff" )
    state ("light_medium", label:'Medium', action:"light_off",  icon:"st.Lighting.light11", backgroundColor:"#00a0dc")
    state ("light_on", label:'On', action:"light_medium", icon:"st.Lighting.light11", backgroundColor:"#00a0dc")
	state ("light_updating", label:'Sending...')
    state ("off", label:'')

}

Would be updated this way in Parse:

	events << createEvent(name: "light",     	value: "light_${result.hpa250b.light}", isStateChanged:true)   

where is “on” or “off” or “medium”

So basically, either you send a value, either you send a state. That’s how I use it.

Search and you will find this question asked a bunch with no way of doing what you want. Example: Change labels of child device programatically?

With that said see this for a work around: https://github.com/vseven/SmartThings_VSeven/blob/master/devicetypes/vseven/enhanced-konnected-contact-sensor.src/enhanced-konnected-contact-sensor.groovy

vseven: I’m not sure that’s true. At least the first example you give is a post where someone is trying to use a preference value or state variable within a label. I believe that is not possible because the tiles have no awareness of any values from the device except the current value of the specified attribute (in this case device.status). However, merely changing the label based on the currentValue should work fine. Here is an example from something I am working on:

multiAttributeTile(name: "overview", type: "generic", width: 6, height: 4) {
    tileAttribute("device.unsecured", key: "PRIMARY_CONTROL") {
        attributeState "0", label: "secure", icon: "st.presence.house.secured", backgroundColor: "#00A0DC"
        attributeState "unsecured", label: '${currentValue}', icon: "st.contact.contact.open", backgroundColor: "#dd4b39", defaultState:true
        // Note: Must use single quotes around currentValue
        }
    }

Niv_Gal_Waizer: It looks to me like the problem is that you are trying to access the “file” attribute, but you list “device.status” as the attribute to be read. So change device.status to device.file.

valueTile(“file”, “device.file”, width: 3, height: 1, decoration: “flat”) {
    state (“name”, label:’${currentValue}’)
    }

If changing that does not work, then ask for help again and be sure to answer these questions:

  1. What happens when you test the code? Does no tile show up, or is the tile blank, etc.?
  2. Have you checked the device’s events on the IDE to see what is the current value of device.file? In other words, have you verified that parse() is successfully updating the file attribute?

I read this as not being able to change the labels programmatically but if its the value of the label then current value should work.

@Niv_Gal_Waizer - See if this gives you some hints: http://docs.smartthings.com/en/latest/device-type-developers-guide/tiles-metadata.html#multimedia-multi-attribute-tile

SWEET,
Indeed this helped, but the tile is updated, only after I enter the device.
When I am in the device view and cause an action that changes this status, it is not updated.
device handler

So whenever you are doing something that changes status you should be calling a sendEvent to update your tile.

Or I would try to use that documentation and covert your main tile over to the multiAttribute tile…might be easier in the long run.

if he’s calling it from the parse() function he will need to use createEvent() instead. I suspect this is what is he needs to change with his code.

thanks,
but in parse() sendevents works and createEvent does not.

I’m afraid you have that backwards. You need to use createEvent to generate an event from parse() not sendEvent. I suggest you check the documentation to get started.

The createEvent just creates a data structure (a Map) with information about the Event. It does not actually fire an Event.

Only by returning that created map from your parse method will an Event be fired by the SmartThings platform.

http://docs.smartthings.com/en/latest/device-type-developers-guide/parse.html

Yeah, SteveWhite is correct. Parse should either return an event created by createEvent(), or else an array of events created by createEvent().

My guess is that sendEvent() works but may be causing some kind of delay that might be responsible for the update problem you are having.

Other than that, it may simply be lag that is causing it not to update the way that you expect.

1 Like

Thanks. @Philippe_Portes provided the correct answer with sample code. Not sure why the OP cannot get that to work for his code.

1 Like

Thanks @Philippe_Portes and @SteveWhite, obviously you were correct.
I jumped in to coding and missed the tutorial.
I think the device handler for the music player is really good solution, in terms of automation and audio quality.
Last I seek help with a tile label from the preferences:
In my preferences:

preferences {
    input name: "Preset1", type: "text", title: "Preset1", defaultValue:"kcrw", required: false, displayDuringSetup: true
    input name: "Preset2", type: "text", title: "Preset2", defaultValue:"bet", required: false, displayDuringSetup: true
}

I then want to use this to show a label in the device handler:

    standardTile("preset2", "device.preset2", width: 1, height: 1, decoration: "flat") {
  		state "preset2", label:"$Preset2", action:"preset2"
    }

Any idea how to?

If I am understanding you correctly, you want to set the value of your “preset2” standardTile to whatever is specified as “Preset 2” in settings?

If that is the case, then you should change your tile state as follows:

state "default", label:'${currentValue}'

This should work:

standardTile("preset2", "device.preset2", width: 1, height: 1, decoration: "flat") {
	state "default", label:"${currentValue}", action:"preset2"
}

Then, add this in your updated() function:

sendEvent(name: "preset2", value: settings.Preset2, displayed: false)

You don’t actually have to use the prefix “settings.” on preferences but it’s helpful to identify the source where the value is coming from.

Repeat that for as many preset tiles that you wish to create. Good luck!

1 Like