Temperature logging and graph

I am currently using an Electric Imp to log my room temperature.

I have based on this project and I can read the temp off the Electric Imp IDE but unfortunately COSM does not seem to work anymore.

I would like Electric Imp to log temperature and have a graph on a website so I can better monitor my room temperature…
I’ve done some research on the web but I can’t find any projects that I can base on… So here I am starting a new discussion.

I need some help with where to start and what is the best way to pull off my project.

COSM is now Xively and there’s some reference code for connecting imps here:

https://github.com/electricimp/reference/tree/master/webservices/xively

I wrote a tutorial for collecting temperature and logging it to Xively on the Adafruit learn system. It uses a thermocouple, which is overkill for room temperature, but allows you to measure really high and low temps, like your freezer or stove.

If you look around the forums and documentation, there are a number of other temperature sensor projects as well.

I recently discovered GroveStreams (www.grovestreams.com). They offer free service if the transaction rate doesn’t get too high and if you use email notifications in lieu of SMS. I believe they offer very rich functionality and should be considered as an alternative to Xively. I had previously used ThingSpeak and would recommend them to hobbyists, too.

I can’t really code and I’m on a very long holiday and since I have been postponing this project 3 times this year, I am pulling all nighter. So lack of sleep has affected my brain’s ability to process the code…

I am having trouble figuring it out why Xively is not getting the data. Please help me out… (I have put two different codes (agent one and device one) from two different tutorials done by two different people so no wonder why I am having an issue.)

This is my Agent code:
`API_Key <- “**"; //Type your Xively API Key
Feed_ID <- "
” //Type your Feed ID
Channel_ID <- “Thermometer”; //Type your Channel ID

Xively <- {}; // this makes a 'namespace’
class Xively.Client {
ApiKey = null;
triggers = [];

    constructor(apiKey) {
            this.ApiKey = apiKey;
    }
    
    /*****************************************
     * method: PUT
     * IN:
     *   feed: a XivelyFeed we are pushing to
     *   ApiKey: Your Xively API Key
     * OUT:
     *   HttpResponse object from Xively
     *   200 and no body is success
     *****************************************/
    function Put(feed){
            local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
            local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
            local request = http.put(url, headers, feed.ToJson());

            return request.sendsync();
    }
    
    /*****************************************
     * method: GET
     * IN:
     *   feed: a XivelyFeed we fulling from
     *   ApiKey: Your Xively API Key
     * OUT:
     *   An updated XivelyFeed object on success
     *   null on failure
     *****************************************/
    function Get(feed){
            local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
            local headers = { "X-ApiKey" : ApiKey, "User-Agent" : "xively-Imp-Lib/1.0" };
            local request = http.get(url, headers);
            local response = request.sendsync();
            if(response.statuscode != 200) {
                    server.log("error sending message: " + response.body);
                    return null;
            }
    
            local channel = http.jsondecode(response.body);
            for (local i = 0; i < channel.datastreams.len(); i++)
            {
                    for (local j = 0; j < feed.Channels.len(); j++)
                    {
                            if (channel.datastreams[i].id == feed.Channels[j].id)
                            {
                                    feed.Channels[j].current_value = channel.datastreams[i].current_value;
                                    break;
                            }
                    }
            }
    
            return feed;
    }

}

class Xively.Feed{
FeedID = null;
Channels = null;

constructor(feedID, channels)
{
    this.FeedID = feedID;
    this.Channels = channels;
}

function GetFeedID() { return FeedID; }

function ToJson()
{
    local json = "{ \"datastreams\": [";
    for (local i = 0; i < this.Channels.len(); i++)
    {
        json += this.Channels[i].ToJson();
        if (i < this.Channels.len() - 1) json += ",";
    }
    json += "] }";
    return json;
}

}

class Xively.Channel {
id = null;
current_value = null;

constructor(_id)
{
    this.id = _id;
}

function Set(value) { 
        this.current_value = value; 
}

function Get() { 
        return this.current_value; 
}

function ToJson() { 
        local json = http.jsonencode({id = this.id, current_value = this.current_value });
    server.log(json);
    return json;
}

}

client <- Xively.Client(API_Key);`

