Help with simple http query device driver

Hi All,

Anyone have any simple polling (over web) drivers that query something for json-ish data and pull out the needed piece?

Looking to query my geiger counter that reports to gmcmap.com. I can pull it's current info via:

http://www.gmcmap.com/historyData-plain.asp?Param_ID=37264604156&timezone=-7

Keep meaning to work on this, but my groovy is less than weak, it's basically non-existent. So something to point me at would be super helpful.

Thanks!

Unfortunately, that's a bit of a contradiction. You're doing this from a driver, correct? What attributes/capabilities are you going to use to present the data in Hubitat? What attributes do you want to create events for?

look at this one
https://raw.githubusercontent.com/hubitat/HubitatPublic/master/examples/drivers/httpGetSwitch.groovy
and make some change
in sendCmd

    def params = [
        uri: "http://www.gmcmap.com/historyData-plain.asp?Param_ID=37264604156&timezone=-7",
        requestContentType: 'application/json',
        contentType: 'application/json'
        ]
    httpGet( params ) { resp ->
        if (resp.success) {
            sendEvent(name: "**CPM**", value: resp.data.**CPM**)

I'm not getting it, sorry. I have looked at that code previously, and had the following:

/*
 * gmcmap.com Geiger Counter Query
 */
import groovy.json.JsonSlurper
import groovy.json.JsonOutput

metadata {
    definition(name: "gmcmap.com Geiger Counter", namespace: "staze", author: "Ryan Stasel", importUrl: "https://raw.githubusercontent.com/hubitat/HubitatPublic/master/examples/drivers/httpGetSwitch.groovy") {
        capability "Sensor"
	capability "Refresh"
    }
}

preferences {
    section("URIs") {
        input "GeigerID", "text", title: "Geiger ID", required: true
        input "Timezone", "text", title: "Timezone", required: false
        input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
    }
}

def logsOff() {
    log.warn "debug logging disabled..."
    device.updateSetting("logEnable", [value: "false", type: "bool"])
}

def updated() {
    log.info "updated..."
    log.warn "debug logging is: ${logEnable == true}"
    if (logEnable) runIn(1800, logsOff)
}

def parse(String description) {
    if (logEnable) log.debug(description)
}

def getParams() { "http://www.gmcmap.com/historyData-plain.asp?Param_ID=${GeigerID}&timezone=${Timezone}" }

def refresh() {
def responseBody

try {
	if (logEnable) log.debug "Params:  ${getParams()}"
	httpGet(getParams()) { resp -> 
		if (logEnable) log.debug resp.getData()
		responseBody = resp.getData()
		state.geiger = new JsonSlurper().parseText(responseBody)
	}
		//responseBody = resp.getData()}
} catch(Exception e) {
	log.debug "error occured calling httpget ${e}"
}
if (logEnable) log.info responseBody
}

But doesn't work (or rather, I think it's incomplete as I got stuck trying to have the driver echo out the complete response). I'm used to working in situations where I can first get a response back then narrow down the part of the response I want (powershell, bash, etc).

For your example, I don't see "sendCmd" in the linked driver, so I'm not entirely sure where to stick this...

I mean, I would assume the driver should ask for URL to poll (or at least Geiger number so someone could just enter that and not worry about whole string), and then how often to poll (in minutes). Then return back CPM I'd assume.

tested, this should work.
state.geiger = jsonSlurper.parseText(resp.data.toString())

what exactly is the geiger data? (sounds like rocket science)

It’s radiation info. So if there was a nuclear accident, etc.

Will give that a go. I have no control over server side output. And yeah, I think last I looked I noticed it wasn’t true json.

so here's a question... there has to be a good way to actually develop basic drivers without doing it directly on the hub... or do people just have a second (or third, forth, etc) hub just for development? like, what's it take to get an approximate groovy install on a VM to test with?

Getting close!

Here's what i'm getting from logs with the code I posted with your change.

[dev:1729](http://10.0.6.4/logs#dev1729)2020-08-16 21:39:31.995 [info](http://10.0.6.4/device/edit/1729) {"time": "2020-08-16 21:37:38", "CPM": "22", "ACPM": "18.09", "uSv": "0.14"}

[dev:1729](http://10.0.6.4/logs#dev1729)2020-08-16 21:39:31.990 [debug](http://10.0.6.4/device/edit/1729)error occured calling httpget java.lang.NullPointerException: Cannot invoke method parseText() on null object

[dev:1729](http://10.0.6.4/logs#dev1729)2020-08-16 21:39:31.985 [debug](http://10.0.6.4/device/edit/1729) {"time": "2020-08-16 21:37:38", "CPM": "22", "ACPM": "18.09", "uSv": "0.14"}

[dev:1729](http://10.0.6.4/logs#dev1729)2020-08-16 21:39:31.960 [debug](http://10.0.6.4/device/edit/1729)Params: http://www.gmcmap.com/historyData-plain.asp?Param_ID=37264604156&timezone=-7

--- Live Log Started, waiting for events ---

Here's code btw: hubitat-gmcmap/hubitat-gmcmap.groovy at master · staze/hubitat-gmcmap · GitHub

Made some changes for you, please try this version:

/*
 * gmcmap.com Geiger Counter Query
 */
import groovy.json.JsonSlurper

metadata {
    definition(name: "gmcmap.com Geiger Counter", namespace: "staze", author: "Ryan Stasel", importUrl: "https://raw.githubusercontent.com/staze/hubitat-gmcmap/master/hubitat-gmcmap.groovy") {
        capability "Sensor"
	    capability "Polling"
        attribute "CPM", "NUMBER"
        attribute "ACPM", "NUMBER"
        attribute "uSv", "NUMBER"
    }
}

preferences {
    section("URIs") {
        input "GeigerID", "text", title: "Geiger ID", required: true
        input "Timezone", "text", title: "Timezone", required: false
	    input name: 'updateMins', type: 'enum', description: "Select the update frequency", title: "Update frequency (minutes)\n0 is disabled", defaultValue: '5', options: ['0', '1', '2', '5','10','15','30'], required: true
        input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
    }
}

def logsOff() {
    log.warn "debug logging disabled..."
    device.updateSetting("logEnable", [value: "false", type: "bool"])
}

def updated() {
    unschedule()
    log.info "updated..."
    log.warn "debug logging is: ${logEnable == true}"
    if (logEnable) runIn(1800, logsOff)
    if(updateMins != "0") {
        schedule("0 */${updateMins} * ? * *", poll)
    }
    
}

def parse(String description) {
    if (logEnable) log.debug(description)
}

def poll() {
    if (logEnable) log.debug "polling..."
    def url = "http://www.gmcmap.com/historyData-plain.asp?Param_ID=${GeigerID}&timezone=${Timezone}"
    try {
        httpGet(url) { resp -> 
            if (logEnable) log.debug resp.getData()
            def respValues = new JsonSlurper().parseText(resp.data.toString().trim())
            sendEvent(name: "CPM", value: respValues.CPM)
            sendEvent(name: "ACPM", value: respValues.ACPM)
            sendEvent(name: "uSv", value: respValues.uSv)
	}
    } catch(Exception e) {
    	log.debug "error occured calling httpget ${e}"
    }
}
1 Like

Thank you, that seems to work perfectly! Updated my repo with that code. Thank you again! Awesome.

1 Like