[RELEASE] Value Tiles - DTH for displaying webCoRE variables / Stats in a 'Thing'


#98

@Robin, any chance of getting a value tiles version hat works with the new ST app? I use this capability and derivatives for a lot of things. Appreciate all you do.


#99

I’m in the same boat, I’ve discovered that if you can use standard capabilities then they will natively appear in the new app (temp, on/off, battery, etc). The issue with changeValue or any other custom capability is that each would need to be defined individually in the new ST ecosystem which I have not yet tried but doesn’t seem to be going well based on the ST community. Additionally, the lose of the tile structure in the new app makes me think I should simplify some of the DTHs anyway.

@stav242 has some good examples of using standard capabilities.


#100

Thanks. I was thinking how I could use standard capabilities. I was thinking a simulated thermostat might provide a capability for value adjustment but I can’t find examples of using the standard capabilities. I will look at what @stav242 has done to see if I can extend that. Appreciate the links!


#101

I took a look at the whole CLI thing… I cant get past the 'Install it on your path and rename it to ‘smartthings’ part lol

I think I’ll just stick with Hubitat… ST have pushed out hobby coders like me by making it too complicated.


#102

Working in the Classic App, but not in the new app, does anyone have a solution? Tks!!


#103

After banging my head against this CLI thing for a couple weeks, I think I finally understand it. or I have gone insane. Hard to tell. Anyway, the following DTH works in both classic and new apps to display/change webcore global variables. This is a bit of an experiment to see if sharing actually works. Here is the DTH:

/*
 Value tiles with adjustment capability-with new app support
*/

metadata {
 	definition (name: "Adjust Integer Values", namespace: "guxdude", author: "guxdude" ,"vid": "7f05b788-4020-3d65-9977-a76c6ebb049e","mnmn": "SmartThingsCommunity"
    					) { 
        capability "dictionaryfabric11101.adjustTextA"
		capability "dictionaryfabric11101.adjustIntegerA"
        capability "dictionaryfabric11101.adjustTextB"
		capability "dictionaryfabric11101.adjustIntegerB"
        capability "dictionaryfabric11101.adjustTextC"
		capability "dictionaryfabric11101.adjustIntegerC"
        capability "dictionaryfabric11101.adjustTextD"
		capability "dictionaryfabric11101.adjustIntegerD"

		capability "Health Check"
        capability "Refresh"
        
        attribute "GVstatus", "string"
 //       attribute "stepA", "number"

    	command "value1Up"
    	command "value1Down"
    	command "value2Up"
    	command "value2Down"
    	command "value3Up"
    	command "value3Down"
    	command "value4Up"
    	command "value4Down"
        
 //       command "changeStep", ["number"]

		command ResetGV
     } // End of definition
     
    tiles(scale:2) {
        valueTile("Label1", "labelA", width: 4, height: 1, decoration: "flat") {
			state("val", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF", defaultState: true )
		}
        valueTile("Blank11", "labelA", width: 1, height: 1, decoration: "flat") {
			state("val", label:"", foregroundColor: "#000000", backgroundColor: "#FFFFFF", defaultState: true )
		}
        valueTile("Blank1", "labelA", width: 4, height: 1, decoration: "flat") {
			state("val", label:"", foregroundColor: "#000000", backgroundColor: "#FFFFFF", defaultState: true  )
		}
		valueTile("Value1", "valueA", width: 2, height: 2, decoration: "flat") {
			state("val", label:'${currentValue}')
		}
    	standardTile("value1Up", "valueA", width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label: '', action:"value1Up", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_up.png"
			state "", label: ''
		}
		standardTile("value1Down", "valueA",  width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label:'', action:"value1Down", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_down.png"
			state "", label: ''
		}
        valueTile("Label2", "labelB", width: 4, height: 1, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}
        valueTile("Value2", "valueB", width: 2, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}'/*, foregroundColor: "#FFFFFF",
				backgroundColors: [ [value: -1, color: "#FF0000"], [value: 0, color: "#000000"], [value: 1, color: "#00FF00"] ]*/)
		}
		standardTile("value2Up", "valueB", width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label: '', action:"value2Up", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_up.png"
			state "", label: ''
		}
		standardTile("value2Down", "valueB",  width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label:'', action:"value2Down", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_down.png"
			state "", label: ''
		}
        valueTile("Label3", "labelC", width: 4, height: 1, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}
        valueTile("Value3", "valueC", width: 2, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}')
		}
		standardTile("value3Up", "valueC", width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label: '', action:"value3Up", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_up.png"
			state "", label: ''
		}
		standardTile("value3Down", "valueC",  width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label:'', action:"value3Down", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_down.png"
			state "", label: ''
		}
        valueTile("Label4", "labelD", width: 4, height: 1, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}
        valueTile("Value4", "valueD", width: 2, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}')
		}
		standardTile("value4Up", "valueD", width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label: '', action:"value4Up", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_up.png"
			state "", label: ''
		}
		standardTile("value4Down", "valueD",  width: 2, height: 2, canChangeIcon: false, decoration: "flat") {
			state "default", label:'', action:"value4Down", 
            icon:"https://raw.githubusercontent.com/tonesto7/nest-manager/master/Images/Devices/heat_arrow_down.png"
			state "", label: ''
		}

		// "Value1" will appear in the things view
 		main(["Value1"])
        // these tiles will appear in the Device Details view
        // (order is left-to-right, top-to-bottom)
 		details([
        "Blank11","Label1","Blank11",
        "value1Up","Value1","value1Down",
        "Blank11","Blank1","Blank11",
        "Blank11","Label2","Blank11",
        "value2Up","Value2","value2Down",
        "Blank11","Blank1","Blank11",
        "Blank11","Label3","Blank11",
        "value3Up","Value3","value3Down",
        "Blank11","Blank1","Blank11",
        "Blank11","Label4","Blank11",
        "value4Up","Value4","value4Down",
        "Blank11","Blank1","Blank11"])

 	}  // End of tiles
    
 	preferences {
      //  input name: "GVup", type: "boolean", title: "Updated", description: "Settings updated", required: true, defaultValue: false
	}   // End of preferences   
 }   // End of metadata
 
 