This is my device code:
`hardware.pin1.configure(ANALOG_IN);

// LED pin config
hardware.pin2.configure(DIGITAL_OUT_OD_PULLUP);
// initially set to off
hardware.pin2.write(0);

/*
If you don’t have a Hannah board but want to try the
Cosm.com temperature logging exercise, here it is!

temperature sensor used is tmp36 from adafruit.com for $2.00
http://learn.adafruit.com/tmp36-temperature-sensor
temp range -40°C to 150°C / -40°F to 302°F
*/

local output = OutputPort(“temp”,“number”);
local postInit = false;
local oldTemp = null;
local reading = null;
local ratio = null;
local voltage = null;
local temperatureC = null;

local temp = null;

function update_temp() {
// keep the imp awake
imp.wakeup(10, update_temp);

// get the raw voltage value from temp sensor btw 0-65535
// in this case that needs mapping to the range 0-3.3v
reading = hardware.pin1.read();

// get the ratio
ratio = 65535.0 / reading;

// make units milivolts and get voltage we can work with
//voltage = (hardware.voltage() * 1000) / divider;
voltage = 3300 / ratio;

// get temperature in degrees Celsius
temperatureC = (voltage - 500) / 10.0;

server.log(postInit);

server.log("temp: " + temperatureC + “°C”);

// set our output to desired temperature unit
temp = temperatureC;

// after function’s first run set flag to true
postInit = true;

}

server.show(temp);

// Register with the server
imp.configure(“Tempreature Logger V2.0”, [], [output]);

update_temp();`

It looks like you’re trying to use OutputPorts in your device code. OutputPorts essentially write data to the blueprint/planner, which isn’t used anymore. So it’s not going to do much. Luckily, with the Xively class you found, there isn’t much you need to change.

The first thing we’re going to do is strip out the old blueprint functionality in your code. You want to remove the following 3 lines of code:

`local output = OutputPort(“temp”,“number”);

server.show(temp);

imp.configure(“Temperature Logger V2.0”, [], [output]);`

The next thing we need to do is tell the agent (server-side code) what the temperature is whenever we read it. At the bottom of your update_temp() function, add this line of code to send a message to the agent:

agent.send("temp", temp);

We’re done with the device code now, so let’s move on to the agent. Since we’re sending a “temp” message from the device, we need to catch it with device.on. When we catch the message, we’re going to send it to Xively, using the Xively class you’ve found!

`device.on(“temp”, function(temp) {
// create the channel
local tempChannel = Xively.Channel(Channel_ID);
// set the channel
tempChannel.Set(temp);

// create the feed:
local tempFeed = Xively.Feed(Feed_ID, [tempChannel]);

// create the client
local client = Xively.Client(API_KEY);

// push the data
client.Put(tempFeed);

});`

To make this a little cleaner/more efficient, we should declare our Channel, Feed, and Client as global variables in the agent:

`TempChannel <- Xively.Channel(Channel_ID)
TempFeed <- Xively.Feed(Feed_ID, [TempChannel]);
Client <- Xively.Client(API_KEY);

device.on(“temp”, function(temp) {
TempChannel.Set(temp);
client.Put(TempChannel)
});`

And that should about do it… I coded all of this in the forums editor, so there’s a good chance there are errors - but it should be enough to get you going, and hopefully shed some light on what’s going on :slight_smile:

I couldn’t figure it out by myself so I am asking for help again… Haha

I’m not sure why I am getting this error:
…UTC+13: [Agent] the index ‘FeedID’ does not exist
…UTC+13: [Agent] from unknown:147
…UTC+13: [Agent] at Put:45

I’m sure that there is no problem with the string that Electric Imp is sending it to the agent.

Agent code Line 45:
local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";

Agent code Line 147:
client.Put(TempChannel)

