Xively Namespace: Updated with class to post all of the Location data

Many of us use the Xively class that @beardedinventor wrote. I am adding the ability to send GPS data from your iPhone to an Imp using Pitchfork, and wanted a way to easily plot that data, so I added a Xively class that pushes location data. Here is the class, as well as an example function of how I am using it.
Link to the Xively API Docs about locations:
https://xively.com/dev/docs/api/metadata/waypoints/

`
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();
}
function PutLocation(location){
	local url = "https://api.xively.com/v2/feeds/" + location.FeedID + ".json";
	local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
	local request = http.put(url, headers, location.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.Location {
FeedID = null;
disposition = null;
name = null;
exposure = null;
domain = null;
ele = null;
lat = null;
lon = null;

constructor(feedID)
{
    this.FeedID = feedID;
}
function GetFeedID() { return FeedID; }

function Set(disposition, name, exposure, domain, ele, lat, lon) {
    this.disposition = disposition;
    this.name = name;
    this.exposure = exposure;
    this.domain = domain;
    this.ele = ele;
    this.lat = lat;
    this.lon = lon;
}
function ToJson() { 
    local json = http.jsonencode({ "location": {disposition = this.disposition, name = this.name,
    exposure = this.exposure, domain = this.domain, ele = this.ele, lat = this.lat, lon = this.lon}});
    //server.log(json);
    return json;
}

}
class Xively.Channel {
id = null;
current_value = null;
mytag = “”;

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

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

function Get() { 
	return this.current_value; 
}

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

}
APIKEY <- “YOUR API KEY”;
client <- Xively.Client(APIKEY);

function setLocation(ele, lat, lon) {
server.log(“sending to Xively”);
location <- Xively.Location(“YOUR FEED ID”);
location.Set(“mobile”, “Lancaster”, “outdoor”, “physical”, ele, lat, lon)
client.PutLocation(location);
}
`

Well, thanks a lot.
Looks like we have it all now…

@jwehr - do you want to submit a pull request in GitHub to add that class.

https://github.com/electricimp/reference/blob/master/webservices/xively/xivelyClient.agent.nut

Ok, hopefully I did it correctly. Github makes me feel dumb on a regular basis. :slight_smile:

hello there i tried your example, i am not sure what i am doing wrong but i get:
2013-12-23 15:02:44 UTC-8: [Device] ERROR: the index ‘Xively’ does not exist

agent code is the github code
and device code is
`APIKEY <- “YOUR API KEY”;
client <- Xively.Client(APIKEY);

function setLocation(ele, lat, lon) {
server.log(“sending to Xively”);
location <- Xively.Location(“YOUR FEED ID”);
location.Set(“mobile”, “Lancaster”, “outdoor”, “physical”, ele, lat, lon)
client.PutLocation(location);
}`

of course feedid and api key and ele lat and lon have been replaced.
Any tips? thanks

ok i figured out my issue partially but got into another problem.
So for agent code i have the code from github plus:

APIKEY <- "xxx"; client <- Xively.Client(APIKEY); device.on("SendToXively", function(data) { server.log("data:"+data.id); server.log("data:"+data.value); mychannel <- Xively.Channel(data.id); mychannel.Set(data.value); myfeed <- Xively.Feed("xxxx", [mychannel]); client.Put(myfeed); });

on the device side i have this code :

agent.send(“SendToXively”, {id = “RSSI”, value = rssi});

and the error i get is

2013-12-23 15:29:26 UTC-8: [Agent] wrong number of parameters

2013-12-23 15:29:26 UTC-8: [Agent] at unknown:246

Any ideas?

What is the agent code at 246? Try putting the table data in a variable first, and then send it?

BTW, I would pull the code from the Electric Imp Github page, as the forum editor sometimes makes changes to the code. Also, note that tags are now included with the channel class and something must be passed there… even if it is a blank string.

I would like some help sending location info for a mobile device to Xively.
This is the code that I’m using for channel updates:

`// 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)
`

On the device (with calculations, etc.) is:

agent.send("putPs",{ "tagID": ID, "volts": voltage, "speed": speed, "blower": blow });

It works fine. Very easy to use.

Now I want to add location, but the code in the github doesn’t look to me like the code I’m using for channels and I don’t want to start over.

What is the best way to extend my app?

The Electric Imp version of the code is somewhat different. Are you just looking to add a location one time, or do you have data coming in from the device?

Data is coming from the device. I have had no problems with the code above with channels and for testing, I have switched the agent to the github code. What is supposed to be on the device?
I have:
function setLocation(ele, lat, lon) {
server.log(“sending to Xively”);
location <- Xively.Location(“1250102917”);
location.Set(“mobile”, “TrackCleaner”, “outdoor”, “physical”, ele, lat, lon)
client.PutLocation(location);
}
Called from my device.

Don’t I need some code at the top of the device to link it to the agent? Don’t know what. Or is this a ‘agent.send’ instruction?

Code deleted by dbbotkin

OK, jwher solved the problem! Check Xively.bssid on GitHub for agent and device code. I had to modify the device code to agent.send(“RFID”,{“lat”: lat,“lon”:lon}); get rid of the bssid stuff and change the agent to “RFID” for my app, but it works.

Thanks!