Document API with Literate Coffeescript

This commit is contained in:
Andrew Stewart 2013-11-05 15:10:53 -08:00
parent 3cfc1927fa
commit d184528312
3 changed files with 175 additions and 135 deletions

70
dist/api.js vendored
View File

@ -1,20 +1,12 @@
/*
* api
* cylonjs.com
*
* Copyright (c) 2013 The Hybrid Group
* Licensed under the Apache 2.0 license.
*/
(function() {
'use strict';
var express, namespace;
express = require('express.io');
namespace = require('node-namespace');
namespace("Api", function() {
namespace('Api', function() {
return this.Server = (function() {
var master;
@ -55,34 +47,36 @@
return _results;
})());
});
this.server.get("/robots/:robotid", function(req, res) {
return master.findRobot(req.params.robotid, function(err, robot) {
this.server.get("/robots/:robotname", function(req, res) {
return master.findRobot(req.params.robotname, function(err, robot) {
return res.json(err ? err : robot.data());
});
});
this.server.get("/robots/:robotid/devices", function(req, res) {
return master.findRobot(req.params.robotid, function(err, robot) {
this.server.get("/robots/:robotname/devices", function(req, res) {
return master.findRobot(req.params.robotname, function(err, robot) {
return res.json(err ? err : robot.data().devices);
});
});
this.server.get("/robots/:robotid/devices/:deviceid", function(req, res) {
var deviceid, robotid, _ref;
_ref = [req.params.robotid, req.params.deviceid], robotid = _ref[0], deviceid = _ref[1];
return master.findRobotDevice(robotid, deviceid, function(err, device) {
this.server.get("/robots/:robotname/devices/:devicename", function(req, res) {
var devicename, params, robotname;
params = [req.params.robotname, req.params.devicename];
robotname = params[0], devicename = params[1];
return master.findRobotDevice(robotname, devicename, function(err, device) {
return res.json(err ? err : device.data());
});
});
this.server.get("/robots/:robotid/devices/:deviceid/commands", function(req, res) {
var deviceid, robotid, _ref;
_ref = [req.params.robotid, req.params.deviceid], robotid = _ref[0], deviceid = _ref[1];
return master.findRobotDevice(robotid, deviceid, function(err, device) {
this.server.get("/robots/:robotname/devices/:devicename/commands", function(req, res) {
var devicename, params, robotname;
params = [req.params.robotname, req.params.devicename];
robotname = params[0], devicename = params[1];
return master.findRobotDevice(robotname, devicename, function(err, device) {
return res.json(err ? err : device.data().commands);
});
});
this.server.post("/robots/:robot/devices/:device/commands/:command", function(req, res) {
var commandid, deviceid, key, params, robotid, value, _ref;
params = [req.params.robot, req.params.device, req.params.command];
robotid = params[0], deviceid = params[1], commandid = params[2];
this.server.post("/robots/:robot/devices/:device/commands/:commandname", function(req, res) {
var commandname, devicename, key, params, robotname, value, _ref;
params = [req.params.robotname, req.params.devicename, req.params.commandname];
robotname = params[0], devicename = params[1], commandname = params[2];
params = [];
if (typeof req.body === 'object') {
_ref = req.body;
@ -91,36 +85,38 @@
params.push(value);
}
}
return master.findRobotDevice(robotid, deviceid, function(err, device) {
return master.findRobotDevice(robotname, devicename, function(err, device) {
var result;
if (err) {
return res.json(err);
}
result = device[commandid].apply(device, params);
result = device[commandname].apply(device, params);
return res.json({
result: result
});
});
});
this.server.get("/robots/:robotid/connections", function(req, res) {
return master.findRobot(req.params.robotid, function(err, robot) {
this.server.get("/robots/:robotname/connections", function(req, res) {
return master.findRobot(req.params.robotname, function(err, robot) {
return res.json(err ? err : robot.data().connections);
});
});
this.server.get("/robots/:robot/connections/:connection", function(req, res) {
var connectionid, robotid, _ref;
_ref = [req.params.robot, req.params.connection], robotid = _ref[0], connectionid = _ref[1];
return master.findRobotConnection(robotid, connectionid, function(err, connection) {
var connectionname, params, robotname;
params = [req.params.robot, req.params.connection];
robotname = params[0], connectionname = params[1];
return master.findRobotConnection(robotname, connectionname, function(err, connection) {
return res.json(err ? err : connection.data());
});
});
this.server.get("/robots/:robotid/devices/:deviceid/events", function(req, res) {
this.server.get("/robots/:robotname/devices/:devicename/events", function(req, res) {
return req.io.route('events');
});
return this.server.io.route('events', function(req) {
var deviceid, robotid, _ref;
_ref = [req.params.robotid, req.params.deviceid], robotid = _ref[0], deviceid = _ref[1];
return master.findRobotDevice(robotid, deviceid, function(err, device) {
var devicename, params, robotname;
params = [req.params.robotname, req.params.devicename];
robotname = params[0], devicename = params[1];
return master.findRobotDevice(robotname, devicename, function(err, device) {
if (err) {
req.io.respond(err);
}

View File

@ -1,91 +0,0 @@
###
* api
* cylonjs.com
*
* Copyright (c) 2013 The Hybrid Group
* Licensed under the Apache 2.0 license.
###
express = require('express.io')
namespace = require 'node-namespace'
namespace "Api", ->
# The Cylon API Server provides an interface to communicate with master class
# and retrieve information about the robots being controlled.
class @Server
master = null
constructor: (opts = {}) ->
@host = opts.host || "127.0.0.1"
@port = opts.port || "3000"
master = opts.master
@server = express().http().io()
@server.set 'name', 'Cylon API Server'
@server.use(express.bodyParser())
@server.get "/*", (req, res, next) ->
res.set 'Content-Type', 'application/json'
do next
do @configureRoutes
@server.listen @port, @host, =>
Logger.info "#{@server.name} is listening at #{@host}:#{@port}"
configureRoutes: ->
@server.get "/robots", (req, res) ->
res.json (robot.data() for robot in master.robots())
@server.get "/robots/:robotid", (req, res) ->
master.findRobot req.params.robotid, (err, robot) ->
res.json if err then err else robot.data()
@server.get "/robots/:robotid/devices", (req, res) ->
master.findRobot req.params.robotid, (err, robot) ->
res.json if err then err else robot.data().devices
@server.get "/robots/:robotid/devices/:deviceid", (req, res) ->
[robotid, deviceid] = [req.params.robotid, req.params.deviceid]
master.findRobotDevice robotid, deviceid, (err, device) ->
res.json if err then err else device.data()
@server.get "/robots/:robotid/devices/:deviceid/commands", (req, res) ->
[robotid, deviceid] = [req.params.robotid, req.params.deviceid]
master.findRobotDevice robotid, deviceid, (err, device) ->
res.json if err then err else device.data().commands
@server.post "/robots/:robot/devices/:device/commands/:command", (req, res) ->
params = [req.params.robot, req.params.device, req.params.command]
[robotid, deviceid, commandid] = params
params = []
if typeof req.body is 'object'
params.push(value) for key, value of req.body
master.findRobotDevice robotid, deviceid, (err, device) ->
if err then return res.json err
result = device[commandid](params...)
res.json result: result
@server.get "/robots/:robotid/connections", (req, res) ->
master.findRobot req.params.robotid, (err, robot) ->
res.json if err then err else robot.data().connections
@server.get "/robots/:robot/connections/:connection", (req, res) ->
[robotid, connectionid] = [req.params.robot, req.params.connection]
master.findRobotConnection robotid, connectionid, (err, connection) ->
res.json if err then err else connection.data()
@server.get "/robots/:robotid/devices/:deviceid/events", (req, res) ->
req.io.route 'events'
@server.io.route 'events', (req) ->
[robotid, deviceid] = [req.params.robotid, req.params.deviceid]
master.findRobotDevice robotid, deviceid, (err, device) ->
req.io.respond(err) if err
device.on 'update', (data) ->
req.io.emit 'update', { data: data }

View File

@ -5,14 +5,19 @@ with the currently running robots.
First of all, let's make sure we're running in ECMAScript 5's [strict mode][].
[strict mode]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
'use strict';
## Dependencies
Our server needs to primarily respond to HTTP requests with JSON responses, but
also needs to handle a WebSocket connection to listen for events. To accomodate
both of these requirements, we're going to use [express.io][].
[express.io]: http://express-io.org
express = require 'express.io'
`express.io` integrates some [socket.io][] functionality on top of the popular
@ -20,9 +25,14 @@ both of these requirements, we're going to use [express.io][].
types of connections, and also use Express-style routing to resolve to
a Socket.IO connection.
[socket.io]: http://socket.io
[express]: http://expressjs.com
To keep in line with the rest of Cylon, we'll also be namespacing our API server
with the [node-namespace][] module.
[node-namespace]: https://github.com/kaero/node-namespace
namespace = require 'node-namespace'
## Namespacing
@ -90,11 +100,136 @@ Next up, we run a function to define all our routes (you'll see it in a minute)
And finally, we start our server, announcing so via the Logger.
@server.listen @port, @host, =>
Logger.info "#{@server.name} is listening at #{@host}:#{@port}"
@server.listen @port, @host, =>
Logger.info "#{@server.name} is listening at #{@host}:#{@port}"
[strict mode]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
[express.io]: http://express-io.org
[express]: http://expressjs.com
[socket.io]: http://socket.io
[jnode-namespace]: https://github.com/kaero/node-namespace
## Routes
We'll use the previously referenced `@configureRoutes` function to define our
server's routes.
configureRoutes: ->
### GET /robots
Our first route returns all the Robots the master class knows about in JSON
format.
@server.get "/robots", (req, res) ->
res.json (robot.data() for robot in master.robots())
### GET /robots/:robotname
Given a robot's name, returns JSON information about the requested Robot:
@server.get "/robots/:robotname", (req, res) ->
master.findRobot req.params.robotname, (err, robot) ->
res.json if err then err else robot.data()
### GET /robots/:robotname/devices
Given a robot's name, returns JSON information about the devices belonging to
the requested Robot:
@server.get "/robots/:robotname/devices", (req, res) ->
master.findRobot req.params.robotname, (err, robot) ->
res.json if err then err else robot.data().devices
### GET /robots/:robotname/devices/:devicename
Given the names of a device and the robot it belongs to, returns data on the
specified device.
@server.get "/robots/:robotname/devices/:devicename", (req, res) ->
params = [req.params.robotname, req.params.devicename]
[robotname, devicename] = params
master.findRobotDevice robotname, devicename, (err, device) ->
res.json if err then err else device.data()
### GET /robots/:robotname/devices/:devicename/commands
Given the names of a device and the robot it belongs to, returns all commands
available for the specified device.
@server.get "/robots/:robotname/devices/:devicename/commands", (req, res) ->
params = [req.params.robotname, req.params.devicename]
[robotname, devicename] = params
master.findRobotDevice robotname, devicename, (err, device) ->
res.json if err then err else device.data().commands
### POST /robots/:robotname/devices/:devicename/commands/:commandname
Given a robot name, device name, and command name, executes a robot's command
and returns the result.
@server.post "/robots/:robot/devices/:device/commands/:commandname", (req, res) ->
params = [
req.params.robotname,
req.params.devicename,
req.params.commandname
]
[robotname, devicename, commandname] = params
This parses params from the request body into values that can be used while
calling the command, if params have been supplied.
params = []
if typeof req.body is 'object'
params.push(value) for key, value of req.body
Runs the command on the Robot's device, passing in params as provided.
master.findRobotDevice robotname, devicename, (err, device) ->
if err then return res.json err
result = device[commandname](params...)
res.json result: result
### GET /robots/:robotname/connections
Given a robot's name, returns JSON information about the connections belonging
to the requested Robot:
@server.get "/robots/:robotname/connections", (req, res) ->
master.findRobot req.params.robotname, (err, robot) ->
res.json if err then err else robot.data().connections
### GET /robots/:robotname/connections/:connectionname
Given a robot's name, returns JSON information about the connections belonging
to the requested Robot:
@server.get "/robots/:robot/connections/:connection", (req, res) ->
params = [req.params.robot, req.params.connection]
[robotname, connectionname] = params
master.findRobotConnection robotname, connectionname, (err, connection) ->
res.json if err then err else connection.data()
### GET /robots/:robotname/devices/:devicename/events
Routes to a Socket.IO route to handle WebSockets connections requesting updates
on device events.
@server.get "/robots/:robotname/devices/:devicename/events", (req, res) ->
req.io.route 'events'
### WS_GET /events
A Socket.IO route to handle updating clients whenever a device sends
an 'update' event.
Listens for the 'update' event on a particular Robot's device, and whenever the
device sends the 'update' event, passes the data along to the client.
@server.io.route 'events', (req) ->
params = [req.params.robotname, req.params.devicename]
[robotname, devicename] = params
master.findRobotDevice robotname, devicename, (err, device) ->
req.io.respond(err) if err
device.on 'update', (data) ->
req.io.emit 'update', { data: data }