def installed() {
    sendEvent(name: "valueA", value: 0, displayed: false)
    sendEvent(name: "valueB", value: 0, displayed: false)
    sendEvent(name: "valueC", value: 0, displayed: false)
    sendEvent(name: "valueD", value: 0, displayed: false)

    sendEvent(name: "labelA", value: "Value A", displayed: false)
    sendEvent(name: "labelB", value: "Value B", displayed: false)
    sendEvent(name: "labelC", value: "Value C", displayed: false)
    sendEvent(name: "labelD", value: "Value D", displayed: false)

    sendEvent(name: "GVstatus", value: "start", displayed: false, isStateChange: true)
}

def updated() {
    sendEvent(name: "GVstatus", value: "update", displayed: false, isStateChange: true)
}

def setValueA(value) {
    valueChange("valueA", value)

/*
    sendEvent(name: "valueA", value: value, displayed: false)
    sendEvent(name: "GVstatus", value: "valueA", displayed: false, isStateChange: true)
*/
}

def setValueB(value) {
    valueChange("valueB", value)

/*

    sendEvent(name: "valueB", value: value, displayed: false)
    sendEvent(name: "GVstatus", value: "valueB", displayed: false, isStateChange: true)
*/
}

def setValueC(value) {
    valueChange("valueC", value)

/*

    sendEvent(name: "valueC", value: value, displayed: false)
    sendEvent(name: "GVstatus", value: "valueC", displayed: false, isStateChange: true)
*/
}

def setValueD(value) {
    valueChange("valueD", value)

/*

    sendEvent(name: "valueD", value: value, displayed: false)
    sendEvent(name: "GVstatus", value: "valueD", displayed: false, isStateChange: true)
*/
}

def setLabelA(value) {
	textChange("labelA", value)

/*
    sendEvent(name: "labelA", value: value, displayed: false)
    sendEvent(name: "GVstatus", value: "labelA", displayed: false, isStateChange: true)
*/
}

def setLabelB(value) {
	textChange("labelB", value)
}

def setLabelC(value) {
	textChange("labelC", value)
}

def setLabelD(value) {
	textChange("labelD", value)
}

def value1Up () {
	def newVal = (device.currentValue("valueA").toInteger())+1
    valueChange("valueA", newVal)
/*
    def incVal = (device.currentValue("Increment").toInteger())
    if (isTime1) {
		timeChange("Value1",incVal)
    } else {
		valueChange("Value1",incVal)
    }
*/
}
def value1Down () {
	def newVal = (device.currentValue("valueA").toInteger())-1
    valueChange("valueA", newVal)
}
def value2Up () {
	def newVal = (device.currentValue("valueB").toInteger())+1
    valueChange("valueB", newVal)
}
def value2Down () {
	def newVal = (device.currentValue("valueB").toInteger())-1
    valueChange("valueB", newVal)
}
def value3Up () {
	def newVal = (device.currentValue("valueC").toInteger())+1
    valueChange("valueC", newVal)
}
def value3Down () {
	def newVal = (device.currentValue("valueC").toInteger())-1
    valueChange("valueC", newVal)
}
def value4Up () {
	def newVal = (device.currentValue("valueD").toInteger())+1
    valueChange("valueD", newVal)
}
def value4Down () {
	def newVal = (device.currentValue("valueD").toInteger())-1
    valueChange("valueD", newVal)
}

