I wrote an app that logs data to a ThingSpeak channel. It does not currently allow you to log humidity, but that would be trivial to add. Here is the code:
/**
* ThingSpeak Logger
*
* Author: florianz
* Date: 2013-11-27
*
*
* Create a ThingSpeak channel with a write key. The app must be given the channel id and key.
* Then, create a field for each device and name the field according to the label given to the
* device in SmartThings.
*
*/
preferences {
section("Log devices...") {
input "temperatures", "capability.temperatureMeasurement", title: "Temperatures", required:false, multiple: true
input "contacts", "capability.contactSensor", title: "Contacts", required: false, multiple: true
input "accelerations", "capability.accelerationSensor", title: "Accelerations", required: false, multiple: true
input "motions", "capability.motionSensor", title: "Motions", required: false, multiple: true
input "switches", "capability.switch", title: "Switches", required: false, multiple: true
}
section ("ThinkSpeak channel id...") {
input "channelId", "number", title: "Channel id"
}
section ("ThinkSpeak write key...") {
input "channelKey", "text", title: "Channel key"
}
}
def installed() {
initialize()
}
def updated() {
unsubscribe()
initialize()
}
def initialize() {
subscribe(temperatures, "temperature", handleTemperatureEvent)
subscribe(contacts, "contact", handleContactEvent)
subscribe(accelerations, "acceleration", handleAccelerationEvent)
subscribe(motions, "motion", handleMotionEvent)
subscribe(switches, "switch", handleSwitchEvent)
updateChannelInfo()
log.debug state.fieldMap
}
def handleTemperatureEvent(evt) {
logField(evt) { it.toString() }
}
def handleContactEvent(evt) {
logField(evt) { it == "open" ? "1" : "0" }
}
def handleAccelerationEvent(evt) {
logField(evt) { it == "active" ? "1" : "0" }
}
def handleMotionEvent(evt) {
logField(evt) { it == "active" ? "1" : "0" }
}
def handleSwitchEvent(evt) {
logField(evt) { it == "on" ? "1" : "0" }
}
private getFieldMap(channelInfo) {
def fieldMap = [:]
channelInfo?.findAll { it.key?.startsWith("field") }.each { fieldMap[it.value?.trim()] = it.key }
return fieldMap
}
private updateChannelInfo() {
log.debug "Retrieving channel info for ${channelId}"
def url = "http://api.thingspeak.com/channels/${channelId}/feed.json?key=${channelKey}&results=0"
httpGet(url) {
response ->
if (response.status != 200 ) {
log.debug "ThingSpeak data retrieval failed, status = ${response.status}"
} else {
state.channelInfo = response.data?.channel
}
}
state.fieldMap = getFieldMap(state.channelInfo)
}
private logField(evt, Closure c) {
def deviceName = evt.displayName.trim()
def fieldNum = state.fieldMap[deviceName]
if (!fieldNum) {
log.debug "Device '${deviceName}' has no field"
return
}
def value = c(evt.value)
log.debug "Logging to channel ${channelId}, ${fieldNum}, value ${value}"
def url = "http://api.thingspeak.com/update?key=${channelKey}&${fieldNum}=${value}"
httpGet(url) {
response ->
if (response.status != 200 ) {
log.debug "ThingSpeak logging failed, status = ${response.status}"
}
}
}