Az NodeMCU V3 (Wifi) alaplap Arduino IDE környezetben

Tartalom:

  • Műszaki adatok és lábkiosztás
  • Alaplapkezelő telepítése
  • Wifi alapok, STA és Acces Point üzemmód
  • Webszerver kialakítása, adatmegjelenítés mobiltelefon webböngészőben
  • Adatkapcsolat TCP protokoll-al itt!
  • Elérés internet irányából (router beállítások)

Az Arduino UNO és Nano alaplapokhoz kaphatók ethernet és wifi képességekkel rendelkező modulok. Azonban a 32Kbyte flash memória semmire nem elég, ha nyitni szeretnénk ebbe az irányba. Ezért keresgélem más alaplapok között. Akkoriban még csak az internetről szerettem volna pontos időt szinkronizálni, de a leírások között találtam példát arra, hogyan lehet mobiltelefonról vezérelni áramköreinket, telefonon megjeleníteni az adatainkat, és ez felkeltette az érdeklődésemet. A NodeMCU alaplap már jó két három éve pihen a fiókban, mert nem volt rá időm. Akkoriban 1000Ft körüli összegért vettem aliexpress országban, azóta már 2000Ft szállítással, míg kishazánk kereskedőinél sem drágább 4-5000Ft-nál. Érdemes keresgéli, mert jelenleg is van 1000Ft-ért hasonló képességű alkatrész (pl. NodeMCU V1 mini).

Az alaplapra felszereltek egy ESP8266 Wifi képességekkel rendelkező vezérlőt. Ennek néhány jellemző tulajdonsága:

  • 80 – 160 MHz órajel.
  • 128kB belső RAM
  • 4MB flash
  • 802.11b / g / n Wi-Fi adó-vevő

A vezérlő 17db  digitális ki és bemenettel rendelkezik. Analóg bemenete is csak egy van, ami mögött egy 10 bites ADC lapul. Tapasztalatom, hogy sok esetben ennyi kivezetés is bőven elegendő. Fontos különbség a Nano-hoz képest, hogy a ki és bemenetek 3.3V-os feszültségtartományban működnek, így egyes külső alakatrészeknél erre figyelni kell, szükség lehet szintillesztésre.

Természetsen a kivezetések a megszokott módon sokfunkciósok. Megtalálunk mindent, amire szükség lehet:

  • 2 UART interfész
  • 4 PWM kimenet
  • SPI, I2C és I2S interfész (I2S egy digitális hangcsatorna létrehozásához hasznos)

Az alaplapon még találunk egy kék LED-et, amit a D4 kivezetéshez kapcsolódik, de tudni kell, hogy LOW kimeneti állapotban világít, tehát fordítva működik. Van egy reset és egy flash gomb. A falsh gombot a programjainkban is felhasználhatjuk, mert a D3 kivezetést húzza le GND-re ha azt bemenetnek állítottuk. A szokásos pinout ábra:

Találunk két olyan kivezetést, amivel a Nano esetében nem találkozhattunk! Az EN kivezetés segítségével a chip-et minimális fogyasztású állapotba lehet küldeni alacsony jelszinttel. A WAKE kivezetéssel pedig fel lehet éleszteni az alvó chip-et! Csak azt írom amit olvastam, még nem próbáltam ki!

Nekem azért is tetszett meg ez az eszköz, mert továbbra is a megszokott Arduino IDE környezetet használhatom. Ehhez a Fájl / Beállítások menüpontban a további alaplapkezelők közé fel kell venni pluszban a meglévők mellé az alábbi sort:

http://arduino.esp8266.com/stable/package_esp8266com_index.json

Majd pedig a szokásos módon az Eszközök / Alaplap menüpontban az Alaplap kezelő.. almenüpontban kereshetjük meg a megfelelő könyvtárat. Írjuk „ESD8266” és válasszuk ki a megjelenő (jelenleg) egyetlen lehetőséget:

Telepítés után az alaplap csatlakoztatásakor létrejön a Windows-ban egy sorosport. Nálam COM4 lett! Az Eszközök menüben válasszuk ki az alaplapot:

…és ezzel kész is, lehet feltölteni az első programot. Észre fogjuk venni, hogy a fordítás és a feltöltés is nagyon megfontoltan halad. A Nano-val szemben itt jelentős ideig tart a feltöltés, és ez eddigi tapasztalataim szerint független a program méretétől. Azonban a későbbiekben (nem első alkalommal) megpróbálkoztam a feltöltési sebesség növelésével. Az alaplap beállításai között az „Upload Speed” átállítható. 921600-ra következmény nélkül átállítható, így talán még az Arduino nano-ra történő programfeltöltésnél is rövidebb ideig tart. Meg kell jegyezni azonban, hogy a tényleges sebesség ennél kisebb, de az alaplap és az Arduino IDE egymás közt lebeszélték a maximumot! Ez e feltöltés előtt megjelenített adatokban látható! A fordítási sebesség pedig a gépsebességtől függ, és a 2018-ból származó laptopom nem a legcombosabb!

Egy Arduino IDE újraindítás után meg fognak jelenni a mintapéldák, amiket érdemes tanulmányozni, mert rengeteg van belőlük:

Kezdő lökésnek beidéznék egy egyszerű példát, amiben a beépített flash nyomógombbal vezéreljük a led-et:

void setup()

void setup()
{
  pinMode(D4, OUTPUT);   //D4 kimenet
  pinMode(D3, INPUT);    //D3 bemenet
  digitalWrite(D3, HIGH); //D3 felhúzó ellenállás be
}
void loop()
{
  if (digitalRead(D3)==0) {digitalWrite(D4,LOW);}  //Ha nyomom a gombot, akkor led világit (fordítva működik)
  else {digitalWrite(D4,HIGH);}                      //he nem nyomom, nem világít
}

Ezzel át is estünk a kötelező körökön! Nézzük végre a lényeget, hogyan is lehet ezzel az alaplappal wifi hálózathoz csatlakozni.

Alapvetően kétféle módon tudunk dolgozni:

STA üzemmód

Általában ezt a megoldást fogjuk használni! Ebben a szituációban már van a lakásunkban egy Wifi router, ami csatlakozik az internethez. Ha nem nyúltunk az alapbeállításokhoz, akkor a router a 192.168.0.1 vagy hasonló IP címet kapja a belső hálózaton, és minden hozzá csatlakozó eszköznek ad a 192.168.1.x tartományban egy önálló IP címet. Amikor a NodeMCU-val csatlakozni fogunk ehhez a Wifi routerhez, eszközünk is kapni fog egy IP címet, ami minden csatlakozáskor más lehet. Ha ez baj, akkor a routerben manuálisan kell kiosztani az IP címeket az egyes eszközöknek. Ha egyik eszköz a másikkal hálózaton belül akar kommunikálni, akkor az IP címmel fogják elérni egymást. Ha az interneten kívülről akarjuk elérni eszközünket, akkor vagy az internet szolgáltatónál kell fix IP címre előfizetnünk (ez nagyon drága), vagy valamilyen fix IP cím „helyettesítő” szolgáltatást kell igénybe vennünk. Érdemes megnézni a router menüjét, mert sok esetben a router rendelkezik ilyen ingyenes szolgáltatással. Ehhez regisztrálni kell a router gyártó weboldalán, és nem csak az aktuális IP címmel érhetjük eli hálózatunkat, hanem valamilyen értelmes áltaunk megadott névvel. Természetesen a router IP címe állandóan változik, de egy központi szervernek beküldi az éppen aktuális IP címét. Ha hivatkozunk az általunk regisztrált névre, akkor először a központi IP cím kezelő szerverre kerülünk, ami név helyett majd behelyettesíti az aktuális IP címet. A routerben még egy port átirányítást is be kell kapcsolni, ami majd az interneten érkező adatokat átirányítja eszközünkre.

A következőkben leírt példában a NodeMCU webszerverként fog működni. Ha a hálózaton belül található számítógépünk vagy mobiltelefonunk böngészőjébe beírjuk a router által kiosztott IP címet, akkor visszaadja a böngészőnek az általunk megtervezett weboldal képét HTML kód formájában. Mint látni fogjuk, ez nagyon egyszerű.

AccesPoint (AP) üzemmód

Ez a konfiguráció kicsit más felhasználások esetén lehet hasznos. Mint láthatjuk, a NodeMCU ekkor átveszi a router szerepét. Mivel sehol nem kötjük bele az internet kábelünket, az internetet nem fogjuk elérni ezzel a megoldással. Azonban a létrehozott Wifi állomásra felcsatlakoztathatjuk telefonunkat, számítógépünket, és ami ennél sokkal fontosabb, egy másik NodeMCU eszközt is. A később található forráskód ugyanazt a példa funkciót fogja megvalósítani, azaz itt is webszerver funkciót lát el. A kliens gép ezt a webszervert éri el böngészőből. Egy csatlakozó telefon vagy számítógép esetén nyilván egy böngészőt indítunk és az mutatja meg nekünk a számára küldött adatokat. Azonban egy másik NodeMCU (vagy hasonló wifi képes alaplap) esetén ez értelmetlen, hiszen nem biztos, hogy van rajta kijelző! Lehetséges, hogy csak vezérelni akarjuk a kliens valamelyik kivezetését. Minden esetre látható, hogy ez az üzemmód akkor lesz igazán hasznos, ha routerünktől függetlenül akarunk kapcsolatot kiépíteni két eszköz között az alaplapok wifi képességeinek kihasználásával. Ez jól jön akkor, ha a közelünkben nincs internet vagy wifi router, nem is lényeges számunkra, hogy „kívülről” is elérjük az eszközeinket!

Példa program

Rengeteg weboldalon találtam ismertetőt a lehetséges megoldásokról. Lényegében ugyanazt a mintapéldát ismételgeti mindenki, így túl sok kérdésre nem lehet ezektől az oldalaktól választ kapni. Azt már előre meg kell mondani, hogy nem lehet megkerülni a HTML nyelv megismerését legalább alapszinten. Tehát ha valaki a mobiltelefonjáról szeretné otthon bekapcsolni a lakás karácsonyi diszkivilágítását, vagy kinyitni az autónak a garázskaput, annak ezzel is foglalkoznia kell, sőt ez lesz az időigényesebb folyamat. Nekem nem célom a HTML nyelv ismertetése, már csak azért sem, mert magam sem rendelkezem ebben gyakorlattal. Az alapokat könnyen meg lehet tanulni oktatóvideókból.

