MAC Detector ESP32

Hello everyone

Today we want to introduce you to a project to which we became aware through a customer request. We show you a MAC address detector with our ESP32 Dev Board C.

No more hardware than this board is required. The Mac-Detector scans consecutively for the addresses stored in the code and outputs them in the serial monitor as soon as a device approaches. For this purpose, we use the Promiscuous mode, which can be used much more easily with the ESP32 than with the predecessor ESP8266. The presence detection works quite reliably, but it is important to note that the scanner only outputs something when the WiFi device is "awake" and communicates. So it may take some time for the address to appear in the serial monitor. Depending on the device used and its configuration, they often save energy and switch off unused components. Various iPhones have proved to be particularly keen to communicate.

Simply enter the desired addresses under :adress list, ready.

Here is the 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 There;   MacAddr Sat;   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 =8;<=8+6+1;++){ This reads the first couple of bytes of the packet. This is where you can read the whole packet replacethe "8+6+1" with "p->rx_ctrl.sig_len"      Packet += String(P->Payload[],Hex);   }   for(Int =4;<=15;++){ This removes the 'nibble' bits from the stat and end of the data we want. So we only get the mac address.     Mac += Packet[];   }   Mac.Touppercase();      Int Added = 0;   for(Int =0;<=63;++){ checks if the MAC address has been added before     If(Mac == maclist[][0]){       maclist[][1] = defaultTTL;       If(maclist[][2] == "OFFLINE"){         maclist[][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("Start!");
}

Void Purge(){ This manages the TTL   for(Int =0;<=63;++){     If(!(maclist[][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 :)

Esp-32Projects for beginners

4 comments

Hans

Hans

Bei diesem code werden nicht alle Mac-Adressen richtig erkannt.
Beispiel:
Korrekte mac-adresse vom Gerät: D4:AE:05:0D:D7:28
Der Code erkennt: D4AE5DD728
Die 0 fehlen.

Erklärung:
Hexadezimal: D4:AE:05:0D:D7:28
Dezimal: 212:174:5:13:215:1C

- Dezimal 05 ist Hexa 5. Das 0 wird gestrichen.
- Dezimal 13 ist Hexa D. Das 0 wird gestrichen.

Der fehlerhafte code-abschnitt habe ich für mich wie folgt gelöst:

String packet; String packet3; String mac; int fctl = ntohs(wh→fctl); for (int i = 8; i <= 8 + 6 + 1; i++) { String packet2 = String(p→payload[i], HEX); if (packet2.length() == 1) { packet3 = “0” + packet2; packet += packet3; } else { packet += packet2; } }
Markus Hopfner

Markus Hopfner

Guten Tag (nochmals),

wollte Sie nur nochmals darauf Aufmerksam machen das der Code nicht mit MAC-Adressen mit zwei Nullen in folge funktioniert.

mfg

Markus

Markus Hopfner

Markus Hopfner

Guten Tag,
zuerst einmal vielen dank für den Code.

Mir ist aufgefallen das er nicht funktioniert wenn die MAC eine Doppelnull hat, da wird eine verschluckt. können Sie mir sagen wieso?

Mfg Markus

Willy

Willy

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.

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN