MKR1000 - Skenovanie WiFi siete

Zápisník experimentátora

Hierarchy: Arduino MKR1000

V tomto článku si vyskúšame skenovanie WiFi siete pomocou Arduina MKR1000. Budeme vychádzať zo vzorového príkladu, ktorý je dodávaný ku knižnici WiFi101, program ale upravíme tak, aby sa výsledok zobrazoval na displeji Nokia 5110.

Skenovanie WiFi siete je vďačný projekt pre každého zvedavca. Poskladáte si skener a môžete s ním vyraziť na sídlisko a sledovať, aké siete sa tam nachádzajú. Alebo budete len tak sedieť za stolom a sledovať, čo všetko sa nachádza vo vašej blízkosti. Napríklad ja vidím od môjho stola na 5-7 sietí. Dve z toho sú u mňa doma a okolité sa nachádzajú niekde v blízkych bytoch.

Nokia 5110

Tento displej rád používam v mojich projektoch. Klasické Arduino na 5 V potrebuje na jeho ovládanie level shifter. Toto všetko môže pri MKR1000 odpadnúť, pretože používa rovnako ako displej 3,3 V. Čiže celé zapojenie sa scvrkne do prepojenia niekoľkých vodičov.

Na ovládanie displeja budeme používať knižnicu Adafruit_PCD8544. Dá sa nainštalovať aj v správcovi knižníc, ale má to jeden háčik. Je potrebná minimálne verzia 1.0.1, ktorá vie spolupracovať s mikrokontrolérmi SAMD21. V čase písania článku bola už úprava na GitHub, ale nebola ešte k dispozícii v správcovi knižníc. Preto ju bolo potrebné z GitHub stiahnuť ručne a prepísať s ňou nainštalovanú knižnicu.

WiFi101

Ďalšou potrebnou knižnicou je WiFi101. Táto sa dá nainštalovať aj v správcovi knižníc. V čase písania článku tam bola verzia 0.11.0.

IDE

Celé zapojenie som testoval v IDE 1.6.12.

Správanie programu

Program som zmodifikoval podľa pôvodného vzorového príkladu ku knižnici WiFi101 ScanNetworks. Ten vypisoval nájdené WiFi siete na sériový port. To všetko som v kóde nechal, aj keď som niektoré funkcie mierne upravil. Doplnil som výpisy na displeji Nokia 5110.

Funguje to tak, že sa prehľadá zoznam WiFi sietí a ten sa postupne zobrazuje na displeji. Príklad je dobre viditeľný na priložených obrázkoch. Vypisuje:

  • poradové číslo siete
  • SSID siete - Toto je názov siete. Aby som majiteľom sietí zachoval nejaké súkromie, na obrázku sú vždy dva posledné znaky nahradené znakom otáznika. V zdrojovom texte si to môžete v prípade potreby vypnúť a vidieť celý názov siete.
  • silu signálu
  • šifrovanie

Výpis sa mení každé dve sekundy. Po vypísaní všetkých sietí sa zase vyhľadá aktuálny zoznam WiFi sietí a pokračuje sa jeho výpisom.

Includovanie knižníc a nastavenie displeja.

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <WiFi101.h>

// Software SPI (slower updates, more flexible pin options):
// pin 1 - Serial clock out (SCLK)
// pin 2 - Serial data out (DIN)
// pin 3 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 5 - LCD reset (RST)
Adafruit_PCD8544 nokia = Adafruit_PCD8544(1, 2, 3, 4, 5);

Nastavenie. Kontrast si možno budete musieť doladiť. Hodnoty nad 60 vedú k veľkému šumu na displeji, pod 50 pravdepodobne nebudete nič vidieť. Súčasťou nastavenia je aj zobrazenie intra funkciou drawIntro. To pozostáva zo zobrazenia dvoch obrazoviek informácií. Na chvíľu sa zobrazí aj MAC adresa mikrokontroléra.

void setup()   {
  Serial.begin(9600);

  nokia.begin();
  nokia.setContrast(60);
  nokia.clearDisplay();   // clears the screen and buffer
  drawIntro();
  nokia.clearDisplay();
  nokia.display();

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    nokia.setCursor(0, 0);
    nokia.print("WiFi shield not present");
    nokia.display();
    // don't continue:
    while (true);
  }

  // Print WiFi MAC address:
  printMacAddress();
}

Takto vyzerá kód intra.

void drawIntro()
{
  nokia.setCursor(0, 0);
  nokia.print("WiFi Scan Network");
  Serial.println("WiFi Scan Network");
  nokia.setCursor(0, 20);
  nokia.print("www.arduinoslovakia.eu");
  nokia.display();
  delay(2000);
  nokia.clearDisplay();
  nokia.setCursor(0, 0);
  nokia.print("List of all WiFi networks.");
  Serial.println("List of all WiFi networks.");
  nokia.display();
  delay(2000);
}

Zobrazenie MAC adresy. V pôvodnom kóde to vypisovali po jednotlivých bajtoch. Ale funkcia print neformátuje dobre hexadecimálne čísla, menšie ako 0F a zobrazuje ich ako F. V mikrokontroléri MKR1000 máme ale dostatok pamäte, aby sme si mohli dovoliť komfortné vypisovanie funkciou sprintf. A vyzerá to aj krajšie.

void printMacAddress() {
  // the MAC address of your Wifi shield
  byte mac[6];
  char draw[30];

  // print your MAC address:
  WiFi.macAddress(mac);
  sprintf(draw, "MAC:%02X:%02X:%02X:%02X:%02X:%02X", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);

  nokia.clearDisplay();
  nokia.setCursor(0, 0);
  nokia.print(draw);
  Serial.println(draw);

  nokia.display();
}

Hlavný cyklus programu. Periodicky sa volá funkcia listNetworks, ktorá sa stará o vykresľovanie.

void loop() {
  // scan for existing networks:
  Serial.println("Scanning available networks...");
  nokia.clearDisplay();
  nokia.setCursor(0, 0);
  nokia.print("Scanning...");
  nokia.display();
  listNetworks();
}

Samotná funkcia na výpisovanie informácii na sériový port (pôvodný kod) a displej Nokia 5110 (nový kód). Na vypisovanie textov využíva premenné draw a ssid. Všimnite si, ako sa využíva funkcia strlen (vracia dĺžku reťazca) na zamaskovanie posledných dvoch znakov SSID. Všetký výpisy sú opäť pripravované pomocou funkcie sprintf.

void listNetworks() {
  char draw[30];
  char ssid[M2M_MAX_SSID_LEN];
  
  // scan for nearby networks:
  int numSsid = WiFi.scanNetworks();
  if (numSsid == -1)
  {
    Serial.println("Couldn't get a wifi connection");
    while (true);
  }

  // print the list of networks seen:
  Serial.print("Number of available networks: ");
  Serial.println(numSsid);

  // print the network number and name for each network found:
  for (int thisNet = 0; thisNet < numSsid; thisNet++) {
    strcpy(ssid,WiFi.SSID(thisNet));
    int dl=strlen(ssid);
    if(dl>2) { // hide some details
      ssid[dl-2]='?';
      ssid[dl-1]='?';
    }
    
    Serial.print(thisNet+1);
    Serial.print(") ");
    Serial.print(ssid);
    Serial.print("\tSignal: ");
    Serial.print(WiFi.RSSI(thisNet));
    Serial.print(" dBm");
    Serial.print("\tEncryption: ");
    Serial.println(getEncryptionType(WiFi.encryptionType(thisNet)));
    Serial.flush();

    nokia.clearDisplay();
    nokia.setCursor(0, 0);
    sprintf(draw,"Net: %d/%d",thisNet+1,numSsid);
    nokia.print(draw);
    nokia.setCursor(0, 8);
    nokia.print(ssid);
    nokia.setCursor(0, 24);
    sprintf(draw,"Sig: %d dBm",WiFi.RSSI(thisNet));
    nokia.print(draw);
    nokia.setCursor(0, 32);
    sprintf(draw,"Enc: %s",getEncryptionType(WiFi.encryptionType(thisNet)));
    nokia.print(draw);
    nokia.display();

    delay(2000);
  }
}

Nasledujúcu funkciu som kompletne prepísal. Pôvodný kód priamo vypisoval na sériový port. Teraz funkcia iba vráti pointer na textový reťazec.

const char S_WEP[]="WEP";
const char S_TKIP[]="WPA";
const char S_CCMP[]="WPA2";
const char S_NONE[]="None";
const char S_AUTO[]="Auto";
const char S_UNKNOWN[]="Unkn.";

const char* getEncryptionType(int thisType) {
  // read the encryption type and print out the name:
  switch (thisType) {
    case ENC_TYPE_WEP:
      return S_WEP;
    case ENC_TYPE_TKIP:
      return S_TKIP;
    case ENC_TYPE_CCMP:
      return S_CCMP;
    case ENC_TYPE_NONE:
      return S_NONE;
    case ENC_TYPE_AUTO:
      return S_AUTO;
    default:
      return S_UNKNOWN;
  }
}

Zdrojový kód

Zdrojový kód sa nachádza na GitHub.

Video

Video k článku je na Youtube. Vo videu je vidno skenovanie WiFi sietí okolo mňa a pripojenie WiFi bodu z mobilného telefónu a akčnej kamery Xiaomi Yi.


15.11.2016


Menu