ESP8266 WiFiScaner.

Skaner sieci WiFi. 

Program, który wyświetla dane dostępnych sieci WiFi.

Do budowy skanera będzie potrzebne dowolne urządzenie z ESP8266, ja tradycyjnie korzystam z WeMos D1 mini.
Skaner WiFi pozwala sprawdzić jakie AP znajdują się w zasięgu tego urządzenia. Jak widać na foto obok pokaże nazwy AP,  ich kanały, MAC adresy, siłę sygnału, czy AP zabezpieczony i czy nie jest ukryty. Gdy jest połączony z AP, to wyświetli jego dane. Gdy brak połączenia, to wyświetli „Brak połączenia z siecią WiFi.”. Aby połączyć się z jakimś AP należy wybrać go z wyświetlanych i podać hasło dla tego AP. LED wbudowany sygnalizuje brak połączenia z WiFi (świeci), gdy jest połączenie LED jest wyłączony.
Aby połączyć się ze Skanerem należy wybrać w sieci WiFi AP_WiFiScaner i podać hasło 12345678, dane te są ustawiane w programie. Następnie za pomocą przeglądarki www połączyć się z IP 192.168.4.1, reszta jak na ekranie. Na stronie głównej jest wyświetlany czas od uruchomienia i przycisk do strony skanowania. Najnowszy kod źródłowy tego programu znajduje się na tutaj.

Uruchom Arduino IDE. 
Nowy szkic i zaraz zapisz go pod WiFiScaner.
Do pliku WiFiScaner.ino wklej poniższy kod.

//WiFiScaner.ino
#include "Arduino.h"
#include "ESP8266WiFi.h"
#include <ESP8266WebServer.h>
#include "WebWiFiScan.h"

#define pinLED BUILTIN_LED
//#define IP_STATIC
//#define DEBUG

//dane dla AP
const char* ap_ssid = "AP_WiFiScaner"; // SSID AP
const char* ap_pass = "12345678"; // password do AP
int ap_channel= 2; //numer kanału dla AP


extern ESP8266WebServer server;

#ifdef IP_STATIC
IPAddress IPadr(10,110,2,105); //stały IP
IPAddress netmask(255,255,0,0);
IPAddress gateway(10,110,0,1);
#endif

void setup()
{
#ifdef DEBUG
 Serial.begin(115200);
#endif
 pinMode(pinLED, OUTPUT);
 digitalWrite(pinLED, LOW);
 //ustaw SSID, pass i kanał dla AP
 WiFi.softAP(ap_ssid, ap_pass, ap_channel);
#ifdef IP_STATIC
 WiFi.config(IPadr,gateway,netmask); // stały IP
#endif
 WiFi.mode(WIFI_AP_STA); //tryb AP_STATION
 WiFi.begin(); 
 int it = 20;
 while ((WiFi.status() != WL_CONNECTED) and it>0) { // czekaj na połączenie z WiFi
 delay(500);
 it-- ;
 #ifdef DEBUG
 Serial.print(".");
 #endif
 }
 #ifdef DEBUG 
 if (it>0) {
 Serial.println("");
 Serial.println("WiFi połączone");
 Serial.println(WiFi.localIP());
 Serial.println(WiFi.macAddress());
 Serial.print("Tryb pracy: ");
 Serial.println(WiFi.getMode());
 Serial.print("Tryb modulacji: ");
 Serial.println(WiFi.getPhyMode());
 Serial.print("Nr kanału: ");
 Serial.println(WiFi.channel());
 Serial.print("IP AP: ");
 Serial.println(WiFi.softAPIP() );
 //WiFi.printDiag(Serial);
 }else {
 Serial.println();
 Serial.println("Brak połączenia z WiFi!.");
 }
 #endif
 setservers();
}

void loop()
{
server.handleClient();
if (WiFi.status() != WL_CONNECTED){
 digitalWrite(pinLED, LOW);
 if (WiFi.getMode() != WIFI_AP_STA){
 WiFi.mode(WIFI_AP_STA);}
 }
 else{ // wyłącz LED gdy jest połączenie z WiFi
 digitalWrite(pinLED, HIGH);
 // if (WiFi.getMode() != WIFI_STA){
 // WiFi.mode(WIFI_STA);}
 }
}

Potrzebne jeszcze są dwa pliki – WebWiFiScan.h i WebWiFiScan.cpp.

/*
 * WebWiFiScan.h
 *
 * Created on: 11.04.2017
 * Author: Jan Trzciński poljant@post.pl
 */

#ifndef WEBWIFISCAN_H_
#define WEBWIFISCAN_H_

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>

String HTMLHeader();
String HTMLFooter();
String HTMLPage();
String HTMLPage1();
String HTMLPage2();
String HTMLWiFiScan();
void setservers(void);

#endif /* WEBWIFISCAN_H_ */ 

Do pliku WebWiFiScan.cpp wklej poniższy kod.

//WebWiFiScaner.cpp
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>

// login i hasło do sytemu
const char* www_login = "admin";
const char* www_pass = "esp8266";
const char* epass[32];
const char* essid[32];

const char* modes[] = {"NULL","STA","AP","STA+AP"};
const char* phymodes[] = { "","B", "G", "N"};

const int port = 80; // port serwera www
ESP8266WebServer server(port);
ESP8266HTTPUpdateServer httpUpdate;

char* IPAdrToStr(int ip)
{
 char* ip_str = new char[16];
 sprintf(ip_str, "%d.%d.%d.%d",
 (ip ) & 0xFF,
 (ip >> 8) & 0xFF,
 (ip >> 16) & 0xFF,
 (ip >> 24) & 0xFF);
 return ip_str;
}

String HTMLHeader() { // nagłówek strony
 String h = "<!DOCTYPE html>\n";
 h += "<html>";
 h += "<head>";
 h += "<title> WiFi Scaner</title>";
 // h += "<meta http-equiv=\"Refresh\" content=\"30\" />"; //odświerzaj stronę co 30 sek.
 h += "<meta charset=\"utf-8\">";
 h += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";
 h += "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\" >";
 h += "</head>";
 h += "<body style=\"text-align: center;color: white; background: black;font-size: 1.5em;\">\n";
 return h;
 }

String HTMLFooter() { // stopka strony www
 String f = "";
 f += "<p>Jan Trzciński &copy; 2017</p></td></tr>";
 f += "</body>\n";
 f += "</html>\n";
 return f;
 }

String HTMLPage1() { // pierwsza część strony www
 String t;
 unsigned long sec = millis() / 1000;
 unsigned long min = (sec / 60);
 unsigned long hour = (min / 60);
 unsigned long days = hour / 24;
 sec = sec % 60;
 min = min % 60;
 hour = hour % 24;
 t = "<h1>WiFi skaner</h1>";
 t += "<p> Wersja oprogramowania 1.0 z dnia 11-04-2017";
 t += "</p>";
 t += "<p>Czas od uruchomienia dni: ";
 t += (days);
 t += " godz:" ;
 t += ((hour<10) ? "0" : ""); //gdy mniej niż 10 wstaw zero wiodące
 t += (hour);
 t += ":";
 t += ((min<10) ? "0" : ""); //gdy mniej niż 10 wstaw zero wiodące
 t += (min);
 t += ":";
 t += ((sec < 10) ? "0" : ""); //gdy mniej niż 10 wstaw zero wiodące
 t += (sec);
 t += "</p>";
 t +="<p><a href = \"/wifiscan\"><button class=\"btn btn-info\">Skanuj sieć WiFi</button></a></p>";
 return t;
 }

