IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 12 - BLE na ESP-32 - Komunikace serveru s klientem - Server Nové

V předchozí lekci, Bluetooth Low Energy na modulu ESP-32 - Praktický příklad, jsme využili nabytých teoretických vědomostí o Bluetooth Low Energy k vytvoření jednoduchého projektu.

V tomto tutoriálu Internetu věcí s ESP-32 se budeme opět věnovat technologii Bluetooth Low Energy (BLE). Společně si sestavíme trochu složitější projekt, ve kterém už budeme využívat dvou mikrokontrolerů ESP-32, které mezi sebou budou komunikovat. Jeden mikrokontroler se bude chovat jako server a druhý jako klient. Prostřednictvím jejich vzájemné komunikace, zejména impulsů ze serveru, budeme ovládat LED diodu pomocí tlačítka. Díky tomuto projektu si vyzkoušíme připojení klienta k serveru, navázání komunikace a přenos signálu mezi dvěma deskami.

V této lekci vytvoříme pouze první polovinu projektu, a to serverovou část. Využívat budeme teoretických znalostí z předchozích lekcí, není třeba se proto zabývat novou teorií. Pojďme tedy rovnou na to.

Serverová část projektu

Abychom se k serveru mohli připojit, je důležité mu nastavit, aby byl viditelný pro zařízení v okolí. Server taktéž obsahuje klientem čitelná data, která se po připojení začnou přenášet. Tento přenos dat, kdy je připojen právě jeden klient k serveru, se nazývá Point To Point, to už ale víme z lekce Bluetooth Low Energy na modulu ESP-32 - Úvod. Pojďme si tedy nyní sestavit obvod pro náš server.

Schéma zapojení serveru

V obvodu využijeme tyto součástky:

  • ESP-32,
  • 1x rezistor 220Ω,
  • 1x tlačítko,
  • nepájivé pole,
  • propojovací vodiče.

Součástky osadíme následujícím způsobem:

Schéma - Internet věcí s ESP32

Program pro ESP-32

Pojďme se nyní vrhnout na samotný kód. Ten bude vcelku podobný jako v lekci Bluetooth Low Energy na modulu ESP-32 - Praktický příklad, bude se však lišit v několika drobnostech. Začneme opět hlavičkou.

Hlavička programu

Zde opět máme výhodu, že všechny použité knihovny jsou obsaženy v základní konfiguraci prostředí a nemusíme žádnou knihovnu instalovat zvlášť. Hlavička bude vypadat takto:

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

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

BLEServer* pServer = NULL;
BLECharacteristic* pCharakteristika = NULL;
BLEAdvertising* pViditelnost = NULL;
bool zarizeniPripojeno = false;

int tlacitko = 33;
bool stavTlacitka = false;

Pojďme si popsat kód. Knihovna BLEDevice.h obsahuje základní funkce pro práci s BLE zařízením, knihovna BLEUtils.h poskytuje pomocné funkce pro manipulaci s BLE daty, obsahuje také formátování identifikátorů. Poslední knihovnou je BLEServer.h, která se zaměřuje na funkcionalitu BLE serveru a poskytuje metody pro vytváření služeb a charakteristik.

Makra SERVICE_UUID a CHARACTERISTIC_UUID obsahují specifické identifikátory služby, resp. charakteristiky, které jsou klíčové pro správné navázání spojení.

Tyto naše identifikátory byly vytvořeny generátorem UUID. Při práci s BLE se musí jednat o UUID verze 4, které tento generátor dokáže vytvořit.

Vytvoříme si rovnou také objekty serveru, charakteristiky a viditelnosti našeho serveru, inicializovat je však budeme až později. Dále si vytvoříme booleovskou proměnnou zarizeniPripojeno, ve které budeme uchovávat informaci, zda je aktuálně připojeno zařízení, či nikoliv. Nastavíme také pin, ke kterému jsme připojili tlačítko.

Třídy s callbacky

Pod pojmem callback si lze představit jakési zpětné volání, které se provede při určitých situacích, např. při připojení nebo odpojení klienta. Pojďme si tedy vytvořit dvě třídy s callbacky. Nejdříve vytvořme callbacky při připojení, resp. odpojení klienta:

class MojeCallbacky : public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
        zarizeniPripojeno = true;
    }

    void onDisconnect(BLEServer* pServer) {
        zarizeniPripojeno = false;
    }
};

Třídu pojmenujeme MojeCallbacky. Důležité je, aby třída dědila ze třídy BLEServerCallbacks. V této třídě už pak jednoduše vytvoříme metodu onConnect(), která se spustí při připojení klienta na náš server. Tato metoda jen změní hodnotu proměnné zarizeniPripojeno na true. Tím získáme informaci, zda je zařízení připojeno. Tu pak využijeme v jiných částech kódu. Metoda onDisconnect() má opačnou funkci. Při odpojení zařízení změní hodnotu proměnné na false.

Pojďme nyní vytvořit třídu s callbacky pro kontrolu změny stavu na připojeném tlačítku:

class CallbackCharakteristiky : public BLECharacteristicCallbacks {
  void onRead(BLECharacteristic* pCharakteristika) {
    int aktualniStav = digitalRead(tlacitko);

    if (aktualniStav == HIGH) {
      stavTlacitka = !stavTlacitka;
    }

    pCharakteristika->setValue(stavTlacitka?"1":"0");
    pCharakteristika->notify();
  }
};

Tato třída obsahuje jedinou metodu onRead(), která má za úkol odesílat připojenému klientu aktuální stav na tlačítku.

