MAC Detector ESP32

Hallo zusammen,

heute wollen wir euch ein Projekt vorstellen auf welches wir durch eine Kundenanfrage aufmerksam wurden. Wir zeigen euch einen MAC-Adressen Detektor mit unserem ESP32 Dev Board C.

Mehr Hardware als dieses Board ist nicht erforderlich. Der Mac-Detector scannt kontiniuerlich nach den im Code hinterlegten Adressen und gibt diese, sobald sich ein Gerät nähert, im Seriellen Monitor aus. Dafür nutzen wir den Promiscuous Mode der sich beim ESP32 deutlich unkomplizierter benutzen lässt als noch beim Vorgänger ESP8266. Die Anwesenheitserkennung funktioniert recht zuverlässig, allerdings gilt es zu beachten, dass der Scanner erst etwas ausgibt wenn das WiFi-Gerät "wach ist" und kommuniziert. So kann es mitunter etwas dauern bis die Adresse im Seriellen Monitor erscheint. Je nach verwendetem Gerät und dessen Konfiguration sparen diese oft Energie und schalten dabei ungenutze Komponenten ab. Als besonders Kommunikationsfreudig haben sich dabei diverse iPhones erwiesen.

Einfach unter //adress list die gewünschten Adressen eintragen, fertig.

Hier der Code:

 

#include <WiFi.h>
#include <Wire.h>

#include "esp_wifi.h"


String maclist[64][3]; 
int listcount = 0;

String KnownMac[10][2] = {  // adress list
  {"Chef1","8C1ABF8A6A36"},
  {"Chef2","E894BA82BC83"},
  {"NAME","MACADDRESS"},
  {"NAME","MACADDRESS"},
  {"NAME","MACADDRESS"},
  {"NAME","MACADDRESS"},
  {"NAME","MACADDRESS"},
  {"NAME","MACADDRESS"},
  {"NAME","MACADDRESS"}
  
};

String defaultTTL = "60"; // Maximum time (Apx seconds) elapsed before device is consirded offline

const wifi_promiscuous_filter_t filt={
    .filter_mask=WIFI_PROMIS_FILTER_MASK_MGMT|WIFI_PROMIS_FILTER_MASK_DATA
};

typedef struct { 
  uint8_t mac[6];
} __attribute__((packed)) MacAddr;

typedef struct { 
  int16_t fctl;
  int16_t duration;
  MacAddr da;
  MacAddr sa;
  MacAddr bssid;
  int16_t seqctl;
  unsigned char payload[];
} __attribute__((packed)) WifiMgmtHdr;


  
#define maxCh 13 //max Channel -> US = 11, EU = 13, Japan = 14


int curChannel = 1;


void sniffer(void* buf, wifi_promiscuous_pkt_type_t type) { //This is where packets end up after they get sniffed
  wifi_promiscuous_pkt_t *p = (wifi_promiscuous_pkt_t*)buf;
  int len = p->rx_ctrl.sig_len;
  WifiMgmtHdr *wh = (WifiMgmtHdr*)p->payload;
  len -= sizeof(WifiMgmtHdr);
  if (len < 0){
    Serial.println("Receuved 0");
    return;
  }
  String packet;
  String mac;
  int fctl = ntohs(wh->fctl);
  for(int i=8;i<=8+6+1;i++){ // This reads the first couple of bytes of the packet. This is where you can read the whole packet replaceing the "8+6+1" with "p->rx_ctrl.sig_len"
     packet += String(p->payload[i],HEX);
  }
  for(int i=4;i<=15;i++){ // This removes the 'nibble' bits from the stat and end of the data we want. So we only get the mac address.
    mac += packet[i];
  }
  mac.toUpperCase();

  
  int added = 0;
  for(int i=0;i<=63;i++){ // checks if the MAC address has been added before
    if(mac == maclist[i][0]){
      maclist[i][1] = defaultTTL;
      if(maclist[i][2] == "OFFLINE"){
        maclist[i][2] = "0";
      }
      added = 1;
    }
  }
  
  if(added == 0){ // If its new. add it to the array.
    maclist[listcount][0] = mac;
    maclist[listcount][1] = defaultTTL;
   // Serial.println(mac);
    listcount ++;
    if(listcount >= 64){
      Serial.println("Too many addresses");
      listcount = 0;
    }
  }
}