String HTMLWiFiScan(void){
 String p="";
 String ix="";
 uint8_t n = WiFi.scanNetworks();
 if (n == 0) return "<p>Brak sieci WiFi.</p>";
 p +="<div><h3>Skanowanie sieci WiFi</h3></div>";
 p +="<table align=\"center\" border=\"2\" >";
 p +="<thead ><tr><th> </th><th style = \"text-align: center;\">SSID</th>";
 p +="<th>kanał</th><th style = \"text-align: center;\">MAC</th>";
 p +="<th>RSSI</th><th>zabezp</th><th>ukryta</th><tr>";
 p +="</thead><tbody>";
 for (uint8_t i=0; i<n;i++){
 p +="<tr><td>";
 p +="<form action=\"/wifiset\" metod=\"post\">";
 p +="<labe><input id=\"SSID\" type=\"radio\" name=\"SSID\" value=\""+WiFi.SSID(i)+"\">";
 p +="</label>";
 p +="</td>";
 p +="<td>"+WiFi.SSID(i)+"</td>"; //nazwa sieci
 p +="<td>"+String(WiFi.channel(i))+"</td>"; //kanał
 p +="<td>"+WiFi.BSSIDstr(i)+"</td>"; //MAC adres
 p +="<td>"+String(WiFi.RSSI(i))+" dBm</td>"; //siła sygnału
 p +="<td>";
 p +=((WiFi.encryptionType(i)==ENC_TYPE_NONE) ? "nie" : "tak");//czy szyfrowanie
 p +="</td><td>";
 p +=((WiFi.isHidden(i)) ? "tak" : "nie");//czy sieć ukryta
 p +="</td></tr>";
 } //end for
 p +="</tbody></table>";
 p +="<div><p></p> </div>";
 // gdy połączenie z WiFi
 if(WiFi.status() == WL_CONNECTED){
 p += "<p>Jesteś połączony z siecią </p>";
 p +="<table align=\"center\" border=\"2\" ><tbody>";
 p +="<thead ><tr><th style = \"text-align: center;\">SSID</th>";
 p +="<th>kanał</th><th style = \"text-align: center;\">MAC</th>";
 p +="<th>RSSI</th></thead><tbody>";
 p += "<td>"+WiFi.SSID()+"</td>";
 p += "<td>"+String(WiFi.channel())+"</td>";
 p += "<td>"+WiFi.BSSIDstr()+"</td>";
 p += "<td>"+String(WiFi.RSSI())+" dBm</td></tbody></table>";
 p +="<label>IP: "+String(IPAdrToStr(WiFi.localIP()))+"</label>";
 p += "<p>Aby zmienić sieć WiFi.</p>";
 }else{ //gdy brak połączenia z WiFi.
 p += "<p>Brak połączenia z siecią WiFi.</p>";
 p += "<label>IP AP: "+String(IPAdrToStr(WiFi.softAPIP()))+"</label>";
 } //end if
 p += "<p>Wybierz sieć powyżej i podaj hasło</p>";
 p +="<label for=\"password\">Hasło do WiFi:</label>";
 p +="<input style=\"color: black;\" type=\"password\" name=\"password\" />" ; //required=\"required\"/>";
 p +="<input style=\"text-align: center;color: black;\" type=\"submit\" value=\"Połącz z WiFi.\"/></form>";
 p += "<p><a href = \"/wifiscan\"><button class=\"btn btn-info\">Skanuj ponownie</button></a></p>";
 p += "<p><a href = \"/\"><button class=\"btn btn-info\">Powrót do strony głównej</button></a></p>";
 return p;
}

String WebPageScan(){
 return (HTMLHeader()+HTMLWiFiScan()+HTMLFooter());
}

String WebPage() { // połącz wszystkie części strony www
 return (HTMLHeader()+ HTMLPage1()+HTMLFooter());
}

// funkcja ustawia wszystkie strony www
void setservers(){
 httpUpdate.setup(&server,"/update", www_login, www_pass); // umożliwia aktualizację poprzez WiFi

 server.on("/", [](){

 server.send(200, "text/html", WebPage());
 });

 server.on("/wifiscan", [] ()
 {

 server.send(200, "text/html", WebPageScan());
 });

 server.on("/wifiset", [] ()
 {
 String ESSID = server.arg("SSID");
 String Epass = server.arg("password");
 const char* essid = ESSID.c_str();
 const char* epass = Epass.c_str();
 WiFi.disconnect() ;
 WiFi.mode(WIFI_AP_STA);
 WiFi.begin(essid,epass);
 delay(200);
 int it = 20;
 while ((WiFi.status() != WL_CONNECTED and it>0)) { // czekaj na połączenie z WiFi
 delay(500);
 it--;
 }
 server.send(200, "text/html", WebPageScan());
 });

server.begin(); // Start serwera www
#ifdef DEBUG
Serial.println("Server started");
#endif
}

Program zawiera sporo komentarzy, które wyjaśniają prawie wszystko. Wiele rzeczy zostało opisanych w poprzednich wpisach. Po zalogowaniu się do nowej sieci należy odczekać kilka sekund.
Po odłączeniu i ponownym włączeniu zasilania, układ pamięta dane ostatnio wybranej sieci. Aby zmienić sieć należy ponownie wybrać ją przez stronę www.
Miłej zabawy.

5 odpowiedzi na “ESP8266 WiFiScaner.”

  1. Witam,

    mam mały problem z biblioteką ESP8266WiFi.h.

    Metody np. WiFi.SSID(parametr) czy WiFi.channel(parametr) ja w Twoim przypadku nie pozwalają na podanie parametru a tym samym nie można się odwołać do wykrytego konkretnego AP.

    Osobiście używam Eclipsa w do programowania i w tym przypadku wbudowanej biblioteki.

    Pozdrawiam GM

    1. Witam
      U mnie Eclipse też sygnalizuje błąd typu, ale kompiluje prawidłowo i skompilowany program działa.
      Wygląda na to, że kompilator widzi błąd typu danych, ale kompiluje zgodnie z oczekiwaniem.
      Nie analizowałem tego dokładnie, bo mimo wszystko program działa prawidłowo.
      W Arduino nie sygnalizuje tego błędu.
      pozdrawiam
      Jan

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *