SmartThings Community

Updating Temp Sensor Device

(JukeBox) #1

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:  '',
        path: '/api/',
        contentType: 'application/json',
        query: [device:'1', token: 'xxx']
    try {
        httpGet(params) {resp ->
            log.debug "raw response data: ${}"
            vtemp = ${}
            vhumi = ${}
    } 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
            //"temperature: ${vtemp}")
            //"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.


(sidjohn1) #2

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.

(John S) #3

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

(John S) #4

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

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

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

(JukeBox) #5

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 = ${}
            vhumi = ${}

Is this an incorrect process for setting these values?


(JukeBox) #6

OK, would seem like you just use minus the ${}

(JukeBox) #7

The next piece in the puzzle:


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

(John S) #8

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

(JukeBox) #9

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"

(JukeBox) #10

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?

(John S) #11

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

(John S) #12

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

(JukeBox) #13

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!

(John S) #14

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!

(Casper) #15

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