def valueChange(String valString, Integer newval) {
    // def targetVal = (device.currentValue(valString).toInteger())+offset
    
    // reset to avoid losing sync with WebCoRE
    ResetGV()
    Logger("valueChange: ${valString} Target ${newval}")
    sendEvent("name":valString, "value":newval, displayed: true)
    sendEvent(name: "GVstatus", value: valString, displayed: false, isStateChange: true)
}

def textChange(String valString, String newval) {
    Logger("valueChange: ${valString} Target ${newval}")
    sendEvent("name":valString, "value":newval, displayed: true)
    sendEvent(name: "GVstatus", value: valString, displayed: false, isStateChange: true)
}

//def changeStep(Integer newval) {
	//valueA
//}

def ResetGV() {
    sendEvent(name: "GVstatus", value: "clear", displayed: false, isStateChange: true)
}

def Logger(String logString) {
	log.info(logString)
}

This is the piston for setting/updating the global variables from this device.

Once you copy, paste and publish the DTH, create a device using it. Then you will need to edit the piston to use your new device and the variables you want to view/change. Hope it is helpful.

EDIT: Forgot to mention, in order to add this device to webcore, you need to look under capability 2 “refreshable devices”. Also, note this only supports integer values at this time.

EDIT2: Very slight modification to the DTH to help avoid getting stuck if changing values too fast for webcore to keep up.


#104

I would love to be able to test this but i’m getting an odd error when creating the DTH.

Groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method physicalgraph.device.CapabilityService#syncCustomCapabilityWithDuplo. Cannot resolve which method to invoke for [null] due to overlapping prototypes between: [class physicalgraph.device.Capability] [class physicalgraph.device.cache.CapabilityDTO]

Maybe a copy paste issue?

Edit: I was finally able to save, had to a replace with ASCII double quotes.


#105

You are the man. I’m happy to see that someone has figured out the custom attributes piece. Makes my somewhat more optimistic for the future of ST in general.

I didn’t adjust the piston other than to switch to local variables for testing purposes. Values loaded correctly upon initial piston test. Piston also successfully ran and updated following a value adjustment. Reflected in both new and classic apps.


#106

It was a bit of a headache but it turned out the biggest problem is I had to start from scratch. Editing an existing DTH didn’t work as there is some cache issue. But I got the process down now, I think. Really glad it worked for you.

I thought I used double quotes everywhere. Where was it messed up for you?


#107

I’m going to try and apply it to a device that displays my WAN IP. I need to rework my current piston and won’t need the adjustment aspect.

I did not go through line by line, I copied to notepad first, did a replace all changing “curly”
double quotes to straight double quotes (if that makes sense). It happens sometimes with copy/paste of code.

Update: Removed all the new app capabilities except TextA and TextB to display my IP Address, worked like a charm. Going to remove B as well…IP Address is somewhat redundant since the device name is also displayed.


#108

@fieldsjm can you share the ip address DTH? And your method for getting the ip address into WebCoRE please.


#109

Is it possible to perform value changes in decimal rather then a whole number? If so, what do I need to change in the DTH?


#110

I used patrick stuarts dth for a long time but it seemed to stop polling. Since then i’ve used webcore to run the show, pulling my ip locally from my router using a web request similar to this

The rest was a simple DTH using changeValue. I am out of town for the week so I haven’t had much opportunity to tinker with guxdude’s custom attributes other than what you see above.


#111

Sorry I’m out of town for a few weeks. Need to change the data type from integer to number but it has to be done in the CLI and a new DTH built. I can do it when I get back but don’t have my computer with me on the road. Sorry.


#112

@Alwas - Just following up, my edited DTH is below. Works in both apps but the IP does not appear on the home screen in the new app, you have to click into the device to see it. This is related to vid and since I am using a striped down version of the DTH/vid created by @guxdude; it cannot be directly edited (valueA is set to appear not labelA in his vid).

Once you figure out a way to pull your IP, you only need to use the setLabelA command in webCore. (cIP is my current IP)


image

DTH:

/**
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */

preferences {
    }
    
metadata {
	definition (name: "WAN-IP", namespace: "fieldsjm", "vid": "7f05b788-4020-3d65-9977-a76c6ebb049e","mnmn": "SmartThingsDHs") {
		capability "dictionaryfabric11101.adjustTextA"
		capability "Health Check"
        capability "Refresh"
                
		attribute "labelA", "string"
	    attribute "GVstatus", "string"

		command ResetGV
    }

	simulator {
    
    }

	tiles {
        valueTile("labelA", "device.labelA", inactiveLabel: false, decoration: "flat", width: 3, height: 1) {
        	state "default", label:'${currentValue}'
        }
        
        main "labelA"
        details(["labelA"])
	}
}