Metody onRead(), onConnect() a onDisconnect() necháme v angličtině. Jelikož třídy může většinou využívat více uživatelů i z jiných zemí, bude tak zřejmé, o jaké funkce se jedná. Na projektu tohoto rozsahu nejspíše budeme pracovat sami, ale je dobré na toto také myslet.

Funkcí digitalRead() přečteme aktuální stav na tlačítku. Jestliže bude tato hodnota na HIGH, změní se hodnota proměnné stavTlacitka na opačnou. Tímto způsobem zapříčiníme to, že tlačítko bude fungovat jako přepínač hodnot. Po nastavení hodnot se ve funkci setValue() objektu pCharakteristika pomocí ternárního operátoru rozhodneme, jakou hodnotu chceme odeslat na server. Pokud je stav na HIGH, odešleme 1, v opačném případě 0.

Funkce setup()

Jelikož máme připraveny všechny potřebné součásti, půjdeme je nyní využít ve funkci setup(). Nastavíme náš mikrokontroler jako BLE server, určíme jeho callbacky již vytvořenými třídami a zviditelníme jej zařízením v okolí. Pojďme si nyní postupně popsat kód této funkce:

Serial.begin(115200);
pinMode(tlacitko, INPUT);
Serial.println("Spoustim BLE sluzbu!");

BLEDevice::init("ESP32 - BLEserver");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MojeCallbacky());

Na začátku nastavíme výstup do sériového monitoru, kde se nám budou zobrazovat informace o aktuálním stavu serveru, na hodnotu 115200. Pomocí funkce pinMode() nastavíme pin u tlačítka na typ INPUT. Pomocí metody init() statické třídy BLEDevice inicializujeme název našeho serveru. Do proměnné pServer uložíme instanci nově vytvořeného serveru a pomocí funkce setCallbacks() nastavíme serveru to, které callbacky má využívat. Jelikož máme vytvořenou vlastní třídu, vytvoříme nový objekt této třídy. Nyní pojďme nastavit vlastnosti službě a charakteristice:

BLEService *pSluzba = pServer->createService(SERVICE_UUID);
pCharakteristika = pSluzba->createCharacteristic(
    CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_NOTIFY
);
pCharakteristika->setCallbacks(new CallbackCharakteristiky());
pSluzba->start();

Do proměnné *pSluzba si pomocí funkce createService() vytvoříme službu danému serveru, abychom se k němu mohli připojit. Jejím parametrem je předem definovaná konstanta SERVICE_UUID. Nyní ještě vytvoříme BLE charakteristiku serveru pro tuto službu. K tomu využijeme funkci createCharacteristic(), jejíž první parametr je identifikátor charakteristiky, který máme uložený v konstantě CHARACTERISTIC_UUID. Druhým parametrem jsou vlastnosti charakteristiky. V našem případě se jedná o vlastnosti PROPERTY_READ a PROPERTY_NOTIFY, což udává, že charakteristika může být čtena a zároveň používána pro notifikace změn. Poté už jen nastavíme zpětná volání pro charakteristiku, kdy jako parametr funkce setCallbacks() použijeme nový objekt námi vytvořené třídy CallbackCharakteristiky. To znamená, že při čtení hodnoty charakteristiky budou vyvolány všechny metody této třídy. Nakonec už jen zahájíme provoz služby. V poslední části funkce setup() zviditelníme server ostatním zařízením v okolí:

BLEAdvertising *pViditelnost = BLEDevice::getAdvertising();
pViditelnost->addServiceUUID(SERVICE_UUID);
pViditelnost->setScanResponse(true);
BLEDevice::startAdvertising();

Serial.println("Charakteristika byla definovana a byla spustena viditelnost serveru.");

Nejprve vytvoříme instanci třídy zajišťující viditelnost serveru. Do ní pomocí funkce addServiceUUID() vložíme identifikátor služby, který má obsahovat zařízení, které se bude moci připojit. Funkcí setScanResponse() udáváme, že server má reagovat na skenování ostatních zařízení. Nakonec zapneme viditelnost serveru funkcí startAdvertising().

Funkce loop()

Poslední částí tohoto kódu je funkce loop(). V ní budeme zjišťovat stav na tlačítku a podle toho budeme na připojené zařízení odesílat příslušnou hodnotu:

if (zarizeniPripojeno) {
  int aktualniStav = digitalRead(tlacitko);
  if (aktualniStav == HIGH) {
    stavTlacitka = !stavTlacitka;
  }
  pCharakteristika->setValue(stavTlacitka?"1":"0");
  pCharakteristika->notify();
  delay(200);
}

delay(10);

Zjistíme, zda je zařízení připojeno, a pokud ano, uložíme do proměnné stavTlacitka aktuální stav. Poté pomocí ternárního operátoru odešleme příslušnou hodnotu na připojené zařízení pomocí funkce setValue(). Funkce notify() slouží k oznámení připojenému zařízení, že byla změněna hodnota charakteristiky.

Z této části projektu je to vše, archiv s programem je ke stažení pod lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 8x (1.44 kB)
Aplikace je včetně zdrojových kódů v jazyce C++

 

Předchozí článek
Bluetooth Low Energy na modulu ESP-32 - Praktický příklad
Všechny články v sekci
Internet věcí s ESP32
Článek pro vás napsal Adam Hudeczek
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor se věnuje zejména programování mikrokontrolerů a tvorbou a provozem webových stránek a webových aplikací.
Aktivity