Updating Temp Sensor Device

Two questions for the community:

  1. What is the best way to do input validation on incoming data from GET APIs etc? I’ve got a very rudimentary way at present which I’m sure is very clunky…

  2. I’ve created a new Temperature Sensor and would like to update it based on the temperature and humidity values received by the API (sounds simple enough?)

Error Messages:

error java.lang.NullPointerException: Cannot invoke method setTemperature() on null object @ line 68

error error: groovy.lang.MissingMethodException: No signature of method: cript14342832688371907786814.$() is applicable for argument types: script14342832688371907786814$_makeJSONWeatherRequest_closure2_closure4) values: script14342832688371907786814$_makeJSONWeatherRequest_closure2_closure4@16a09c76] Possible solutions: is(java.lang.Object), now(), url(), run(), any(), app(java.util.Map)


def makeJSONWeatherRequest() {

    def vtemp = 0.0
    def vhumi = 0

    def params = [
        uri:  'http://host.com',
        path: '/api/',
        contentType: 'application/json',
        query: [device:'1', token: 'xxx']
    try {
        httpGet(params) {resp ->
            log.debug "raw response data: ${resp.data}"
            vtemp = ${resp.data.temp}
            vhumi = ${resp.data.humi}
    } catch (e) {
        log.error "error: $e"
 //silly way of doing input validation?
    if (vtemp.toString().isDouble() && vhumi.toString().isInteger()) {
    	if (vtemp.toString().length() <= 7 && vhumi.toString().length() <= 3) {
        	log.debug "Correct data recieved."
            //Update temp
            //settings.target.parse("temperature: ${vtemp}")
            //settings.target.parse("humidity: ${vhumi}")
	} else {
    	    log.error "error: dataset was incomplete or invalid."

Really do appreciate the help! I’m trying to translate my ancient perl skills into groovy! oh, how things have changed.


I’m not sure if this line will work. You set vtemp and vhumi to strings. i don’t think they can be a string and a double or a interger as well.

To my knowledge string = text, integer = whole number, double = decimal places. You might want to kill the .toString and see if that works better.

target isn’t set anywhere in this method, so it’s null. Unless I missed something. That’s exactly what the error message is saying, at least.

Did you mean to use settings.target?

Separate question :smile:

Everything comes in as a string. Groovy mostly feels like java for string processing, and also has the same try/catch things

so, doing something like this should work

def dvtemp = -1.0
def ivhumi = -1
try {
  dvtemp = vtemp.toDouble();
  ivhumi = vhumi.toInteger();
  // still here? seems plausible. validate dvtemp and ivhumi to be within whatever range
  // you accept, and if so, call the set() methods
  if ((dvtemp > 30.0) && (dvtemp < 90.0)) settings.target.setTemperature(dvtemp)

} catch (e) {
  // invalid data passed in. Ignore it
  // DON'T exit here  

No need to exit, your SmartApp only runs when its needed

Thanks John and Sid. Appreciate the help, and I have been able to tighten up the error checking. However, I’m still getting the following error:

error: groovy.lang.MissingMethodException: No signature of method: script1434322929919539404578.$() is applicable for argument types: (script1434322929919539404578$_makeJSONWeatherRequest_closure2_closure4) values: [script1434322929919539404578$_makeJSONWeatherRequest_closure2_closure4@6565730]
Possible solutions: is(java.lang.Object), now(), url(), run(), any(), app(java.util.Map)

Which seems to relate to this code:

def vtemp = 0.0
def vhumi = 0
httpGet(params) {resp ->
            vtemp = ${resp.data.temp}
            vhumi = ${resp.data.humi}

Is this an incorrect process for setting these values?


OK, would seem like you just use resp.data.humi minus the ${}

The next piece in the puzzle:



error: dataset was incomplete or invalid. java.lang.IllegalArgumentException: Command 'setTemperature' is not supported. Supported commands: []

What is settings.target? Where is that initialized? It’s telling you that whatever that is, it doesn’t have any commands at all.

Hi John,

target is the device (that I created manually) that I am trying to set the temp/humi on.

I initialise it with the following:

preferences {
    section("Choose a target virtual temperature tile... "){
        input "target", "capability.temperatureMeasurement", title: "Tile"

It would seem that you can’t set the temperature (or humidity) on a Thermostat Sensor manually created in the IDE… Not sure what is missing? Any clues?

I made one with setters for you from the template - the templates don’t have setters

Using custom device types is pretty much the same as Smart Apps. Here is a great writeup if you don’t want to slog through the docs

For this, save this as a new device type, and then edit the device you made to use this new device type, and you should be good to go

Hi John,

Thanks very much for your help. So, lesson: I was trying to update the default device which couldn’t be updated.

I’ve been able to now get the SmartApp to work with the Custom Device. The data is flowing, I need to make some tweaks to the device code as I’m using C not F.

Last question on this topic: where do you get the code for the Devices? You used the Temperature Sensor template - are they all available?

Thanks again for your help!

See the link in my post above :smile:

tl;dr version:
Click Create New Device Type
Select From Template
Scroll down list of template device types - if you see the device type you want to modify, choose it and modify away!

Hi, I’m looking for the exact same thing, could you share the code on the device type that pull data from an API?