Mohykáni si možno ešte spomínajú na moju implementáciu Webkitu z roku 2019 až 2020 pre hlasové ovládanie v slovenčine pre mikrokontróler ESP32 či ESP8266. Existovali dve webaplikácie a to demo pre jednoduché ON/OFF ovládanie, kde sa na webe dynamicky menil stav ESP8266 Lolin, jeho integrovanej LED diódy, alebo rozšírená web aplikácia pre ovládanie auta v štyroch rôznych smeroch. Implementácia bola navrhnutá pre ESP8266 s motor shieldom, ktorý cez H-mostík dokáže obsluhovať motor autíčka. Bola tam aj možnosť doprogramovania si ďalších vlastných funkcionalít. Toho času to fungovalo výhradne iba na Google Chrome.

2019-2020 Webkit funkčný len pod Chrome prehliadačom
V tom čase ESP8266 či ESP32 fungovali ako HTTP(S) klienti, ktorí periodicky načítavali obsah .txt súboru, ktorý obsahoval príkaz. Ak bol príkaz detekovaný, vykonal sa a následne mikrokontróler zavolal PHP script a nastavil príkaz na východzí, po ktorého načítaní sa nevykonávala akcia ovládania motorov H-mostíkom L298N na strane ESP.
Doba pokročila, Webkit okrem Google Chrome začali podporovať aj iné prehliadače (určite funguje na Edge, aj v Mi prehliadači), ba dokonca sa prešlo aj k univerzálnemu API SpeechRecognition pre preklad hlasu na text Speech-to-text (STT). Toto API funguje už vo všetkých prehliadačoch, isté problémy, resp. nepodporované funkcionality sa objavujú pri prehliadačoch Firefox a Opera, sú tam aj isté rozdiely v podpore pre Windows a Android verzie. Okrem angličtiny je podporovaný aj slovenský jazyk, ale dnes sa budeme držať angličtiny, konkrétne americkej s jazykovým kódom en-US.
Ukážeme si implementáciu hlasového ovládania s API SpeechRecognition, pričom využijeme Firebase Realtime databázu pre uchovanie posledného príkazu, ktorý bude preberať mikrokontróler ESP32 a na jeho základe vykonávať akciu. Firebase je produkt Googlu, ktorý je určený pre vývoj mobilných a webových aplikácii. Obsahuje množstvo nástrojov a služieb a jedna z nich je Realtime databáza, ktorú dnes použijeme. Tieto aplikácie je možné používať aj samostatne a nemusia sa viazať ani na vyvíjanú mobilnú či webovú aplikáciu v rámci Firebase. V rámci Firebase Google ponúka aj možnosť použitia jeho nástroja Gemini pre umelú inteligenciu, ktorá vám uľahčí vývoj aplikácii.

Na začiatku je nutné vytvoriť si projekt v rámci Firebase, ku ktorému je pridelený unikátny identifikátor, ktorý bude súčasť URL linku aplikácie. Nnásledne je potrebné vytvoriť Realtime databázu skrz záložku Build v navigácii a cez tlačidlo Create Database. Táto databáza v službe Firebase je typom NoSQL databázy, ktorá umožňuje ukladať a zároveň sychronizovať dáta v reálnom čase so všetkými klientmi, ktorí ju používajú. Môže tak ísť o mobilné zariadenia, 3rd party služby, či mikrokontroléry. Pre optimálnu rýchlosť databázy sa pri jej vytváraní volí región. Sú dostupné 3 servery, z toho jeden v USA, druhý v Belgicku a tretí v Singapure. Najoptimálnejšie je tak samozrejme Belgicko.

Databáza ukladá dáta v štruktúre JSON, ktorá je optimálna pre naše použitie. Je to štandardná štruktúra, ktorú používajú REST API systémy a je tak vhodná aj pre integráciu so systémami pre smart home napr. Hassio, Domoticz a iné. Táto štruktúra je hierarchická a prístup k databáze môže byť riadený rôzne s nastavením špecifických pravidiel pre čítanie a zápis. Pre testovací účel necháme prístup na čítanie a zápis komukoľvek bez autorizácie (verejná aplikácia).

Základným kameňom v štruktúre je koreňový uzol (root node) a ten má pod sebou jednotlivé dáta v JSON štruktúre. Môžeme si to predstaviť ako istú entitu, ktorá je evidovaná pod určitým názovom. V našom prípade budeme ukladať premenné, JSON kľúče text (hlasový príkaz prevedený na text) a timestamp (časovú značku). Samotný koreňový uzol nie je nutné vytvárať, vytvorí sa dynamicky v momente, keď sú do databázy zapísané dáta smerujúce na uzol a odvtedy je už viditeľný v databáze prakticky navždy.

Aby sme si mohli lepšie demonštrovať hierarchickú štruktúru, budeme potrebovať najprv do Firebase Realtime databázy dostať nejaké dáta. Využijeme statickú webstránku na Github Pages, kde budeme hostovať jednoduchú HTML stránku, ktorá umožuje preklad reči na text skrz SpeechRecognition API. Keďže Github Pages nepodporuje backend a ide iba o statické stránky, musíme sa vynájsť.

Použijeme preto request skrz Javascript funkciu fetch(), ktorý bude smerovaný na Firebase Realtime databázu. Nakoľko budeme iba prepisovať posledné dáta a nepotrebujeme históriu hlasových príkazov, použijeme HTTP metódu PUT. Ak by sme využili metódu POST, uchovali by sme kompletne všetky hlasové príkazy, pričom pre každý záznam by Firebase realtime databáza vygenerovala aj identifikátor, ktorý sa nazýva aj push key / unique key. Ukážeme si vzorovo oba prípady.

Request budeme smerovať na Firebase realtime databázu na koreňový uzol data s JSON štruktúrou spomenutou vyššie, ktorá okrem príkazu zahŕňa aj časovú značku v UNIX formáte (Epoch, počet sekúnd od 1. Januára 1970). Takýto request je smerovaný na URL databázy/data.json.
Viditeľnosť dát vo Firebase realtime databáze zapísané POST metódou:


Viditeľnosť dát vo Firebase realtime databáze zapísané PUT metódou:

Ako môžeme vidieť, v prípade PUT metódy budú v databáze iba posledné známe dáta. Teda aj keby sme v nej mali skoršie dáta zapísané POST metódou, v momente zapísania PUT metódou sú odstránené a je tu iba posledný príkaz. Zadávali sme celkom sériu 3 príkazov a to hi, how are you doing a is today Monday.
K dátam môžeme pristupovať rôznymi spôsobmi, najľahšie cez metódu HTTP GET, na ktorej si môžeme jednoducho ukázať hierarchiu realtime databázy pod Firebase. Môžeme dopytovať celú štruktúru pre konkrétny koreňový uzol, čím získame kompletnú JSON štruktúru, ktorá je pod ním. V tomto prípade je štruktúra tvorená textom hlasového príkazu a časovou značkou. Pre získanie konkrétnej hodnoty musíme vykonať parsovanie podľa JSON kľúča, ktorému hodnota prislúcha.

Rovnako tak môžeme dopytovať aj konkrétnu položku už priamo v URL dopyte a prevziať si tak v response len konkrétnu hodnotu bez ďalších položiek. V reálnych aplikáciách môžete naraziť na JSON štruktúry, ktoré môžu mať stovky položiek, viacúrovňové usporiadania a podobne. Je to vec, ktorá vám môže uľahčiť značné množstvo zdrojov na strane vášho mikrokontroléra, najmä RAM-ku, ktorá môže byť kritická v mnohých aplikáciách.


Klienti tejto Firebase realtime databázy sú schopní detekovať, že boli do databázy zapísané nové dáta a na základe callbacku môžu vykonať určitú akciu jednorázovo. Teda nie je potrebné aktuálny obsah štruktúry mazať, ale vykoná sa iba raz a to v momente, keď sa pod konkrétny koreňový uzol zapíšu nové dáta. Môžeme si to prv demonštrovať Python scriptom, ktorý skrz callback vypíše dáta a to iba vtedy, keď sa zmenia (onReceive). Dáta naďalej zostávajú v databáze, nie je ich potrebné mazať a klientovi sa callback už nespustí. Celkom tak pod koreňovým uzlom data boli 3 sady príkazov, ktoré sa vzájomne prepisovali a boli do databázy zapísané ihneď po dokončení procesu premeny hlasu na text. Teda synchrónne desiatky klientov môžu vykonať určitú akciu na hlasové ovládania a vzájomne sa nijako neovplyvnia.

Pre implementáciu na strane mikrokontroléra ESP32 môžeme využiť knižnicu FirebaseESP32, alebo FirebaseClient. Vstavané funkcie umožňujú zareagovať práve na callback. Skrz ArduinoJSON knižnicu dokáže ESP32 parsovať dáta a vykonať požadovanú akciu práve raz. Vďaka nízkej latencii z dôvodu hostovaného servera v Európe môže byť hlasové ovládanie prakticky real-time a odozva je zanedbateľná, pár ms.
Hlasové ovládanie týmto spôsobom môže nájsť využitie aj do pokročilejších aplikácii, napríklad pre akcie s protokolmi pre smart home ako Matter, či Zigbee, ktoré sa stávajú ďalej populárne s ESP32-C6, či čoskoro aj s dual-band ESP32-C5. Toto riešenie je možné použiť aj na slovenský jazyk, čo je výhodné, ak by systém používali aj staršie osoby. Mnoho iných riešení pre obdobnú funkcionalitu je obmedzených práve na anglický jazyk. Finálnej aplikácii sa medze nekladú a môžete to využiť aj na obojsmernú hlasovú komunikáciu s ESP32, kedy môže ESP32 hlasom prehrávaným z reproduktora reagovať na vašu požiadavku.