Entire Agent Code:
`API_Key <- “"; //Type your Xively API Key
Feed_ID <- "
” //Type your Feed ID
Channel_ID <- “Thermometer”; //Type your Channel ID

device.on(“temp”, function(temp) {
// create the channel
local tempChannel = Xively.Channel(Channel_ID);

// set the channel
tempChannel.Set(temp);

// create the feed:
local tempFeed = Xively.Feed(Feed_ID, [tempChannel]);

// create the client
local client = Xively.Client(API_Key)

// push the data
client.Put(tempFeed);

});

Xively <- {}; // this makes a 'namespace’
class Xively.Client {
ApiKey = null;
triggers = [];

    constructor(apiKey) {
            this.ApiKey = apiKey;
    }
    
    /*****************************************
     * method: PUT
     * IN:
     *   feed: a XivelyFeed we are pushing to
     *   ApiKey: Your Xively API Key
     * OUT:
     *   HttpResponse object from Xively
     *   200 and no body is success
     *****************************************/
    function Put(feed){
            local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
            local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
            local request = http.put(url, headers, feed.ToJson());

            return request.sendsync();
    }
    
    /*****************************************
     * method: GET
     * IN:
     *   feed: a XivelyFeed we fulling from
     *   ApiKey: Your Xively API Key
     * OUT:
     *   An updated XivelyFeed object on success
     *   null on failure
     *****************************************/
    function Get(feed){
            local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
            local headers = { "X-ApiKey" : ApiKey, "User-Agent" : "xively-Imp-Lib/1.0" };
            local request = http.get(url, headers);
            local response = request.sendsync();
            if(response.statuscode != 200) {
                    server.log("error sending message: " + response.body);
                    return null;
            }
    
            local channel = http.jsondecode(response.body);
            for (local i = 0; i < channel.datastreams.len(); i++)
            {
                    for (local j = 0; j < feed.Channels.len(); j++)
                    {
                            if (channel.datastreams[i].id == feed.Channels[j].id)
                            {
                                    feed.Channels[j].current_value = channel.datastreams[i].current_value;
                                    break;
                            }
                    }
            }
    
            return feed;
    }

}

class Xively.Feed{
FeedID = null;
Channels = null;

constructor(feedID, channels)
{
    this.FeedID = feedID;
    this.Channels = channels;
}

function GetFeedID() { return FeedID; }

function ToJson()
{
    local json = "{ \"datastreams\": [";
    for (local i = 0; i < this.Channels.len(); i++)
    {
        json += this.Channels[i].ToJson();
        if (i < this.Channels.len() - 1) json += ",";
    }
    json += "] }";
    return json;
}

}

class Xively.Channel {
id = null;
current_value = null;

constructor(_id)
{
    this.id = _id;
}

function Set(value) { 
        this.current_value = value; 
}

function Get() { 
        return this.current_value; 
}

function ToJson() { 
        local json = http.jsonencode({id = this.id, current_value = this.current_value });
    server.log(json);
    return json;
}

}

TempChannel <- Xively.Channel(Channel_ID)
TempFeed <- Xively.Feed(Feed_ID, [TempChannel]);
client <- Xively.Client(API_Key);

device.on(“temp”, function(temp) {
TempChannel.Set(temp)
client.Put(TempChannel)
});`

Oops - the last line of code: client.Put(TempChannel) should actually be client.Put(TempFeed):

device.on("temp", function(temp) { TempChannel.Set(temp); client.Put(TempFeed); });

Thank you so much.

Project that got hold off so many times has now finished.

I would like to recommend following videos that goes in detail for design of temperature logger and this can also be done using arduino.
Temperature Logger(part1)- https://youtu.be/jfbrsoNRE5c
Temperature Logger(Part2)- https://youtu.be/_DDib9X4U-A
Temperature Logger(part3)- https://youtu.be/pEov-ki7BRQ
Temperature Logger(part4)- http://youtu.be/og27aVmc9iE
Temperature Logger(part5)- https://youtu.be/TyC7cJKFmVo
Temperature Logger(part6)- https://youtu.be/eca88zQzoEU