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


#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
    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.


#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)
}