void setup() {

  Serial.begin(115200);

  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  esp_wifi_init(&cfg);
  esp_wifi_set_storage(WIFI_STORAGE_RAM);
  esp_wifi_set_mode(WIFI_MODE_NULL);
  esp_wifi_start();
  esp_wifi_set_promiscuous(true);
  esp_wifi_set_promiscuous_filter(&filt);
  esp_wifi_set_promiscuous_rx_cb(&sniffer);
  esp_wifi_set_channel(curChannel, WIFI_SECOND_CHAN_NONE);
  
  Serial.println("starting!");
}

void purge(){ // This manages the TTL
  for(int i=0;i<=63;i++){
    if(!(maclist[i][0] == "")){
      int ttl = (maclist[i][1].toInt());
      ttl --;
      if(ttl <= 0){
        //Serial.println("OFFLINE: " + maclist[i][0]);
        maclist[i][2] = "OFFLINE";
        maclist[i][1] = defaultTTL;
      }else{
        maclist[i][1] = String(ttl);
      }
    }
  }
}

void updatetime(){ // This updates the time the device has been online for
  for(int i=0;i<=63;i++){
    if(!(maclist[i][0] == "")){
      if(maclist[i][2] == "")maclist[i][2] = "0";
      if(!(maclist[i][2] == "OFFLINE")){
          int timehere = (maclist[i][2].toInt());
          timehere ++;
          maclist[i][2] = String(timehere);
      }
      
     // Serial.println(maclist[i][0] + " : " + maclist[i][2]);
      
    }
  }
}

void showpeople(){ // This checks if the MAC is in the reckonized list and then displays it on the OLED and/or prints it to serial.
  String forScreen = "";
  for(int i=0;i<=63;i++){
    String tmp1 = maclist[i][0];
    if(!(tmp1 == "")){
      for(int j=0;j<=9;j++){
        String tmp2 = KnownMac[j][1];
        if(tmp1 == tmp2){
          forScreen += (KnownMac[j][0] + " : " + maclist[i][2] + "\n");
          Serial.print(KnownMac[j][0] + " : " + tmp1 + " : " + maclist[i][2] + "\n -- \n");
        }
      }
    }
  }
}

void loop() {
    //Serial.println("Changed channel:" + String(curChannel));
    if(curChannel > maxCh){ 
      curChannel = 1;
    }
    esp_wifi_set_channel(curChannel, WIFI_SECOND_CHAN_NONE);
    delay(1000);
    updatetime();
    purge();
    showpeople();
    curChannel++;
    
    
}

 

In einem folgendem Beitrag werden wir versuchen die Anwesenheitserkennung mittels BLE umzusetzten. Bis zum nächsten mal :)

Letzter Artikel I²C Scanner mit LC Display
Neuer Artikel ESP Easy konfigurieren

Kommentar

Willy - Oktober 11, 2018

Das ist ein interessantes Projekt. Kann ich auch die MAC-Adressen mit einem ESP8266 scannen?
Genauer gesagt will ich den Amazon Dash-Button im WLAN erkennen. Der ESP8266 ist der Hotspot mit dem sich der DASH-Button verbindet. Aber ich weiss nicht wie ich die MAC-Adresse erkennen kann das der Dash-Button sich verbunden hat. Die MAC-Adresse des Dash-Button kenne ich.

Hinterlasse einen Kommentar

Kommentare müssen vor der Veröffentlichung überprüft werden

Erforderliche Angabe