api workshop

21
APIs for your Hardware Electric Imp Matt Haines Community Manager @beardedinventor

Upload: matt-haines

Post on 25-Jan-2015

192 views

Category:

Technology


2 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Api workshop

APIs for your Hardware

Electric Imp

Matt HainesCommunity Manager@beardedinventor

Page 2: Api workshop

● HTTP Handler Deep Dive ● APIs that change hardware states● APIs that read hardware states

What are we doing tonight

Page 3: Api workshop

The Circuit

Page 4: Api workshop

HTTP Handlers

● The HTTP Handler is the code that executes when your agent receives an incoming http request

● Register your handler with: http.onrequest(HTTPHandler)

● http://electricimp.com/docs/api/httphandler/

Page 5: Api workshop

Basic Handlerfunction HTTPHandler(req, resp) {

// ALWAYS WRAP YOUR HANDLERS IN A TRY/CATCH

try {

// "200: OK" is standard return message

resp.send(200, "OK");

} catch (ex) {

// Send 500 response if error occured

resp.send(500, format("Agent Error: %s", ex));

}

}

Page 6: Api workshop

The Request table

method - The method (GET, PUT, POST, etc)path - The HTTP path minus the agentURLquery - Table containing the query parametersbody - The body of the requestheaders - Table containing the request headers

Page 7: Api workshop

Let’s make an APIfunction HTTPHandler(req, resp) {

try {

// "200: OK" is standard return message

logRequest(req);

resp.send(200, "OK");

} catch (ex) {

// Send 500 response if error occured

resp.send(500, format("Agent Error: %s", ex));

}

}

Page 8: Api workshop

function logRequest(req) {

server.log(format("Method: %s", req.method));

server.log(format("Path: %s", req.path));

server.log(format("Body: %s", req.body));

server.log("Query Parameters:");

foreach(k,v in req.query) {

server.log(format("%s: %s", k, v));

}

server.log("Headers:");

foreach(k,v in req.headers) {

server.log(format("%s: %s", k, v));

}

}

Page 9: Api workshop

Let’s make some requests// basic requestcurl "agenturl"

// set the methodcurl -X POST "agenturl"

// set a path and some query parameterscurl -X POST "agenturl/api?led1=1&led2=test"

// set a headercurl -X PUT -H "apikey:123" "agenturl"

// send some data in the bodycurl -X PUT -H "apikey:123" "agenturl" --data "{ \"foo\": \"bar\" }"

Page 10: Api workshop

● Use this information to build powerful APIs:○ path - what resource we’re interacting with○ method - what we’re doing with the resource○ body/query - data we need○ headers - authentication, etc

● Example:

// Get the state of the LEDcurl -X GET "agenturl/led"

// Set the state of the LEDcurl -X GET -H "apikey: 123" "agenturl/led" --data "{ \"state\": 1 }”

So what..

Page 11: Api workshop

APIs to Set Hardware

● When we get a request○ Check the verb○ Check the path○ Validate the data○ Send the data to the device○ Send a response

● When the device gets a message○ Do something with it

Page 12: Api workshop

Simple Device Code// configure hardware

led <- hardware.pin9;

led.configure(DIGITAL_OUT);

// set LED from server

agent.on("setLed", function(state) {

led.write(state);

});

Page 13: Api workshop

Let’s make an API// here's the important bit

local path = req.path.tolower();

if (req.method == "POST") {

if (path == "/led" || path == "/led/") {

if (req.body != null && req.body.len() > 0) {

local data = http.jsondecode(req.body);

if ("state" in data) {

device.send("setLed", data.state.tointeger());

resp.send(200, "OK");

}

}

resp.send(406, "Not Acceptable - Missing 'state'");

}

}

Page 14: Api workshop

// wrong urlcurl -X POST "agenturl"

// proper url, but no datacurl -X POST "agenturl/led"

// proper url, and proper datacurl -X POST "agenturl/led" --data "{ \"state\": 0 }"

Let's make some requests

Page 15: Api workshop

● Two ways to query data from the device:○ Send data from device to agent whenever state

changes (or at regular intervals)○ Make a round trip from agent → device → agent

● First method is easy, and fast, but no guarantee data is up to date

● Second method requires a LOT more code, and adds some time (as we need to make a round trip to the device)

What about reading data

Page 16: Api workshop

Sending Data to the Device// configure hardware

led <- hardware.pin9;

led.configure(DIGITAL_OUT);

function setLed(state) {

led.write(state);

agent.send("ledState", state);

}

agent.on("setLed", setLed);

button <- hardware.pin1;

function buttonStateChange() {

setLed(1-led.read()); // invert state

}

button.configure(DIGITAL_IN_PULLUP, buttonStateChange);

Page 17: Api workshop

Catch and Store Message in AgentledState <- "Unknown";

agent.on("ledState", function(state) {

ledState = state;

}

Page 18: Api workshop

Let's make an API// here's the important bit

if (req.method == "GET") {

if (path == "/led" || path == "/led/") {

resp.send(200, http.jsonencode({state = ledState}));

}

}

Page 19: Api workshop

Let's make some requests

// wrong urlcurl -X GET "agenturl"

// proper urlcurl -X GET "agenturl/led"

Page 20: Api workshop

What about security

● All communication is HTTPS● Agent URLs can't be crawled● There are 6412 so guessing them is.. hard ● Security by obscurity● API Keys● Basic Auth● HMAC-SHA Signatures

Page 21: Api workshop

What's Next

● Write webpages or apps to interact with API

● Try implementing some of the auth methods● Class to handle/delegate incoming requests

● Long polling● Serve HTML pages from HTTP Handler