Controlling your appliances in real-time over internet is something that has always fascinated me. This is what made me pursue computer sciences as my career. I always wanted to do something with my home like Tony Stark did to his with J.A.R.V.I.S. (as you might have guessed, I am a huge marvel fan π¬). This isn't science fiction anymore. Many companies are already doing this. You can buy new smart appliances or you can build one on your own by using off-the-shelf hardware components. There are plenty of tools available for enthusiasts to build their own stuff.
But there has always been a void here. One way to build your own solution is to use white label apps like Blynk or Adafruit and the other way is to go all custom through using flagship solutions by major cloud computing companies like Google and Amazon. Both have certain pros and certain cons.
While working with Blynk and Adafruit is a very quick way to get started β because you can build your app by just dragging and dropping pre-built components β but you cannot customize enough without paying a lot. You cannot give Blynk and Adafruit your own feel and color. Which means your project can never graduate out of the prototyping phase. It will always remain a side project. For a person like me who always had this entrepreneurial side, this is just unacceptable.
On the other hand where you can go all custom with production grade solutions like GCP or AWS, getting started is a huge mess. The learning curve is very steep. You gotta integrate multiple services together means you are required to learn multiple services first.
Then I found Grandeur which comes at the sweet spot right in between both of these breeds. It is a new platform with which you can get started with really quickly β like you can do with Blynk or Adafruit β but on the same time you can go totally custom. You can use any opensource microcontroller to build your hardware and then you can use their SDK to build your own custom apps.
So that is what we are going to do in this tutorial. We are going to use ESP8266 and Grandeur to build an internet switch. In other words, we will control the onboard LED of ESP with our custom app built with Grandeur as back-end. So let us dive in π
There is a good news. The Grandeur team has written multiple tutorials on it which makes starting off with Grandeur as fluid as breathing. You can find those at their Hackster hub. For reference, here is a checklist of things that you are required to do.
- Create a new project by visiting Grandeur dashboard web app.
- Visit settings page, get your project's API key, and generate the access credentials as shown below. We will be in need of the API key and access credentials while building our app.
- Create a new user account from the accounts tab. We will later sign into our app with the email and password we create now. This is another cool feature of Grandeur: multiple users can use your app by signing in with their emails and passwords. Each user can pair its own devices and device paired by one user becomes unavailable for others. Authentication is built at the core of Grandeur. User creation is illustrated below:
- Now create a new device through devices page. This operation generates a new device ID which we'll use while writing code for our hardware. So technically, each device that communicates with the cloud needs to have a unique ID. Your device is like your digital asset with a unique ID and you will use this ID whenever you communicate to your device from your app. Plus it also generates an accessToken. Don't forget to copy it and it will be utilized in hardware code and won't be accessible after closing the dialog. Device creation is illustrated below:
- A user cannot interact with a device unless it's paired with it. There are two ways you can pair your device: 1) using the Cloud Dashboard, or 2) through the web app by using
pairDevice()
function of the device API. This second way has a very strong significance if you look at it from production point of view. Like you can now ship your hardware products, and your users can sign in to your app and declare ownership over a hardware by pairing it. Here's how you can pair your device with a user using the Cloud Dashboard:
This is it. You can follow the hello world tutorial of Grandeur to get more details about each step.
In one sentence, Grandeur acts as a universal back-end between your hardware and web app. So all the communication are made through their communication channel and their SDKs are available for both JavaScript and Arduino to make integration simpler.
One of the most amazing things that I discovered about Grandeur is its event-driven architecture. So Grandeur isn't just fast, it is event-driven. Which means there's no need to poll again and again for data. You can simply subscribe to events and you will be notified when they occur. You can subscribe to events from both ends; hardware and application. For this tutorial we are going to extend one of Grandeur's official tutorial. Let's start coding!
Our app will contain two files index.html
where we will design the layout of the page and main.js
where we will build the logic of page. We are going to use the JavaScript SDK to integrate Grandeur into our app.
The layout is very simple. The page contains a heading, a label and a button. The page looks like this and the code is below:
<!-- index.html -->
<!DOCTYPE html>
<html>
<!-- Page Header -->
<head>
<!-- Title of our page -->
<title>Internet Switch</title>
<!-- CDN link to SDK -->
<script src="https://unpkg.com/grandeur-js"></script>
</head>
<!-- Page Body -->
<body>
<!-- Page Heading -->
<h1>Internet Switch with Grandeur</h1>
<!-- Status Label -->
<p id="status">Starting</p>
<!-- Button to toggle onboard LED -->
<button onclick="toggleLED()">Toggle LED</button>
<!-- Link to our main script file -->
<script src="./main.js"></script>
</body>
</html>
We link the SDK using its CDN link and link our main script file. On the button click, we call the toggleLED()
function which we'll define in our main.js
file. Here's the main script:
/*
@file: main.js
Initialize the SDK and get
a reference to the project
*/
var project = grandeur.init("YOUR-API-KEY", "YOUR-ACCESS-KEY", "YOUR-ACCESS-TOKEN");
/*
Variable to store LED state
which will be off on start
*/
var LED = 0;
/*
Function to send request
to the server to toggle the LED
*/
async function toggleLED() {
/*
We will store the device id in a variable
we generated this id while getting started
*/
var deviceID = "YOUR-DEVICE-ID";
/* Then get a reference to device class */
var devices = project.devices();
/* and in a try catch block */
try {
/* Toggle LED variable */
LED = LED? 0: 1;
/* Submit request to update state */
var res = await devices.device(deviceID).data().set("state", LED);
/* Got the response */
switch(res.code) {
case "DEVICE-DATA-UPDATED":
/* Updated the device state successfully */
console.log(`State Updated to ${LED? "ON": "OFF"}`);
break;
default:
/* Failed to update the state */
console.log("Failed to update the state");
}
}
catch(err) {
/*
Error usually got generated when
we are not connected to the internet
*/
console.log("Network Error");
}
}
/*
We will subscribe to connection
status of SDK. Like are we connected
to the communication bridge of server
or not? The SDK automatically connects
to server on successful authentication
of a user
*/
project.onConnection((status) => {
/*
This callback gets fired
whenever the connection status
changes.
*/
switch(status) {
case "CONNECTED":
/*
If SDK is connected,
we set the status.
*/
document.getElementById("status").innerText = "Connected";
break;
default:
/*
If SDK gets disconnected, we display the status
on the app and clear the timer.
*/
document.getElementById("status").innerText = "Disconnected";
}
});
/*
Function to login user
we creating while getting started
*/
/* Function to login user */
async function login() {
/* Store credentials into variables */
var email = "EMAIL";
var password = "PASSWORD";
/* Set the status to logging in */
document.getElementById("status").innerText = "Logging in";
/* Then get a reference to auth class */
var auth = project.auth();
/* and in a try catch block */
try {
/* Submit request using login function */
var res = await auth.login(email, password);
/*
Got the response to login
handle response
*/
switch(res.code) {
case "AUTH-ACCOUNT-LOGGEDIN":
case "AUTH-ACCOUNT-ALREADY-LOGGEDIN":
/*
User Authenticated
Set the status to success
*/
document.getElementById("status").innerText = "User Authenticated";
break;
default:
/*
Logging failed due
to invalid data
*/
document.getElementById("status").innerText = "Authentication Failed";
}
}
catch(err) {
/*
Error usually got generated when
we are not connected to the internet
*/
document.getElementById("status").innerText = "Network Error";
}
}
/* Call login on startup */
login();
So in short, when the app loads it logs into the user account that we hard-coded. After logging in, it establishes the communication channel with the Cloud using the API key, access key and token which we got in the previous section. And when the button clicking calls the toggleLED
function, we send a request to the Cloud to update the state variable.
So we sent the data from the app to the Cloud, but our hardware device won't receive it unless it's listening for it. For this purpose, we'll use the Arduino SDK of Grandeur. The code is as below: π€
/* Including the SDK and WiFi library */
#include <Grandeur.h>
#include <ESP8266WiFi.h>
/* Configurations */
String deviceID = "YOUR-DEVICE-ID";
String apiKey = "YOUR-APIKEY";
String token = "YOUR-ACCESS-TOKEN";
/* WiFi credentials */
String ssid = "WIFI-SSID";
String password = "WIFI-PASSWORD";
/* Create variable to hold project and device */
Project project;
Device device;
/* Function to check device's connection status */
void onConnection(bool status) {
switch(status) {
case CONNECTED:
/* Device connected to the cloud */
Serial.println("Device is connected to the cloud.");
return;
case DISCONNECTED:
/* Device disconnected from cloud */
Serial.println("Device is disconnected from the cloud.");
return;
}
}
/* Function to handle data update event */
void updateHandler(bool state, const char* path) {
/* Print state */
Serial.printf("Updated state is %d\n", state);
/* Update pin level */
digitalWrite(2, state);
}
/* Function to connect to WiFi */
void connectWiFi() {
/* Set mode to station */
WiFi.mode(WIFI_STA);
/* Connect using the ssid and password */
WiFi.begin(ssid, password);
/* Block till the WiFi is connected */
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
/* Print message */
Serial.println("");
Serial.println("WiFi connected");
/* And IP address */
Serial.println(WiFi.localIP());
}
void setup() {
/* Begin the serial */
Serial.begin(9600);
/* Connect to WiFi */
connectWiFi();
/* Initializes the global object "grandeur" with your configurations. */
project = grandeur.init(apiKey, token);
/* Get reference to device */
device = project.device(deviceID);
/* Sets connection state update handler */
project.onConnection(onConnection);
/* Add event handler on data update */
device.data().on("state", updateHandler);
/* Set mode of LED to output */
pinMode(2, OUTPUT);
/* Turn the LED off by default */
digitalWrite(2, 0);
}
void loop() {
/*
Synchronizes the SDK with the cloud
SDK will loop till we are connected to WiFi
*/
project.loop(WiFi.status() == WL_CONNECTED);
}
The logic is very simple. We use the WiFi class to connect to the WiFi. Then we init the SDK with device ID, API key and the access token which we got in the first section. We listen to the Cloud for connection event β as we did in the web app to keep track of connection status β and data update event to toggle device pin as soon as an update from the web app arrives.
Step 4: Testing LocallyHere we are finally. Let's test what we have build. For this purpose we hook an ESP8266 to Arduino IDE and we burn the code. Then we open serial monitor to view live activity. But we gotta run our web app to send the data. For that we run a local server with Grandeur CLI. But there's a security measure. You cannot send data from your app to the Cloud unless you whitelist your domain (the address that is shown in the browser's URL bar when you open your app) from the Cloud Dashboard. This prevents all the unidentified sources from accessing your Cloud project's data in case you lose your access key.
The command line interface helps us with testing by running a local server. So simply download CLI from npm (you need nodejs, for now). Run the following command in your terminal:
npm install grandeur-cli -g # Installs the cli in your computer
Then go into the directory of your web app and run the following commands in your terminal:
grandeur init # Command associates your directory with your project
and finally run the server:
grandeur serve
This has been documented very well in the official tutorial.
This is it π₯ Now you can click on toggle button and watch the LED follow you in real time.
Bonus: Style your appSince we are talking about giving our thing our own touch and feel, I thought of leaving you guys with an extra step. Let us style our app by adding a little bit of CSS. The style sheet is as below:
/* Custom Font */
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
/* Apply Font to body*/
body {
font-family: 'Roboto', sans-serif;
margin: 0;
top: 0;
left: 0;
}
/* Apply styling to button */
button {
width: 150px;
height: 40px;
background-color: rgb(36, 107, 206);
color: white;
outline: none;
border: none;
border-radius: 5px;
transition: background-color 100ms ease-in-out;
cursor: pointer;
margin-left: 20px
}
/* Button hover */
button:hover {
background-color: rgb(36, 107, 220);
}
/* Apply styling to h1 */
h1 {
min-height: 25px;
width: 100%;
background-color: rgb(36, 107, 206);
color: white;
padding: 20px;
font-size: 20px;
margin: 0;
box-sizing: border-box;
}
/* Apply styling to p */
p {
margin-left: 20px;
color: grey
}
Woohoo π Our own custom app to control our own hardware device.
So in this tutorial we created an internet switch. We built an app through which we sent data to our ESP and toggled its onboard LED. Now you can extend it in so many ways, like you can connect a relay to the LED pin and control your appliances in real-time. In fact I am planning to do a tutorial on this topic as well. I hope it went well but if there is some kind of confusion, you can always reach me out.
Finally, if you haven't tried Grandeur yet, then do. They offer a good free tier and in my opinion, they are worth a shot. Here's the register link just in case I motivated you enough π. Do let me know about your feedback in comments.
Till next time.
Comments