Graphing from Smartsense Multi

I’m planning to build a wine cellar in my basement using smartthings for some basic automation (lights, door status, temperature / humidity monitoring and alerts), but I want to gather some baseline data on the space before I start insulating to make sure I have the right r-value and temperature controls.

What I was hoping to do was graph the humidity and temperature over time, and it seems to me that a Smartsense Multi should be able to provide that input, but I have no idea how to create a graph of the output. I was thinking that I could use IFTTT to log the data from the Multi to a Google Spreadsheet, but that might have been wishful thinking.

Any ideas? I feel like there’s a way to make this work that I’m just missing.

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}"
        }
    }
}
4 Likes

Thanks amazing. Thanks FlorianZ! I’m new to coding for Smartthings, so this will be a good project to get me started since 99% of the work is here. Really appreciate it.

My pleasure. What you want to do is add an input for your humidity sensor(s) in the preferences meta-data section, then subscribe to events from these sensors in the initialize() function. You will also have to add a new event handler (handleHumidityEvent, or similar). For starters, the implementation of that handler would be exactly the same as the handleTemperatureEvent handler, and just log the event value as a string to the ThingSpeak field.

Let me know if you have any questions.

Woah @florianz! I had no idea ThingSpeak existed… it’s so simple, it’s brilliant. Thank you for posting this!

Thanks so much for posting this. I am new to Smart & have been working with this example. I keep thinking I must be missing a manual somewhere, is there somewhere with basic documentation on the language in use here? For example, how to get the current date/time, syntax for the logging functions, etc? Are there loops?

Specifically on this code you use it.toString in the temperature event handler, but I can’t figure out where that object came from. It doesn’t seem to have been passed to the event handler, so I’m thinking it must be built it somewhere, but I can’t figure it out.

I’d like to convert this code to send temperature data periodically using the schedule function, but I keep reaching for a manual I don’t seem to have.

Sorry if this is a stupid question, any pointers appreciated.

@chrisl

The language is called groovy. See here http://groovy.codehaus.org/User+Guide. The ‘it’ is an implicit variable. See here http://groovy.codehaus.org/Closures

Thanks!

Sorry, total newb here. I’m trying to figure out if SmartThings has any “built in” functionality to save historical data such as for temperature, humidity, and motion before I buy the smart hub. Looking for time graphs similar to the OP question. Or will I need to code things like this? I’d prefer something out of the box pre-built since I don’t have time to code, debug, etc. I see IFTTT integration and would think I could build a graph and capture data on that, but would be better if something “prettier” and more seamless already existed.

@florianz I have been using your code since getting ST setup, I recently modified it to log if the HVAC was running or not using thermostatOperatingState, however since both the temperature and thermostatOperatingState come from the same named device “Thermostat” the logging for temperature and state get mixed up between the two separate graphs. Any idea how this could be fixed?

This may help:

Thanks @gecko I noticed that one when I was hunting around for a fix. I didn’t want to start the logging all over but I decided to. I now have my temperature sensors all logging to Xively.

@mattjfrank, sounds like you were able to resolve your issue. My app assumes that each device has exactly one channel, you could fix that by passing some variable suffix to the logField method, e.g:

private logField(evt, suffix, Closure c)

Then use this line to create the device name for looking up the ThingSpeak field:

def deviceName = evt.displayName.trim() + suffix

You could then log fields like this:

logField(evt, "_temperature") { ... }

or

logField(evt, "_operatingState") { ... }

Your ThingSpeak fields would have to be named appropriately (e.g. “Thermostat_temperature”, etc.)

Having said that, I don’t use ThingSpeak anymore. The service has just been too unreliable for me. You can use Xively, like @geko mentioned, or try to write an app for another IoT logging service. There are quite a few, now. For example, SparkFun just added a cool looking one.

@florianz I’m using Xively I modified an app to log what I wanted logged and it’s working as I’d hoped. I like Xively graphs better anyway.

Thanks

Is there any way to add this to the mobile Dashboard? I would love to see a “Monitors” or “Reports” section that had a way of displaying e.g. Temperatures in a table/list (current status) or chart/graph (historical) and allowing grouping/add/remove of select Multi or other Temperature sensors. (Probably similar with Humidity, Ambient Light and other value-monitoring sensors.)
The ability to set up Alerts e.g. for too cold/too hot is great, but sometimes it’s just as important to see a quick overview of status (just like the Open/Closed sensor view). Similarly, although timelines might show certain values, a graphical representation that aggregates just specific types of data is important to show historical trending.
Where in the forum would be a good place to discuss that as a future project/wishlist?
Thanks,
John

1 Like

[quote=“florianz, post:2, topic:930”]
/**

  • ThingSpeak Logger

I’ve tried this code and used my WriteAPIKey and ChannelID# from thingspeak but I’m not seeing any data getting published to my channel. Does Thingspeak still work with Smartthings? Is there a different set of code I should be using? Can anybody help me get Thingspeak working with my sensors?
Thank you.

If you’re still interested, I just installed this app and it worked for me. Make sure that your field names in ThinkSpeak are typed in exactly the same as your sensor names. Then watch the Live Logging page in case there are errors.

Does anyone have the latest copy of this code for thinkspeak? I tried the link above but when I end it pasting it in to the code window for a new app. But I get Metadata definition not found when I try to save.

Anyone have any ideas?

Thanks,

This worked for me.

2 Likes

Hmm so you can only graph 8 devices?