# Interface
- [Fab Academy Interface ](http://academy.cba.mit.edu/classes/interface_application_programming/index.html)
- [Vote and prototype your application idea](https://miro.com/app/board/o9J_lGV-AYI=/)
![](https://i.imgur.com/dOGLlk6.png)
- [Hello World](http://helloworldcollection.de/)
## IoT Design
![](https://i.imgur.com/Sc8DURH.png)
### WebSocket
The WebSocket is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
![](https://i.imgur.com/CFBv2fN.png)
#### Example:
Source: https://esp8266-shop.com/blog/websocket-connection-between-esp8266-and-node-js-server/
## JSON
JSON is a lightweight format for storing and transporting data
JSON is often used when data is sent from a server to a web page
JSON is "self-describing" and easy to understand
- Example SmartCitizen:
+ [Map](https://smartcitizen.me/kits/)
+ [JSON](https://api.smartcitizen.me/v0/devices/world_map)
## A-Frame
A-Frame is a web framework for building virtual reality (VR) experiences. A-Frame is based on top of HTML, making it simple to get started. But A-Frame is not just a 3D scene graph or a markup language; the core is a powerful entity-component framework that provides a declarative, extensible, and composable structure to three.js.
![](https://i.imgur.com/FpkHdWU.png)
- [Official WebSite + Examples](https://aframe.io/)
- [A-Frame School](https://aframe.io/aframe-school/#/)
- [Server WebVR - A_Frame](http://15.237.42.128:1880/aframe/)
- [Glitch -> Editor](https://glitch.com)
## App Inventor
- [Download Example](https://drive.google.com/file/d/1vrDfUdV1SZK2rNtoWDHSSWezXMpudodw/view?usp=sharing)
### Extensions
- [MQTT Extension](https://drive.google.com/file/d/1YOfH7gJwZqjPF3pk5Ok_AtPMRXJRd2Mp/view?usp=sharing)
- [Sound Pressure Level](https://drive.google.com/file/d/1zsXg5OXODRPmIBTfz3QxMWsY_RYLEOJu/view?usp=sharing)
## MQTT in ESP32 Feather
:::success
IP address of BROKER:
91.126.132.8
or
um.fablabbcn.org
MQTT: um.fablabbcn.org:1883
NODE-RED: um.fablabbcn.org:1880
:::
![](https://hackaday.com/wp-content/uploads/2016/05/mqtt_dash.png =200x) ![](https://2.bp.blogspot.com/-p2fCwjQl2Ag/XHm2_Lz7EhI/AAAAAAAAI8Q/mQnXwIv0B7YTcVkV6m-ibOX172AaQUeNgCLcBGAs/s1600/adafruithuzzah32pin.jpg =200x)
[Here]() you can find information about the MQTT protocol and how it works.
You need the [Arduino IDE](https://www.arduino.cc/en/software) installed. And the [PubSubClient](https://github.com/knolleary/pubsubclient) library.
If you don't know how to install libraries on the Arduino IDE here is a [guide](https://www.arduino.cc/en/guide/libraries).
### Code Example
:::spoiler Full Code
~~~c=
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "Iaac-Wifi";
const char* password = "iaacpassword";
WiFiClient wifiClient;
const char* mqttBroker = "um.fablabbcn.org";
const char* mqttClientName = "teamx";
const char* topicToSub = "teamx/in";
const char* topicToPub = "teamx/out";
bool timeToPublish = false;
PubSubClient mqttClient(wifiClient);
void mqttConnect() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect(mqttClientName)) {
Serial.println("connected");
mqttClient.publish("hello", mqttClientName);
// Topic(s) subscription
mqttClient.subscribe(topicToSub);
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* message, unsigned int length) {
String receivedMsg;
for (int i = 0; i < length; i++) {
receivedMsg += (char)message[i];
}
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
Serial.println(receivedMsg);
if (String(topic) == topicToSub) {
// Add here the code to act on input --------------
// Arduino String obejct reference :
// https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
if (receivedMsg == ("on")) {
Serial.println("on");
digitalWrite(LED_BUILTIN, HIGH);
} else if (receivedMsg == "off") {
Serial.println("off");
digitalWrite(LED_BUILTIN, LOW);
}
//-------------------------------------------------
}
}
void setup() {
Serial.begin(115200);
// Connect to wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// MQTT setup
mqttClient.setServer(mqttBroker, 1883);
mqttClient.setCallback(callback);
// Led setup
pinMode(LED_BUILTIN, OUTPUT);
}
unsigned long lastMsg = 0;
char msg[50];
void loop() {
// Check if we are still connected to the MQTT broker
if (!mqttClient.connected()) {
mqttConnect();
}
// Let PubSubClient library do his magic
mqttClient.loop();
// Add your publish code here --------------------
// OPTION 1 -- Publish based on events
if (timeToPublish) {
timeToPublish = false;
myValue = 23; // Replace this with the value of your sensor
snprintf (msg, 50, "%i", myValue);
mqttClient.publish(topicToPub, msg);
}
// OPTION 2 -- Publish based on Timer
// Only publish every 5 seconds
unsigned long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
snprintf (msg, 50, "%ld - hello again!", now);
Serial.print("Publish message: ");
Serial.println(msg);
mqttClient.publish(topicToPub, msg);
}
//-----------------------------------------------
}
~~~
:::
### Global setup
#### Include Libraries
~~~c
#include <WiFi.h>
#include <PubSubClient.h>
~~~
#### Wifi
Change the WiFi **ssid** and **password** to fit your's.
~~~c
const char* ssid = "myWiFiName";
const char* password = "myWifiPassword";
WiFiClient wifiClient;
~~~
#### MQTT
Set the **IP address or name of your MQTT broker**, the name that will identify your device and the names of a topic(s) to subscribe and/or publish.
~~~c
const char* mqttBroker = "172.16.20.17";
const char* mqttClientName = "myAwesomeDevice";
const char* topicToSub1 = "led";
const char* topicToSub2 = "motor";
const char* topicToPub = "myOutput";
PubSubClient mqttClient(wifiClient);
~~~
:::info
Adding **variables for topic names is optional** but in this way if you need to change them you can do it in one point instead of tracking all the places where they are used.
:::
### Helper functions
#### MQTT connect function
This function is called on the main loop, it checks if the connection with the MQTT broker is alive and reconnects if necessary.
Here **we subscribe to the topics we want to receive.**
~~~c
void mqttConnect() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect(mqttClientName)) {
Serial.println("connected");
mqttClient.publish("hello", mqttClientName);
// Topic(s) subscription
mqttClient.subscribe(topicToSub1);
mqttClient.subscribe(topicToSub2);
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
~~~
#### Subscription callback
This function is executed every time a message is received. In this example if we receive the words _on_ or _off_ in a specific topic we change the led state.
~~~c
void callback(char* topic, byte* message, unsigned int length) {
String receivedMsg;
for (int i = 0; i < length; i++) {
receivedMsg += (char)message[i];
}
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
Serial.println(receivedMsg);
if (String(topic) == topicToSub1) {
if (receivedMsg == ("on")) {
Serial.println("on");
digitalWrite(LED_BUILTIN, HIGH);
} else if (receivedMsg == "off") {
Serial.println("off");
digitalWrite(LED_BUILTIN, LOW);
}
} // Here you can check for other subscribed topics
}
~~~
:::info
Subscribing to a new topic is done in three points of the code:
1. Near the top create a variable with the **topic name** you want to subscribe to.
2. In the `mqttConnect()` function add a line **subscribing to the new topic**: `mqttClient.subscribe(newName)`
3. In the `callback()` function check if the new topic is **receiving** something, **evaluate** the message and **take some actions!**
:::
### Main functions
#### Setup
Start Serial communication, WiFi, MQTT and the pin to control internal led.
~~~c
void setup() {
Serial.begin(115200);
// Connect to wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// MQTT setup
mqttClient.setServer(mqttBroker, 1883);
mqttClient.setCallback(callback);
// Led setup
pinMode(LED_BUILTIN, OUTPUT);
}
~~~
#### Loop
In the main loop we **check if the MQTT connection is still alive** and call the `mqttConnect()` function if needed.
We need to call the `mqttClient.loop()` function every cycle so the _PubSubClient_ library has time to do his inner works.
~~~c
// Declare needed variables
unsigned long lastMsg = 0;
char msg[50];
void loop() {
// Check if we are still connected to the MQTT broker
if (!mqttClient.connected()) {
mqttConnect();
}
// Let PubSubClient library do his magic
mqttClient.loop();
// Only publish every 5 seconds
unsigned long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
snprintf (msg, 50, "%ld - hello again!", now);
Serial.print("Publish message: ");
Serial.println(msg);
mqttClient.publish(topicToPub, msg);
}
}
~~~
Now make sure your broker is running and it is on the right address and power your feather!
:::info
**Publishing a MQTT message** can be done just adding a call to the `publish(topic, message)` function of the MQTT client.
:::
### Troubleshooting
* Check the output of the Feather **Serial port**
* Is WiFi connection successfull?
* Is your Feather finding the MQTT broker?
* To **interact with MQTT from your computer** you can use
[mosquitto](https://mosquitto.org/) software.
* Try sending a MQTT message to a subscribed topic and check if the feather receives it.
* Subscribe to a topic whre your Feather is posting and check if you receive something.
* **Log in** your Raspberry Pi MQTT broker.
* Check the logs of the Mosquitto broker (`/var/log/mosquitto/mosquitto.log`)
* Stop the broker `sudo systemctl stop mosquitto` and run it manually (just type `mosquitto` and hit enter) to see the the console output.
:::info
Printing **debug messages to the Serial port** can make your code big and more complicated, but when something doesn't work you will be gratefull of those lines!
:::
| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Text | Text | Text |
| Text | Text | Text |
| Text | Text | Text |
| Text | Text | Text |
| Text | Text | Text |
| Text | Text | Text |
| Text | Text | Text |
| Text | Text | Text |