Skip to content

Instantly share code, notes, and snippets.

@metadaddy
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save metadaddy/8ad615a5e740185ffba1 to your computer and use it in GitHub Desktop.
Save metadaddy/8ad615a5e740185ffba1 to your computer and use it in GitHub Desktop.
Run OAuth from the Agent, log 9DOF data from device, including click events
#require "Salesforce.class.nut:1.0.0"
CLIENT_ID <- "CLIENT_ID_GOES_HERE";
CLIENT_SECRET <- "CLIENT_SECRET_GOES_HERE";
LOGIN_HOST <- "login.salesforce.com";
// Uncomment to clear saved OAuth state
//server.save({});
OAUTH <- server.load();
deviceID <- null;
// -----------------------------------------------------------------------------
// Run OAuth web server flow to get access token
function webserver(req, res) {
switch (req.method) {
case "GET":
if ("code" in req.query) {
// We have the OAuth code - exchange it for the access token
local code = req.query["code"];
local request = http.post("https://login.salesforce.com/services/oauth2/token",
{ "Content-Type" : "application/x-www-form-urlencoded" },
"code="+code+"&grant_type=authorization_code&client_id="+CLIENT_ID+"&client_secret="+CLIENT_SECRET+"&redirect_uri="+http.agenturl());
local response = request.sendsync();
if (response.statuscode == 200) {
// All is well - save the OAuth response
OAUTH = http.jsondecode(response.body);
server.log(OAUTH.access_token);
server.save(OAUTH);
server.log("Saved OAuth config");
listenToDevice();
} else {
server.err(response.body);
}
// All done!
res.send(200, "Authentication complete - you may now close this window");
} else {
// We need the OAuth code - redirect to OAuth authorization service
res.header("Location",
"https://"+LOGIN_HOST+"/services/oauth2/authorize?response_type=code&client_id="+CLIENT_ID+"&redirect_uri="+http.agenturl());
res.send(302, "Found");
}
break;
// Any other method is an error
default:
server.log("Method Not Allowed")
res.send(405, "Method Not Allowed");
}
}
// Exchange the refresh token for a new access token
function refresh(cb) {
local request = http.post("https://login.salesforce.com/services/oauth2/token",
{ "Content-Type" : "application/x-www-form-urlencoded" },
"grant_type=refresh_token&client_id="+CLIENT_ID+"&client_secret="+CLIENT_SECRET+"&refresh_token="+OAUTH.refresh_token);
local response = request.sendsync();
if (response.statuscode == 200) {
OAUTH.access_token = http.jsondecode(response.body).access_token;
server.log(OAUTH.access_token);
server.save(OAUTH);
server.log("Refreshed OAuth config");
cb();
} else {
server.err(response.body);
}
}
// Start listening for updates
function listenToDevice() {
force <- Salesforce(CLIENT_ID, CLIENT_SECRET);
// Inject the token and instance URL from the OAuth exchange
force._token = OAUTH.access_token;
force._instanceUrl = OAUTH.instance_url;
device.on("data", function(data) {
// Cook the data for Salesforce
data = {
Acc_X__c = data.acc.x,
Acc_Y__c = data.acc.y,
Acc_Z__c = data.acc.z,
Gyr_X__c = data.gyr.x,
Gyr_Y__c = data.gyr.y,
Gyr_Z__c = data.gyr.z,
Mag_X__c = data.mag.x,
Mag_Y__c = data.mag.y,
Mag_Z__c = data.mag.z,
Temp__c = data.temp
};
server.log(http.jsonencode(data));
force.request("post", "sobjects/Reading__c",
http.jsonencode(data),
function(err, data) {
if (err) {
server.error("ERROR: " + http.jsonencode(err));
return;
}
server.log("Created reading with Id "+data.id);
}
);
});
device.on("impact", function(data) {
server.log("Detected impact on device " + deviceID);
force.request("post", "sobjects/Case",
http.jsonencode({
Subject = "Impact event!",
Description = "Impact detected on device " + deviceID
}),
function(err, data) {
if (err) {
server.error("ERROR: " + http.jsonencode(err));
return;
}
server.log("Created Case with Id "+data.id);
})
});
}
if ("refresh_token" in OAUTH) {
server.log("Loaded OAuth config");
server.log(http.jsonencode(OAUTH));
refresh(listenToDevice);
}
function loadDeviceID () {
local data = server.load();
if ("deviceID" in data) {
deviceID = data.deviceID;
} else {
device.send("getDeviceID", null);
}
server.log("loadDeviceID: deviceID is "+deviceID);
}
function saveDeviceID(id) {
local data = server.load();
if (!("deviceID" in data)) {
data["deviceID"] <- null;
}
data.deviceID = id;
server.save(data);
deviceID = data.deviceID;
server.log("saveDeviceID: deviceID is "+deviceID);
}
device.on("deviceID", saveDeviceID);
loadDeviceID();
http.onrequest(webserver);
#require "lsm9ds0.class.nut:1.1"
agent.on("getDeviceID", function(data) {
agent.send("deviceID", hardware.getdeviceid());
});
// Callback for 'click' events
function xm_int1_cb() {
if (xm_int1.read()) {
if (imu.clickIntActive()) {
agent.send("impact", null);
imp.sleep(1); // Debounce
}
} else {
// interupt cleared, do nothing
}
}
xm_int1 <- hardware.pin2;
i2c <- hardware.i2c89;
i2c.configure(CLOCK_SPEED_400_KHZ);
// Register callback for 'click' events
xm_int1.configure(DIGITAL_IN_PULLDOWN, xm_int1_cb);
// Preproduction tail needs 0x3c for Accelerometer/Magnetometer address,
// rather than the default 0x3a
imu <- LSM9DS0(i2c,0x3c);
// Enable accel at 100 Hz
imu.setEnable_A(1);
imu.setDatarate_A(100);
// Set interrupt 1 polarity to active-high
// Accel/mag interrupts are push-pull by default
// Enable latching on interrupt 1 only
imu.setIntActivehigh_XM();
imu.setInt1LatchEn_XM(1);
// Enable single-click interrupts
imu.setSnglclickIntEn_P1(1);
// Eet click detection threshold to 1.5g
imu.setClickDetThs(1.5);
// Set click window to 16 ms
imu.setClickTimeLimit(16);
// Enable temperature collection
imu.setTempEn(1);
// Send data to the agent every minute
function sendData() {
agent.send("data", {
acc = imu.getAccel(),
mag = imu.getMag(),
gyr = imu.getGyro(),
temp = imu.getTemp()
});
imp.wakeup(60, sendData);
}
sendData();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment