Esp8266 wifi

De The Linux Craftsman
Aller à la navigation Aller à la recherche

Introduction

Warning manual.jpg

Soyez sûr de comprendre la section sur comment écrire un sketch avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.

La puce ESP8266 peut se configurer en point d'accès, en client WiFi ou les deux en même temps.

Client WiFi

Commençons par nous connecter à un réseau en utilisant le DHCP :

#include <ESP8266WiFi.h>

const char ssid[] = "CAMPUSCD-CROIXVERTE2";
const char password[] = "";

void setup() {
	// on démarre le port série
	Serial.begin(115200);
	// On attend "un peu" que le buffer soit prêt
	delay(10);
	// On efface la configuration précédente
	WiFi.disconnect(true);
	Serial.println();
	Serial.print("Connexion a ");
	Serial.println(ssid);
	// Initialisation de la connection
	WiFi.begin(ssid, password);
	// Test pour déterminer quand la connection est prete
	while (WiFi.status() != WL_CONNECTED) {
		delay(500);
		Serial.print(".");
	}
	// Affichage des informations
	Serial.println("");
	Serial.println(" connecte");
	Serial.print("Adresse IP: ");
	Serial.println(WiFi.localIP());
	Serial.print("Adresse MAC: ");
	Serial.println(WiFi.macAddress());
	Serial.print("Masque : ");
	Serial.println(WiFi.subnetMask());
	Serial.print("Passerelle : ");
	Serial.println(WiFi.gatewayIP());
	Serial.print("RSSI (force du signal): ");
	Serial.println(WiFi.RSSI());
	Serial.print("Canal: ");
	Serial.println(WiFi.channel());
}

Le code précédent vous donne le résultat suivant sur le port série :

Connexion a CAMPUSCD-CROIXVERTE2.. connecte
Adresse MAC: 2E:3A:E8:17:2C:A7
Adresse IP: 192.168.52.85
Masque : 255.255.252.0
Passerelle : 192.168.55.250
RSSI (force du signal): -67
Canal: 6

Maintenant que nous connaissons les paramètres données par le réseau, essayons de nous y connecter de manière statique. Dans la partie des variables statiques ajoutez les lignes suivantes :

IPAddress ip(192, 168, 52, 85);
IPAddress dns(192, 168, 55, 250);
IPAddress gw(192, 168, 55, 250);
IPAddress mask(255, 255, 252, 0);

Avant la ligne :

WiFi.begin(ssid, password);

Insérez les lignes :

// Application de la configuration de niveau 3 OSI
WiFi.config(ip, gw, mask, dns);

La connexion devrait être quasiment instantanée !

Point d'accès

Pour mettre en place un point d'accès, rien de plus simple :

#include <ESP8266WiFi.h>

const char ssid[] = "tala";
const char password[] = "informatique";

void setup() {
	// on démarre le port série
	Serial.begin(115200);
	// On attend "un peu" que le buffer soit prêt
	delay(10);
	// On efface la configuration précédente
	WiFi.disconnect(true);
	Serial.println();
	Serial.println("Demarrage du point d'acces...");
	// Initialisation du point d'accès
	WiFi.softAP(ssid, password);
	// Réglage de la puissance (0dBm < x < 20dBm)
	WiFi.setOutputPower(5);
	// Affichage de l'adresse IP
	Serial.print("Adresse MAC: ");
	Serial.println(WiFi.softAPmacAddress());
	Serial.print("Adresse IP: ");
	Serial.println(WiFi.softAPIP());
}

void loop() {
}
Warning-icon.png Gardez à l'esprit que le mot de passe doit faire au moins 8 caractères pour respecter la norme WPA !

Le code précédent vous donne le résultat suivant sur le port série :

Demarrage du point d'acces...
Adresse MAC: 2E:3A:E8:17:2C:A7
Adresse IP: 192.168.4.1

Il est possible de modifier certain paramètres de niveau 3 OSI. Dans la partie des variables statiques ajoutez les lignes suivantes :

IPAddress ip(192, 168, 10, 1);
IPAddress gw(192, 168, 10, 254);
IPAddress mask(255, 255, 252, 0);

Avant la ligne :

WiFi.softAP(ssid, password);

Insérez les lignes :

// Application de la configuration de niveau 3 OSI
WiFi.softAPConfig(ip, gw, mask);

La sorite console doit afficher :

Demarrage du point d'acces... 
Adresse MAC: 2E:3A:E8:17:2C:A7
Adresse IP: 192.168.10.1

Lorsque vous utilisez l'ESP comme point d'accès, un serveur DHCP fournira automatiquement la configuration de niveau 3 OSI.

Programmation événementielle

Il est possible de définir une fonction de callback qui sera appelée lorsqu'un événements arrive. Les événements possibles sont les suivants :

