Get data on app load

I am trying to get started writing smart apps and I don’t know why I have to press the refresh button to get the data from my thermostat. Is there a way to get the data when I go into the thermostat with out having to press the refresh button?

metadata {

definition (name: "mystat", namespace: "mystat", author: "Me") {
	capability "ThermostatHeatingSetpoint"
	capability "thermostatOperatingState"
	capability "TemperatureMeasurement"
    capability "Configuration"
	capability "Refresh"

	attribute "outdoorTemp", "string"
	attribute "outputPercentDisplay", "number"

	command "getThermo"
}

simulator {
	// TODO: define status and reply messages here
}

tiles(scale: 2) {
	multiAttributeTile(name:"temperature", type: "thermostat", width: 6, height: 4){
		tileAttribute ("device.temperature", key: "PRIMARY_CONTROL") {
			attributeState("temperatureMeasurement", label:'${currentValue}°', unit: "dF", backgroundColor:"#269bd2")
		}
		tileAttribute("device.heatingSetpoint", key: "VALUE_CONTROL") {
			attributeState("VALUE_UP", action: "heatingSetpointUp")
			attributeState("VALUE_DOWN", action: "heatingSetpointDown")
		}
		tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE",inactiveLabel: true) {
			attributeState("idle",backgroundColor:"#44b621")
			attributeState("heating",backgroundColor:"#ffa81e")
		}
		
		tileAttribute("device.humidity", key: "SECONDARY_CONTROL") {
            attributeState("humidity", label: '${currentValue}%', unit: "%", defaultState: true)
        }
		
		tileAttribute("device.heatingSetpoint", key: "HEATING_SETPOINT") {
			attributeState("default", label: '${currentValue}', unit: "dF")
		}
	}

	// //Heating Set Point Controls
	// controlTile("levelSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 6, inactiveLabel: false, range:"(5..30)", decoration: "flat") {
    // state "heatingSetpoint", action:"heatingSetpoint"
	// }
	
	standardTile("heatLevelDown", "device.heatingSetpoint", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state "heatLevelDown", action:"heatingSetpointDown", icon:"st.thermostat.thermostat-down"
    }
    standardTile("heatLevelUp", "device.heatingSetpoint", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state "heatLevelUp", action:"heatingSetpointUp", icon:"st.thermostat.thermostat-up"
    }
	controlTile("heatingSetpointSlider", "device.heatingSetpoint","slider", height: 2, width: 2, range:"5..86") {
    state "heatingSetpoint", label:'${currentValue}', action:"setHeatingSetpoint"
	}
   	valueTile("heatingSetpoint", "device.heatingSetpoint", width: 2, height: 2, inactiveLabel: false) {
		state "heatingSetpoint", label:'${currentValue}', backgroundColor:"#153591"
	}
	standardTile("refresh", "device.thermostatMode", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
		state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
	}
	standardTile("error", "device.error", width: 4, height: 2, inactiveLabel: false, decoration: "flat") {
	    state "default", label:'${currentValue}', backgroundColor:"#ffffff", icon:"st.Office.office8"
	}

	main (["temperature"])
    details(["temperature", /*"heatLevelDown", "heatingSetpoint", "heatLevelUp", */"refresh", "error"])
}

}

def getThermo() {
log.debug “thermo starting”
def destIp = “10.0.0.112”
def destPort = “80”
def hosthex = convertIPtoHex(destIp)
def porthex = convertPortToHex(destPort)
device.deviceNetworkId = “$hosthex:$porthex”
log.debug "device id is " + device.deviceNetworkId

def hubAction = new physicalgraph.device.HubAction(
 		'method': 'GET',
		'path': "/query/info",
    	'headers': [ HOST: "$destIp:$destPort" ]) 

// log.debug "hubaction is: " + hubAction
def device = devices.find { it?.key?.contains(body?.device?.UDN?.text()) }
hubAction // also tried to “return hubAction”

}

def updated() {
log.debug “Executing ‘updated’”
unschedule()
runEvery5Minutes(refresh)

}
def initialize() {
// Device-Watch simply pings if no device events received for 32min(checkInterval)
log.debug “Inital”
// Poll device for additional data that will be updated by refresh tile
refresh()
}

def parse(description) {
def slurper = new groovy.json.JsonSlurper()
def msg = parseLanMessage(description)
def body = msg.body
def result = slurper.parseText(body)
//log.debug msg
log.debug msg.body
sendEvent(name: “temperature”, value:result.spacetemp, state: “refresh”)
sendEvent(name: “humidity”, value:result.hum, state: “refresh”)
}

private String convertIPtoHex(ipAddress) {
String hex = ipAddress.tokenize( ‘.’ ).collect { String.format( ‘%02X’, it.toInteger() ) }.join()
return hex
}

private String convertPortToHex(port) {
String hexport = port.toString().format( ‘%04X’, port.toInteger() )
return hexport
}

