Discover The AREST Framework by Marco Schwartz
Discover The AREST Framework by Marco Schwartz
Discover The AREST Framework by Marco Schwartz
Legal
Copyright 2016 by Marc-Olivier Schwartz
All rights reserved. No part of this book may be used or reproduced in any manner
whatsoever without permission except in the case of brief quotations embodied in critical
articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is given without
warranty, either expressed or implied. Neither the author nor the dealers & distributors of
this book will be held liable for any damages caused or alleged to be caused directly or
indirectly by this book.
First eBook edition: January 2016
Introduction
0.3 Prerequisites
In this book, you will see that I mix several platforms, like Arduino, the Raspberry Pi, and
the ESP8266. However, as the aREST framework is universal, you can perfectly apply
everything you will learn in this book to Arduino for example.
Therefore, any prior knowledge in at least one of those platforms is really recommend to
follow the content of this book. However, you dont need to be an expert in embedded
electronics: well really keep the hardware part simple, to focus on the aREST framework.
In terms of programming languages, I will mainly use two of them: C/C++ for Arduino &
the ESP8266, and JavaScript for the rest (via Node.js and the Meteor platform).
Any knowledge in those languages is also recommended for this book. However, I will
really take things from the very basics to more advanced projects, so you can perfectly
learn project after project.
In terms of required hardware, I will provide a list of all the required components in every
section of the book. I will also give an overview of what you need in terms of software &
hardware in the next section.
This sketch is really basic, but already illustrates a lot about the aREST framework. It
always starts by including the aREST library:
#include <aREST.h>
In the setup() function of the sketch, we also set an ID and name that identify the board:
rest.set_id("1");
rest.set_name("serial");
Finally, in the loop() function, we process the requests sent to the aREST library:
rest.handle(Serial);
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
You can now open the Arduino IDE, and put this first sketch inside the IDE. Then, upload
the sketch to the Arduino board. After, that, open the Serial monitor, and make sure that
the Serial speed is set to 115200, and the Carriage Return option is selected.
Now, type the following command and send it to the board:
/mode/13/o
This will make pin number 13, which is connected to a LED on the Arduino Uno board, to
an output. You will also see the confirmation inside the Serial monitor:
This will make a digitalWrite() command to pin 13, and it will turn the LED on. If that
works, it means that aREST is working correctly. As earlier, you will also get the
confirmation in the serial port:
Lets now try to read data from inputs. You can simply read data from pin 7 by typing
first:
/mode/7/o
Followed by:
/digital/7
To change the value of pin 7 of the board, you can simply connect a wire cable between
the 5V pin and pin 7.
We can also read analog data from the Arduino board via aREST. At the moment there is
nothing connect to the Arduino board on analog pins, but you will be able to read out
analog fluctuations on this pin. Simply type:
/analog/0
This will read the value on the analog pin A0, and return a value between 0 and 1023:
From this very first project of the book, you should know already have the foundations of
the aREST framework. You can already experiment with those commands now to really
get familiar with them, as we will use them in the whole book.
For the LED, simply connect it in series with the resistor, with the longest pin of the LED
connected to the resistor.
Then, connect the remaining pin of the resistor to pin 6 of the Arduino board, and the
remaining pin of the LED to the GND pin of the Arduino board.
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init variables and expose them to REST API
temperature = 24;
humidity = 40;
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id("008");
rest.set_name("dapper_drake");
// Start the Ethernet connection and the server
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
rest.handle(client);
}
As you can notice, there are several similarities between this sketch and the basic Serial
example that we saw in the first project.
Here however, there are some details that you need to modify in the code. You need to set
the MAC address of your Ethernet shield, which you can find on the bottom of the shield:
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0E, 0xFE, 0x40 };
Its also time to introduce a new feature of aREST: variables. Variables can be used to
automatically fetch values by using aREST commands. This is perfect to get
measurements from a sensor for example. Here, to simplify things, we will simply define
fixed values for two variables:
temperature = 24;
humidity = 40;
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
Finally, in the loop() part of the sketch, we handle the request in a very similar fashion to
the first example of the book:
EthernetClient client = server.available();
rest.handle(client);
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
You can now configure your board with the code from this section. Dont forget to modify
the MAC address inside the code.
Then, open the Serial monitor. You should see the IP address of the board being displayed.
I will assume for the rest of this chapter that it is 192.168.115.102. After that, go to your
favorite web browser, and type:
192.168.115.102/id
You should instantly get the confirmation from the board in JSON format:
{
"id": "008",
"name": "dapper_drake",
"connected": true
}
Congratulations, you can now control your Arduino projects remotely via Ethernet! Lets
try more commands, for example to light up the LED on pin 6. First, go back to your
browser and type:
192.168.115.102/mode/6/o
Followed by:
192.168.115.102/digital/6/1
This should instantly light up the LED connected to pin 6, with the same commands that
we used in the first project of this book.
"connected": true
}
You can now access any variable that you define on your board via your web browser!
This is something you can use just for your own information, for your own web
applications, or as we will see in the second chapter of this book, for aREST server-side
applications.
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Function to be exposed
rest.function("led",ledControl);
// Give name and ID to device
rest.set_id("008");
rest.set_name("mighty_cat");
// Set up CC3000 and get connected to the wireless network.
if (!cc3000.begin())
{
while(1);
}
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
while(1);
}
while (!cc3000.checkDHCP())
{
delay(100);
}
Serial.println();
// Print CC3000 IP address. Enable if mDNS doesn't work
while (! displayConnectionDetails()) {
delay(1000);
}
// Start server
restServer.begin();
Serial.println(F("Listening for connections"));
// Enable watchdog
wdt_enable(WDTO_4S);
}
void loop() {
// Handle REST calls
Adafruit_CC3000_ClientRef client = restServer.available();
rest.handle(client);
wdt_reset();
// Check connection, reset if connection is lost
if(!cc3000.checkConnected()){while(1){}}
wdt_reset();
}
// Print connection details of the CC3000 chip
bool displayConnectionDetails(void)
{
In this sketch, you will need to modify some things so it can work. You need to change
your WiFi network settings:
#define WLAN_SSID "your_wifi_name"
#define WLAN_PASS "your_wifi_password"
#define WLAN_SECURITY WLAN_SEC_WPA2
We also introduced a new feature of aREST, functions. Those are functions that you define
inside your sketch, and that you then declare to be exposed to the aREST API. You will
then be able to call them from a web browser, for example.
First, you need to declare your function in the setup() function of the sketch:
rest.function("led",ledControl);
Then, implement the details of your function in the sketch. It needs to return an int, and
take a String as the input parameters. The parameters in the String are then separated by
commas.
For example, in this project I defined a simple function to switch the LED on or off
according to the input parameter:
int ledControl(String command) {
// Get state from command
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Now, put all the code inside your Arduino IDE, and modify your WiFi name & password.
After that, upload the code to the board, and open the Serial monitor.
After a while, you should see the IP address of the board inside the Serial monitor. Lets
suppose for the rest of this project that it is 192.168.115.104. To check if your board is
responding to aREST commands, go to a web browser and type:
http://192.168.115.104/id
Now, lets try a new function of the aREST API: the possibility to write analog values on
outputs. On the Arduino Uno board, this will have the effect of sending PWM signal on
the desired pin. First, set pin 6 as an output:
http://192.168.115.104/mode/6/o
This is basically the equivalent of an analogWrite(6, 10) function inside Arduino. You
should see that the LED is now only lightly glowing. You can basically use values from 0
to 255, just as you would do directly in the code.
We will see that it is really easy to access this function remotely. Simply type:
http://192.168.115.104/led?params=1
As we passed 1 as a parameter, you should also see that the LED is now on. Note that
you can pass several parameters to the function, and they need to be separated by commas.
You can now define your own aREST functions, and call them remotely!
rest.set_name("xbee");
// Variables
rest.variable("temperature", &temperature);
rest.variable("humidity", &humidity);
// Start DHT
dht.begin();
}
void loop() {
// Read data
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Handle REST calls
rest.handle(Serial);
}
As you can see, it is really similar to the sketch that we saw in the first project of this
book. The only difference is the code for the DHT sensor, as well as the speed of the Serial
port (9600).
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to program our board. Make sure to set the switch on DLINE on the XBee
shield, and upload the sketch. Then, set it again to UART.
After that, select the Serial port corresponding to your XBee explorer board, go to the
Serial monitor (make sure the speed is set to 9600), and type:
/id
The command will be sent to your Arduino board via XBee. You should immediately get
the answer inside the Serial monitor:
Then, you can really easily get the temperature data with:
/temperature
You should immediately get the answer from the board inside the Serial monitor:
You can now control your projects via XBee as well, using the aREST commands!
BTLEserial.begin();
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id("008");
rest.set_name("dapper_drake");
pinMode(6,OUTPUT);
}
aci_evt_opcode_t laststatus = ACI_EVT_DISCONNECTED;
void loop() {
// Tell the nRF8001 to do whatever it should be working on.
BTLEserial.pollACI();
// Ask what is our current status
aci_evt_opcode_t status = BTLEserial.getState();
// If the status changed.
if (status != laststatus) {
// print it out!
if (status == ACI_EVT_DEVICE_STARTED) {
Serial.println(F("* Advertising started"));
}
if (status == ACI_EVT_CONNECTED) {
Serial.println(F("* Connected!"));
}
if (status == ACI_EVT_DISCONNECTED) {
Serial.println(F("* Disconnected or advertising timed out"));
}
// OK set the last status change to this one
laststatus = status;
}
// Handle REST calls
if (status == ACI_EVT_CONNECTED) {
rest.handle(BTLEserial);
}
}
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
You can now grab the whole code, and also upload it to the board. Also open the Serial
monitor. Then, you are going to need some way to communicate with the BLE breakout
board. The best is to use the mobile application that you downloaded earlier.
I will use the iOS application as an example, but you can of course use the Android
version as well.
Open the app, and you should see a list of devices listed. Click on UART:
You should see inside the Serial monitor that a device is connected to the BLE module:
Note that here you need to send another / character at the end of the command, to
indicate that it is the end of the message.
You can now try all the usual aREST commands, you can for example try to turn the LED
on:
Congratulations, you can now control your Arduino projects via Bluetooth LE!
This will give you the IP address of your Pi, you will need it in a moment.
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
You can now take the file to a folder on your Raspberry Pi, go this folder via a terminal,
and type:
sudo npm install pi-arest express
This will install all the required components for pi-aREST. Then, start the software with:
sudo node pi_arest.js
The aREST API is now available on your Pi as well. Lets assume for the rest of this
chapter that the IP address of your board is 192.168.115.106. You can test the aREST
API by simply going to your web browser, and type:
http://192.168.115.106/id
Lets now try to light up the LED. Here, there is a difference with the Arduino aREST
software: we dont need to set the pin as an output first, this is done by the Raspberry Pi
software for you. Simply type:
http://192.168.115.106/digital/7/1
You should that the LED is now on, and you should also get the confirmation in the
browser:
{
"id":"34f5eQ",
"name":"my_new_Pi",
"hardware":"rpi",
"connected":true,
"message":"Pin 7 set to 1"
}
Then, we will also test the variable command of aREST, which also works with the
Raspberry Pi. This is done by defining variables in the code with:
piREST.variable('temperature',temperature);
piREST.variable('humidity',humidity);
Here, we just set values to those variables, but you could of course link them to
measurements coming from a sensor.
Open Boards Manager from Tools > Board menu and install the esp8266 platform.
You will also need to install the Adafruit DHT library, that you can install from the
Arduino library manager.
float temperature;
float humidity;
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init DHT
dht.begin();
// Init variables and expose them to REST API
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id("1");
rest.set_name("esp8266");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
//rest.glow_led();
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
Just as with Arduino with the CC3000 WiFi chip, you will need to set your WiFi name and
password:
const char* ssid = "wifi-name";
const char* password = "wifi-password";
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to upload the sketch. Make sure you opened the file in the Arduino IDE, and
modify your WiFi name and password. Then, connect the FTDI USB converter to the
board, put your board into bootloader mode. You can check the documentation of your
board to know how to do this.
Now, upload the sketch to the board, and open the Serial monitor. Then, reset the board.
You should see the IP address of the board displayed in the Serial monitor.
After that, go to your favorite web browser, and type:
http://192.168.115.102/temperature
As you can see, its really easy to use the same aREST commands that we used so far on
the ESP8266 chip.
{
"variables":
{
"temperature": 25.00,
"humidity": 32.00
},
"id": "1",
"name": "esp8266",
"connected": true
}
As you can see, you can now access all the variables on the board, using a single
command. Note that this is also available on other boards running the aREST framework!
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init DHT
dht.begin();
// Init variables and expose them to REST API
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id("1");
rest.set_name("esp8266_ui");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
// Create UI
rest.title("ESP8266 UI");
rest.button(4);
rest.label("temperature");
rest.label("humidity");
}
void loop() {
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
Lets now see the differences between this new sketch and other sketches using aREST.
You need to include the aREST UI library:
#include <ESP8266WiFi.h>
#include <aREST.h>
#include <aREST_UI.h>
#include "DHT.h"
After that, in the setup() function, we define the interface elements of our sketch. We set a
title, a button to control the LED, and two labels for the sensor measurements:
rest.title("ESP8266 UI");
rest.button(4);
rest.label("temperature");
rest.label("humidity");
Now, grab the code again from the GitHub repository of the book, and upload it to the
board, following the instructions we saw earlier.
Then, open the Serial monitor to grab the IP address of the board. Then, you can simply
type this IP address in a web browser, to access the interface, like:
http://192.168.115.102/
You should immediately see the interface inside your web browser:
You can try it now: for example, just click on the ON button. The LED should instantly
turn on. You can now create your own interfaces that are running on your ESP8266 board,
without the help of any external component or service!
Now, you can connect an electrical appliance to the PowerSwitch Tail Kit, for example a
lamp. I used a 30W lamp for this project. Also connect the other part of the PowerSwitch
Tail to the mains electricity.
{
// Start Serial
Serial.begin(115200);
// Give name and ID to device
rest.set_id("1");
rest.set_name("lamp_control");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
// Create UI
rest.title("Lamp control");
rest.button(5);
}
void loop() {
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Now, grab the complete code, modify your WiFi network parameters, and upload the code
to the board using the instructions we saw earlier. Also open the Serial monitor to get the
IP address of the board. You might need to reset the board at this point.
Then, go to your web browser, and type the IP address of the board:
http://192.168.115.102/
You can now try the interface: just by pressing a button, you can switch the lamp on and
off. Congratulations, you can now built home automation projects using the aREST
framework!
tag, you need to import jQuery, AjaxQ, and of course the aREST.js library:
You also need to import the script.js file, that will contain our JavaScript code.
Then, we define a simple interface where we have two buttons to control the LED on the
board:
Digital pin 6:
On
Off
I also added several other elements to illustrate all the functions of aREST. This is an
element to use PWM commands on pin 6:
PWM pin 6:
Finally, we also create an element that will contain the readings of the analog pin A0 on
the board:
Lets now see the script.js file. The first step is to create a new aREST device, with the IP
address of the board:
var device = new Device("192.168.115.105");
As you can see, each button calls a digitalWrite() function, which is really similar to the
function that you can use on an Arduino sketch. The first command will simply call a
/digital/6/1 function on the aREST API, which in return will call a digitalWrite(6, 1)
function on the board.
For the PWM control of the same pin, I created a slider:
$('#slider').mouseup(function() {
var val = $('#slider').val();
device.analogWrite(6, val);
});
This will call the analogWrite() function on the board every time the slider is modified.
Finally, we create a loop to read data from the analog pin A0, every 5 seconds:
device.analogRead(0, function(data) {
$("#A0").html(data.return_value);
});
setInterval(function() {
device.analogRead(0, function(data) {
$("#A0").html(data.return_value);
});
}, 5000);
As you can see, we use the analogRead() function, which does exactly the same thing as
its Arduino counterpart.
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to test our project! Make sure to grab the code from the GitHub repository,
and modify the script with the IP address of your board.
Then, simply open the HTML file with any web browser. You should immediately see the
interface in your browser:
You can now try the different controls, and the LED should react accordingly. Especially
use the slider to modify the luminosity of the LED.
We can now build simple interfaces for your aREST projects. Later in this book, we are
going to see how to build more complex applications to also record data locally.
rest.set_name("dapper_drake");
// Start the Ethernet connection and the server
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
rest.handle(client);
}
This is something we already saw in the previous chapter, so I wont go into details here.
Just make sure to modify the MAC address in the sketch, and upload it to your Arduino
board. Then, open the Serial monitor to get the IP address of the board.
We are now going to see the to build the interface for this project. It will be composed of
two parts: an HTML page, and a JavaScript file.
Lets first see the content of the HTML page. In the
WiFiServer server(LISTEN_PORT);
// Variables to be exposed to the API
float temperature;
float humidity;
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init DHT
dht.begin();
// Init variables and expose them to REST API
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id("1");
rest.set_name("esp8266");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
As you can see, its a typical sketch for the ESP8266 that we already saw earlier. Just
make sure to modify the WiFi network name and password, and upload the sketch to the
board. Then, open the Serial monitor to grab the IP address of the board.
Lets now see the details of the interface. As in the previous section, it will be composed
of an HTML page and a JavaScript file. This is the part in the HTML page to display the
temperature & humidity:
<div class='row'>
<div class="col-md-2">Temperature:
<span id='temperature'></span>
</div>
<div class="col-md-2">Humidity:
<span id='humidity'></span>
</div>
</div>
To update those fields, we need to define some code inside the JavaScript file:
// Temperature display
device.getVariable('temperature', function(data) {
$('#temperature').html(data.temperature);
});
// Humidity display
device.getVariable('humidity', function(data) {
$('#humidity').html(data.humidity);
});
Those commands are basically the equivalent of calling a variable exposed by the aREST
API. Note that we need to use callbacks here, as we can only update the value of the
indicator in the interface when we have the answer from the board.
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to test our project! Make sure to grab the code from the GitHub repository,
and modify the JavaScript file with the IP address of your board.
Then, simply open the HTML file with any web browser. You should immediately see the
interface in your browser:
As you can see, the temperature & humidity data is immediately displayed inside the
interface. Here, this is just the instant values from the board. We are going to learn how to
store measurements data on your computer later in this chapter.
// Libraries
#include <SPI.h>
#include <Ethernet.h>
#include <aREST.h>
#include "DHT.h"
// DHT 11 sensor
#define DHTPIN 7
#define DHTTYPE DHT11
// DHT sensor
DHT dht(DHTPIN, DHTTYPE);
// Enter a MAC address for your controller below.
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0E, 0xFE, 0x40 };
// IP address in case DHCP fails
IPAddress ip(192,168,2,2);
// Ethernet server
EthernetServer server(80);
// Create aREST instance
aREST rest = aREST();
// Variables to be exposed to the API
int temperature;
int humidity;
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init variables and expose them to REST API
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id("1");
rest.set_name("dapper_drake");
// Start the Ethernet connection and the server
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// Make measurements
humidity = (int)dht.readHumidity();
temperature = (int)dht.readTemperature();
// listen for incoming clients
EthernetClient client = server.available();
rest.handle(client);
}
This is a sketch we already saw several times in this book, so I wont detail it. Just make
sure to modify the MAC address of the board, and upload the code to the board. Then,
open the Serial monitor to grab the IP address of the board.
Finally, go to a web browser, and check that the board is online with:
http://192.168.115.104/id
</body>
</template>
This file is really basic, as it only contains two containers for the temperature and
humidity.
Then, inside a JavaScript file, we will define both the code for the server and the client:
if (Meteor.isServer) {
Meteor.startup(function () {
// Add device
aREST.addDevice('http', '192.168.115.104');
});
}
if (Meteor.isClient) {
// Main route
Router.route('/', {name: 'home'});
// Rendered
Template.home.rendered = function() {
// Refresh temperature & humidity
Meteor.call('getVariable', 1, 'temperature', function(err, data) {
console.log(data);
$('#temperature').text(data.temperature);
});
Meteor.call('getVariable', 1, 'humidity', function(err, data) {
$('#humidity').text(data.humidity);
});
}
}
Lets see the detail of this code. On the server side, we need to call the aREST module to
add the board to the application database:
aREST.addDevice('http', '192.168.115.104');
Dont worry about the database itself: Meteor is taking care about it for you. Then, on the
client side, we define a route for our application:
Router.route('/', {name: 'home'});
This will simply load the home template whenever we access the root of the server.
Then, still on the client side, we call the getVariable method, which is also included into
the Meteor aREST module.
To call this function, we simply need to send the ID of the device we set in the code, and
In the same time, we update the indicators in the interface inside the callbacks of those
methods.
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to test the project! Grab all the code from the GitHub repository, and put all
the files in a folder on your computer. Then, go to this folder with a terminal, and type:
meteor create .
This will initialize a new Meteor project inside this folder. Then, install the aREST Meteor
module with:
meteor add marcoschwartz:arest
You should immediately see the interface in your web browser, with the measurements
made by the board.
At this point, you can wonder why we are doing all this, as we could do the same without
Meteor. However, the difference is that we now have a much more solid infrastructure for
our project, from which we could easily record data for example.
restServer.begin();
Serial.println(F("Listening for connections"));
// Enable watchdog
wdt_enable(WDTO_4S);
}
void loop() {
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Handle REST calls
Adafruit_CC3000_ClientRef client = restServer.available();
rest.handle(client);
wdt_reset();
// Check connection, reset if connection is lost
if(!cc3000.checkConnected()){while(1){}}
wdt_reset();
}
// Print connection details of the CC3000 chip
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask,
&gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
Make sure to modify the WiFi network name and password, and upload the code to the
board. Then, open the Serial monitor to grab the IP address of the board, you will need it
later.
interface. Here again, we are going to use the Meteor aREST module.
This is the template that we will use for the interface:
<template name='home'>
<body>
<div class='container'>
<h3>Arduino WiFi Control & Monitoring</h3>
<div class='row'>
<div class="col-md-2">
<button id='on' class='btn btn-primary btn-block' type="button">
On
</button>
</div>
<div class="col-md-2">
<button id='off' class='btn btn-danger btn-block' type="button">
Off
</button>
</div>
</div>
<div class='row'>
<div class='col-md-3'>Temperature:
<span id='temperature'></span> C</div>
<div class='col-md-3'>Humidity:
<span id='humidity'></span>%</div>
</div>
</div>
</body>
</template>
If we compare this file to the interface we created in the previous section, we can notice
that we added two buttons, that we will use to control the relay.
Lets now see the JavaScript file, that will contain all the code for the server & the client.
For the server, we just need to set the IP address of the target board using the aREST
Meteor module:
if (Meteor.isServer) {
Meteor.startup(function () {
// Add device
aREST.addDevice('http', '192.168.115.105');
});
Now, inside the client code, we need to define two events, that will link the buttons inside
the interface to actual commands sent to the board.
This is done by the following piece of code:
Template.home.events({
'click #on': function() {
Meteor.call('digitalWrite', 1, 7, 1);
},
'click #off': function() {
Meteor.call('digitalWrite', 1, 7, 0);
}
});
As you can see, you can call the digitalWrite() method inside Meteor, just as you would
call the function inside an Arduino sketch.
Finally, we also need to do some things at the moment the page is loaded. This is done
inside the rendered function of Meteor. This is the equivalent of the setup() function of
Arduino.
Inside this function, we will set pin 7 as an output, and also refresh the measurements of
the sensor:
Template.home.rendered = function() {
// Set pin
Meteor.call('pinMode', 1, 7, 'o');
// Refresh temperature & humidity
Meteor.call('getVariable', 1, 'temperature', function(err, data) {
console.log(data);
$('#temperature').text(data.temperature);
});
Meteor.call('getVariable', 1, 'humidity', function(err, data) {
$('#humidity').text(data.humidity);
});
}
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to test the project! Grab all the code from the GitHub repository, and put all
the files in a folder on your computer. Then, go to this folder with a terminal, and type:
meteor create .
This will initialize a new Meteor project in this folder. Then, install the aREST Meteor
module with:
You can try it now, for example to control the relay. We could stop here, but we are going
to do an extra thing here. Because we now have a solid application running with the
Meteor framework, its easy for us to define triggers, for example to take a given action
when a condition is met.
As an example, well set the relay to the On state whenever the temperature falls below
20 degrees. This could simulate the behavior of a thermostat, for example.
To do that, we need to implement it on the server side. Indeed, you dont want to have the
page opened in your browser so the application can check if the condition is met.
To implement that, we will the SyncedCron module for Meteor, that allows us to create
automated tasks that will be repeated automatically on the server in the background.
This is the code for this part:
SyncedCron.add({
name: 'Check temperature',
schedule: function(parser) {
return parser.text('every 1 minute');
},
job: function() {
Meteor.call('getVariable', 1, 'temperature', function(err, data) {
// Check temperature value
if (data.temperature < 20) {
// Activate relay
Meteor.call('digitalWrite', 1, 7, 1);
}
});
}
});
As you can see, whenever the temperature falls below 20 degrees, we simply switch the
relay to on.
You can now build more complex applications based on the aREST Meteor module, by
defining triggers that are executed when a given condition is met.
Save this code inside a JavaScript file on your Pi, and then navigate to the folder with a
terminal. Then, type:
This will install all the required modules for this project. Then, start the software with:
sudo node arest.js
Then, inside the JavaScript file, we add the Raspberry Pi board to the Meteor application:
if (Meteor.isServer) {
Meteor.startup(function () {
// Add device
aREST.addDevice('http', '192.168.115.107');
});
}
For the client part, we link the buttons to the digitalWrite function of the aREST Meteor
module:
if (Meteor.isClient) {
// Main route
Router.route('/', {name: 'home'});
// Events
Template.home.events({
Now, repeat the procedure that we saw earlier to start the Meteor application, and then
visit the server with the web browser. You should immediately have access to the
interface:
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
// Start counter
counter = millis();
}
void loop() {
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Publish
if ( (millis() - counter) > measurement_interval) {
if (restClient.connect(servername, port)) {
rest.publish(restClient, "temperature", temperature);
rest.publish(restClient, "humidity", humidity);
}
counter = millis();
}
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
This sketch is quite similar to what we already saw in previous projects, with some
differences. First, we define a server name and port at the beginning of the sketch:
char* servername = "192.168.115.101";
int port = 3000;
The servername variable is basically the IP address of your computer. This will tell the
ESP8266 to send data to the server running on your computer. You need to modify this
variable with the IP address of the computer where your Meteor server will run.
Then, we define the interval between two measurements made by the board:
int measurement_interval = 60 * 1000; // 1 minute
In the loop() function of the sketch, we actually publish the data at the interval we defined
before:
if ( (millis() - counter) > measurement_interval) {
if (restClient.connect(servername, port)) {
As you can see, the publish() function is quite simple to use: we just pass the client, the
name of the event (here the variables names), and the value to publish.
You can now already upload this code to the board. However, it wont do anything until
we have the server running on your computer.
You can see that we use a template called event, and this is what we need to define now.
This is the definition of the event template, which is located inside the same file:
<template name='event'>
<div class='row'>
<div class='col-md-3'>
<span class='label label-primary'>
{{livestamp timestamp}}
</span>
</div>
<div class='col-md-1'>{{device}}</div>
<div class='col-md-2'>{{variable}}</div>
<div class='col-md-2'>{{value}}</div>
</div>
</template>
For each event (or each datapoint published by the board and recorded on the server), we
will print the timestamp, the device ID, the variable name, and the value of the recorded
data.
On the server side, we add the device on startup:
if (Meteor.isServer) {
Meteor.startup(function () {
aREST.addDevice('http', '192.168.115.104');
});
}
For the client, we create a helper called event to return all the events recorded by the
server:
if (Meteor.isClient) {
// Main route
Router.route('/', {name: 'home'});
Template.home.helpers({
events: function() {
return Events.find({}, {sort: {timestamp: -1}});
}
});
}
Its now time to test the project! Make sure that you grab the code from the GitHub
repository, and navigate to the folder where the files are located. Then, type:
meteor create .
This will initialize a new Meteor project in this folder. Then, install the aREST Meteor
module with:
meteor add marcoschwartz:arest
You should immediately see the interface displayed on your computer, with no recordings
at the moment:
You should see that after a few seconds, some data will appear on the main page:
Every minute, you will see another couple of points being added to the page:
You can also use the API of the aREST Meteor module to get all events as a JSON array.
Just go to:
http://localhost:3000/1/events
This will immediately return all the events that were recorded by this device so far on this
server. You can now record events on your Meteor server, allowing you to build your own
applications using those recordings! Of course, you can use those events as you wish
inside your own applications.
// Interface routes
app.get('/interface', function(req, res){
res.render('interface');
});
Now, lets see the interface, defined in interface.jade. Jade is basically a templating
language for HTML, that can allow us to easily create HTML files. This is the header of
this file:
doctype
html
head
title Raspberry Pi Interface
link(rel='stylesheet',
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css
link(rel='stylesheet',
href="/css/interface.css")
script(src="https://code.jquery.com/jquery-2.1.1.min.js")
script(src="/js/interface.js")
Then, this is how we define the interface, with buttons to control the PowerSwitch Tail
Kit, indicators for sensor data, and a space for the picture taken by the camera:
body
.container
h1 Raspberry Pi Interface
.row.voffset
.col-md-4
div Lamp
.col-md-4
button.btn.btn-block.btn-lg.btn-primary#on On
.col-md-4
button.btn.btn-block.btn-lg.btn-danger#off Off
.row.voffset
.col-md-6
div#temperature Temperature:
.col-md-6
div#humidity Humidity:
.row.voffset
.col-md-6
img#camera(width=640, height=360)
Now, we will define the behavior of the interface in a file called interface.js. First, we need
to link the buttons of the interface to the corresponding aREST commands:
// Click on buttons
$("#on").click(function() {
$.get('/digital/7/1');
});
$("#off").click(function() {
$.get('/digital/7/0');
});
Then, we define functions to refresh the data coming from the sensor:
function refreshSensors() {
$.get('/temperature', function(json_data) {
$("#temperature").text('Temperature: ' + json_data.temperature + ' C');
$.get('/humidity', function(json_data) {
$("#humidity").text('Humidity: ' + json_data.humidity + ' %');
});
});
}
Now, lets see how to take a picture from the camera at regular intervals. This is
something that is also integrated into the pi-aREST module, using the /camera/snapshot
command. We define a function inside the script to take a new picture every 10 seconds,
and we use this picture to refresh the picture inside the interface:
setInterval(function() {
// Take picture
$.get("/camera/snapshot");
}, 10000);
setInterval(function() {
// Reload picture
d = new Date();
$("#camera").attr("src","/pictures/image.jpg?" + d.getTime());
}, 1000);
Its now time to test the project! Make sure to grab the code from the GitHub repository of
the book, put all the files in a folder, and navigate to this folder using a terminal. Then,
type:
sudo npm install node-dht-sensor express pi-arest
Be patient, this can take a while on older Raspberry Pi boards. Then, start the project with:
sudo node app.js
Now, you can access the interface by going to the IP address of your Pi, followed by port
3000, and the interface route. For example:
http://localhost:3000/interface
You should immediately see the interface inside your browser, with the buttons, sensor
data, and also the picture taken by the Pi. Note that this interface is really running on the
Pi itself, and does not require an external computer to work.
humidity = (int)dht.readHumidity();
temperature = (int)dht.readTemperature();
// Publish
if ( (millis() - counter) > measurement_interval) {
if (restClient.connect(servername, port)) {
rest.publish(restClient, "temperature", temperature);
rest.publish(restClient, "humidity", humidity);
}
counter = millis();
}
// Listen for incoming clients
EthernetClient client = server.available();
rest.handle(client);
}
There are some things you will need to modify in this sketch. First, modify the MAC
address and put the one from your Ethernet shield.
Then, you need to set the IP address of the server inside the sketch:
char* servername = "192.168.115.101";
int port = 3000;
In the loop() function, we publish data (temperature and humidity) to the server at regular
intervals:
if ( (millis() - counter) > measurement_interval) {
if (restClient.connect(servername, port)) {
rest.publish(restClient, "temperature", temperature);
rest.publish(restClient, "humidity", humidity);
}
counter = millis();
}
You can now already upload the code to the board. Also open the Serial monitor to get the
IP address of the board. At this point it wont do anything, as you need the server to be
running on your computer.
<div class='row'>
<div class='col-md-6'>
{{> highchartsHelper chartId="temperature"
chartWidth="100%" charHeight="100%"
chartObject=temperatureChart}}
</div>
<div class='col-md-6'>
{{> highchartsHelper chartId="humidity"
chartWidth="100%" charHeight="100%"
chartObject=humidityChart}}
</div>
</div>
</div>
</body>
</template>
The most important elements in this interface are the charts, defined by the following line
(here for temperature):
{{> highchartsHelper chartId="temperature"
chartWidth="100%" charHeight="100%"
chartObject=temperatureChart}}
For this project, we are going to use HighCharts (http://www.highcharts.com/) to plot the
data recorded on the server. This is a very convenient library to plot data in JavaScript
applications, and it is easy to integrate in Meteor.
On the server side, we need to add the board in our project:
if (Meteor.isServer) {
Meteor.startup(function () {
aREST.addDevice('http', '192.168.115.104');
});
}
Then, in the rendered function, we need to format the data so it can be used by the charts
elements. This is done by the following piece of code:
Template.home.rendered = function() {
Tracker.autorun(function () {
// Get all events for temperature
eventsTemperature = Events.find({variable: 'temperature'}).fetch();
eventsHumidity = Events.find({variable: 'humidity'}).fetch();
// Split in arrays
timestamps = [];
temperatureData = [];
humidityData = [];
for (i = 0; i < eventsTemperature.length; i++){
timestamps.push(moment(eventsTemperature[i].timestamp).format('HH:mm'));
temperatureData.push(parseFloat(eventsTemperature[i].value));
humidityData.push(parseFloat(eventsHumidity[i].value));
}
// Set session variables
Session.set('timestamps', timestamps);
Session.set('temperatureData', temperatureData);
Session.set('humidityData', humidityData);
});
}
This will ensure that the data is refreshed whenever a new measurement point comes in,
and therefore that we will plot live data.
Then, we can finally link this data to the charts we defined before. This is for example for
the temperature chart:
Template.home.temperatureChart = function() {
return {
title: {
text: 'Temperature',
x: -20 //center
},
xAxis: {
categories: Session.get('timestamps'),
tickInterval: 10
},
yAxis: {
title: {
text: 'Temperature (C)'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
valueSuffix: 'C'
},
series: [{
name: 'Temperature',
data: Session.get('temperatureData')
}]
};
};
Its now time to test the project! First, grab all the code from the GitHub repository of the
book:
https://github.com/marcoschwartz/discover-arest
Then, navigate to the folder where the files are located with a terminal, and type:
meteor create .
After that, add the aREST Meteor module and the HighCharts module with:
meteor add maazalik:highcharts marcoschwartz:arest
You should immediately see the live recording of the data being displayed on your screen.
This is the result after several minutes of recording:
You can of course build on this project to make other recording applications. For example,
you can personalize the graphs for your own needs, by visiting the HighCharts website
and looking at the examples there. You can also add more boards to the projects, and plot
all the data in live inside the application.
Now, for the lamp controller, connect the Vin+ pin of the kit to the ESP8266 pin 4. Then,
connect the two other pins to GND pins of the ESP8266.
This is the assembled lamp controller:
Also connect a lamp or another appliance to the PowerSwitch Tail, and the other end of
the PowerSwitch Tail to the mains electricity.
The motion sensor module is quite easy to assemble. Connect the OUT (or SIG) pin of the
motion sensor to pin number 5 of the ESP8266. Then, connect the VCC pin of the sensor
to the 3.3V, and GND to GND.
This is the completely assembled motion sensor:
// Variables
float temperature;
float humidity;
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init DHT
dht.begin();
// Give name and ID to device
rest.set_id("1");
rest.set_name("esp8266_control");
// Expose variables
rest.variable("temperature", &temperature);
rest.variable("humidity", &humidity);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
This is already a sketch with saw several times, so I wont detail it here. Just make sure to
change your WiFi name and password, and upload the sketch to the board. Then, open the
Serial monitor and reset the board to get the IP address of the board.
Now, just check that the board is responding to aREST commands by typing the following
command in your web browser, of course by changing the IP address:
http://192.168.115.104/temperature
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
This is already a sketch with saw several times, so I wont detail it here. Just make sure to
change your WiFi name and password, and upload the sketch to the board. Then, open the
Serial monitor and reset the board to get the IP address of the board.
Now, just check that the board is responding to aREST commands by typing the following
command in your web browser, of course by changing the IP address:
http://192.168.115.105/mode/4/o
Then, switch on the lamp or the appliance connected to the PowerSwitch Tail by typing:
http://192.168.115.105/digital/4/1
// WiFi parameters
const char* ssid = "wifi-name";
const char* password = "wifi-password";
// The port to listen for incoming TCP connections
#define LISTEN_PORT 80
// Create an instance of the server
WiFiServer server(LISTEN_PORT);
WiFiClient restClient;
// Variable
bool motion = false;
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Give name and ID to device
rest.set_id("3");
rest.set_name("esp8266_motion");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
// Set motion sensor pin
pinMode(5, INPUT);
}
void loop() {
// Reading temperature and humidity
bool motionStatus = digitalRead(5);
// Publish
if (motionStatus != motion) {
if (restClient.connect(servername, port)) {
rest.publish(restClient, "motion", motionStatus);
}
}
motion = motionStatus;
This is already a sketch with saw several times, so I wont detail it too much here. What
changes here is that we only publish data to the server when we detect a change on the
motion detector, which is done by the following piece of code:
// Reading temperature and humidity
bool motionStatus = digitalRead(5);
// Publish
if (motionStatus != motion) {
if (restClient.connect(servername, port)) {
rest.publish(restClient, "motion", motionStatus);
}
}
motion = motionStatus;
Just make sure to change your WiFi name and password, as well as the IP address of your
computer, and upload the sketch to the board. Then, open the Serial monitor and reset the
board to get the IP address of the board.
The interface is composed of three elements: buttons to control the lamp, text indicators
for the sensor readings, and finally another indicator for the motion sensor status.
Then, on the server side, we add the three modules to the server:
if (Meteor.isServer) {
Meteor.startup(function () {
// Add device
aREST.addDevice('http', '192.168.115.104');
aREST.addDevice('http', '192.168.115.105');
aREST.addDevice('http', '192.168.115.106');
});
}
Then, in the rendered function, we set pin 4 to an output, and also refresh the
measurements from the sensors:
Template.home.rendered = function() {
// Set pin
Meteor.call('pinMode', 2, 4, 'o');
// Refresh temperature & humidity
Meteor.call('getVariable', 1, 'temperature', function(err, data) {
console.log(data);
$('#temperature').text(data.temperature);
});
Meteor.call('getVariable', 1, 'humidity', function(err, data) {
$('#humidity').text(data.humidity);
});
}
We also create a dedicated helper for the motion sensor status. As this is directly linked to
the database of Meteor, this will be automatically refreshed whenever a new status is
recorded by the application. This is the code to do that:
Template.home.helpers({
motionStatus: function() {
// Motion sensor
var sensorState = Events.find({}, {sort: {timestamp: -1}}).fetch()[0];
console.log(sensorState);
if (sensorState.value == '1') {
return 'Motion detected';
}
if (sensorState.value == '0') {
return 'No motion';
}
}
});
Finally, we define two events to link the buttons inside the interface:
Template.home.events({
'click #on': function() {
Meteor.call('digitalWrite', "2", 4, 1);
},
'click #off': function() {
Meteor.call('digitalWrite', "2", 4, 0);
}
});
Now, grab all the code from the GitHub repository of the book, and put it all inside a
folder on your computer. Then, initialise a new Meteor project with:
meteor create .
You can now try it, for example by clicking on a button. You can also pass your hand in
front of the motion sensor: the indicator inside the interface will change immediately.
You can of course now connect more modules to the interface, as its really easy to do
using the Meteor aREST module. At the end, you can have a complex home automation
system based on the aREST framework.
void loop() {
// Connect to the cloud
rest.loop(client);
}
// Handles message arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length) {
rest.handle_callback(client, topic, payload, length);
}
Lets see what we modified compared to other aREST sketches we saw so far. The cloud
version of aREST uses MQTT t communicate with a server deployed in the cloud, so well
need to set several things related to MQTT communications.
First, we included the PubSubClient library in addition to the other required libraries:
#include <SPI.h>
#include "Ethernet.h"
#include <PubSubClient.h>
#include <aREST.h>
Then, in the setup() function, we set the callback. Well see what that does later:
client.setCallback(callback);
We also set an ID for our aREST device. This is very important, as it will identify the
device on the cloud server. You will use this ID later to control your board from the cloud
server. Please modify this ID here so you have your own unique ID on the server:
char* device_id = "9u2co4";
We also set the output topic for the aREST cloud server communications:
char* out_topic = rest.get_topic();
In the loop() function, we simply need to pass the client instance to aREST:
rest.handle(client);
This function will simply handle the data received by the board via MQTT from the cloud
server, and answer accordingly.
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
You can now open the Arduino IDE and open the code for this project. Save the sketch
somewhere, and modify MAC address inside the sketch. You will find the MAC address
below the Ethernet shield. Also give an unique ID to your board. Then, upload the sketch
to the Arduino board.
Go to your favorite web browser, and type:
cloud.arest.io/9u2co4/id
Now, try to power down the device, wait around 10 seconds, and type the same command
again. You should get the following answer:
{
"message": "Requested device is not online",
"connected": false,
"id": "9u2co4"
}
Next, activate the device again, and type the following inside your browser:
cloud.arest.io/9u2co4/mode/5/o
This will make pin number 5, which is connected to the LED, to an output. After that,
type:
cloud.arest.io/9u2co4/digital/5/1
This will make a digitalWrite() command to pin 5 and it will turn the LED on. If that
works, it means that aREST is working correctly, and that you can access your board from
anywhere in the world.
// Libraries
var express = require('express');
var app = express();
var piREST = require('pi-arest')(app);
var sensorLib = require('node-dht-sensor');
// Set ID & name
piREST.set_id('p5dgwt');
piREST.set_name('pi_cloud');
// Connect to cloud.aREST.io
piREST.connect();
// Start server
var server = app.listen(80, function() {
console.log('Listening on port %d', server.address().port);
});
// Sensor readout
var sensor = {
initialize: function () {
return sensorLib.initialize(11, 4);
},
read: function () {
// Read
var readout = sensorLib.read();
temperature = readout.temperature.toFixed(2);
humidity = readout.humidity.toFixed(2);
// Set variables
piREST.variable('temperature', temperature);
piREST.variable('humidity', humidity);
console.log('Temperature: ' + temperature + 'C, ' +
'humidity: ' + humidity + '%');
// Repeat
setTimeout(function () {
sensor.read();
}, 2000);
}
};
// Init sensor
if (sensor.initialize()) {
sensor.read();
} else {
console.warn('Failed to initialize sensor');
}
Lets now see the most important parts of this code. First, we declare the Node.js modules
that we will use for this project:
var express = require('express');
var app = express();
var piREST = require('pi-arest')(app);
Then, we set an ID & a name to our project. Make sure to modify the ID, as it will identify
your Raspberry Pi project on the aREST server:
piREST.set_id('p5dgwt');
piREST.set_name('pi_cloud');
After that, the rest of the code is dedicated to connecting to the cloud server. At the end of
the code, we initialise the DHT11 sensor:
if (sensor.initialize()) {
sensor.read();
} else {
console.warn('Failed to initialize sensor');
}
Note that you can find all the code inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Its now time to test it. Put all the code into a file (named here cloud.js), and inside the
folder where the file is located type:
sudo npm install pi-arest express node-dht-sensor
This will take a while, especially on the first versions of the Raspberry Pi. After that, type:
sudo node cloud.js
This will connect the Raspberry Pi to the cloud API, and you should see the confirmation
in the console.
We are now going to use the cloud API by hand before using it from a dashboard later in
this book. For that, go to your favorite web browser, and type:
https://cloud.arest.io/p5dgwt/temperature
Of course, replace the ID of the board in the URL by the one you set in the code. You
should get the answer of the Pi in JSON format:
{
"id": "p5dgwt",
"name": "pi_cloud",
"hardware": "rpi",
"connected": true,
"temperature": 24
}
As you can see, the temperature is returned as a field in the JSON object. This will be
useful for later to grab the temperature from a dashboard.
We can now do the same to turn on any electrical device connected to the PowerSwitch
tail kit:
https://cloud.arest.io/p5dgwt/digital/13/1
Its really important here to notice that those commands are called from a cloud server,
and that they can be called from anywhere in the world!
WiFiClient espClient;
PubSubClient client(espClient);
// Create aREST instance
aREST rest = aREST(client);
// Unique ID to identify the device for cloud.arest.io
char* device_id = "9u2co4";
// WiFi parameters
const char* ssid = "wifi-name";
const char* password = "wifi-password";
// Declare functions to be exposed to the API
int ledControl(String command);
// Functions
void callback(char* topic, byte* payload, unsigned int length);
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Set callback
client.setCallback(callback);
// Function to be exposed
rest.function("led",ledControl);
// Give name and ID to device
rest.set_id(device_id);
rest.set_name("esp8266");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Set output topic
char* out_topic = rest.get_topic();
}
void loop() {
// Connect to the cloud
rest.loop(client);
}
// Handles message arrived on subscribed topic(s)
As you can see, the code is quite similar to what we saw earlier in this book. What you
need to change here is the device ID, which identifies the device on the network:
char* device_id = "9u2co4";
Then, modify the WiFi network name and password in the code:
const char* ssid = "wifi-name";
const char* password = "wifi-password";
You can now open the Arduino IDE, and grab the code from the GitHub repository of the
book. Save the sketch somewhere, and modify the WiFi name & password inside the
sketch. Also give an unique ID to your board. Then, upload the sketch to the ESP8266
board. Go to your favourite web browser, and type:
cloud.arest.io/9u2co4/id
Its also easy to call a function present on the board, that has been exposed to the aREST
API. First, type:
cloud.arest.io/9u2co4/mode/5/o
"connected": true
}
You can now control your ESP8266 boards from anywhere! As they only cost around $5,
it makes it the perfect solution for your Internet of Things projects.
First, place the ESP8266 board on the breadboard. Then, place the resistor in series with
the LED. Connect the resistor to pin number 5 of the ESP8266 board, and the other end of
the LED to one GND pin of the ESP8266.
This is the final result:
// Functions
void callback(char* topic, byte* payload, unsigned int length);
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Set callback
client.setCallback(callback);
// Init variables and expose them to REST API
temperature = 24;
humidity = 40;
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id(device_id);
rest.set_name("esp8266");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Set output topic
char* out_topic = rest.get_topic();
}
void loop() {
// Connect to the cloud
rest.loop(client);
}
// Handles message arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length) {
rest.handle_callback(client, topic, payload, length);
}
For this section, I didnt want to complicate things by using a sensor, so I just defined two
variables that contains data:
int temperature;
int humidity;
temperature = 24;
humidity = 40;
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
Of course, you could perfectly connect a sensor to your board, and use the readings from
this sensor to feed the aREST variables that we declared in the sketch.
As usual, you will also need to change the ID of the device in the sketch, as well as you
WiFi name & password.
After that, put the board in bootloader mode, and upload the code to the board. You can
quickly check in the Serial monitor that the board is indeed connected to aREST.io.
After creating a new dashboard, you will see it in the main window:
Click on your newly created dashboard, and create a first element to control the LED on
the board. Put a name, the ID of your device, and also assign pin 5 to this dashboard
element. This is how it looks like:
Then, add the element by clicking on the Create button, and you will see that the element
has been added to the dashboard:
Finally, its time to test your dashboard element! Simply click on the ON button: you
should immediately see the LED turning on on your board.
Also note that every time you create a new dashboard element to control a digital pin, this
You will rapidly see the value of the variable displayed in your dashboard. You can now
do the same for the temperature variable:
You can now create a dashboard to control a single board, in the cloud, using the aREST
framework. You can of course use what you learned in this chapter to control all kind of
on/off devices from your dashboard, for example a relay.
You can also use the cloud dashboard service to display temperature, humidity, or
measurements coming from other sensors.
sensor) of the sensor to the RPi 3.3V, and GND to GND. Finally, insert the 4.7K Ohm
resistor between pin number 1 and 2.
This is a close-up of the final result:
},
read: function () {
// Read
var readout = sensorLib.read();
temperature = readout.temperature.toFixed(2);
humidity = readout.humidity.toFixed(2);
// Set variables
piREST.variable('temperature', temperature);
piREST.variable('humidity', humidity);
console.log('Temperature: ' + temperature + 'C, ' +
'humidity: ' + humidity + '%');
// Repeat
setTimeout(function () {
sensor.read();
}, 2000);
}
};
// Init sensor
if (sensor.initialize()) {
sensor.read();
} else {
console.warn('Failed to initialize sensor');
}
As for the previous chapter, make sure to give an unique ID to the board. Also, make sure
to give a name to the board here, it will be used in the dashboard to identify which boards
is connected to the dashboards functions.
Its now time to connect this Raspberry Pi to the cloud server. Put all the code into a file
(named here cloud.js), and inside the folder where the file is located type:
sudo npm install pi-arest express node-dht-sensor
This will take a while, especially on the first versions of the Raspberry Pi. After that, type:
sudo node cloud.js
This will connect the Raspberry Pi to the cloud API, and you should see the confirmation
in the console.
Lets now deal with the Raspberry Pi that will control an electrical appliance. This is the
code for this Pi:
// Libraries
var express = require('express');
var app = express();
var piREST = require('pi-arest')(app);
// Set ID & name
piREST.set_id('r6hwcy');
piREST.set_name('pi_lamp');
// Connect to cloud.aREST.io
piREST.connect();
// Start server
var server = app.listen(80, function() {
console.log('Listening on port %d', server.address().port);
});
As with the other Pi, make sure to modify the ID & name in the code.
Again, we will connect this Pi to the cloud API. Put all the code into a file (named here
cloud.js), and inside the folder where the file is located type:
sudo npm install pi-arest express
This will take a while, especially on the first versions of the Raspberry Pi. After that, type:
sudo node cloud.js
This will connect the Raspberry Pi to the cloud API, and you should see the confirmation
in the console.
Both our Raspberry Pi boards are now connected to the cloud API. You can test that a
board is actually connected by typing the ID in the board after the URL of the cloud API
server. For example:
https://cloud.arest.io/p5dgwt
If you can see the device answering with its name and ID, it means that it is currently
online.
From there, you will be able to access all the variables from your Pi board and control
them remotely. First, add the temperature & humidity indicators from the Raspberry board
with the DHT sensor:
As you can see, the name of the device will appear on the dashboard, so you can easily
identify to which device the data corresponds.
Finally, add an On/Off element for the second Raspberry Pi. This is is the final result
inside the dashboard:
Of course, feel free to try the button for example. Any electrical appliance connected to
the second Raspberry Pi should immediately turn on. Congratulations, you can now
control several devices from your a cloud dashboard, from anywhere in the world!
In this section, we integrated several Raspberry Pi boards into a single dashboard, so you
can control your home automation projects from anywhere. Of course, you could perfectly
add more boards to the project, and control them all from a single interface. And you can
of course pack several sensors and controllers on every board as well!
You can choose the cheapest plan, as we wont need a lot of computing power:
You will see the Droplet in the list of Droplets on your account, along with the IP address
of the Droplet:
You will need this IP address in a moment. Now, you should also have received a
password via email. However, I recommend setting up SSH keys on your computer, to
access your server without password. You can learn how to do it using the tutorial found
on this page:
https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys2
https://github.com/marcoschwartz/meteor-arest-mqtt
Put the code in a folder on your computer, and type:
meteor create .
This will initialise a new Meteor project. Then, install the required Meteor modules with:
meteor add meteorhacks:npm percolate:synced-cron iron:router http
If everything goes well, stop the local Meteor server. We are now going to install a tool
called Meteor Up to easily deploy our project on your Digital Ocean server. For that, type:
npm install -g mup
Followed by:
mup init
This will create several files in your folder, including a file called mup.json. Open this file,
and paste the following code:
{
// Server authentication info
"servers": [
{
"host": "159.203.92.147",
"username": "root",
//"password": "password"
// or pem file (ssh based authentication)
"pem": "~/.ssh/id_rsa"
}
],
// Install MongoDB in the server,
// does not destroy local MongoDB on future setup
"setupMongo": true,
// WARNING: Node.js is required! Only skip
// if you already have Node.js installed on server.
"setupNode": true,
// WARNING: If nodeVersion omitted will setup 0.10.36 by default.
// Do not use v, only version number.
"nodeVersion": "0.10.40",
// Install PhantomJS in the server
"setupPhantom": true,
// Show a progress bar during the upload of the bundle to the server.
// Might cause an error in some rare cases if set to true,
// for instance in Shippable CI
"enableUploadProgressBar": true,
// Application name (No spaces)
"appName": "arest",
// Location of app (local directory)
"app": ".",
// Configure environment
"env": {
"ROOT_URL": "http://localhost",
"PORT": 3000
},
// Meteor Up checks if the app comes online just after the deployment
// before mup checks that, it will wait for no. of seconds configured below
"deployCheckWaitTime": 15
}
The only thing you need to modify here is the IP address of your Droplet, and also insert
your password if you are using the password method to access your server.
Then, you can configure the server with:
mup setup
Once this is done, congratulations, your deployed your own aREST server on the cloud!
PubSubClient client(espClient);
// Create aREST instance
aREST rest = aREST(client, "159.203.92.147");
// Unique ID to identify the device for cloud.arest.io
char* device_id = "9u2co4";
// WiFi parameters
const char* ssid = "wifi-name";
const char* password = "wifi-password";
// Declare functions to be exposed to the API
int ledControl(String command);
// Functions
void callback(char* topic, byte* payload, unsigned int length);
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Set callback
client.setCallback(callback);
// Give name and ID to device
rest.set_id(device_id);
rest.set_name("esp8266");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Set output topic
char* out_topic = rest.get_topic();
}
void loop() {
// Connect to the cloud
rest.loop(client);
}
// Handles message arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length) {
rest.handle_callback(client, topic, payload, length);
As you can see, the code is really similar to the one we saw earlier in this chapter. The
only difference is this part:
aREST rest = aREST(client, "159.203.92.147");
As you can see, you need to pass the IP address of the server as a second argument. This
will indicate to aREST to connect to your own server and not the aREST cloud server.
Now, configure the board with the code we just saw, by making sure to insert the IP
address of your server, and also to enter your WiFi name and password.
Then, upload the code to the board. You can now check the connection with your own
server by going to the IP address of the Droplet, followed by port 3000. For example:
http://159.203.92.147:3000/9u2co4/id
Congratulations, you just connected a board to your own cloud server! You can now do
everything we did so far in this chapter, but this time by using your own server. You can
now also buy a domain name if you wish, and redirect it to the IP address of your Droplet.
float humidity;
// Functions
void callback(char* topic, byte* payload, unsigned int length);
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Init DHT
dht.begin();
// Set callback
client.setCallback(callback);
// Init variables and expose them to REST API
rest.variable("temperature",&temperature);
rest.variable("humidity",&humidity);
// Give name and ID to device
rest.set_id(device_id);
rest.set_name("sensor2");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Set output topic
char* out_topic = rest.get_topic();
}
void loop() {
// Reading temperature and humidity
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// Connect to the cloud
rest.loop(client);
}
// Handles message arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length) {
rest.handle_callback(client, topic, payload, length);
}
There are some things you will need to change here before uploading the code. For each
module, you need to set your own WiFi network name and password. Note that you could
perfectly use different WiFi networks for different modules: as they will all connect to the
same cloud server, this wont be an issue.
Then, you need to give an unique ID to every module, defined by the line:
char* device_id = "9u2co4";
Now, upload the code to each module. You can also verify that each module is connected
to the aREST cloud server by checking the Serial monitor or by sending them the id
command via the aREST cloud server.
For each module, create two entries, one for the temperature, and one for the humidity:
You can now monitor several boards from anywhere in the world, allowing you to monitor
the complete status of your home or a cabin while you are away! Of course, you can add
other sensors to each module to monitor even more data using aREST.
From there, we will be able to create a virtual device on which we will run the application.
From the menu, select the default device:
Then, in the next menu, you will need to select the x86_64 image for Android 5.1. Indeed,
at the time this book was written, Meteor didnt support Android 6.0. Click on the
Download button:
You should the virtual device inside the virtual devices manager:
Now, we are going to see the code for the application we will deploy on the Android
device.
First, the interface. We will simply use an interface with two buttons to turn the LED on or
off:
<head>
<title>Android</title>
<meta name="viewport" content="width=device-width,
initial-scale=1, maximum-scale=1, user-scalable=no">
</head>
<body>
<h1>ESP8266 Android Control</h1>
{{> home}}
</body>
<template name="home">
<div class='container'>
<div class='row'>
<div class='col-md-3'>
<button id='on' class='btn btn-block btn-primary'>
On
</button></div>
<div class='col-md-3'>
<button id='off' class='btn btn-block btn-warning'>
Off
</button></div>
</div>
</div>
</template>
Note here that we inserted this line, that we didnt see earlier in this book:
<meta name="viewport" content="width=device-width,
initial-scale=1, maximum-scale=1, user-scalable=no">
This will allow the interface to be perfectly scaled for your mobile device.
Then, lets see the JavaScript code for the client:
if (Meteor.isClient) {
Template.home.rendered = function() {
// Pin mode
Meteor.call('pinMode', "192.168.115.105", 5, 'o');
}
// Events
Template.home.events({
'click #on': function() {
Meteor.call('digitalWrite', "192.168.115.105", 5, 1);
},
'click #off': function() {
Meteor.call('digitalWrite', "192.168.115.105", 5, 0);
}
});
}
As you can see, we simply call Meteor methods at each click of a button.
As the Meteor aREST module doesnt support mobile applications yet, we need to define
those methods in the code:
if (Meteor.isServer) {
Meteor.methods({
digitalWrite: function(ipAddress, pin, state) {
HTTP.get('http://' + ipAddress + '/digital/' + pin + '/' + state);
},
pinMode: function(ipAddress, pin, state) {
HTTP.get('http://' + ipAddress + '/mode/' + pin + '/' + state);
}
});
}
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Then, navigate to the folder where the code is located, and type:
meteor create .
This will open the Android virtual device emulator, from which you will be able to use the
interface. Try to press on a button: it should instantly turn the LED on or off.
Of course, you can also deploy your application on your own Android device! Simply
make sure your phone is connected to your computer, and type:
meteor run android-device
Then, you need to open Xcode at least once, so you can install the required components
and to accept the Xcode terms. The procedure is over once you get to the Xcode main
screen:
<title>iOS</title>
<meta name="viewport" content="width=device-width,
initial-scale=1, maximum-scale=1, user-scalable=no">
</head>
<body>
<h1>ESP8266 iOS Control</h1>
{{> home}}
</body>
<template name="home">
<div class='container'>
<div class='row'>
<div class='col-md-3'>
<button id='on' class='btn btn-block btn-primary'>
On
</button></div>
<div class='col-md-3'>
<button id='off' class='btn btn-block btn-warning'>
Off
</button></div>
</div>
</div>
</template>
Note here that we inserted this line, that we didnt see earlier in this book:
This will allow the interface to be perfectly scaled for your mobile device.
Then, lets see the JavaScript code for the client:
if (Meteor.isClient) {
Template.home.rendered = function() {
// Pin mode
Meteor.call('pinMode', "192.168.115.105", 5, 'o');
}
// Events
Template.home.events({
'click #on': function() {
Meteor.call('digitalWrite', "192.168.115.105", 5, 1);
},
'click #off': function() {
Meteor.call('digitalWrite', "192.168.115.105", 5, 0);
}
});
}
As you can see, we simply call Meteor methods at each click of a button.
As the Meteor aREST module doesnt support mobile applications yet, we need to define
Note that you can find all the code for this part inside the GitHub repository of the book:
https://github.com/marcoschwartz/discover-arest
Make sure to enter the IP address of the board you want to control inside the Meteor code.
Then, navigate to the folder where the code is located, and type:
meteor create .
You are now ready to test the project! You can simply start it by typing:
meteor run ios
After a while, the iOS emulator will start, and your application will be loaded:
You can use it by pressing one of the buttons: the LED connected to the ESP8266 board
should immediately respond.
If you now want to deploy this application on your iOS device, you will need to have a
paid Apple iOS Developer Account.
If thats the case, simply make sure your device is connected to your computer, and type:
meteor run ios-device
After a while, you will have your application ready to be used on your iOS device.
Congratulations, you can now build iOS applications to control aREST devices!
Compared to previous projects in this chapter, you can see that we added indicators for
temperature & humidity.
Therefore, we will need to update this data inside the code for the client:
if (Meteor.isClient) {
// Events
Template.home.events({
'click #on': function() {
Meteor.call('digitalWrite', "192.168.115.105", 5, 1);
},
'click #off': function() {
Meteor.call('digitalWrite', "192.168.115.105", 5, 0);
}
});
Template.home.rendered = function() {
// Pin mode
Meteor.call('pinMode', "192.168.115.105", 5, 'o');
// Variables
Meteor.call('variable', "192.168.115.105",
'temperature', function (err, data) {
$('#temperature').text(data.temperature);
});
Meteor.call('variable', "192.168.115.105",
'humidity', function (err, data) {
$('#humidity').text(data.humidity);
});
}
}
Of course, you will need to change the IP address for the one of the board you are using.
Then, for the server code, we simply define all the function we need to communicate with
the aREST API running on the board:
if (Meteor.isServer) {
Meteor.methods({
digitalWrite: function(ipAddress, pin, state) {
HTTP.get('http://' + ipAddress + '/digital/' + pin + '/' + state);
},
pinMode: function(ipAddress, pin, state) {
HTTP.get('http://' + ipAddress + '/mode/' + pin + '/' + state);
},
variable: function(ipAddress, variable) {
var answer = HTTP.get('http://' + ipAddress + '/' + variable);
return answer.data;
}
});
}
Now, grab all the files for this project, and navigate to the folder with a terminal. Then,
initialise a new Meteor project with:
meteor create .
As you can see, the measurement from the sensor immediately appeared inside the
application. You can also deploy it on your own iOS device (if you are part of the iOS
developer program) with:
meteor run ios-device
You now have all the required knowledge to build an application to control your smart
home! You can for example add more devices, and control them all within the same
application.
Conclusion
This is already the end of this book, and I really hope you enjoyed learning about the
aREST framework! Before I give you some parting advices, lets summarize what we
learned in this book.
In the first part of the book, we saw the basics of the aREST framework, and you learned
how to control individual boards using aREST. In the second part of the book, we saw
how to build graphical interfaces & server-side applications to control your aREST
projects.
In the third part of the book, we learned how to control your projects from anywhere in the
world. Finally, in the last part of the book you learned how to build mobile applications to
control your aREST projects.
You now have all the tools to build your own projects using the power of the aREST
framework. There are limitless possibilities, but here are three project ideas that could use
the aREST framework:
1. Inexpensive remote monitoring and control of a mountain cabin using the aREST
cloud platform and ESP8266 boards
2. Control of a mobile robot based on the Raspberry Pi using the aREST meteor
application and a nice graphical interface, using the Raspberry Pi camera as the
robots eyes
3. Web-connected healthcare sensors based on the ESP8266, that send results in realtime to your own aREST cloud server
If you create a project using the aREST framework and you would like to share it with the
community, or if you have feedback about this book or aREST itself, dont hesitate to send
me an email at:
contact@arest.io
Thanks again for reading this book, and have fun creating amazing projects with the
aREST framework!