Événement Description Mode
AP WiFi.onSoftAPModeStationConnected(<function>) Connexion d'un client
AP WiFi.onSoftAPModeStationDisconnected(<function>) Déconnexion d'un client
client WiFi.onStationModeAuthModeChanged(<function>) Changement du mode d'authentification
client WiFi.onStationModeConnected(<function>) Connexion au réseau réussie
client WiFi.onStationModeDHCPTimeout(<function>) Configuration DHCP non reçue
client WiFi.onStationModeGotIP(<function>) Configuration OSI 3 reçue
client WiFi.onStationModeDisconnected(<function>) Déconnexion du réseau

Point d'accès

Pour gérer les événements, il faut créer un handler qui va se charger d'appeler la bonne fonction. Dans la partie des variables statiques ajoutez les lignes suivantes :

WiFiEventHandler stationConnectedHandler;
WiFiEventHandler stationDisconnectedHandler;

Pour spécifier les fonctions à exécuter, après la ligne :

WiFi.disconnect(true);

ajoutez :

// Gestion des événements
stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onConnect);
stationDisconnectedHandler = WiFi.onSoftAPModeStationDisconnected(&onDisconnect);

Il ne nous reste plus qu'à ajouter les fonctions suivantes :

/**
 * Gestion des connexions
 */
void onConnect(const WiFiEventSoftAPModeStationConnected& evt){
	Serial.println("client connecte\n");
	Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x", evt.mac[0], evt.mac[1], evt.mac[2], evt.mac[3], evt.mac[4], evt.mac[5]);
}

/**
 * Gestion des déconnexions
 */
void onDisconnect(const WiFiEventSoftAPModeStationDisconnected& evt){
	Serial.println("client deconnecte\n");
	Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x", evt.mac[0], evt.mac[1], evt.mac[2], evt.mac[3], evt.mac[4], evt.mac[5]);
}

Le résultat sera le suivant :

Demarrage du point d'acces... 
Adresse MAC: 2E:3A:E8:17:2C:A7 
Adresse IP: 192.168.10.1
client connecte: d8:eb:97:19:7b:55
client deconnecte: d8:eb:97:19:7b:55

Client

Pour gérer les événements, il faut créer un handler qui va se charger d'appeler la bonne fonction. Dans la partie des variables statiques ajoutez les lignes suivantes :

WiFiEventHandler stationModeConnected;
WiFiEventHandler stationModeGotIP;
WiFiEventHandler stationModeDisconnected;

Pour spécifier les fonctions à exécuter, après la ligne :

WiFi.disconnect(true);

ajoutez :

// Gestion des événements
stationModeConnectedHandler = WiFi.onStationModeConnected(&onConnect);
stationModeDisconnectedHandler = WiFi.onStationModeDisconnected(&onDisconnect);
stationModeGotIPHandler = WiFi.onStationModeGotIP(&onGotIP);

Il ne nous reste plus qu'à ajouter les fonctions suivantes :

/**
 * Gestion de la connexion
 */
void onConnect(const WiFiEventStationModeConnected& evt){
	Serial.println("\nClient connecte: ");
	Serial.print("\tbssid: ");
	Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n", evt.bssid[0], evt.bssid[1], evt.bssid[2], evt.bssid[3], evt.bssid[4], evt.bssid[5]);
	Serial.print("\tssid: ");
	Serial.println(evt.ssid);
	Serial.print("\tcanal: ");
	Serial.println(evt.channel);
}

/**
 * Gestion de la déconnexion
 */
void onDisconnect(const WiFiEventStationModeDisconnected& evt){
	Serial.println("\nClient deconnecte: ");
	Serial.print("\tbssid: ");
	Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n", evt.bssid[0], evt.bssid[1], evt.bssid[2], evt.bssid[3], evt.bssid[4], evt.bssid[5]);
	Serial.print("\tssid: ");
	Serial.println(evt.ssid);
	Serial.print("\traison: ");
	Serial.println(evt.reason);
}

/**
 * Gestion des paramètres OSI 3
 */
void onGotIP(const WiFiEventStationModeGotIP& evt){
	Serial.println("\nConfiguration OSI 3: ");
	Serial.print("\tip: ");
	Serial.println(evt.ip);
	Serial.print("\tmasque: ");
	Serial.println(evt.mask);
	Serial.print("\tpasserelle: ");
	Serial.println(evt.gw);
}

Enfin, nous allons supprimer les lignes qui se trouvent dans la fonction setup après :

// Affichage des informations

et les remplacer par :

// Affichage des informations
WiFi.disconnect(true);

Le résultat sera le suivant :

Connexion a CAMPUSCD-CROIXVERTE2
.....
Client connecte: 
	bssid: 14:dd:a9:99:04:00
	ssid: CAMPUSCD-CROIXVERTE2
	canal: 6
...
Configuration OSI 3: 
	ip: 192.168.1.197
	masque: 255.255.255.0
	passerelle: 192.168.1.254
.
Client deconnecte: 
	bssid: 14:dd:a9:99:04:00
	ssid: 
	raison: 8

