Skip to content

Instantly share code, notes, and snippets.

@azdle
Created June 18, 2013 21:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save azdle/5809542 to your computer and use it in GitHub Desktop.
Save azdle/5809542 to your computer and use it in GitHub Desktop.
Exosite Demo Application for the Electric Imp
// Class for Communication to Exosite
class Exosite{
cik = null;
vendor = null;
model = null;
serial = null; // Consider hardware.getimpeeid() or imp.getmacaddress()
constructor(cikp = null, vendorp = null, modelp = null, serialp = null){
if(cikp == null){
server.log("No CIK, need to provision.")
if(vendorp != null, modelp != null, serialp != null){
server.error("Vender, Model, and Serial must be set to provision.")
cik = this.provision();
}
}else{
cik = cikp;
}
}
function provision(){
server.error("Provisioing Not Yet Implimented")
}
// Read from Exosite
function read(aliases, callback){
local alias_url_format = "";
foreach(alias in aliases){
alias_url_format = alias_url_format + alias + "&";
}
local response = http.get(
"https://m2.exosite.com/onep:v1/stack/alias?"+alias_url_format,
{"Accept": "application/x-www-form-urlencoded",
"X-Exosite-CIK": cik}
).sendsync();
if(response.statuscode == 200 || response.statuscode == 204){
server.log(response.body);
callback(http.urldecode(response.body));
}else{
server.error("Could not read from the OnePlatform. HTTP Response Code: "+response.statuscode)
return null;
}
}
// Write to Exosite
function write(data){
local response = http.post(
"https://m2.exosite.com/onep:v1/stack/alias",
{"Content-Type": "application/x-www-form-urlencoded",
"X-Exosite-CIK": cik},
http.urlencode(data)
).sendsync();
if(response.statuscode != 204 || response.statuscode == 200){
server.error("Could not write to the OnePlatform. HTTP Response Code: "+response.statuscode)
}
}
}
// Setup Exosite Object
exoComms <- Exosite("654a29f2f230a2810a28036f79ab2fef17c058c4");
// Agent 'write' to datasource(s) call.
device.on("write", function(keyValuePairs) {
foreach(alias, value in keyValuePairs){
server.log("Write to "+alias+": "+value);
}
exoComms.write(keyValuePairs);
});
//Agent 'read' from datasource(s) call.
device.on("read", function(aliasArray) {
foreach(alias in aliasArray){
server.log("Read from "+alias+".");
}
local data = exoComms.read(aliasArray, function(data){
device.send("readresp", data);
});
});
imp.configure("Exosite Test", [], []);
// Temperature logging example for Hannah Modified to Report to Exosite
// Temperature Sensor Class for SA56004X
class TemperatureSensor
{
i2cPort = null;
i2cAddress = null;
conversionRate = 0x04;
constructor(port, address)
{
if(port == I2C_12)
{
// Configure I2C bus on pins 1 & 2
hardware.configure(I2C_12);
i2cPort = hardware.i2c12;
}
else if(port == I2C_89)
{
// Configure I2C bus on pins 8 & 9
hardware.configure(I2C_89);
i2cPort = hardware.i2c89;
}
else
{
server.log("Invalid I2C port specified.");
}
i2cAddress = address << 1;
// Configure device for single shot, no alarms
write(0x09, 0xD5);
// Set default conversion rate (1Hz)
setRate(conversionRate);
}
// Read a byte
function read(register)
{
local data = i2cPort.read(i2cAddress, format("%c", register), 1);
if(data == null)
{
server.log("I2C Read Failure");
return -1;
}
return data[0];
}
// Write a byte
function write(register, data)
{
i2cPort.write(i2cAddress, format("%c%c", register, data));
}
// Set continuous conversion rate, 0 = 0.06Hz, 4 = 1Hz, 9 = 32Hz
function setRate(rate)
{
if(rate >= 0 && rate <= 9)
{
write(0x0a, rate);
conversionRate = rate;
}
else
{
write(0x0a, 0x04);
conversionRate = 0x04;
server.log("Invalid conversion rate, using default 1Hz");
}
}
// Stop continuous conversion
function stop()
{
write(0x09, 0xD5);
}
// Start conversion, continuous or single shot
function start(continuous)
{
if(continuous == true)
{
write(0x09, 0x55);
}
else
{
write(0x0f, 0x00);
}
}
// Check if conversion is completed
function isReady()
{
return (read(0x02) & 0x80)?false:true;
}
// Retrieve temperature (from local sensor) in deg C
function getTemperature()
{
// Get 11-bit signed temperature value in 0.125C steps
local temp = (read(0x00) << 3) | (read(0x22) >> 5);
if(temp & 0x400)
{
// Negative two's complement value
return -((~temp & 0x7FF) + 1) / 8.0;
}
else
{
// Positive value
return temp / 8.0;
}
}
}
// Instantiate the sensor
local sensor = TemperatureSensor(I2C_89, 0x4c);
// Output port to send temperature readings
local output = OutputPort("Temperature", "number");
// Capture and log a temperature reading every 5s
function capture()
{
// Set timer for the next capture
imp.wakeup(10.0, capture);
// Start a single shot conversion
sensor.start(false);
// Wait for conversion to complete
while(!sensor.isReady()) imp.sleep(0.05);
// Output the temperature
local packet = {};
packet.temp <- sensor.getTemperature();;
agent.send("write", packet);
}
// Color Blink code example for Hannah
// IO Expander Class for SX1509
class IoExpander
{
i2cPort = null;
i2cAddress = null;
constructor(port, address)
{
if(port == I2C_12)
{
// Configure I2C bus on pins 1 & 2
hardware.configure(I2C_12);
i2cPort = hardware.i2c12;
}
else if(port == I2C_89)
{
// Configure I2C bus on pins 8 & 9
hardware.configure(I2C_89);
i2cPort = hardware.i2c89;
}
else
{
server.log("Invalid I2C port specified.");
}
i2cAddress = address << 1;
}
// Read a byte
function read(register)
{
local data = i2cPort.read(i2cAddress, format("%c", register), 1);
if(data == null)
{
server.log("I2C Read Failure");
return -1;
}
return data[0];
}
// Write a byte
function write(register, data)
{
i2cPort.write(i2cAddress, format("%c%c", register, data));
}
// Write a bit to a register
function writeBit(register, bitn, level)
{
local value = read(register);
value = (level == 0)?(value & ~(1<<bitn)):(value | (1<<bitn));
write(register, value);
}
// Write a masked bit pattern
function writeMasked(register, data, mask)
{
local value = read(register);
value = (value & ~mask) | (data & mask);
write(register, value);
}
// Set a GPIO level
function setPin(gpio, level)
{
writeBit(gpio>=8?0x10:0x11, gpio&7, level?1:0);
}
// Set a GPIO direction
function setDir(gpio, output)
{
writeBit(gpio>=8?0x0e:0x0f, gpio&7, output?0:1);
}
// Set a GPIO internal pull up
function setPullUp(gpio, enable)
{
writeBit(gpio>=8?0x06:0x07, gpio&7, enable);
}
// Set GPIO interrupt mask
function setIrqMask(gpio, enable)
{
writeBit(gpio>=8?0x12:0x13, gpio&7, enable);
}
// Set GPIO interrupt edges
function setIrqEdges(gpio, rising, falling)
{
local addr = 0x17 - (gpio>>2);
local mask = 0x03 << ((gpio&3)<<1);
local data = (2*falling + rising) << ((gpio&3)<<1);
writeMasked(addr, data, mask);
}
// Clear an interrupt
function clearIrq(gpio)
{
writeBit(gpio>=8?0x18:0x19, gpio&7, 1);
}
// Get a GPIO input pin level
function getPin(gpio)
{
return (read(gpio>=8?0x10:0x11)&(1<<(gpio&7)))?1:0;
}
}
// RGB LED Class
class RgbLed extends IoExpander
{
// IO Pin assignments
pinR = null;
pinG = null;
pinB = null;
constructor(port, address, r, g, b)
{
base.constructor(port, address);
// Save pin assignments
pinR = r;
pinG = g;
pinB = b;
// Disable pin input buffers
writeBit(pinR>7?0x00:0x01, pinR>7?(pinR-7):pinR, 1);
writeBit(pinG>7?0x00:0x01, pinG>7?(pinG-7):pinG, 1);
writeBit(pinB>7?0x00:0x01, pinB>7?(pinB-7):pinB, 1);
// Set pins as outputs
writeBit(pinR>7?0x0E:0x0F, pinR>7?(pinR-7):pinR, 0);
writeBit(pinG>7?0x0E:0x0F, pinG>7?(pinG-7):pinG, 0);
writeBit(pinB>7?0x0E:0x0F, pinB>7?(pinB-7):pinB, 0);
// Set pins open drain
writeBit(pinR>7?0x0A:0x0B, pinR>7?(pinR-7):pinR, 1);
writeBit(pinG>7?0x0A:0x0B, pinG>7?(pinG-7):pinG, 1);
writeBit(pinB>7?0x0A:0x0B, pinB>7?(pinB-7):pinB, 1);
// Enable LED drive
writeBit(pinR>7?0x20:0x21, pinR>7?(pinR-7):pinR, 1);
writeBit(pinG>7?0x20:0x21, pinG>7?(pinG-7):pinG, 1);
writeBit(pinB>7?0x20:0x21, pinB>7?(pinB-7):pinB, 1);
// Set to use internal 2MHz clock, linear fading
write(0x1e, 0x50);
write(0x1f, 0x10);
// Initialise as inactive
setLevels(0, 0, 0);
setPin(pinR, 0);
setPin(pinG, 0);
setPin(pinB, 0);
}
// Set LED enabled state
function setLed(r, g, b)
{
if(r != null) writeBit(pinR>7?0x20:0x21, pinR&7, r);
if(g != null) writeBit(pinG>7?0x20:0x21, pinG&7, g);
if(b != null) writeBit(pinB>7?0x20:0x21, pinB&7, b);
}
// Set red, green and blue intensity levels
function setLevels(r, g, b)
{
if(r != null) write(pinR<4?0x2A+pinR*3:0x36+(pinR-4)*5, r);
if(g != null) write(pinG<4?0x2A+pinG*3:0x36+(pinG-4)*5, g);
if(b != null) write(pinB<4?0x2A+pinB*3:0x36+(pinB-4)*5, b);
}
}
// Construct an LED
led <- RgbLed(I2C_89, 0x3E, 7, 5, 6);
// Enable the LED outputs and start color changing
led.setLed(1, 1, 1);
led.setLevels(20,20,20);
// Convert Hex to Int
function Hex2RGB(hexStr){
try{
local vString = hexStr.tostring().toupper();
local hexChars = "0123456789ABCDEF";
// Make sure it's 6 digits long
if(vString.len() == 6){
// Return the new colors
return [ (hexChars.find(vString[0].tochar())*16) + hexChars.find(vString[1].tochar()),
(hexChars.find(vString[2].tochar())*16) + hexChars.find(vString[3].tochar()),
(hexChars.find(vString[4].tochar())*16) + hexChars.find(vString[5].tochar()) ];
}
} catch(ex){
server.error(ex);
}
return [0, 0, 0]
}
function readvals(){
imp.wakeup(10, readvals);
agent.send("read", ["data", "led"]);
}
function readresp(data){
local datastring = "";
foreach(alias, value in data){
datastring = datastring + " { " + alias + ": " + value + " }, ";
}
try{
if(data.led != null){
if(data.led == "1"){
led.setLevels(20,20,20);
}
else if(data.led.len() == 6){
local rgb = Hex2RGB(data.led);
led.setLevels(rgb[0],rgb[1],rgb[2]);
}
else{
server.error("Unknown LED Value: "+data.led)
}
}
}catch(ex){
led.setLevels(0,0,0);
server.error(ex);
}
}
// Register Read Response with Agent
agent.on("readresp", readresp);
// Start capturing temperature
capture();
readvals();
// End of code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment