Pepper 2019 – Localisation wifi par ESP8266

Il n’est pas possible d’utiliser les commandes systèmes de Pepper en programmation normale. En effet, les accès « sudo » sont verrouillés par le constructeur. Pour localiser le robot en fonction des signaux wifi, il faut donc y embarquer un matériel communicant supplémentaire, un peu comme un GPS dans une voiture.



Taille : 75mm x 35mm
Le principe retenu utilise une carte ESP8266 qui scanne le réseau wifi en permanence,
et publie le résultat sur une page HTML de son site internet local.

Le logiciel embarqué dans la carte ESP :

  1. s’initialise pour avoir une adresse IP fixe
  2. se connecte au Wifi local
  3. initialise un serveur web
  4. scanne en permanence le wifi local
  5. la page HTML d’accueil est recrée en fonction des résultats du scan, avec
    les 4 signaux les plus forts.



Page renvoyée par l’ESP

Initialisation de l’ESP


void setup() {
  Serial.begin(115200);
  // IP statique
  IPAddress ip(192, 168, 1, 222);
  IPAddress gateway(192, 168, 1, 254);
  IPAddress subnet(255, 255, 255, 0);
  IPAddress dns(192, 168, 1, 254);
  WiFi.config(ip, dns, gateway, subnet);
  WiFi.begin(ssid, password);
  Serial.println("");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("\nConnexion ");
  Serial.println(ssid);
  Serial.print("Addresse IP: ");
  Serial.println(WiFi.localIP());
  ...
}

Scan réseau

La fonction Wifi.scanNetworks() renvoie le nombre de wifi détectés. Les fonctions Wifi.SSID(i) et Wifi.RSSI(i) renvoient respectivement
le i-ème SSID détecté ainsi que la force du signal (le rssi)

void loop() {

    Serial.println("scan ...");
    // WiFi.scanNetworks renvoie le nombre de reseaux trouves
    int n = WiFi.scanNetworks();
    Serial.println("scan ok");
    if (n == 0)  Serial.println("Pas de reseau");
    else {
      Serial.print(n);
      Serial.println(" Wifi : ");
      SCAN=1;
      raz(); 
      for (int i = 0; i < n; ++i)  {
          ajoute((WiFi.SSID(i)).c_str(), WiFi.RSSI(i)); 
          Serial.print(i + 1);
          Serial.print(": ");
          Serial.print(WiFi.SSID(i));
          Serial.print(" (");
          Serial.print(WiFi.RSSI(i));
          Serial.println(")\n");
      }
      SCAN=0;
    }
   server.handleClient();
}

 

Stockage des n meilleurs résultats

Les wifi détectés sont stockés dans un tableau de structures.
Chaque structure contient un SSID et son RSSI. On ne conserve que les NWIFI les meilleurs

#define NWIFI 4

struct Swifi {
  char wf[128];
  int rssi;
} TW[NWIFI];


// RAZ du tableau des meilleurs wifi
void raz() {
  for (int i=0; i<NWIFI; i++) {
     TW[i].rssi=-1000;
     TW[i].wf[0] = 0;
  }
}

// Ajout d'un wifi dans la sélection.
// Seulement s'il fait partie des meilleurs ..
void ajoute(const char *ssid, int rssi){
   int r = 0;
   while (rr; i--) TW[i]=TW[i-1];
   TW[r].rssi = rssi;
   strcpy(TW[r].wf, ssid);
}

 

Fabrication de la page HTML

La page HTML est fabriquée à partir de la dernière mesure de wifi.
La fonction handleRoot() renvoie le message à chaque client web
qui a fait la requête http://192.168.1.222/

 


// page html
char html[128*NWIFI];

void handleRoot() {
  char b[128];
  html[0] = 0;
  while (SCAN==1) delay(10);
  for (int i=0; i<NWIFI; i++) {
     sprintf(b,"%s;%d\n", TW[i].wf, TW[i].rssi);
     strcat(html, b);
  }
  server.send(200, "text/plain", html);
}

 

Code complet

ScannerDoc.ino

Récupération des informations en python

Le programme python utilise le module requests. Le code est trivial :


La trace d’exécution est dans la partie droite