Xively Agent Library

A few people have been wondering about a library for interfacing with Xively, so I figured I would work something up to make everyone’s life a little bit easier.

You can find the results of my efforts in the repo at the end of the post, along with some documentation to get started with it. Hopefully everything is clear, if not feel free to ask questions! The example folder contains a simple (and somewhat boring) example of what pushing data to Xively looks like.

As a side note: I am super excited to see what all of you end up doing with the new Trigger feature :slight_smile:

Xively Agent API

Edit: Changed linked

Haha, that’s funny!
I was just working on a Xively class today and yesterday, using xively plus triggers to share data between imps. I’m having trouble to create triggers through the xively API though. I get either a 403 Forbidden response (when using my feed key), or a 500 Internal Server Error (when using my master key). I do have a working example using manually created triggers, but the idea was to have the triggers created by the agent.

Now let’s first take a look what you cooked up… :slight_smile:

That sounds cool to be able to create a trigger on the fly!
I hope you figure it out?

Also, this code is meant to be a starting point. There is a lot of functionality in the Xivley API I haven’t exposed (but I’m hoping there is enough for 90% of what people want to do).

If you guys expand on the functionality in the code I posted, please make a pull request :slight_smile:

Thanks for posting this beardedInventor - I used it and got a single item of data flowing to Xively and then out to a JS graph. Now I’m trying to figure out how to get multiple data items output, through the agent to Xively and to the graph.
I’ve declared them in the EI nut, and they are present and selectable in the Planner device “Impee Source Selection Screen”, but I can’t figure out how to connect them to the Xively agent.
It doesn’t seem intuitive -on the planner screen I can’t figure out to have the agent accept multiple parameters.
I have also declared a new paramter on the Xively.Channels page.
Can anybody give me a pointer or suggest some documentation?
many thanks

I was wondering if its possible to have two or more parameters exported from an imp to an Cosm/Xively Agent. Can’t see any examples of how two or more parameters are received on the Cosm/Xively agent.
Seems like it should be simple but haven’t been able to figure it out.
Any help appreciated on this.

Your screenshots seem to indicate that you’re still using the old COSM node, which you should be staying away from :slight_smile:

Using the library I linked to above, you should be able to do this quite easy. Simply create a feed with multiple channels in it, and the API takes care of the rest.

The basic premis looks something like this (note - I coded this on the fly and haven’t tested it, so there might be errors… it’s more to show the flow of how to do this):

In Xively: create a new feed with two channels named “sensor1” and “sensor2”

Device Code (reads values from pins and sends to Xively every 15 minutes):
`//Setup hardware
sensor1 <- hardware.pin1;
sensor2 <- hardware.pin2;

sensor1.configure(ANALOG_IN);
sensor2.configure(ANALOG_IN);

function getValuesAndSendToXively() {
// read values from pins
local s1 = sensor1.read();
local s2 = sensor2.read();

// make array of {key/value} objects to send to agent
data = [];
data.push( { key = "sensor1", value = s1 } );
data.push( { key = "sensor2", value = s2 ) );

// send to agent
agent.send("sendToXively", data);

// wakeup in 15 minutes, and do it again
imp.wakeup(900, getValuesAndSendToXively);

}

getValuesAndSendToXively();
`

Agent Code (I’ve omitted the Xively API so the code isn’t cluttered):
`/*** Insert Xively API Here ***/

agent.on(“sendToXively”, sendToXively);

function sendToXively(data) {
//data is an array of key value pairs
local channels = [];

// loop through array and create 1 channel per item
for (local i = 0; i < data.len(); i++) {
    local channel = Xively.Channel(data.key);
    channel.Set(data.value);
    channels.push(channel);
}

// create our feed and push to Xively
local feed = Xively.Feed(Xively.FEED_ID, channels);
local resp = Xively.Put(feed);

}`

Not to compete with beardedinventor, but you could also take a look at my solution for posting to Xively. Posting to several channels is quite trivial with Xively, you don’t even have to create the channel in advance. By posting to a feed, the channel(s) will be created if not existent.
Using my XivelyFeed class, it looks like this:

