Skip to content

Latest commit

 

History

History
220 lines (182 loc) · 7.27 KB

README.md

File metadata and controls

220 lines (182 loc) · 7.27 KB

ESP32 Coding Sessions

Connect to WiFi and send data to AWS IoT

Create a BLE server and interact with devices through Bluetooth

This coding session is the first video of a series where I will be exploring the ESP32 board following capabilities:

  • Different WiFi modes
  • Different Bluetooth abilities (Bluetooth Classic and BLE)
  • Sending / Receiving data from AWS IoT

→ ESP32 dev board I used in this tutorial: https://amzn.to/3ifzLSY

Youtube Videos

Description

In this video, I walk you through all the necessary steps to programme an ESP32 dev board to connect to WiFi, create a "Thing" on AWS IoT and secure it with a generated certificate, then use the certificate to connect the ESP32 board to the Thing. Then, we create a JSON document that we send to AWS IoT over an MQTT Topic every 2 seconds.

I'm using "VS Code" with "PlatformIO" plugin and standard Arduino libraries.

APPS

Libraries

Code Walk Through

The code starts by including the required libraries. These libraries offer features to work with WiFi, Bluetooth, Json and more

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLE2902.h>

#include "WiFi.h"
#include "secrets.h"
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>

The next line defines a few macros (Constant in other languages) we will use throughout the program:

We will use later to chose when to print something for debugging

#define DEBUG

Names for the pub/sub MQTT topics

#define AWS_IOT_SUBSCRIBE_TOPIC "thing/esp32/sub"
#define AWS_IOT_PUBLISH_TOPIC   "thing/esp32/pub"

Bluetooth service and characteristic IDs

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

Then, create an instance BLEServer called pServer, an instance of BLECharacteristic called pCharacteristic, an instance of WiFiClientSecure called net and an instance of MQTTClient called client

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(256);

setup()

In the setup(), initialize a serial communication at a baud rate (speed) of 115200, but only if debug mode is defined (see macro above)

#ifdef DEBUG
    Serial.begin(115200);
#endif

And call some self explanatory methods

connectToWIFI();
connectToAWS();

startBLEserver();
startAdvertising();

Followed by printing another debug message. At this point, the ESP32 has started the Bluetooth server and is looking for client devices

#ifdef DEBUG
    Serial.println("Listening for new devices");
#endif

connectToWIFI()

This function starts by setting the WiFi mode to STA. The Station (STA) mode is used to get the ESP32 connected to a WiFi network established by an access point, so basically it's setting up to connect to your home network.

WiFi.mode(WIFI_STA);

Then, initializes the WiFi library's network settings with the credentials defined in the secrets.h file and provides the current status.

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

Prints a debug message indicating the operation has started

#ifdef DEBUG
    Serial.println("Connecting to Wi-Fi");
#endif

And waits for the connection to be established while printing a "." every half a second

while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
}

connectToAWS()

After the ESP32 is connected to the WiFi network, it's time to connect to AWS IoT using the certificate generated earlier (check the video for the steps)

// Configure WiFiClientSecure to use the AWS IoT device credentials
net.setCACert(AWS_CERT_CA);
net.setCertificate(AWS_CERT_CRT);
net.setPrivateKey(AWS_CERT_PRIVATE);

Connect to the MQTT broker on the AWS endpoint and the certifications defined earlier, it uses the default 8883 port

client.begin(AWS_IOT_ENDPOINT, 8883, net);

This line defines a way to handel incoming messages from AWS IoT through the MQTT Topic we subscribed to. In this instance, every time a message comes through, we call messageHandler

client.onMessage(messageHandler);

Print a debug message and try to establish the connection to our Thing using its THINGNAME while printing a "." every 100ms

#ifdef DEBUG
    Serial.println("AWS IoT: Connecting...");
#endif

while (!client.connect(THINGNAME)) {
    Serial.print(".");
    delay(100);
}

Prints a debug message and exits if connection can not be established

if (!client.connected()) {
    Serial.println("AWS IoT: Timeout!");
    return;
}

Otherwise, if connection is successful, then subscribe to the topic defined above and prints another success debug message

client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);

#ifdef DEBUG
    Serial.println("AWS IoT: Connected");
#endif

startBLEserver()

Initialize a new BLE (BlueTooth Low Energy) server and call it ESP32-BLE. This server will be discoverable by smartphones or any other compatible device

BLEDevice::init("ESP32-BLE");
pServer = BLEDevice::createServer();

Set a function that will handle all callbacks received by the server

pServer->setCallbacks(new ServerCallbacks());

Create a service and attach it to the server while giving it ability to read, write and notify any connected device.

BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
                                          CHARACTERISTIC_UUID,
                                          BLECharacteristic::PROPERTY_READ   |
                                          BLECharacteristic::PROPERTY_WRITE  |
                                          BLECharacteristic::PROPERTY_NOTIFY
                                       );

Set a function that will handle all callbacks that interact will the characteristic

pCharacteristic->setCallbacks(new CharCallbacks());

And finally start the server

pService->start();

startAdvertising()

Once the BLE server has started, it's time to start advertising it, which basically means making it public and waiting for connections.

BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06);  // helps w/ iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();