[Tuto] Créer des services GATT sur ESP32

Posté sur: nov. 14, 2022

Catégories: Arduino

Auteur: Fabien

Tags: ibeacon , gatt , ble , bluetooth , 4.0

Créer des services GATT sur ESP32

La technologie Gatt est un technologie basée sur du Bluetooth. Cette technologie rend accessible toute une série de services ayant chacun plusieurs caractéristiques. Certains services sont dédiés à des usages spécifiques et sont ont un identifiant et un format fixé par Bluetooth, ceci est consultable sur le site de l'organisation Bluetooth. Par exemple, le niveau de batterie devra être dans le service 0x180F (Document "Assigned numbers").

Chaque caractéristique va avoir un identifiant (UUID), une valeur (Value), parfois une description (Descriptor) et des droits (Lecture / écriture).

L'avantage du GATT est qu'il peut fonctionner sans appairage (En mode broadcasting), cela signifie qu'un élément central peut être connecté à plusieurs éléments périphériques. L'ESP32 étant Bluetooth 4, il peut faire l'élément central et périphérique.

Pour aller plus loin, voici un excellent article d'Adafruit autour des services GATT.

Exemple avec l'ESP32

Dans notre exemple, nous allons générer une caractéristique pour piloter une LED (On utilisera la 0x07C2 désignée comme "LED lamp") et une caractéristique pour afficher l'état d'un bouton (On utilisera la 0x04C3 désignée comme "Button"). La caractéristique de LED doit être écrite par le master alors que celle du bouton doit être lu uniquement.

  #include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEUtils.h"
#include "BLE2902.h"

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
BLECharacteristic* ledCharacteristic = NULL;
BLECharacteristic* buttonCharacteristic = NULL;
bool deviceConnected = false;
uint32_t value = 0;

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define LED_CHARACTERISTIC_UUID 0x07C2
#define BUTTON_CHARACTERISTIC_UUID 0x04C3
#define LED_PIN LED_BUILTIN
#define BUTTON_PIN 23

uint8_t button_state = false;
boolean led_state = false;
boolean led_change = false;

class MyServerCallbacks: public BLEServerCallbacks {
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};

class MyCallback : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* ledCharacteristic) {
std::string rxValue = ledCharacteristic->getValue();
if (rxValue == "1") {
led_state = true;
} else {
led_state = false;
}
led_change = true;
}
};

void setup() {
Serial.begin(115200);

// Pinout
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);

// Initier le Device
BLEDevice::init("ESP32");

// Initier le Serveur
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

// Initier le Service
BLEService *pService = pServer->createService(SERVICE_UUID);

// Initier les Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
ledCharacteristic = pService->createCharacteristic(
(uint16_t) LED_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_INDICATE
);
ledCharacteristic->setCallbacks(new MyCallback());
buttonCharacteristic = pService->createCharacteristic(
(uint16_t) BUTTON_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
buttonCharacteristic->setValue(&button_state, 1);

// Lancer le service
pService->start();

// Broadcaster
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0);
BLEDevice::startAdvertising();
}

void loop() {
// Deconnexion
if (!deviceConnected) {
delay(500); // Laisser du temps pour que le Bluetooth revienne
pServer->startAdvertising(); // relancer le broadcast
Serial.println("start advertising");
deviceConnected = true;
}
// Boutton
if (digitalRead(BUTTON_PIN) != button_state) {
Serial.println("Changement bouton");
button_state = !button_state;
buttonCharacteristic->setValue(&button_state, 1);
buttonCharacteristic->notify();
}
// LED
if (led_change == true) {
Serial.println("Changement LED");
digitalWrite(LED_PIN, led_state);
led_state = !led_state;
led_change = false;
}
}

Pour tester on utilise l'application Android Nrf Connect

Coté information sur les services GATT et l'ESP32, nous avons utilisé ce très bon tutoriel.

laissez un commentaire

Se connecter