Lássuk a medvét! Alaposan felkommenteztem az általam megvalósított példaprogramot. Ez a program egy nagyon egyszerű weboldalt jelenít meg a mobiltelefonon, vagy számítógépen. Ezen a weboldalon található egy nyomógomb, amivel a NodeMCU alaplapra szerelt LED-et tudjuk ki és bekapcsolni. Ugyanakkor látunk a nyomógomb alatt egy feliratot is, ami arról tájékoztat, hogy a NodeMCU flash feliratú nyomógombját nyomva tartjuk-e éppen, vagy sem.

Mivel a nyomógomb állapota bármikor megváltozhat, az információt valahogyan frissíteni kell a böngészőben. Én egy egyszerű, de primitív megoldást építettem be a html kódba, ami utasítja a böngészőt, hogy másodpercenként töltse be újra a weboldalt. Látszik is, hogy villan néha a képernyő. Ezt azért lehet sokkal kulturáltabban is pl. AJAX-al. Én azonban nem vagyok profi ebben sem, és ennél a primitív weboldalnál felesleges is lett volna.

Nekem a megfelelő html kódrészlet kialakításához nagy segítség volt, hogy létrehoztam egy index.htm nevű szövegfájlt és belemásoltam az alábbi kódrészletet. Ez a csupasz html kód, ezzel könnyebb volt kísérletezni, mit állandóan fordítgatni a programot és megvárni az időigényes feltöltést a flash-be. A html kódban természetesen nincsenek benne a változó kódrészek, a nyomógomb és led státus feliratból is csak az egyik változatot raktam bele. Ezt a szöveges állományt a böngésző dupla klikkre azonnal megjeleníti:

