Instantly share code, notes, and snippets.
Last active
December 17, 2015 15:58
-
Star
1
(1)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save marcboon/5634981 to your computer and use it in GitHub Desktop.
Using xively.com to share data between two or more electric imps. The imps can read and update named channels in the same feed, and notify each other after every successful update, so that data is synchronized between imps, without the need for polling. Upon start-up, every imp automatically adds a tag to the feed, containing its unique agent id…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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" } | |
local req = http.put(url + feedID + ".json", headers, http.jsonencode(body)) | |
req.sendasync(callback) | |
} | |
// Get current feed state | |
function get() { | |
local headers = { "X-ApiKey": apiKey } | |
local req = http.get(url + feedID + ".json", headers) | |
local res = req.sendsync() | |
server.log("GET: " + res.statuscode) | |
return res.statuscode == 200 ? http.jsondecode(res.body) : null | |
} | |
// Get a datastream (channel) | |
function getStream(id) { | |
local feed = get() | |
if(feed != null) { | |
foreach(stream in feed.datastreams) { | |
if(stream.id == id) return stream // stream found | |
} | |
} | |
return null // stream not found | |
} | |
// Get tags for this feed as array | |
function getTags() { | |
local feed = get() | |
if(feed != null) { | |
if("tags" in feed) return feed.tags // return array with tags | |
else return [] // no tags, return empty array | |
} | |
return null // failed to get tags | |
} | |
// Set tags for this feed | |
function setTags(tags) { | |
local body = { "version": "1.0.0", "tags": tags } | |
local headers = { "X-ApiKey": apiKey, "Content-type": "application/json" } | |
local req = http.put(url + feedID + ".json", headers, http.jsonencode(body)) | |
if(req.sendsync().statuscode == 200) { | |
server.log("tags updated: " + http.jsonencode(tags)) | |
return tags | |
} | |
server.log("setTags failed") | |
return null | |
} | |
// Add a tag to this feed | |
function addTag(tag) { | |
local tags = getTags() | |
if(tags != null) { | |
if(tags.find(tag) == null) { | |
tags.push(tag) | |
tags = setTags(tags) | |
} | |
} | |
return tags | |
} | |
// Remove a tag from this feed | |
function removeTag(tag) { | |
local tags = getTags() | |
if(tags != null) { | |
local i = tags.find(tag) | |
if(i != null) { | |
tags.remove(i) | |
tags = setTags(tags) | |
} | |
} | |
return tags | |
} | |
} | |
// Send notification message to other agent | |
function notifyAgent(agent, state) { | |
local agentURL = "https://agent.electricimp.com/" + agent | |
local body = { "agent_id": MyAgentID, "feed_id": MyFeedID, "datastream": state } | |
local headers = { "Content-type": "application/json" } | |
local req = http.put(agentURL, headers, http.jsonencode(body)) | |
req.sendasync(null) // send notification without waiting for result (target might be offline) | |
} | |
// Post-update handler, notifies other devices | |
function onUpdate(res) { | |
server.log("PUT: " + res.statuscode) | |
local tags = feed.getTags() | |
if(tags != null) { | |
// notify agents | |
local state = feed.getStream("LED") | |
foreach(tag in tags) { | |
// agentIDs are prefixed with @ | |
if(tag[0] == '@') { | |
// Skip self | |
if(tag != MyAgentID) | |
notifyAgent(tag.slice(1), state) | |
} | |
} | |
} | |
} | |
// Add agentID to this feed's tags when device connects | |
device.onconnect(function() { | |
server.log("device connected") | |
feed.addTag(MyAgentID) | |
}) | |
// Remove agentID from this feed's tags when device disconnects | |
device.ondisconnect(function() { | |
server.log("device disconnected") | |
feed.removeTag(MyAgentID) | |
}) | |
// Handler for updates from device | |
device.on("put", function(data) { | |
server.log(http.jsonencode(data)) | |
feed.put(data, onUpdate) | |
}) | |
// Handler for updates from other agents | |
http.onrequest(function(req, res) { | |
// send OK response to the sender | |
res.send(200, "OK") | |
local feed = http.jsondecode(req.body) | |
// verify if this is our feed | |
if("feed_id" in feed && feed.feed_id == MyFeedID) { | |
device.send("update", feed.datastream) | |
} | |
}) | |
// Start agent | |
server.log("agent started") | |
// Create xively feed object | |
feed <- XivelyFeed(MyApiKey, MyFeedID) | |
// This imp's agentID (agentURL with domain replaced by @) | |
MyAgentID <- "@" + http.agenturl().slice(29) | |
server.log("agentID: " + MyAgentID) | |
// Add agentID to this feed's tags | |
feed.addTag(MyAgentID) | |
// Get initial state | |
state <- feed.getStream("LED") | |
server.log(http.jsonencode(state)) | |
device.send("update", state) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
imp.configure("xively-shared-data-tags", [], []) | |
sw <- hardware.pin1 | |
led <- hardware.pin2 | |
sw.configure(DIGITAL_IN_PULLUP) | |
led.configure(DIGITAL_OUT) | |
agent.on("update", function(data) { | |
if("id" in data && data.id == "LED") { | |
local val = data.current_value.tointeger() | |
server.log("update: " + val) | |
led.write(val) | |
} | |
}) | |
// toggle LED when switch is pressed | |
function readswitch() { | |
imp.wakeup(0.05, readswitch) | |
local now = sw.read() | |
if(now != prev && now == 0) { | |
local val = 1 - led.read() | |
led.write(val) | |
agent.send("put", { "LED": val }) | |
} | |
prev = now | |
} | |
prev <- sw.read() | |
readswitch() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment