Socket.IO Tutorial
This page explains how an app can use the Flare Socket.IO API to discover and interact with things in an environment.
The API tab gives generic examples of how you can exchange JSON messages with the server using a Socket.IO client library on your platform of choice.
The JavaScript, Swift and Java tabs give higher-level examples that show how you can use the Flare platform libraries to do the same thing.
Device setup
Get info
GET /environments/123/devices/234
getDevice(environment_id, device_id, function(info) {
device = info;
document.title = device.name
$("input#name").val(device.name);
$("input#description").val(device.description);
});
flareManager.getDevice(deviceId, environmentId: environment.id} {
(json: JSONDictionary) -> () in
let device = Device(json: json)
}
flareManager.getDevice(deviceId, environment.getId(), (json) -> {
this.device = new Device(json);
});
The device client makes a REST API call to the server to get information about the device.
Response
{
"environment": "123",
"_id": "234",
"name": "Andrew's iPhone",
"description": "iPhone 6 (32 GB)",
"data": {
"angle": 60
},
"position": {
"x": 2,
"y": 1
}
}
The server's response contains the name, description, etc. for the device.
Subscribe
subscribe {"device":"234"}
subscribe({device:device_id});
flareManager.subscribe(device)
flareManager.subscribe(device);
The client then subscribes to the device so that it will receive any notifications about it.
Get data
getData {"device":"234"}
getData({device:device_id});
flareManager.getData(device)
flareManager.getData(device);
Then it requests the most recent data.
Data message
data {"device":"234", "data":{"angle": 60}}
function gotData(message) {
if (message.device == device_id) {
var data = message.data;
for (key in data) {
var value = data[key];
var input = $("input#" + key);
input.val(value);
}
}
}
func didReceiveData(flare: Flare, data: JSONDictionary) {
if flare == selectedFlare {
if let angle = data["angle"] as? Double {
angleField.doubleValue = angle
}
}
}
public void didReceiveData(Flare flare, JSONObject data) {
if (flare == selectedFlare) {
double angle = data.getDouble("angle");
}
}
The server replies by sending back the data.
Get position
getPosition {"device":"234"}
getPosition({device:device_id});
flareManager.getPosition(device)
flareManager.getPosition(device);
The client requests the most recent position.
Position message
position {"device":"234", "position":{"x":2, "y":1}}
function gotPosition(message) {
if (message.device == device_id) {
currentPosition = message.position;
$("input#x").val(currentPosition.x);
$("input#y").val(currentPosition.y);
}
}
func didReceivePosition(flare: Flare, position: CGPoint) {
if flare == selectedFlare {
xField.doubleValue = Double(position.x)
yField.doubleValue = Double(position.y)
}
}
public void didReceivePosition(Flare flare, PointF position) {
if flare == selectedFlare {
double x = position.x;
double y = position.y;
}
}
The server replies by sending back the position.
Thing setup
Get info
GET /environments/123/zones/456/things/789
getThing(environment_id, zone_id, thing_id, function(info) {
thing = info;
document.title = thing.name
$("input#name").val(thing.name);
$("input#description").val(thing.description);
});
flareManager.getThing(thingId, environmentId: environment.id, zoneId: zone.id} {
(json: JSONDictionary) -> () in
let thing = Thing(json: json)
}
flareManager.getThing(thingId, zone.getId(), environment.getId(), (json) -> {
this.thing = new Thing(json);
});
The thing client makes a REST API call call to the server to get information about the thing.
Response
{
"environment": "123",
"zone": "456"
"_id": "789",
"name": "Window",
"description": "In traditional Japanese architecture,
a shÅji (éšœå) is a door, window or room divider
consisting of translucent paper over a lattice of bamboo.",
"data": {
"brightness": 0.7,
"color": "blue"
},
"position": {
"x": 10,
"y": 0
}
}
The server's response contains the name, description, etc. for the thing.
Subscribe
subscribe {"thing":"789"}
subscribe({thing:thing_id});
flareManager.subscribe(thing)
flareManager.subscribe(thing);
The client then subscribes to the thing so that it will receive any notifications about it.
Get data
getData {"thing":"789"}
getData({thing:thing_id});
flareManager.getData(thing)
flareManager.getData(thing);
Then it requests the most recent data.
Data message
data {"thing":"789", "data":{"brightness":0.7, "color":"blue"}}
func didReceiveData(flare: Flare, data: JSONDictionary) {
if flare == selectedFlare {
if let color = data["color"] as? String {
colorField.stringValue = color
}
if let brightness = data["brightness"] as? Double {
brightnessField.doubleValue = brightness
}
}
}
public void didReceiveData(Flare flare, JSONObject data) {
if (flare == selectedFlare) {
String color = data.getString("color");
double brightness = data.getDouble("brightness");
}
}
The server replies by sending back the data.
Get position
getPosition {"thing":"789"}
getPosition({thing:thing_id});
flareManager.getPosition(thing)
flareManager.getPosition(thing);
The client requests the most recent position.
Position message
position {"thing":"789", "position":{"x":10, "y":0}}
function gotPosition(message) {
if (message.thing == thing_id) {
currentPosition = message.position;
$("input#x").val(currentPosition.x);
$("input#y").val(currentPosition.y);
}
}
func didReceivePosition(flare: Flare, position: CGPoint) {
if flare == selectedFlare {
xField.doubleValue = Double(position.x)
yField.doubleValue = Double(position.y)
}
}
public void didReceivePosition(Flare flare, PointF position) {
if (flare == selectedFlare) {
double x = position.x;
double y = position.y;
}
}
The server replies by sending back the position.
When device position changes
Set position
setPosition {"device":"234", "position":{"x":9, "y":1}}
function positionChanged(input, key) {
var x = 1.0 * $("input#x").val();
var y = 1.0 * $("input#y").val();
currentPosition = {x:x, y:y};
setPosition({device:device_id}, currentPosition);
}
@IBAction func changePosition(sender: NSTextField) {
if let device = selectedFlare as? Device {
var position = CGPoint(x: xField.doubleValue, y: yField.doubleValue)
device.position = position
flareManager.setPosition(device, position: position)
}
}
public void changePosition(PointF position) {
device.setPosition(position);
flareManager.setPosition(device, position);
}
When the device's position changes, it sends a message to the server.
The server will then notify all other clients that have subscribed to the device. Note that it won't send a message back to the client that sent the original message, because it already has the latest information.
When a device has become near to a thing
Near message
near {"device":"234", "thing":"789", "distance":1.414}
function near(message) {
nearbyThing = message.thing;
thingDistance = message.distance;
...
}
func near(thing: Thing, device: Device, distance: Double) {
if thing == selectedFlare {
nearbyFlare = device
}
}
public void near(Thing thing, Device device, double distance) {
if (thing == selectedFlare) {
nearbyFlare = device;
}
}
If the server calculates that a device has become near to a thing because the distance between their positions is less than a certain threshold, it will broadcast a near message to all clients that have subscribed to the thing.
Get info
GET /environments/123/zones/-/things/789
getThing(environment_id, '-', nearbyThing, function(info) {
$("input#thingname").val(info.name);
$("input#thingdescription").val(info.description);
});
flareManager.getThing(thingId, environmentId: environment.id, zoneId: "-"} {
(json: JSONDictionary) -> () in
nearbyThing = Thing(json: json)
}
flareManager.getThing(thingId, "-", environment.getId(), (json) -> {
nearbyFlare = new Thing(json);
});
The device client can then get information about the thing.
Note: If the device client doesn't know what zone the thing is in, it can just use a dash. The REST URL syntax is verbose, but the thing ID what matters. The response will be similar to the one above.
Subscribe
subscribe {"thing":"789"}
subscribe({thing:nearbyThing});
flareManager.subscribe(nearbyFlare)
flareManager.subscribe(nearbyFlare);
The device client subscribes to the thing.
Get data
getData {"thing":"789"}
getData({thing:nearbyThing});
flareManager.getData(nearbyFlare)
flareManager.getData(nearbyFlare);
It gets the latest data.
Data message
data {"thing":"789", "data":{"brightness":0.7, "color":"blue"}}
function gotData(message) {
if (message.device == device_id) {
...
} else if (message.thing == nearbyThing) {
var data = message.data;
for (key in data) {
var value = data[key];
var input = $("input#thing" + key);
input.val(value);
}
}
}
func didReceiveData(flare: Flare, data: JSONDictionary) {
if flare == selectedFlare {
...
} else if flare == nearbyFlare {
if let color = data["color"] as? String {
nearbyColorField.doubleValue = color
}
if let brightness = data["brightness"] as? Double {
nearbyBrightnessField.doubleValue = brightness
}
}
}
public void didReceiveData(Flare flare, JSONObject data) {
if (flare == selectedFlare) {
...
} else if (flare == nearbyFlare) {
String color = data.getString("color");
double brightness = data.getDouble("brightness");
}
}
The server replies by sending back the data.
Get position
getPosition {"thing":"789"}
getPosition({thing:nearbyThing});
flareManager.getPosition(nearbyFlare)
flareManager.getPosition(nearbyFlare);
The client requests the most recent position.
Position message
position {"thing":"789", "position":{"x":10, "y":0}}
function gotPosition(message) {
if (message.device == device_id) {
...
} else if (message.thing == nearbyThing) {
thingPosition = message.position;
}
}
func didReceivePosition(flare: Flare, position: CGPoint) {
if flare == selectedFlare {
...
} else if flare == nearbyFlare {
if let device = nearbyFlare as? Device, thing = selectedFlare as? Thing {
var distance = device.position - thing.position
nearbyDistanceField.doubleValue = distance
}
}
}
// when subtracting one point from another, return the Pythagorean distance
func -(point1: CGPoint, point2: CGPoint) -> Double {
let dx = point1.x - point2.x
let dy = point1.y - point2.y
return Double(sqrt(dx * dx + dy * dy))
}
public void didReceivePosition(Flare flare, PointF position) {
if (flare == selectedFlare) {
...
} else if (flare == nearbyFlare) {
double x = position.x;
double y = position.y;
}
}
The server replies by sending back the position.
Near message
near {"device":"234", "thing":"789", "distance":1.414}
function near(message) {
nearbyDevice = message.device;
deviceDistance = message.distance;
...
}
func near(thing: Thing, device: Device, distance: Double) {
if device == selectedFlare {
nearbyFlare = thing
}
}
public void near(Thing thing, Device device, double distance) {
if (device == selectedFlare) {
nearbyFlare = thing;
}
}
The server will also broadcast the same near message to all clients that have subscribed to the device.
Get info
GET /environments/123/devices/234
getDevice(environment_id, nearbyDevice, function(info) {
$("input#devicename").val(info.name);
$("input#devicedescription").val(info.description);
});
flareManager.getDevice(deviceId, environmentId: environment.id} {
(json: JSONDictionary) -> () in
nearbyDevice = Device(json: json)
}
flareManager.getDevice(deviceId, environment.getId(), (json) -> {
nearbyFlare = new Device(json);
});
The thing client can then get information about the device.
The response will be similar to the one above.
Subscribe
subscribe {"device":"234"}
subscribe({device:nearbyDevice});
flareManager.subscribe(nearbyFlare)
flareManager.subscribe(nearbyFlare);
The thing client subscribes to the device.
Get data
getData {"device":"234"}
getData({device:nearbyDevice});
flareManager.getData(nearbyFlare)
flareManager.getData(nearbyFlare);
It gets the latest data.
Data message
data {"device":"234", "data":{"angle": 60}}
function gotData(message) {
if (message.thing == thing_id) {
...
} else if (message.device == nearbyDevice) {
var data = message.data;
for (key in data) {
var value = data[key];
var input = $("input#device" + key);
input.val(value);
}
}
}
The server replies by sending back the data.
Get position
getPosition {"device":"234"}
getPosition({device:nearbyDevice});
flareManager.getPosition(nearbyFlare)
flareManager.getPosition(nearbyFlare);
The client requests the most recent position.
Position message
position {"device":"234", "position":{"x":9, "y":1}}
function gotPosition(message) {
if (message.thing == thing_id) {
...
} else if (message.device == nearbyDevice) {
devicePosition = message.position;
}
}
The server replies by sending back the position.
When thing data changes
Set data
setData {"thing":"789", "key":"color", "value":"purple"}
function dataChanged(input, key) {
var value = input.value;
setData({device:device_id}, key, value);
}
@IBAction func changeColor(sender: NSTextField) {
if let flare = selectedFlare {
var value = sender.stringValue
flare.data["color"] = value
flareManager.setData(flare, key: "color", value: sender.stringValue)
}
}
@IBAction func changeBrightness(sender: NSTextField) {
if let flare = selectedFlare {
var value = sender.doubleValue
flare.data["brightness"] = value
flareManager.setData(flare, key: "brightness", value: value)
}
}
public void changeColor(String color) {
selectedFlare.getData().put("color", color);
flareManager.setData(selectedFlare, "color", color);
}
public void changeColor(double brightness) {
selectedFlare.getData().put("brightness", brightness);
flareManager.setData(selectedFlare, "brightness", brightness);
}
Either client can change the thing's data.
Data message
data {"thing":"789", "data":{"color":"purple"}}
The server will then notify all other clients that have subscribed to the thing.
When device data changes
Set data
setData {"device":"234", "key":"angle", "value":120}
function dataChanged(input, key) {
var value = input.value;
setData({thing:thing_id}, key, value);
}
@IBAction func changeAngle(sender: NSTextField) {
if let flare = nearbyFlare {
var value = sender.doubleValue
flare.data["angle"] = value
flareManager.setData(flare, key: "angle", value: value)
}
}
public void changeAngle(double angle) {
selectedFlare.getData().put("angle", angle);
flareManager.setData(selectedFlare, "angle", angle);
}
Either client can change the device's data.
Data message
data {"device":"234", "data":{"angle":120}}
The server will then notify all other clients that have subscribed to the device.
performAction {"thing":"789", "action":"rainbow"}
performAction({thing:thing_id}, 'rainbow');
@IBAction func performAction(sender: NSButton) {
if let flare = selectedFlare, action = sender.identifier {
flareManager.performAction(flare, action: action)
}
}
public void performAction(String action) {
flareManager.performAction(selectedFlare, action);
}
Any client can perform an action on the thing.
Handle action
handleAction {"thing":"789", "action":"rainbow"}
function handleAction(message) {
if (message.thing == thing_id) {
var action = message.action;
if (action == 'rainbow') {
// do stuff
}
}
}
func handleAction(flare: Flare, action: String) {
if action == "rainbow" {
...
}
}
public void handleAction(Flare flare, String action) {
if (action.equals("rainbow")) {
...
}
}
The action can be handled by the server or any client. If it is not handled by the server, a message will be broadcast to all other clients subscribed to the thing.
performAction {"device":"234", "action":"counterclockwise"}
performAction({device:device_id}, 'counterclockwise');
Any client can perform an action on the device.
Handle action
handleAction {"device":"234", "action":"counterclockwise"}
function handleAction(message) {
if (message.device == device_id) {
var action = message.action;
if (action == 'counterclockwise') {
// do stuff
}
}
}
Similarly, if the action is not handled by the server, a message will be broadcast to all other clients subscribed to the device.
When thing position changes
Set position
setPosition {"thing":"789", "position":{"x":10, "y":1}}
function positionChanged(input, key) {
var x = 1.0 * $("input#x").val();
var y = 1.0 * $("input#y").val();
currentPosition = {x:x, y:y};
setPosition({thing:thing_id}, currentPosition);
}
@IBAction func changePosition(sender: NSTextField) {
if let thing = selectedFlare as? Thing {
var position = CGPoint(x: xField.doubleValue, y: yField.doubleValue)
thing.position = position
flareManager.setPosition(thing, position: position)
}
}
public void changePosition(PointF position) {
selectedFlare.setPosition(position);
flareManager.setPosition(selectedFlare, position);
}
If the thing's position changes, it can send a message to the server.
Position message
position {"thing":"789", "position":{"x":10, "y":1}}
The server will then notify all other clients that have subscribed to the thing.
Note: near and far messages are only triggered when the device's position changes.
When device position changes again
Set position
setPosition {"device":"234", "position":{"x":4, "y":5}}
If the device's position changes again, it will send a message to the server.
Position message
position {"device":"234", "position":{"x":4, "y":5}}
You get the idea by now.
When a device is no longer near to a thing
Far message
far {"device":"234", "thing":"789"}
function far(message) {
if (nearbyDevice) unsubscribe({device:nearbyDevice});
nearbyDevice = null;
}
func far(thing: Thing, device: Device) {
if thing == selectedFlare && device == nearbyFlare {
flareManager.unsubscribe(device)
nearbyFlare = nil
}
}
public void far(Thing thing, Device device) {
if (thing == selectedFlare && device == nearbyFlare) {
flareManager.unsubscribe(device);
nearbyFlare = null;
}
}
The server will notice when the device is no longer near to the thing, and notify all clients subscribed to the device.
Unsubscribe
unsubscribe {"thing":"789"}
The device can then unsubscribe from the thing, and then it won't receive notifications about the thing anymore.
Far message
far {"device":"234", "thing":"789"}
function far(message) {
if (nearbyThing) unsubscribe({thing:nearbyThing});
nearbyThing = null;
}
func far(thing: Thing, device: Device) {
if device == selectedFlare && thing == nearbyFlare {
flareManager.unsubscribe(thing)
nearbyFlare = nil
}
}
public void far(Thing thing, Device device) {
if (device == selectedFlare && thing == nearbyFlare) {
flareManager.unsubscribe(thing);
nearbyFlare = null;
}
}
The server will send the same message to all clients subscribed to the thing.
Unsubscribe
unsubscribe {"device":"234"}
And the thing can unsubscribe from the device as well.