def refresh(){
log.trace(“Connexion verifiction - ${device.name}”)
def timeInSeconds = (Math.round(now()/1000))
getThermo()

}

It looks like your driver is already updating the data every 5 minutes. A set schedule is the only way that you can do that. It doesn’t know when you’ve opened the device on the app…so it can’t respond to that action.

Ok I had Thought when I open The app it would execute some section of the code to get an update of settings from the device. I’ll dig into it some more because the Auto refresh does not Work either at 5 min. I still have to press the refresh button to get the latest temp reading from the thermostat

That I don’t understand. Because every 5 minutes it’s running the same method as the refresh button. So, it shouldn’t matter.

So it is running the getThermo() but not parse(description) so I am not getting the json return but when I hit the refresh button it runs getThermo() and returns the json but the every 5 min does not return the json section

I have to say that looks more like a device handler than a smartapp to me. Anyway …

I believe your problem is that when you call refresh() ‘manually’ you are calling it as a command. If a command returns a hubAction (which is just a data structure) then SmartThings will process it and make stuff happen.

When you call refresh() from the scheduler you are not calling a command, just any old Groovy method, so SmartThings has no interest in the hubAction returned and it doesn’t process it

Have refresh() return a hubAction and then create a separate method for the scheduler that does sendHubCommand(refresh()) and you should get some joy.

Yes it is a device handler. I am quering my thermostat which returns this

{“name”:“MYSTAT”,“mode”:1,“state”:1,“fan”:0,“fanstate”:1,“tempunits”:0,“schedule”:0,“schedulepart”:255,“away”:0,“spacetemp”:65.0,“heattemp”:68.0,“cooltemp”:69.0,“cooltempmin”:35.0,“cooltempmax”:99.0,“heattempmin”:35.00,“heattempmax”:99.0,“activestage”:1,“hum_active”:1,“hum”:45,“hum_setpoint”:47,“dehum_setpoint”:99,“setpointdelta”:2.0,“availablemodes”:0}

I am just trying to send these variables to a tile, when i press the refresh it updates but I don’t want to have to press the refresh button everytime I want to see updated data from my thermostat.

Without pressing refresh I get java.lang.IllegalArgumentException: Text must not be null or empty @line 100 (parse)
which is def result = slurper.parseText(body)

The refreshevery5min never worked fine for me and a bunch of people in this forum.
We mostly use the polling capability and the Pollster smartapp which doesn’t skip any 5min trigger.

You can give is a try:

add to your capabilities:
capability “Poll”

install the Pollster smartapp and select your device in the list.

What??? I’m sorry…there’s a difference between running a job on a schedule and running in manually? No, there isn’t. That should be executing the same hub action as you pressing the refresh button manually. They are exactly the same.

I am suggesting if you call e.g. refresh() from a SmartApp, or by pressing a button in the mobile app, you are calling it from a context where it is acting as a command and any returned hubAction data structure is used to generate a hub command.

However if you use refresh() in the scheduler from within the device handler it just behaves like a normal Groovy method so you would need to do the sendHubCommand() yourself. Similar sort of idea as returning a createEvent() from parse() but calling sendEvent() elsewhere.

That’s just how it worked for me when I was writing device handlers. Haven’t done that for quite a while.

That is incorrect. Executing a method manually from a button or an app and executing it from a cron schedule are the exact same thing.

I got it I had to change my hubresponse to this and it was failing at the sluper, using the refresh button was invoking something in sluper, but it is working now I get updates from the termostat every min.

def getThermo() {
 def result = new physicalgraph.device.HubAction(
method: “POST”,
path: “/query/info”,
 headers: [
 “HOST” : “10.0.0.112:80”,
 “Content-Type”: “application/json”],
 null,
 [callback: parse]
 )
l og.debug result.toString()
 sendHubCommand(result);
 }

    def parse(physicalgraph.device.HubResponse hubResponse) {

    def results = hubResponse.body
    // log.debug “in parse: hubResponse" // log.debug "{hubResponse.body}”
    // log.debug hubResponse.name

    //log.debug results

    def slurper = new groovy.json.JsonSlurper()
    def msg = parseLanMessage(results)
    //def body = msg.body
    //def result = createEvent(slurper.parseText(body))
    def result = createEvent(slurper.parseText(results))
    //def body = msg.body
    //def result = createEvent(slurper.parseText(body))
    log.debug “results” + msg

FYI, when uploading code, it is always helpful to use the preformatting option for code by highlighting the code and clicking on the code icon.

image

This will allow it to be properly formatted and not use any of the discourse formatting that can screw with your code.

© 2019 SmartThings, Inc. All Rights Reserved. Terms of Use | Privacy Policy

SmartThings; SmartApps®; Physical Graph; Hello, Home; and Hello, Smart Home are all trademarks of the SmartThings, Inc.