On peut se demander à quoi peut bien correspondre la raison 8 ? Elle fait partie de l'Enum WiFiDisconnectReason qui possède les valeurs suivantes:

Nom Valeur
WIFI_DISCONNECT_REASON_UNSPECIFIED 1
WIFI_DISCONNECT_REASON_AUTH_EXPIRE 2
WIFI_DISCONNECT_REASON_AUTH_LEAVE 3
WIFI_DISCONNECT_REASON_ASSOC_EXPIRE 4
WIFI_DISCONNECT_REASON_ASSOC_TOOMANY 5
WIFI_DISCONNECT_REASON_NOT_AUTHED 6
WIFI_DISCONNECT_REASON_NOT_ASSOCED 7
WIFI_DISCONNECT_REASON_ASSOC_LEAVE 8
WIFI_DISCONNECT_REASON_ASSOC_NOT_AUTHED 9
WIFI_DISCONNECT_REASON_DISASSOC_PWRCAP_BAD 10
WIFI_DISCONNECT_REASON_DISASSOC_SUPCHAN_BAD 11
WIFI_DISCONNECT_REASON_IE_INVALID 13
WIFI_DISCONNECT_REASON_MIC_FAILURE 14
WIFI_DISCONNECT_REASON_4WAY_HANDSHAKE_TIMEOUT 15
WIFI_DISCONNECT_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
WIFI_DISCONNECT_REASON_IE_IN_4WAY_DIFFERS 17
WIFI_DISCONNECT_REASON_GROUP_CIPHER_INVALID 18
WIFI_DISCONNECT_REASON_PAIRWISE_CIPHER_INVALID 19
WIFI_DISCONNECT_REASON_AKMP_INVALID 20
WIFI_DISCONNECT_REASON_UNSUPP_RSN_IE_VERSION 21
WIFI_DISCONNECT_REASON_INVALID_RSN_IE_CAP 22
WIFI_DISCONNECT_REASON_802_1X_AUTH_FAILED 23
WIFI_DISCONNECT_REASON_CIPHER_SUITE_REJECTED 24
WIFI_DISCONNECT_REASON_BEACON_TIMEOUT 200
WIFI_DISCONNECT_REASON_NO_AP_FOUND 201
WIFI_DISCONNECT_REASON_AUTH_FAIL 202
WIFI_DISCONNECT_REASON_ASSOC_FAIL 203
WIFI_DISCONNECT_REASON_HANDSHAKE_TIMEOUT 204

Scanner les réseaux

Il est possible de scanner les réseaux WiFi environnant et de récupérer certaines informations. Pour accomplir cela nous allons démarrer l'ESP en mode client mais sans se connecter a un réseau grâce à la fonction WiFi.mode():

#include "ESP8266WiFi.h"

void setup() {
	Serial.begin(115200);
	// On attend "un peu" que le buffer soit prêt
	delay(100);
	// Passage de la puce en mode client
	WiFi.mode(WIFI_STA);
	// Effacement de la configuration précédente
	WiFi.disconnect();
	Serial.println("\n!--- Scanner pret ---!\n");
}

Nous allons ensuite lancer un scan grâce à la fonction WiFi.scanNetworks() :

void loop() {
	Serial.print("scan en cours... ");
	// WiFi.scanNetworks retroune le nombre de réseau(x) trouvé(s)
	int n = WiFi.scanNetworks();
	if (n == 0) {
		Serial.println("aucun reseau trouve");
	} else {
		Serial.print(n);
		Serial.println(" reseau(x) trouve(s)");
		for (int i = 0; i < n; ++i) {
			// Print SSID and RSSI for each network found
			displayNetwork(i);
			delay(10);
		}
	}
	Serial.println("");
	// On attend un certain temps avant le nouveau scan
	delay(5000);
}

Il ne nous reste plus qu'a afficher les informations:

void displayNetwork(uint8_t index) {
	Serial.print(index + 1);
	Serial.print(": ");
	Serial.print(WiFi.SSID(index));
	Serial.print(" (");
	Serial.print(WiFi.RSSI(index));
	Serial.print(") security ");
	if(WiFi.encryptionType(index) == ENC_TYPE_NONE){
		Serial.println("none");
	}else if(WiFi.encryptionType(index) == ENC_TYPE_CCMP){
		Serial.println("ccmp");
	}else if(WiFi.encryptionType(index) == ENC_TYPE_TKIP){
		Serial.println("tkip");
	}else if(WiFi.encryptionType(index) == ENC_TYPE_WEP){
		Serial.println("wep");
	}else if(WiFi.encryptionType(index) == ENC_TYPE_AUTO){
		Serial.println("auto");
	}
}

Le code précédent devrait afficher les lignes suivantes sur la console :

!--- Scanner pret ---!

scan en cours... 3 reseau(x) trouve(s)
1: e900 (-62) security ccmp
2: e900 (-83) security ccmp
3: e900 (-80) security ccmp