Jak na IoT - Díl III. - Ovládání LED JavaScriptem
Dnešní díl seriálu budeme věnovat přesně opačné interakci, než kterou jsme probírali v minulém díle. Budeme se věnovat ovládání něčeho - v našem případě LED (ale stejně tak zde může být cokoliv jiného, třeba relé) - pomocí dynamické stránky s využitím JavaScriptu. Předpokládám, že mírný úvod do teorie dynamických stránek se mi podařilo srozumitelně nastínit minule a hned se vrhneme na to, jak ze stránky browseru dostat informaci pro náš sketch, tedy opačný přístup oproti minulému dílu, kdy jsme naopak ze sketche předávali informace na html stránku.
Vše si budeme pochopitelně demonstrovat na příkladu, jehož struktura je velmi jednoduchá a opět předpokládá, že máte zvládnutý SPIFFS tak, jak byl posán v úvodním dílu. Náš příklad se bude skládat z těchto důležitých komponent:
- Sketch ButtonJS běžící v ESP8266 a obsahující 2 tlačítka pro ovládání 1 vestavěné LED (BUILDIN_LED u modulů NodeMCU, Mini D1 apod.)
- index.htm - homepage našeho příkladu, stránka je umístěna v SPIFFS
- inner.css - descriptor css stylu, opět v SPIFFS
- buttons.js - javascript v externím souboru, který bude zodpovědný za nterakci mezi index.htm stránkou a sketchem v ESP8266, jak jinak i tento soubor máme v SPIFFS
Jak koloběh funguje si budeme opět demonstrovat na níže uvedeném obrázku, ve kterém jsou zakresleny všechny důležité komponenty příkladu (tedy až na css soubor, ten nám dělá jen barvičky a při jeho vynechání budeme mít vše v defaultním zobrazení). Všimněte si také vazeb mezi komponenty, co kam putuje a srovnejte si to s minulým dílem - vidíte, že vazby jsou přesně opačně, protože i naše interakce je přesně opačná.
Co se vlastně děje v momentě, kdy spustíme index.htm stránku - tedy kromě toho, že je načtena browserem se neděje prakticky nic. Dít se začne v momentě, kdy začneme ovládat její elementy - v našem případě 2 tlačítka. Jedno tlačítko jsem určil pro zapnutí a vypnutí LED a druhé tlačítko pouze pro zapnutí LED na 10 sekund. Kombinací si můžete vymyslet neúrekom a tlačítek kolik chcete, je to pouze příklad, takže je potřeba, aby byl přehledný. Takže klikejme postupně na 1. tlačítko, stavy se budou měnit takto:
Po načtení stránky máme 1. tlačítko v oranžové barvě - protože nesledují zpětně stav LED, zda svítí nebo ne, zvolil jsem tuto barvu - pochopitelně mohu použít znalosti z předchozího dílu (a v praxi se tak děje) a stav LED si předat a pak patřičnou barvou: zelená - LED svítí, červená - LED nesvítí, podbarvit element tlačítka. V příkladu pro jednoduchost tato vazba chybí, nicméně i tak po kliknutí na 1. tlačítko se rozvítí LEDka a tlačítko se podbarví zeleně. Kliknu-li znovu, LEDka zhasne a tlačítko se podbarví červeně. A tak pořád dookola. Co se vlastně událo? Html stránka nám přes element <button> zavolala funkci v JavaScriptu a sdělila, že byla způsobená nějaká aktivita. JavaScript tuto aktivitu vyhodnotil, podbarvil příslušným způsobem element <button> a metodou PUT odeslal informaci o stavu tlačítka na stránce sketchi v ESP8266. Ten má nastavené naslouchání na requesty JavaScriptu a v momentě, kdy dostane to, čemu rozumí, pak udělá to, co se po něm žádá - rozsvítí nebo zhasne LEDku.
Pojďme se nyní podívat na obsahy jednotlivých souborů, začneme tím nejjednodušším - to je statická stránka index.htm:
var xmlhttp=createXmlHttpObject();
function createXmlHttpObject()
{
if(window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else{xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');
}
return xmlhttp;
}
//ovládání tlačítky
function buttonHandle(id)
{
//máme aktivitu od tlačítka s ID=onoff?
if(id=='onoff')
{
//Je hodnota tlačítka OFF?
if (document.getElementById(id).value == 'OFF')
{
//změň barvu na zelenou
document.getElementById(id).style.background = '#ff0000';
//změň hodnotu na ON
document.getElementById(id).value = 'ON';
//pošli tuto skutečnost do sketche
xmlhttp.open('PUT', '/button?status=ON', true);
xmlhttp.send(null);
}
else
{
document.getElementById(id).style.background = '#00ff00';
document.getElementById(id).value = 'OFF';
xmlhttp.open('PUT', '/button?status=OFF', true);
xmlhttp.send(null);
}
}
//bylo stisknuto 2. tlačítko?
if (id=='zap10s')
{
//pošli tuto skutečnost do sketche
xmlhttp.open('PUT', '/button?status=zap10s', true);
xmlhttp.send(null);
}
}
void setup() {
......
server.on("/button", handleButton);
......
}
Pak v handleButton zacházíme s přijatými parametry, konkrétně se z JS přenáší /button?status=OFF - pro zapnutí tlačítka (obracený stav), všimněte si, jak je to celé nadrátováno.
void handleButton() { if (server.arg("status") == "OFF") { Serial.println("ON"); digitalWrite(WiFiLED, LOW); onoffState = "ON"; timerInProgress = false; } if (server.arg("status") == "ON") { Serial.println("OFF"); digitalWrite(WiFiLED, HIGH); onoffState = "OFF"; timerInProgress = false; } if (server.arg("status") == "zap10s") { digitalWrite(WiFiLED, LOW); timer10s = 0; timerInProgress = true; } }
void timer()
{
timer10s++;
if ((timer10s > 10) && (timerInProgress == true))
{
timer10s = 0;
timerInProgress = false;
digitalWrite(WiFiLED, HIGH);
}
}