<!DOCTYPE html> <html>
<head><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="refresh" content="1">
<title>LED Control</title>
<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} 
	.button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}
	.button-on {background-color: #1abc9c;}
	.button-on:active {background-color: #16a085;}
	.button-off {background-color: #34495e;}
	.button-off:active {background-color: #2c3e50;}
	p {font-size: 14px;color: #888;margin-bottom: 10px;}
</style>
</head>
<body>
<h1>ESP8266 Web Server</h1>
<h1>LED vezerles</h1>
<p>LED1 Status: BE</p><a class=\"button button-off\" href=\"/ledoff\">KI</a>
<p><span style="color:green;">Nyomogomb: BE<span></p>
</body>
</html>

Sok sikert egy szebb és kellemesebb vezérlőpanel kialakításához!

Megvalósítottam az STA és az AP működést is.

Ha STA módot használunk, a program számára a megfelelő programsorban be kell írni a router állomásnevét és a jelszót. Én ezt a programban „********” és „########” karakterekkel helyettesítettem, át kell írni a saját routered megfelelő adataira. Futáskor a program felcsatlakozik lakásunk routerére, és kiírja azt az IP címet, amit a router kiosztott neki. Itt meg kell jegyeznem, hogy az Arduino nano-nál megszokottaktól eltérően a soros monitor elindítása nem reseteli az alaplapot. Soros monitor indítása után nyomjuk meg a reset gombot, ha látni akarjuk azt a bizonyos IP címet. Ha ezt az IP címet beírjuk bármely lakásban a routerre csatlakozó eszközben elindított böngészőbe, akkor megjelenik a weboldal és máris játszadozhatunk. Íme a program forrás:

//#include <ESP8266WiFi.h>           //ESP8266 Wifi kezelő könyvtár, de az ESP8266WebServer is tartalmazza, ezért kikommentezhető
#include <ESP8266WebServer.h>      //ESP8266 webszerver könyvtár

//STA mód lesz, a lakás wifi routeréhez kapcsolódik az ESP8266 is és a kliens is
ESP8266WebServer server(80);  //létrehozzuk a webkiszolgáló objektumot. Alapértelmezett a szabvány html 80-as port
                              //ezen a porton fog figyelni a szerver, és ha érkezik valamilyen kérés, akkor azt 
                              //kiszolgálja, meghívja a kérésnek megfelelő függvényeket, amik beállítják a 
                              //LEDstatus változót.
                              //A kérések tényleges lekezelése akkor kezdődik el, amikor a loop()-bn meghívjuk 
                              //kliens_kezeles() függvényt. A weboldal is akkor fog frissülni, amikor ezt a függvényt
                              //meghívjuk. Ha időigényes feladatot végez a vezérlő, akkor a böngészőben történő 
                              //akkcióra csak annak befejezése után reagál a weboldal
uint8_t LEDpin = D4;    //ez a nodeMCU modul beépített led-je
bool LEDstatus = LOW;   //ez a változó jelzi a LED aktuális státusát HIGH-nél világít
bool nyomogomb = 0;     //Ez a változó tárolja a nyomógomb aktuális állapotát

void setup() {
  Serial.begin(9600);         //sorosport elindítása
  pinMode(LEDpin, OUTPUT);    //LED kimenet beállítása
  pinMode(D3, INPUT);
  digitalWrite(D3, HIGH);
  Serial.println();
  Serial.print("Wifi kapcsolódás indul a 74ls734 nevű állomáshoz...");
  WiFi.begin("********","########");  //kapcsolódás a megadott wifi állomáshoz STA módban
  //Wifi statuslekérdezés lehetséges válaszai:
  //    WL_CONNECTED : Wi-Fi hálózathoz való csatlakoztatás megtörtént (csak ezt figyeljük ebben a programban
  //                     a többi lehetséges állapot nincs figyelve és lekezelve)
  //    WL_NO_SHIELD : A Wifi egység nem kész
  //    WL_IDLE_STATUS : a WiFi.begin () hívásakor hozzárendelt ideiglenes állapot, és aktív marad mindaddig, 
  //                       amíg a kísérletek száma le nem jár (ami WL_CONNECT_FAILED), vagy létrejön egy 
  //                       kapcsolat (ami WL_CONNECTED)
  //    WL_NO_SSID_AVAIL : Nincs megadva SSID
  //    WL_SCAN_COMPLETED : A hálózatok felderítése kész
  //    WL_CONNECT_FAILED : A kapcsolat meghiúsult (beállított ismétlésszámmal próbálkozás után)
  //    WL_CONNECTION_LOST : A kapcsolat elveszett (Wifi állomás eltűnt)
  //    WL_DISCONNECTED : A hálózat leválasztásra került
  while (WiFi.status() != WL_CONNECTED) {   //Várakozunk a Wifi hálózathoz történő csatlakozásra
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi kapcsolat OK!");
  Serial.print("Kliens saját IP cím:");  Serial.println(WiFi.localIP());
  delay(1000);
  // A bejövő HTTP-kérések kezeléséhez meg kell adni a szervernek, hogy melyik függvény legyen meghívva 
  // amikor beérkezik egy kérés. Első paraméterben az elérési utat kapja meg, második paraméterben
  // A függvény nevét, amit akkor hív meg, amikor a böngésző kliens beküldi az adott elérési utat.
  // Ha a böngésző kliensnek beírjuk az IP címet, akkor a gyökér ( / ) útvonalat kapja meg, ez azonos
  // a kliens csatlakozásával (handle_OnConnect()). Ha megnyomjuk a LED be nyomógombot a weboldalon, akkor ( /Ledon )  
  // útvonalat kap a szerver, és ekkor a be kell kapcsolni a led-et (handle_ledon).
  // Az útvonalak mindig relatív útvonalak!
  server.on("/",kliens_kapcsolodott);       //kliens csatlakozása
  server.on("/ledon",kliens_ledon);         //led be nyomógomb megnyomása
  server.on("/ledoff",kliens_ledoff);       //led ki nyomógomb megnyomása
  server.onNotFound(kliens_hibas_utvonal);  //ha olyan útvonalat kap, amihez nem adtunk meg végrehajtandó függvényt
  server.begin();                           // elindítjuk a webszervert
  Serial.println("HTTP szerver elindult!");
}

void loop() {
  server.handleClient();          //ha van kérés a szerver felé, akkor itt történik meg a lekezelése
                                  //a lekezeletlen kérések pufferben tárolódnak és várakoznak, ezért a loop-ban időigényes
                                  //egyéb feladatokat is lehet végrehajtani
  if(LEDstatus) {digitalWrite(LEDpin, LOW);} //LED bekapcsolása (ellentétesen működik a beépített led
  else {digitalWrite(LEDpin, HIGH);}         //LED kikapcsolása
  if (digitalRead(D3)==0) {nyomogomb=0;}     //nyomógomb lekérdezés
  else {nyomogomb=1;}
  
}

void kliens_kapcsolodott() {         //Amikor a kliens csatlakozik a led-et off állapotba kapcsoljuk
  LEDstatus = LOW;
  Serial.println("LED satus: OFF");
  server.send(200, "text/html", html_kuldes(LEDstatus));   //A LEDstatus változó állípotától függő stringet küld a szerver a kliensnek.
                                                           //A string valójában egy html szintaktika, egy weboldal képe, amit a kliens 
                                                           //böngészője megjelenít.
}

void kliens_ledon() {             //megnyomta a kliensen a led be gombot, /Ledon útvonalat kap a szerver
  LEDstatus = HIGH;               //bekapcsoljuk a led-et
  Serial.println("LED satus: ON");
  server.send(200, "text/html", html_kuldes(true));     //A szerver ezt a választ fogja küldeni a kliensnek
}

void kliens_ledoff() {            //megnyomta a kliensen a led be gombot, /Ledoff útvonalat kap a szerver
  LEDstatus = LOW;                //kikapcsoljuk a led-et
  Serial.println("LED satus: OFF");
  server.send(200, "text/html", html_kuldes(false));    //A szerver ezt a választ fogja küldeni a kliensnek
}

void kliens_hibas_utvonal(){      //nem ismerhető fel az útvonal ami érkezett a klienstől
  server.send(404, "text/plain", "Ertelmezhetetlen utvonal!");
}

String html_kuldes(uint8_t led_allapot){   
 // SendHTML() függvény felelős a weblapon megjelenő tartalomért. Ebben a megoldásban a bemenő paraméter dönti el 
 // Hogy a szerver milyen html kódot küld a böngésző kliensnek. A függvény egy nagy karakterláncot hoz létre,
 // Ezt adja vissza a server.send() függvénynek, ami majd kiküldi a böngésző kliensnek.
 // A szövegen belüli idézőjelek elé "\"-t kell írni, egy html szöveges állományban ez és a "\n" nem kell (ha kimásoljuk
 // a végeredményt egy htm kitejesztésű állományba és megnyitjuk böngészőben, megnézhetjük a végeredményt. Azonban
 // az if() megötti szöveg változatokból csak ez egyiket szabad bemásolni (statikus oldal lesz).
  String ptr = "<!DOCTYPE html> <html>\n"; //azt jelzi, hogy HTML kódot küldünk.
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";  //bármely böngészőben megtekinthető
  ptr +="<meta http-equiv=\"refresh\" content=\"1\">\n";    //Ez a sor utasítja a böngészőt, hogy egy másodpercenként frissítse az oldalt
  ptr +="<title>LED Control</title>\n";    //Ez a weboldal címkéje
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";  //betűtípus és igazítás a soros blokkban
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";  //margó és elhelyezés beállítások
  //nyomógomb kinézetének beállítása
  ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr +=".button-on {background-color: #1abc9c;}\n";
  ptr +=".button-on:active {background-color: #16a085;}\n";
  ptr +=".button-off {background-color: #34495e;}\n";
  ptr +=".button-off:active {background-color: #2c3e50;}\n";
  ptr +="p {font-size: 18px;color: #888;margin-bottom: 10px;}\n";  //bekezdés betűmérete
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>ESP8266 Web Server</h1>\n";      //weboldal fejléce
  ptr +="<h1>LED vezerles</h1>\n";
  if(led_allapot)   //A LED állapotától függ, hogy mit jelenít meg a weboldal
    {ptr +="<p>LED Status: BE</p><a class=\"button button-off\" href=\"/ledoff\">KI</a>\n";}
  else
    {ptr +="<p>LED Status: KI</p><a class=\"button button-on\" href=\"/ledon\">BE</a>\n";}
  if(nyomogomb)    //A nyomógomb állapotától függő szöveg küldése
    {ptr +="<p><span style=\"color:red;\">Nyomogomb: KI<span></p>";}
  else
    {ptr +="<p><span style=\"color:green;\">Nyomogomb: BE<span></p>";}
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

Az AP mód esetén a forrás csaknem teljesen ugyanaz. Kellett néhány új változó (IPAdress típusú), amiben megadhatjuk Wifi állomásunk IP címeit. Ha nem adjuk meg, akkor az alapértelmezett IP 192.168.4.1. További különbségek a setup() első soraiban. Nyilvánvaló, hogy mielőtt a mobiltelefonon elindítjuk a böngészőt, fel kell csatlakozni a telefonnal az újdonsült wifi AccesPonint-ra.

 Ezt követően adhatjuk meg a böngészőben az IP címet a weboldal címének. Jelen esetben ez 192.168.5.1 lett, mert ezt választottam.

Az AP üzemmóddal sokat szívtam, mert a programmal létrehozott AP-hoz tudott a mobiltelefonon csatlakozni, de amikor a böngészőbe beírtam az állomás IP címét, hibaüzenetet kaptam. Napokig próbálkoztam különböző mintapéldákkal, míg rájöttem, hogy a telefonnal van a baj. A tabletem gond nélkül megjelenítette a weboldalt. Az okot még nem tudom.

A Wifi eléréshez szükséges ssid-t (állomás nevet) és jelszót direktben írtam be az egyszerűség kedvéért. AccesPoint megoldásnál a jelszó minimálisan 8 karakter hosszúnak kell lennie. Azonban a jelszó el is hagyható. Ekkor az eszközök jelszó nélkül is tudnak csatlakozni.

Íme ez a forrás is:

//#include <ESP8266WiFi.h>           //ESP8266 Wifi kezelő könyvtár, de az ESP8266WebServer is tartalmazza, ezért kikommentezhető
#include <ESP8266WebServer.h>      //ESP8266 webszerver könyvtár

// AP mód lesz, a kliensek közvetlenül csatlakozhatnak hozzá a setupban megadott állomásnévvel és jelszóvel.
// Az állomás IP címét meg is lehet adni, de alapértelmezett IP cím is van.
IPAddress IPaddr (192, 168, 5, 1);     //ha nem alapértelmezett IP címet akarunk, akkor itt adhatjuk meg
IPAddress IPgateway (192, 168, 5, 1);  //nincs internet kapcsolat, így itt simán megismételjül az ip címet
IPAddress IPmask(255, 255, 255, 0);    //Hálózati maszk
ESP8266WebServer server(80);  //létrehozzuk a webkiszolgáló objektumot. Alapértelmezett a szabvány html 80-as port
                              //ezen a porton fog figyelni a szerver, és ha érkezik valamilyen kérés, akkor azt 
                              //kiszolgálja, meghívja a kérésnek megfelelő függvényeket, amik beállítják a 
                              //LEDstatus változót.
                              //A kérések tényleges lekezelése akkor kezdődik el, amikor a loop()-bn meghívjuk 
                              //kliens_kezeles() függvényt. A weboldal is akkor fog frissülni, amikor ezt a függvényt
                              //meghívjuk. Ha időigényes feladatot végez a vezérlő, akkor a böngészőben történő 
                              //akkcióra csak annak befejezése után reagál a weboldal
uint8_t LEDpin = D4;    //ez a nodeMCU modul beépített led-je
bool LEDstatus = LOW;   //ez a változó jelzi a LED aktuális státusát HIGH-nél világít
bool nyomogomb = 0;     //Ez a változó tárolja a nyomógomb aktuális állapotát

void setup() {
  Serial.begin(9600);         //sorosport elindítása
  pinMode(LEDpin, OUTPUT);    //led kimenet beállítása

  Serial.println();
  Serial.print("Acces Point beállítása..");
  WiFi.softAPConfig(IPaddr, IPgateway, IPmask);    //Az elérési pont IP címe. Ha ezt kikommentezzük, akkor az alapértelmezett
                                                   //IP cím 192.168.4.1 lesz. Ezen az IP címen lehet elérni a weboldalt
  WiFi.softAP("ESP8266_AP", "12345678");           //Az Acces Point elindítása, a megodott állomásnévhez a jelszóvel lehet csatlakozni 
  Serial.print("IP cím:");  Serial.println(WiFi.softAPIP());  //megismételjük az állomás IP címét
  delay(1000);
  // A bejövő HTTP-kérések kezeléséhez meg kell adni a szervernek, hogy melyik függvény legyen meghívva 
  // amikor beérkezik egy kérés. Első paraméterben az elérési utat kapja meg, második paraméterben
  // A függvény nevét, amit akkor hív meg, amikor a böngésző kliens beküldi az adott elérési utat.
  // Ha a böngésző kliensnek beírjuk az IP címet, akkor a gyökér ( / ) útvonalat kapja meg, ez azonos
  // a kliens csatlakozásával (handle_OnConnect()). Ha megnyomjuk a LED be nyomógombot a weboldalon, akkor ( /Ledon )  
  // útvonalat kap a szerver, és ekkor a be kell kapcsolni a led-et (handle_ledon).
  // Az útvonalak mindig relatív útvonalak!
  server.on("/",kliens_kapcsolodott);       //kliens csatlakozása
  server.on("/ledon",kliens_ledon);         //led be nyomógomb megnyomása
  server.on("/ledoff",kliens_ledoff);       //led ki nyomógomb megnyomása
  server.onNotFound(kliens_hibas_utvonal);  //ha olyan útvonalat kap, amihez nem adtunk meg végrehajtandó függvényt
  server.begin();                           // elindítjuk a webszervert
  Serial.println("HTTP szerver elindult!");
}

void loop() {
  server.handleClient();          //ha van kérés a szerver felé, akkor itt történik meg a lekezelése
                                  //a lekezeletlen kérések pufferben tárolódnak és várakoznak, ezért a loop-ban időigényes
                                  //egyéb feladatokat is lehet végrehajtani
  if(LEDstatus) {digitalWrite(LEDpin, LOW);} //LED bekapcsolása (ellentétesen működik a beépített led
  else {digitalWrite(LEDpin, HIGH);}         //LED kikapcsolása
  if (digitalRead(D3)==0) {nyomogomb=0;}     //nyomógomb lekérdezés
  else {nyomogomb=1;}
  
}

void kliens_kapcsolodott() {         //Amikor a kliens csatlakozik a led-et off állapotba kapcsoljuk
  LEDstatus = LOW;
  Serial.println("LED satus: OFF");
  server.send(200, "text/html", html_kuldes(LEDstatus));   //A LEDstatus változó állípotától függő stringet küld a szerver a kliensnek.
                                                           //A string valójában egy html szintaktika, egy weboldal képe, amit a kliens 
                                                           //böngészője megjelenít.
}

void kliens_ledon() {             //megnyomta a kliensen a led be gombot, /Ledon útvonalat kap a szerver
  LEDstatus = HIGH;               //bekapcsoljuk a led-et
  Serial.println("LED satus: ON");
  server.send(200, "text/html", html_kuldes(true));     //A szerver ezt a választ fogja küldeni a kliensnek
}

void kliens_ledoff() {            //megnyomta a kliensen a led be gombot, /Ledoff útvonalat kap a szerver
  LEDstatus = LOW;                //kikapcsoljuk a led-et
  Serial.println("LED satus: OFF");
  server.send(200, "text/html", html_kuldes(false));    //A szerver ezt a választ fogja küldeni a kliensnek
}

void kliens_hibas_utvonal(){      //nem ismerhető fel az útvonal ami érkezett a klienstől
  server.send(404, "text/plain", "Ertelmezhetetlen utvonal!");
}

String html_kuldes(uint8_t led_allapot){   
 // SendHTML() függvény felelős a weblapon megjelenő tartalomért. Ebben a megoldásban a bemenő paraméter dönti el 
 // Hogy a szerver milyen html kódot küld a böngésző kliensnek. A függvény egy nagy karakterláncot hoz létre,
 // Ezt adja vissza a server.send() függvénynek, ami majd kiküldi a böngésző kliensnek.
 // A szövegen belüli idézőjelek elé "\"-t kell írni, egy html szöveges állományban ez és a "\n" nem kell (ha kimásoljuk
 // a végeredményt egy htm kitejesztésű állományba és megnyitjuk böngészőben, megnézhetjük a végeredményt. Azonban
 // az if() megötti szöveg változatokból csak ez egyiket szabad bemásolni (statikus oldal lesz).
  String ptr = "<!DOCTYPE html> <html>\n"; //azt jelzi, hogy HTML kódot küldünk.
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";  //bármely böngészőben megtekinthető
  ptr +="<meta http-equiv=\"refresh\" content=\"1\">\n";    //Ez a sor utasítja a böngészőt, hogy egy másodpercenként frissítse az oldalt
  ptr +="<title>LED Control</title>\n";    //Ez a weboldal címkéje
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";  //betűtípus és igazítás a soros blokkban
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";  //margó és elhelyezés beállítások
  //nyomógomb kinézetének beállítása
  ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr +=".button-on {background-color: #1abc9c;}\n";
  ptr +=".button-on:active {background-color: #16a085;}\n";
  ptr +=".button-off {background-color: #34495e;}\n";
  ptr +=".button-off:active {background-color: #2c3e50;}\n";
  ptr +="p {font-size: 18px;color: #888;margin-bottom: 10px;}\n";  //bekezdés betűmérete
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>ESP8266 Web Server</h1>\n";      //weboldal fejléce
  ptr +="<h1>LED vezerles</h1>\n";
  if(led_allapot)   //A LED állapotától függ, hogy mit jelenít meg a weboldal
    {ptr +="<p>LED Status: BE</p><a class=\"button button-off\" href=\"/ledoff\">KI</a>\n";}
  else
    {ptr +="<p>LED Status: KI</p><a class=\"button button-on\" href=\"/ledon\">BE</a>\n";}
  if(nyomogomb)    //A nyomógomb állapotától függő szöveg küldése
    {ptr +="<p><span style=\"color:red;\">Nyomogomb: KI<span></p>";}
  else
    {ptr +="<p><span style=\"color:green;\">Nyomogomb: BE<span></p>";}
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

Ezzel még természetesen nem fejeztem be az alaplapok vizsgálatát. Megismerkedtem azzal is, hogyan küldhetek adatokat az egyik NodeMCU-ról egy másikra webszerver használata nélkül. Az adatkapcsolathoz TCP vagy UDP kapcsolatot kell használni. A TCP kapcsolatot már megismertem és kipróbáltam, ennek részletei itt olvashatók!

————————————–

A napokban rákényszerültem arra, hogy távolról érjem el a lakásomban működő fejlesztő laptopomat. Eddig Team Viewert használtam, de immár a program „Profi” felhasználónak minősített, és megszüntette számomra az ingyenes használatot. Valóban sokat használtam a munkahelyemen ezt a programot különböző gépek elérésére a munkámhoz, de arról fogalmam sincs, hogyan kötötte össze a Team Viewer a magánéletemet a munkámmal. Sebaj, megtiszteltetésnek veszem, hogy már profinak számítok. Kerestem hát alternatív megoldást. Hálával tartozom a Team Viewer-nek, hogy kiiktathattam az életemből, és megismertem más lehetőségeket is! Ez egyben kapóra jött arra is, hogy kipróbáljam, tudom-e kapcsolgatni ESP8266 alaplapom beépített led-jét egy messzi-messzi galaxisból. És igen!!!

Első lépésben a lakásban működő routert kellene elérni. Mivel a hozzám hasonló csóróknak nincs fix IP címük az internet szolgáltatójuknál, maradnak a kerülő megoldások. Végre belenéztem a wifi routerbe, hogy mit is tud. Kiderült, hogy a gyártója is ad megoldást a problémára, ráadásul ingyen. Ehhez első körben ki kell találnunk egy saját nevet, amit az IP cím helyett fogunk beírni abba a programba, ahol az elérési adatok megadására van szükség. Pl. a VNC távfelügyeleti szoftverek egy IP címmel megadott gépen keresik a saját kiszolgálójukat, ami a távoli asztal szolgáltatást nyújtani fogja. Ezt az ip címet fogjuk helyettesíteni valami mással. A routerben a WAN menüben a képen látható DDNS fülön állíthatjuk be a saját egyedi felhasználó nevünket:

A sajátomat a képen kitakartam, mert féle, hogy a hackerek rám találnak az interneten és ellopják a kalandos úton megszerzett teljes Star Trek sorozat gyűjteményemet, amit nyugdíjas koromban fogok végig nézni! Legyen most a példa kedvéért ez a név „valami.asuscomm.com”! Nem kell igyekezni, ez a név már foglalt és nem az enyém, sokkal nagyobb fantáziára lesz szükséged!

Természetesen a fenti kép csak egy példa! Más gyártók routereiben biztosan egész máshogy zajlik a folyamat. Ha nincs lehetőség a routerben regisztrációra, akkor fel kell keresni valamelyik ingyenes vagy éppen fizetős szolgáltatót, pl. a noip.com weboldalt, és regisztrálni egyet. A regisztráció után a kapott nevet ugyanide lehet beírni. A routerek elég sok szolgáltató elérését már beépítve tartalmazzák. AZ ASUS esetében:

Ha pl. a no-ip-t választjuk, akkor lényegesen több adatot kell majd megadni:

De maradjunk most a kényelmes ASUS szolgáltatásnál amit én is kiválasztottam. Azért is kényelmes, mert a router beépített weboldalán meg lehet csinálni a regisztrációt és beállítást egy lépésben, és ezzel készen is vagyunk. Ha még nem létező nevet írtunk be, akkor ezt a választ kapjuk a router weboldalától:

Pontosabban még nem vagyunk készen. Ezzel csak azt értük el, hogy immár egy értelmes névvel érhetjük el a routerünket a nagyvilágból. Ha pl. nyitunk egy command ablakot a Windows-ban, és beírjuk, hogy „ping valami.asuscomm.com” akkor a ping kérésünkre válaszok fognak érkezni. Ugyanezt értük volna el azzal is, ha a ping után a router pillanatnyi ip címét írjuk be, de az ugyebár bármikor megváltozhat.

A router biztosítja, hogy a megváltozott router ip cím azonnal elkerüljön az ASUS szervereinek nyilvántartásába. Így amikor leírjuk, hogy „valami.asuscomm.com”, akkor ebből a nyilvántartásból behelyettesítődik a pillanatnyi ip cím, és máris elérjük a routert. Egyszerű mint a pofon, és egyenlőre ingyenes. Én azért minden nap mentem az adataimat, mert ki tudja, miért is ingyenesek ezek a szolgáltatások!

Már elérjük a routert, de nekünk nem a router kell, hanem a routerünkhöz kapcsolódó eszköz. Nevezetesen az ESP8266-ot szeretnénk elérni, ami éppen egy webszerver, és amikor a programja elindul kap egy belső lokális IP címet a routertől. Esetemben ez az ip a 192.168.1.67! Emlékezzünk az ESP8266-ra töltött program első sorainak egyikére:

ESP8266WebServer server(80);

Ezzel a programsorral elindítottuk a webszervert, ami az alapértelmezett 80-as portot figyeli. Ezt a portot helyettesítik be a böngésző programok, ha nem adunk meg mást. Nekünk ez nem feltétlenül lesz jó, mert ha lakásunk másik számítógépén esetleg üzemeltetünk egy webszervert, akkor az is a 80-as porton csücsül, és a port átirányítások összevesznének azon, hogy ki szolgálja ki a beérkező kéréseket. Ezért érdemes újdonsült ESP8266 webszerverünk portszámát átírni. Így a következőt írtam be a programba:

ESP8266WebServer server(5022);

Azért pont ezt, mert a szobám órája éppen 5 óra 22 percet mutatott. Ezzel emléket állítok ennek a soha vissza nem térő pillanatnak!

Ha ekkor a belső hálózatban található bármely gép böngészőjébe beírjuk, hogy 192.168.1.67:5022, akkor a böngészőben azonnal megjelenik kicsike ESP8266 weboldalunk, és boldogan kapcsolgathatjuk alaplapunkon a led-et. Tehát azt kell elérnünk, hogy bárhol is tartózkodunk a világban, onnan is elérjük ezt a webkiszolgálót. Ha mobiltelefonunkon ezt az IP címet írjuk be, és nem tartózkodunk a lakás wifi hatósugarában, vagy a mobilon kikapcsoltuk a wifi-t, akkor a weboldalt nem fogjuk elérni. Mi ugyanis csak a routerünket érjük el, azt is csak az ASUS-nál regisztrált névvel. Ha beírjuk a mobilunkba (kikapcsolt wifi esetén, vagy Haway-i nyralásunkon), hogy „valami.asuscomm.com:5022” még akkor sem jelenik meg picike weboldalunk, mert ez még nem az a gép, ami nekünk kell! Ez még csak a router, amiben az 5022-es porton épp nem fut webkiszolgáló, aminek a válaszait a böngésző megjeleníthetné.

Erre a problémára építették be a routerbe a port átirányítás funkciót. Ha a megadott portra, jelen eseben az 5022-re adatok érkeznek, akkor a router képes azokat azonnal változtatás nélkül továbbítani egy megadott ip címre. Ennek beállításához keressük meg a port továbbítás (port forward) menüpontot:

A képet az után készítettem, hogy már beállítottam a szükséges port átirányítást. Ezt a néhány adatot kell megadni, miután a „Profil hozzáadása” gombra kattintottunk:

Esetünkben csak két lényeges és fontos adatot kell megadni, a portszámot, és a cél eszköz ip címét.

Azt hiszen a további eseményeket nem szükséges megmagyarázni. Olyan ez, mint egy amerikai film, happy end a vége. Mobilunkba Haway-on is beírhatjuk: valami.asuscomm.com:5022 és megjelenik a weblap, amiről bekapcsolhatjuk ESP8266 alaplapunk beépített led-jét. Sok sikert másoknak is!

Mennyire volt hasznos amit olvastál? Értékelés után szövegesen is leírhatod megjegyzéseidet és véleményedet!

Kattints egy csillagra az értékeléshez!

Szövegesen is leírhatod véleményedet! Ha kérdésed van, ne felejtsd el megadni az email címedet!