Agent:
`
// Xively account credentials
const MyApiKey = YOUR_API_KEY
const MyFeedID = YOUR_FEED_ID

// Class for reading/writing a feed at xively.com (formerly cosm)
class XivelyFeed {
static url = "https://api.xively.com/v2/feeds/"
apiKey = null
feedID = null

constructor(apiKey, feedID) {
this.apiKey = apiKey
this.feedID = feedID
}

// Send data to feed, expects a table with channel:value pairs
function put(data, callback) {
local datastreams = []
foreach(channel, value in data) {
datastreams.push({ “id”: channel, “current_value”: value })
}
local body = { “version”: “1.0.0”, “datastreams”: datastreams }
local headers = { “X-ApiKey”: apiKey, “Content-type”: “application/json” }
http.put(url + feedID + “.json”, headers, http.jsonencode(body)).sendasync(callback)
}
}

// Post-update handler
function onUpdate(res) {
server.log("result: " + res.statuscode)
}

// Handler for updates from device
device.on(“put”, function(data) {
server.log("put: " + http.jsonencode(data))
feed.put(data, onUpdate)
})

// Create xively feed object
feed <- XivelyFeed(MyApiKey, MyFeedID)
`

On the device, you use this code snippet to update one or more channels on Xively:
// sensor1, sensor2 are analog or digital inputs agent.send("put", { "channel1": sensor1.read(), "channel2", sensor2.read() })

That’s all.
For another code example using my XivelyFeed class, see http://forums.electricimp.com/discussion/1134/sharing-data-between-imps-using-xively-and-agents or https://gist.github.com/marcboon/5634981

By posting to a feed, the channel(s) will be created if not existent.

I did not know that - very cool + good to know!

Hey guys,
I’ve been focusing on something else and now back.
Some very nice insights so trying it out,

I’m trying the agent.send(“put”, …) method both ways and it gives me different errors. So my EI has been updated as I have
Mon Jul 22 2013 20:26:10 GMT-0700 (Pacific Daylight Time): impMac 0c2a69002275 impId 23614ab236a7c9ee SwVer f2f252d - Fri Jun 14 16:08:00 2013
Mon Jul 22 2013 20:26:10 GMT-0700 (Pacific Daylight Time): ssidMac 002275ea53d7 Ram=57.00K

In the code I have
` server.log(format(“1min: particles=%d, ratio=%5.3f%%, concentration=%7.1f, short=%3dms,long=%3dms,low=%3dms”,
particle1min_cnt,ratioMin_per,concentration,pulseshort,pulselong,downmillis));
.
local txData = ;

txData.push({key= “outputRatioMin”, value= ratioMin_per});
txData.push({key= “outputParticleMin”, value= particle1min_cnt});
txData.push({key= “outputPtclSzMin”, value= pulseshort});
txData.push({key= “outputPtclSzMax”, value= pulselong});
txData.push({key= “outputconcentration”, value= concentration});

agent.send("putPs", txData);  `

and the out put I get

Mon Jul 22 2013 20:23:25 GMT-0700 (Pacific Daylight Time): 1min: particles=1, ratio=0.118%, concentration= 62.1, short= 71ms,long= 71ms,low= 71ms
Mon Jul 22 2013 20:23:25 GMT-0700 (Pacific Daylight Time): putPs: [ { “value”: 0.118333, “key”: “outputRatioMin” }, { “value”: 0, “key”: “outputParticleMin” }, { “value”: 201, “key”: “outputPtclSzMin” }, { “value”: 0, “key”: “outputPtclSzMax” }, { “value”: 62.1019, “key”: “outputconcentration” } ]
Mon Jul 22 2013 20:23:26 GMT-0700 (Pacific Daylight Time): result: 400
<< fails on the post>>>
<< so i do>>

