RIOT API Usage Documentation

RIOT API Usage Documentation
Release 1.0.0
James Steele, Keith Hamilton
Apr 27, 2017
Contents
1
What can Composite be used for?
3
2
Quickstart
5
3
Slowstart
3.1 Installation . . . . . . . . . . . . . . . . . . . . . .
3.1.1
Composite Server . . . . . . . . . . . . . .
3.1.2
Composite Client . . . . . . . . . . . . . .
3.2 Application Landscape . . . . . . . . . . . . . . . .
3.2.1
Major Components . . . . . . . . . . . . .
3.2.2
Update Lifecycle . . . . . . . . . . . . . .
3.3 Configuration . . . . . . . . . . . . . . . . . . . . .
3.3.1
application.properties . . . . . . . . . . . .
3.3.2
couchdb.properties . . . . . . . . . . . . .
3.3.3
rabbitmq.properties . . . . . . . . . . . . .
3.3.4
Test Properties . . . . . . . . . . . . . . .
3.4 Appendices . . . . . . . . . . . . . . . . . . . . . .
3.4.1
Composite Client Command Reference . .
3.4.2
Composite (Backend) Messaging Reference
3.4.3
Composite Model Reference . . . . . . . .
3.4.4
Composite CouchDB View Reference . . .
3.4.5
Composite Demo Reference . . . . . . . .
4
License
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
9
9
10
14
16
16
17
18
18
18
18
23
24
26
27
33
i
ii
RIOT API Usage Documentation, Release 1.0.0
Composite is an end-to-end framework for managing web-scale socket communication between devices in a shared
session, allowing devices to communicate with each other, keep each other up-to-date, and to create a multi-screen,
shared experience for the devices.
Think of it like a post office and a mail carrier in one - anyone connected to it can send messages to it, and it will
deliver messages to anyone for whom the messages are intended. Yes, like the post office, but much, much faster.
Composite’s backend is a Spring-based Java application, that relies on CouchDB for managing temporary data storage,
RabbitMQ for message brokering and StompJS for sending/receiving messages with connected clients.
Composite’s frontend client is a Javascript-based application that relies on StompJS for communicating between client
and server.
Contents
1
RIOT API Usage Documentation, Release 1.0.0
2
Contents
CHAPTER
1
What can Composite be used for?
At Wieden+Kennedy, we have built a few web-scale multiplayer games with Composite, using both the proximitybased pairing and direct-pairing features discussed here, but games are not the only thing it could be used for.
Composite is a very simple thing. It doesn’t know what is happening on the user end, which is its beauty. It only
knows how to send and receive messages to a group of connected devices.
Whatever you can think of that can benefit from real-time multi-device communication can use Composite to manage
the communication stream.
3
RIOT API Usage Documentation, Release 1.0.0
4
Chapter 1. What can Composite be used for?
CHAPTER
2
Quickstart
The easiest way to check out Composite in action is to download and run our Vagrant demo. To do this, you will want
to have both of the following tools installed:
• Vagrant
• Virtual Box
$ wget https://compositeframework.io/static/demo/Vagrantfile
$ vagrant up && vagrant ssh
This will download the Vagrant box, spin it up, and ssh into it. Once inside, you’ll just need to run one more command
to get some docker containers spun up and mapped back to your localhost.
$ sudo composite-demo
This command will import and spin up four Docker containers. While this is working, go grab a beverage of your
choice. The imports can take a few minutes, especially if you’re working on a slower connection.
For each container listed, port mapping goes from container to the Vagrant host to your local machine:
Container
Composite
Database
Message Broker
Web Client
Service
Tomcat
CouchDB
RabbitMQ
NGINX
Mapped port
8080
5984
61613
5000
Once these containers are up, you should be able to hit your system’s address on port 5000 with a mobile device or
a browser in emulation mode to get going. Once you hit localhost:5000 with three devices or browsers in emulation
mode, the demo will start.
The demo is our favorite internet cat, Nyancat, streaming across the screens of the paired devices. Dragging Nyancat
will move it up and down across the screens. Totally simple demo, but shows you that the device screens are linked
via Composite messaging.
5
RIOT API Usage Documentation, Release 1.0.0
6
Chapter 2. Quickstart
CHAPTER
3
Slowstart
Installation
Composite Server
Minimum Requirements
• Tomcat version 7.0.47+
• CouchDB (version 1.5.0 used in production)
• RabbitMQ (current)
Getting the Source
The latest Composite backend can be fetched from github:
$ git clone https://github.com/wieden-kennedy/composite
Setting up CouchDB
OS X
To set up CouchDB on OS X, we suggest you use Homebrew:
$ brew install couchdb
7
RIOT API Usage Documentation, Release 1.0.0
Ubuntu
We have created a setup script that works with Ubuntu 12.04 and 14.04. It’s the easiest way to get CouchDB running:
$ git clone https://gist.github.com/8df5e450f34248ad1679.git couchdb_bootstrap
$ cd couchdb_bootstrap && /bin/bash run.bash
Setting up RabbitMQ
OS X
To set up RabbitMQ on OS X, we suggest you use Homebrew:
$ brew install rabbitmq
Ubuntu
We have created a setup script that works with Ubuntu 12.04 and 14.04. It’s the easiest way to get RabbitMQ running:
$ git clone https://gist.github.com/keithhamilton/f2e20127f52618748266 rabbit_
˓→bootstrap
$ /bin/bash rabbit_bootstrap/run.sh
$ rabbitmq-server start
Building Composite
The project is built using Maven, and is packaged as a war file. When building, the -Denv flag is used to indicate
which environment should be used to build the project.
Profiles
The maven POM is currently configured for building in the following environments:
• local
• dev
• test (i.e., staging)
• prod
• unit
The desired build environment is defined using the -Denv flag, as follows:
`mvn -Denv=local clean package`
The above will build the war using the properties files located in `src/main/classpath/local`.
When building for the `unit` profile (for unit testing), the properties files located in `src/main/test/
resources` will be used.
8
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
Composite Client
Getting the Source
The latest Composite frontend can be fetched from github:
$ git clone https://github.com/wieden-kennedy/composite-client
Using the Client
To use the client, first grab the /build/min/composite.min.js file from the client source, then add the following into the head of your HTML document:
<script src="/path/to/composite.min.js"></script>
Building with Gulp
To build the client from source, you will need to first have the following installed:
• Nodejs + NPM
• Git
• Gulp
Once these are installed, building the client is easy:
$ git clone https://github.com/wieden-kennedy/composite-client
$ cd composite-client
$ npm install
This will build the human-readable build/dev/composite.js file and the production-ready build/min/
composite.min.js file.
You can also compile on save with gulp watch
Autobuild (OS X + Ubuntu)
We’ve created an autobuild script you can use to get the client and build it, which can be run thusly:
$ wget https://raw.github.com/wieden-kennedy/composite-client/master/autobuild.sh
$ /bin/bash autobuild.sh
Autobuilding is supported on Ubuntu and OS X, but if you are running a different Debian flavor, you can attepmt to
force the autobuild to run by adding the --force flag:
$ wget https://raw.github.com/wieden-kennedy/composite-client/master/autobuild.sh
$ /bin/bash autobuild.sh --force
Application Landscape
This section describes the general application landscape and event chain for a Composite application.
3.2. Application Landscape
9
RIOT API Usage Documentation, Release 1.0.0
Major Components
Four major components are part of the Composite application landscape:
• a group of mobile phones
• a Tomcat server
• a RabbitMQ message broker server
• a CouchDB NoSQL database server
Ways to Join a Session
Composite supports two main ways of joining into a session:
• Proximity-based: devices are paired up with other devices in their proximity to create a shared session. In this
mode, the session can have many devices, but is by default limited to eight.
• Direct pairing: devices are paired with the next available device for a shared session. In this mode, typically
the session will be limited to two devices.
The key difference between proximity-based pairing and direct pairing is that in the former location information is
used to prioritize which session a new device is paired with, whereas with latter, the first available open session is used
for pairing. This difference occurs in step 2 below.
10
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
1. Registering with the server
Three discrete sub-steps are involved here, denoted 1, 1a, and 1b respectively.
• Firstly, on mobile phone A, a Composite-driven web application is loaded in the browser. Once the user has
approved the use of location services, the phone will try to make contact with the application server via Sockjs
protocol (1).
• Next, the application server has acknowledged the device, and sent it a subscription id for sending and receiving
socket messages (1a).
• Lastly, the phone again contacts the application server to say “I want to join a session.” (1b)
3.2. Application Landscape
11
RIOT API Usage Documentation, Release 1.0.0
2. The application server checks for existing sessions
The application server takes the phone’s geolocation and uses a Haversine function to determine whether any existing,
open sessions are within a tolerated radius of the new phone. If an open session is found, the new phone is added to it,
otherwise, a new session is created. The first and second steps in this process differs depending on the type of pairing
being performed:
For proximity-based pairing:
• First, it queries the CouchDB database for all unlocked (open) sessions (2).
• Next, it receives a list of open sessions back from the database, then either adds the new phone to an existing
open session, if one is found within the tolerated range, or creates a new one, if no open sessions are found that
are close enough (2a).
For direct pairing:
• First, the application server queries the database for one open session (it doesn’t care which) (2).
• Second, if it finds an open session, it adds the new phone to that session. If it does not find an open session, a
new session is created (2a).
In either pairing scenario, lastly the application server will:
• Update the CouchDB database either with the new session, or the updated session that was found (2b).
12
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
3. Pushing the message to the broker
With the phone added to a session, a socket message is pushed to the broker for delivery to the correct subscriber
queue, which is the individual phone’s queue. Other devices in the same session are notified via a topic channel that a
new device has joined (see section 5 below, *Update lifecycle*)
4. Device is notified it is part of a session
Once the device has been recorded in a session and subscribed to that session’s topic, the messaging broker proxies a
message through the Application Server, to the device’s queue letting the device know it’s part of a session.
This process is repeated each time a new phone joins a session.
3.2. Application Landscape
13
RIOT API Usage Documentation, Release 1.0.0
Update Lifecycle
Once devices are in a session, the update cycle begins, where the devices send an update message to the application
server at a rate of 20 messages per second. These updates are then pushed back out on the session’s topic channel, so
that all of the devices in the session are updated with instructions from each other.
5. An update is sent
As an example, let’s consider a situation in which a ball is moving across the screens in session. It would be helpful
for each device to know if the ball was about to enter its screen, so on the client side, an update message containing
the ball position should be fired periodically.
Here the second device is sending an update to the server.
14
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
6. The session record is updated
Before sending the update message on to the broker, the application server updates the database record for the device’s
session. This helps distinguish stale sessions from active ones by updating a lastUpdated timestamp.
7. Pushing the message to the broker
The application then forwards the update message on to the message broker for queueing.
3.2. Application Landscape
15
RIOT API Usage Documentation, Release 1.0.0
8. Broadcasting the message
The update message is sent out to the session topic, so that all session devices are updated with the new information.
Now they all know where the ball is relative to their screens, and if they need to do anything.
Configuration
Composite is set up to be built for local, development, test, and production environments by means of configuration
properties. Each environment has its own set of configuration/properties files, and they can be found in one of two
locations:
• src/main/resources/.
• pom.xml
In each of the properties files, defaults have been left in place, and context-specific values have been omitted.
application.properties
This is where global application settings are stored, such as maximium distance between two devices that should be
considered to be in the same session. Properties that can be edited in this file are:
16
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
Global Composite Properties
Property
staleSessionMinutes
minDistanceThresholdBetweenDevices
maxDistanceThresholdBetweenDevices
Set in
Description
applicathe number of minutes after which a session should be considered stale and
tion.properties
eligible for deletion
applicathe preferred maximum distance between devices that should be considered in
tion.properties
the same session. When a new device contacts the server, this distance will be
checked to find sessions within this range that the device may join.
applicathe maximum distance between devices that should be considered to be in the
tion.properties
same session. This distance will be used to find a session when a device
connects, and no sessions are found within the preferred maximum distance
range are found.
regex.applicationId applicaa regex pattern containing all apps running on a Composite instance, e.g.,
tion.properties
*regex.applicationId=(appOne|appTwo)
deleteUnhealthyapplicawhether to delete unhealthy devices from the database when the periodic
Devices
tion.properties
cleanup task runs.
Application-Specific Properties
Property
Set in
Description
apapplicathe name of the application
pId.applicationIdtion.properties
apapplicathe maximum number of devices that can exist in a session
pId.maxDevicesPerSession
tion.properties
apapplicacomma-separated list of names identifying rooms assigned to sessions. Room
pId.roomNames tion.propertiesnames do not have any bearing on session activity and are used to distinguish
between multiple sessions in close proximity.
couchdb.properties
This is where global settings for the CouchDB connection will be defined, such as host, port, and maximum number
of connections. Properties that can be edited in this file are:
Property
couchdb.host
couchdb.port
couchdb.username
Set in
pom.xml
application.properties
pom.xml
couchdb.password
pom.xml
couchdb.max.connections
application.properties
couchdb.createdb.if- applicanot-exist
tion.properties
couchdb.protocol
application.properties
couchdb.sessions.database.name
application.properties
3.3. Configuration
Description
the host IP or DNS name for the CouchDB server
the port CouchDB is served over
the username used to connect to a CouchDB database that is password
protected. Can be blank if not needed.
the password used to conenct to a CouchDB database that is password
protected. Can be blank if not needed.
the maximum number of connections to allow in the connection pool.
whether to create databases if they do not already exist when the
application first connects to the CouchDB host.
the protocol to use when connecting to the CouchDB database.
the name of the database where session information will be stored.
17
RIOT API Usage Documentation, Release 1.0.0
rabbitmq.properties
This is where global settings for the RabbitMQ broker can be configured, such as host, port, and login. Properties that
can be edited in this file are:
Property
rabbitmq.host
rabbitmq.port
rabbitmq.clientLogin
Set in
pom.xml
rabbitmq.properties
pom.xml
rabbitmq.clientPasscode
pom.xml
rabbitmq.systemLogin
pom.xml
rabbitmq.systemPasscode
pom.xml
rabrabbitmq.systemHeartbeatSendInterval
bitmq.properties
rabrabbitmq.systemHeartbeatReceiveInterval
bitmq.properties
rabbitmq.heartbeatTime
rabbitmq.properties
rabrabbitmq.inboundChannelCorePoolSize
bitmq.properties
rabrabbitmq.outboundChannelCorePoolSize
bitmq.properties
rabrabbitmq.brokerChannelCorePoolSizebitmq.properties
rabbitmq.sendTimeLimit
rabbitmq.properties
rabbitmq.sendBufferSizeLimit rabbitmq.properties
rabbitmq.messageSizeLimit
rabbitmq.properties
Description
the host IP or DNS name for the RabbitMQ server.
the port RabbitMQ is served over
the login name used for the RabbitMQ broker. Can be left
blank if not needed.
the password used for the RabbitMQ broker. Can be left
blank if not needed.
the login name used for the RabbitMQ host system.Can be
left blank if not needed.
the password used for the RabbitMQ host system. Can be
left blank if not needed.
interval, in milliseconds, on which to send a heartbeat
interval, in milliseconds, on which to receive heartbeats
heartbeat interval, in milliseconds, for the Stomp client to
send on
initial number of executor threads for inbound message
processing
initial number of executor threads for outbound message
processing
initial number of executor threads for broker message
processing.
the message timeout value in milliseconds
the maximum number of bytes to buffer when sending
messages in KB.
the maximum message size in KB
Test Properties
The same three properties files are available for unit tests as well, under src/test/resources. Unlike the main
run configuration files, however, the test files have all of their values set in the actual files, not in the pom.
By default, the CouchDB and RabbitMQ hosts are listed as localhost. Update these accordingly, if needed.
Appendices
Composite Client Command Reference
This is a companion guide for using the Composite Client, found here.
Methods
18
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
Constructor
The global Composite constructor. Takes no config options and is used for instantiation purposes.
var app = new Composite();
connect:function (string:url)
Connects to the Composite service. The handshake is over HTTP, so a good example would be:
app.connect('http://localhost:8081/composite');
on:function (string:event, function:callback)
Registers an event handler for a given event.
app.on('app_start', function(){ start_your_app(); });
The following are valid events (Automatic denotes that the event is triggered internally, whilst Manual requires a
client-triggered action):
Property
init
synced
Description
Fires after a successful connect and a valid UUID has been assigned. Automatic.
Fires once the app has determined the average latency between it and the service.
Automatic.
app_start
Fires after the host device in the same session queries the start endpoint. Manual.
app_end
Fires after the host device in the same session queries the end endpoint. Manual.
session_joined
Fires after a successful join query and only to the client that queried it. Manual.
device_update
Fires after a new device has joined the session. Manual
device_disconnect Fires if a device in the session suddenly disconnects. Manual.
data
Fires when a client sends a payload to the data endpoint. Manual.
update
Fires when a client sends a payload to the update endpoint. Manual.
off:function (string:event, function:callback)
Removes an event handler for a given event.
app.off('app_start', function(){ start_your_app(); }); // Must pass the function you
˓→called earlier
3.4. Appendices
19
RIOT API Usage Documentation, Release 1.0.0
syncTime:function
Sends a message to the service with the current time in order to determine latency. This also happens automatically,
but is exposed in case your application needs to check more frequently.
app.syncTime()
join:function (object)
Sends a join request to the service to get a session, requires that the client has already set its location (lat/lon) under
the location array (see location).
The Object passed can have the following parameters: - type: String ‘enter’ or ‘exit’. Defaults to ‘exit’. - geo: Array
with two elements corresponding to a devices longitude/latitude. Defaults to the local lon/lat if not present.
app.join({type: 'exit', geo: [0.1234123, 1.123123]});
sendData:function (object)
Sends a message to all clients in the same session with a data payload. The passed object is the payload you wish to
send to all clients. Requires that clients have ‘‘join‘‘ed successfully prior to sending.
app.sendData({ ballPosition: [103, 234], ballSpeed: 23, activeDevice: 2 });
sendUpdate:function (object)
Sends a message to all clients in the same session with a data payload. The passed object is the payload you wish to
send to all clients. Requires that clients have ‘‘join‘‘ed successfully prior to sending.
app.sendUpdate({ ballPosition: [103, 234], ballSpeed: 23, activeDevice: 2 });
startApp:function
Triggers the app_start event in all other clients. Must be the “host” client to trigger (see host below).
app.startApp()
endApp:function
Triggers the app_end event in all the other clients. Must be the “host” client to trigger (see host below).
20
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
app.endApp();
disconnect:function
Disconnects cleanly from the Composite service. Other clients in the same session will be notified of the disconnect.
app.disconnect()
Properties
connected
Type: boolean
Container indicating if the client is connected to the composite service.
app.connected; // true if connected, false if not
uuid
Type: string
The UUID of the device given from the service, can be used as a way to find the device(s) order.
app.uuid; // "7040550a-3834-4974-a19c-c7d39749a7e5"
timeDifference
Type: number
The median time difference between the client’s Date.now and the services Date.now.
app.timeDifference; // 1121
latency
Type: number (milliseconds)
The average time it takes to send and receive a message through composite. Updated periodically throughout the
application.
3.4. Appendices
21
RIOT API Usage Documentation, Release 1.0.0
app.latency; // 10
host
Type: boolean
If the device is the host device. This is determined by order join``ed, and the first device to join
is given ``host privileges. This is updated during the device_update event as it’s possible for the host to
drop connection. host``s can trigger the ``app_start and app_end events.
app.host; // true
location
Type: array[float]
The container for the devices geographic position in the form of [{latitude}, {longitude}]. Location is
not captured automatically, and must be implemented manually, and is used for session management.
Example:
navigator.geolocation.getCurrentPosition(function(position) {
// Setting the position
app.location = [position.coords.latitude, position.coords.longitude];
});
app.location; // [45.523452, -122.67620699999999]
session
Type: string
The session the device is currently a part of. This is set automatically after successfully join``ing, and is
required when broadcasting ``update``s and ``data.
app.session; // "7040550a-3834-4974-a19c-c7d39749a7e5"
active
Type: boolean If the app is currently in the start state. This happens automatically after the app_start event
and is set to false after the app_end event.
app.active; // true
22
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
Composite (Backend) Messaging Reference
Endpoints
/init
Direct message handler for an init message sent by a device. The init message will follow directly after the device
has made a successful socket connection to the server, and indicates that the device would like to start interacting with
Composite.
Parameters
principal
Description
The device principal that sent the request
Returns to: /queue/device
/join
Direct message handler that receives a join message from a device. When a device joins, a session is attempted to be
found within a tolerated geo-proximity. if one is found, the device is added to it and returned, if not, a new session is
created.
Params
Parameters
j
Description
Stringified JoinMessage sent from the device seeking to join a session
Returns to: /queue/device
/sync
Direct message handler for assisting connected devices in calculating the latency between when messages are sent by
the server and when they are received by the client. Each client should hit this endpoint a number of times just after
the initial connect response is received, and will calculate an average latency time based off of the server responses.
Params
Parameters
s
Description
Stringified SyncMessage sent by client device
Returns to: /queue/device
/{id}
Multiplex handler inbound messages from session devices that are sent to the session topic channel. Uses the following
handlers to determine what information to broadcast back across the session topic:
Handler
update
data
start
stop
devices
Description
Broadcasts an update response back to the session when a device principal sends an update
Broadcasts a data response back to the session when a device principal sends a data message
Broadcasts a start event back to the session when a device principal initiates a start event
Broadcasts a stop event back to the session when a device principal initiates a stop event
Broadcasts a list of devices found in a session back to the session topic
3.4. Appendices
23
RIOT API Usage Documentation, Release 1.0.0
Parameters
principal
id
obj
Description
Device principle sending the message
UUID of the session to which the inbound message need be returned
Map<String, Object> message data for the endpoint. Contains the type of message that corresponds to
one of the above endpoints as well as arbitrary String:Object pairs that contain the main message body
Returns to: /queue/device
/ping
Message handler that receives a ping from a connected client device, and in turn adds the device to a list of “healthy”
session devices, thereby preventing it from being automatically deleted from the session. If a device fails to ping the
server within a specified timeframe, it will be marked as unhealthy, and subsequently deleted.
Parameters
principal
Description
The device principal that sent the request
Returns to: None. Logs the device in a registry that determines which devices to boot if they do not ping regularly.
/disconnect
Handles disconnect messages sent by a client device by removing the device from its associated session. if there are
still devices in its session, they are notified of the disconnect, otherwise, the session is removed.
Parameters
principal
Description
The device principal that sent the request
Returns to: /topic/{id} where id is the session id to which the device belongs.
Composite Model Reference
Composite keeps track of two objects:
• Sessions
• Devices
The relationship between sessions and devices is one-to-many, and devices are stored in an array in a given session
object.
Session Model
All types given are Java types.
24
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
Member
_id
_rev
devices
geoLocation
inserted
locked
Type
Description
String
CouchDB unique id for the session record.
String
CouchDB revision version for the session record.
ArArray of devices in the session.
rayList<Device>
float[]
Array of lat/lon coordinates for the session location.
long
boolean
long
Unix timestamp of when the session was created.
Indicates if the session is unlocked or not. If locked, no more devices join the
session until it is unlocked.
The name of the “room” for the session. Can be used on the client end to
disambiguate multiple sessions in close proximity.
Unix timestamp for when a session’s activity begun. For example, when a shared
game begins.
Unix timestamp for when a session’s activity ended.
long
UUID
Unix timestamp of the last update to the session object.
Unique identifier for the session.
room
string
sessionStarted
sessionEnded
updated
uuid
long
Device Model
All types given are Java types.
Member
uuid
width
height
performance
instructions
Type
UUID
int
int
int
int
Description
Unique identifier for the device.
Device screen width.
Device screen height.
Figure representing relative performance of device. This property is used on the client-side to
manage screen redrawing.
Figure representing client-side instructions that tell the device what to do within the context
of the session and other devices.
Sample Record (CouchDB)
Records are saved as JSON in the CouchDB instance(s). Below is a sample taken from the Composite Demo app.
{
"_id": "39d4e19c25964bb3a6c3b2f806e8fa33",
"_rev": "3-32d6973d965f40261053b2cfb523212f",
"devices": [
{
"uuid": "5c6f9f63-dc2f-4f4c-81dc-b722eb4b0a1f",
"width": 375,
"height": 667,
"performance": 0,
"instructions": 0
},
{
"uuid": "7c528f92-9223-4802-bede-b8b01e8e5aa6",
"width": 375,
"height": 667,
"performance": 0,
"instructions": 0
},
3.4. Appendices
25
RIOT API Usage Documentation, Release 1.0.0
{
"uuid": "b969d6e3-94f8-4c1a-a8e9-efa7b4b58962",
"width": 375,
"height": 667,
"performance": 0,
"instructions": 0
}
],
"geoLocation": [
45.524426,
-122.68396
],
"inserted": 1412097229725,
"locked": false,
"room": "default_room",
"sessionStarted": 1412097232288,
"sessionEnded": 0,
"updated": 1412097232288,
"uuid": "28171d9c-05e4-422b-9dd9-9e8b8ff84609"
}
Composite CouchDB View Reference
Composite instances use the below views to retrieve documents from the CouchDB database via the SessionRepository
class.
application-id
Used to retrieve sessions by application id. Used when multiple Composite-based applications are working from the
same server or set of resources.
function(doc) {
if(doc.applicationId && !doc.locked){
emit(doc.applicationId, doc)
}
}
locked-sessions
Used to retrieve a list of sessions, keyed by their lock status.
function(doc){
emit(doc.locked, doc)
}
session-by-device
Used to retrieve a set of sessions keyed by device UUID.
function(doc) {
if(doc.devices){
for(var i in doc.devices){
26
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
emit(doc.devices[i].uuid, doc)
}
}
}
session-devices
Used to retrieve a set of devices in a session.
function(doc) {
if(doc.devices){
emit(doc.uuid, doc.devices)
}
}
session-by-timestamp
Used to retrieve a session by its inserted timestamp.
function(doc) {
if(doc.inserted){
emit(doc.inserted, doc)
}
}
uuid
Used to retrieve a session by its UUID.
function(doc) {
if(doc.uuid){
emit(doc.uuid, doc)
}
}
Composite Demo Reference
Architecture
The basic concept behind the Composite demo’s architecture is that of Docker containers on a Vagrant host. Nothing
new.
3.4. Appendices
27
RIOT API Usage Documentation, Release 1.0.0
Each Docker container maps the main service port/s back to the Vagrant host, which in turns forwards those ports up
to the OS host, either a Linux or Mac OS X host. The service port mapping is as follows:
Service
Client (NGINX)
RabbitMQ
CouchDB
Composite
Container < - > Vagrant
5000
61613, 5672
5984
8080
Vagrant < - > OS
5000
61613
5984
8080
Base Container
All above containers are built off of a container called local/base. This container is simply an Ubuntu 14.04
container with some basic tools installed:
• vim
• curl
• wget
• openssh-server
• pip
• puppet
• fabric
Importing Composite Containers
If you followed the quickstart guide, after you got the Vagrant host up and running you ran:
$ sudo composite-demo
The underlying mechanics of this command, if you haven’t already peeked, is simply:
28
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
1. Clone the composite-demo repository.
2. Import the Docker containers from S3.
3. Run the Docker containers, linking appropriately, as indicated in the diagram above.
The underlying mechanism for performing steps two and three is a Fabric file at the root of the composite-demo
repository. It contains the following method for importing the Composite Docker containers:
def import_container(container_name=None):
import_containers = CONTAINERS
if container_name:
import_containers = [x for x in import_containers if x['name'] == container_
˓→name]
for c in import_containers:
container = Container(env.environment, c)
print(_white("==> Importing %s container from S3" % container.name))
local('sudo curl %s | sudo docker import - %s/%s' % (container.s3_path,
env.environment.lower(),
container.name))
Taking this into account, should you want to re-import any or all containers, you can navigate to the composite-demo
directory at /home/vagrant/composite-demo and run one or more of the following commands:
# import client, rabbitmq, couchdb, or composite
$ fab import_container:[client|rabbitmq|couchdb|composite]
# import client container
$ fab import_container:client
# import all containers
$ fab import_container
Note that if you ran the quickstart, and imported the Composite containers, the base container will not be built.
Building Composite Containers
By running sudo composite-demo when bringing up the Vagrant host, you may have run into a prompt to build
the containers locally, in the event that your internet connection was considered too slow to make effective use of
downloading/importing all containers. In this event, the containers would have been individually built using another
Fabric method:
def build(container_name=None):
killall_containers()
build_containers = CONTAINERS
base_container = local("sudo docker images | grep base | awk '{print $1}'",
˓→capture=True)
# if container_name was passed, reduce build_containers to just that container
if container_name:
build_containers = [x for x in build_containers if x['name'] == container_
˓→name]
# if the base container doesn't yet exist, build it
if container_name != 'base' and not base_container == 'local/base':
build('base')
3.4. Appendices
29
RIOT API Usage Documentation, Release 1.0.0
# build the service and composite containers
for c in build_containers:
build_container(c, env.environment)
Similar to fab import, containers can be built all at once or individually:
# build one container
$ fab build:[base|client|rabbitmq|couchdb|composite]
# build client container
$ fab build:client
# build all containers
$ fab build
Fabfile Reference
The import_container and build methods are the most commonly used. Below is a reference of the methods
available to you from within the Fabric file included with the composite-demo1 .
Methods
import_container(container_name=None)
Imports one or more containers from S3 by name.
# import client
$ fab import_container:client
# import rabbitmq
$ fab import_container:rabbitmq
# import couchdb
$ fab import_container:couchdb
# import composite
$ fab import_container:composite
# import all containers
$ fab import_container
build(container_name=None)
Builds one or more containers using the Dockerfiles included in the demo repository.
# build client
$ fab build:client
# build rabbitmq
1 Technically there are more methods available in the Fabric file, but the remaining few methods are used internally, for the most part. To see
the rest, check out the fabfile.
30
Chapter 3. Slowstart
RIOT API Usage Documentation, Release 1.0.0
$ fab build:rabbitmq
# build couchdb
$ fab build:couchdb
# build composite
$ fab build:composite
# build all containers
$ fab build
run()
Runs the Composite demo containers, linking the service containers to the web application container
# run all containers
$ fab run
killall_containers()
Kills and removes all running or exited Docker processes.
# kill and remove all Docker processes
$ fab killall_containers
delete_image(container_name=None)
Deletes one or more container images on the Vagrant host machine.
# delete client
$ fab delete_image:client
# delete rabbitmq
$ fab delete_image:rabbitmq
# delete couchdb
$ fab delete_image:couchdb
# delete composite
$ fab delete_image:composite
# delete all Docker images
$ fab delete_image
3.4. Appendices
31
RIOT API Usage Documentation, Release 1.0.0
32
Chapter 3. Slowstart
CHAPTER
4
License
This repository and its code are licensed under the BSD 3-Clause license, which can be found here.
33