def installed() {
    sendEvent(name: "labelA", value: "--", displayed: false)
    sendEvent(name: "GVstatus", value: "start", displayed: false, isStateChange: true)
}

def updated() {
    sendEvent(name: "GVstatus", value: "update", displayed: false, isStateChange: true)
}

def setLabelA(value) {
	sendEvent(name: "labelA", value: "labelA")
    textChange("labelA", value)
}

def textChange(String valString, String newval) {
    Logger("valueChange: ${valString} Target ${newval}")
    sendEvent("name":valString, "value":newval, displayed: true)
    sendEvent(name: "GVstatus", value: valString, displayed: false, isStateChange: true)
}

def ResetGV() {
    sendEvent(name: "GVstatus", value: "clear", displayed: false, isStateChange: true)
}
def Logger(String logString) {
	log.info(logString)
}

#113

@Alwas and @fieldsjm, Here is a DTH which only has text values (5 of them). The first text value will be displayed on the home screen. Due to a bug in the new ST implementation, you cannot edit the values to feed back into webcore but you can display anything from webcore. Hope this helps.

/*
 Value tiles with adjustment capability-with new app support
*/

metadata {
 	definition (name: "Adjust Text Values", namespace: "guxdude", author: "guxdude" ,"vid": "d55576bc-0a21-3f23-ba43-d04d9e485d8e","mnmn": "SmartThingsCommunity"
    					) { 
        capability "dictionaryfabric11101.adjustTextA"
        capability "dictionaryfabric11101.adjustTextB"
        capability "dictionaryfabric11101.adjustTextC"
        capability "dictionaryfabric11101.adjustTextD"
        capability "dictionaryfabric11101.adjustTextE"

		capability "Health Check"
        capability "Refresh"
        
        attribute "GVstatus", "string"

		command ResetGV
     } // End of definition
     
    tiles(scale:2) {
        valueTile("Label1", "labelA", width: 6, height: 2, decoration: "flat") {
			state("val", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF", defaultState: true )
		}
        valueTile("Label2", "labelB", width: 6, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}
        valueTile("Label3", "labelC", width: 6, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}
        valueTile("Label4", "labelD", width: 6, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}
        valueTile("Label5", "labelE", width: 6, height: 2, decoration: "flat") {
			state("default", label:'${currentValue}', foregroundColor: "#000000", backgroundColor: "#FFFFFF" )
		}

		// "Value1" will appear in the things view
 		main(["Label1"])
        // these tiles will appear in the Device Details view
        // (order is left-to-right, top-to-bottom)
 		details([
        "Label1",
        "Label2",
        "Label3",
        "Label4",
        "Label5" ])
 	}  // End of tiles
    
 	preferences {
      //  input name: "GVup", type: "boolean", title: "Updated", description: "Settings updated", required: true, defaultValue: false
	}   // End of preferences   
 }   // End of metadata
 
 
def installed() {
    sendEvent(name: "labelA", value: "Value A", displayed: false)
    sendEvent(name: "labelB", value: "Value B", displayed: false)
    sendEvent(name: "labelC", value: "Value C", displayed: false)
    sendEvent(name: "labelD", value: "Value D", displayed: false)
    sendEvent(name: "labelE", value: "Value E", displayed: false)

    sendEvent(name: "GVstatus", value: "start", displayed: false, isStateChange: true)
}

def updated() {
    sendEvent(name: "GVstatus", value: "update", displayed: false, isStateChange: true)
}

def setLabelA(value) {
	textChange("labelA", value)
}

def setLabelB(value) {
	textChange("labelB", value)
}

def setLabelC(value) {
	textChange("labelC", value)
}

def setLabelD(value) {
	textChange("labelD", value)
}

def setLabelE(value) {
	textChange("labelE", value)
}

def textChange(String valString, String newval) {
    Logger("valueChange: ${valString} Target ${newval}")
    sendEvent("name":valString, "value":newval, displayed: true)
    sendEvent(name: "GVstatus", value: valString, displayed: false, isStateChange: true)
}

def ResetGV() {
    sendEvent(name: "GVstatus", value: "clear", displayed: false, isStateChange: true)
}

def Logger(String logString) {
	log.info(logString)
}

#114

I checked again after some hours and it works :+1:


#115

Worked perfectly, thanks for sharing.

I did have to create a new device as there still seems to be some cache issues in the new app.


#116

@guxdude This has rapidly become one of my favourite dth’s and pistons.
Probably like other people I’m using it as a rolling alert system, with the latest alert always showing at the top (in the dth and piston), like if my IP address changes, wind rises too high, motion in garden etc all called to a single Global variable across my pistons (@zValueStatus). Here’s the piston if anybody wants a go. Also created 5 other global variables zValueA through zValueE.


#117

That’s great. Glad this is helping. And realize you can create as many of these “devices” as you want to if you want more than 5 items.