agent.send("putPs",{ "outputRatioMin": ratioMin_per, "outputParticleMin": particle1min_cnt, "outputPtclSzMin": pulseshort, "outputPtclSzMax": pulselong, "outputconcentration": concentration });
Mon Jul 22 2013 20:33:13 GMT-0700 (Pacific Daylight Time): 1min: particles=0, ratio=0.000%, concentration= 0.6, short= 0ms,long= 0ms,low= 0ms
Mon Jul 22 2013 20:33:13 GMT-0700 (Pacific Daylight Time): putPs: { “outputPtclSzMin”: 201, “outputconcentration”: 0.62, “outputParticleMin”: 0, “outputRatioMin”: 0, “outputPtclSzMax”: 0 }
Mon Jul 22 2013 20:33:14 GMT-0700 (Pacific Daylight Time): result: 200

<< Post succeeds, but it doesn’t report/appears to loose the first two paramters.

I guess I should maybe start simple and just try pushing two parameters.
I’d posted the whole code, but the interface complains its too long
many thanks

Updated: This now works
`
agent.send(“putPs”,{
“outputRatioMin”: ratioMin_per,
“outputParticleMin”: particle1min_cnt,
“outputPtclSzMin”: pulseshort,
“outputPtclSzMax”: pulselong,
“outputconcentration”: concentration
});

HI I’ve another question about the methods - I’m looking at ThingSpeek as an easier place to get data off.
Would you expect this to work consecutively?. Seems like it should
feed <- XivelyFeed(XivelyApiKey, XivelyFeedID) // Create xively feed object feed <- TsFeed(TsApiKey, TsFeedID) // Create ThingSpeak object

@neilh - I’m not sure I know what your question is?

Updated to working code
`// Kind input from marcboon June 13, 2013 - now works
//http://forums.electricimp.com/discussion/1134/sharing-data-between-imps-using-xively-and-agents or
//https://gist.github.com/marcboon/5634981

// Xively account credentials
const XivelyApiKey = "xx"
const XivelyFeedID = “11”

// Class for reading/writing a feed at xively.com (formerly cosm)
class XivelyFeed {
static url = "https://api.xively.com/v2/feeds/"
apiKey = null
feedID = null

constructor(apiKey, feedID) {
this.apiKey = apiKey
this.feedID = feedID
}

// Send data to feed, expects a table with channel:value pairs
function put(data, callback) {
local datastreams = []
foreach(channel, value in data) {
//server.log(“fPut: “+channel+”=”+value)
datastreams.push({ “id”: channel, “current_value”: value })
}
local body = { “version”: “1.0.0”, “datastreams”: datastreams }
local headers = { “X-ApiKey”: apiKey, “Content-type”: “application/json” }
http.put(url + feedID + “.json”, headers, http.jsonencode(body)).sendasync(callback)
}
}

// Post-update handler
function onUpdate2(res) {
server.log("fResult: " + res.statuscode)
}

// Handler for updates from device
device.on(“putPs”, function(data) {
server.log("doPutPs: " + http.jsonencode(data))
feed.put(data, onUpdate2)
})

// Create xively feed object
feed <- XivelyFeed(XivelyApiKey, XivelyFeedID)

//EOF`

Ooooh nice. I had been sending to xively the “old fashioned way”, and hadn’t seen this. I’d actually been thinking that it would be nice to have a xively library for the Imp, as they have some really nice ones for other languages. I’m using the Objective-C library. Are you able to remotely set trigger values in xively (with the agent), or just read the values that are already set?

The reference code has functions for both setting and getting data.

We’ve cleaned up to code a bit, and it’s now available on the Electric Imp GitHub.

Thanks beardedinventor & marcboon,
Got it going - the data flowing from the imp to the Agent to Xively.
I had to verify all the stages, and values in the objects, to see it flowing and appearing on Xively.

@beardedinventor

I just added the Xively API to my code, and I get a compile error here.
function Xively::Get(feed){

expected “(”

I have the class at the top of my agent code, copied from github. Any ideas?

Whoops - looks like I committed some broken code (you should remove “Xively::” from that line of code).

I’ve updated the file in GitHub, and it should be correct now.

Thanks! On a related note, I’d like to learn squirrel/Imp OS thoroughly, but there aren’t that many resources out there for it. Most of my experience so far has been with C#/Objective-C. Would books on C++ be a good foundation for learning Squirrel? Any other resources that you know of?