/* WiFi Sniffer for ESP32 that sends received packages via LoRa This code is heavily based on the code from: https://github.com/ESP-EOS/ESP32-WiFi-Sniffer */ #include "freertos/FreeRTOS.h" #include "esp_wifi.h" #include "esp_wifi_types.h" #include "esp_system.h" #include "esp_event.h" #include "esp_event_loop.h" #include "nvs_flash.h" #include "driver/gpio.h" #include #include // Der LED-Port variiert von Board zu Board. Ich nutze die LED // um zu zeigen, wann das Board sendet #define LED_GPIO_PIN 22 #define WIFI_CHANNEL_SWITCH_INTERVAL (500) #define WIFI_CHANNEL_MAX (13) uint8_t level = 0, channel = 1; int16_t signalwert = 0; String mac; static wifi_country_t wifi_country = {.cc="DE", .schan = 1, .nchan = 13}; //Most recent esp32 library struct typedef struct { unsigned frame_ctrl:16; unsigned duration_id:16; uint8_t addr1[6]; /* receiver address */ uint8_t addr2[6]; /* sender address */ uint8_t addr3[6]; /* filtering address */ unsigned sequence_ctrl:16; uint8_t addr4[6]; /* optional */ } wifi_ieee80211_mac_hdr_t; typedef struct { wifi_ieee80211_mac_hdr_t hdr; uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */ } wifi_ieee80211_packet_t; static esp_err_t event_handler(void *ctx, system_event_t *event); static void wifi_sniffer_init(void); static void wifi_sniffer_set_channel(uint8_t channel); static const char *wifi_sniffer_packet_type2str(wifi_promiscuous_pkt_type_t type); static void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); esp_err_t event_handler(void *ctx, system_event_t *event) { return ESP_OK; } void wifi_sniffer_init(void) { nvs_flash_init(); tcpip_adapter_init(); ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country) ); /* set country for channel range [1, 13] */ ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) ); ESP_ERROR_CHECK( esp_wifi_start() ); esp_wifi_set_promiscuous(true); esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler); } void wifi_sniffer_set_channel(uint8_t channel) { esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); } const char * wifi_sniffer_packet_type2str(wifi_promiscuous_pkt_type_t type) { switch(type) { case WIFI_PKT_MGMT: return "MGMT"; case WIFI_PKT_DATA: return "DATA"; default: case WIFI_PKT_MISC: return "MISC"; } } void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) { if (type != WIFI_PKT_MGMT) return; const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff; const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr; signalwert = ppkt->rx_ctrl.rssi; // Die MAC-Adresse wird addiert. Das ergibt eigentlich keinen // Sinn, aber da wir keine Daten sammeln wollen, sondern nur // Geräte voneinander unterscheiden möchten, ist das für diesen // Zweck doch sinnvoll. mac = hdr->addr2[0] + hdr->addr2[1] + hdr->addr2[2] + hdr->addr2[3] + hdr->addr2[4] + hdr->addr2[5]; } void setup() { Serial.begin(9600); delay(10); pinMode(LED_GPIO_PIN, OUTPUT); digitalWrite(LED_GPIO_PIN, HIGH); // Initialisierung des LoRa-Senders Serial.println("LoRa Sender"); // wir senden im recht unregulierten Frequenzbereich if (!LoRa.begin(869.5E6)) { Serial.println("Starting LoRa failed!"); while (1); } LoRa.setSyncWord(0xF3); LoRa.setTxPower(20); LoRa.setSpreadingFactor(12); wifi_sniffer_init(); } void loop() { delay(1000); vTaskDelay(WIFI_CHANNEL_SWITCH_INTERVAL / portTICK_PERIOD_MS); wifi_sniffer_set_channel(channel); channel = (channel % WIFI_CHANNEL_MAX) + 1; // Wenn das Signal eine gewisse Stärke überschreitet und // überhaupt etwas empfangen wurde (!= 0), dann: if ((signalwert+100) > 0 && signalwert != 0) { digitalWrite(LED_GPIO_PIN, LOW); // schnüre das LoRa-Paket und sende es // wer kein LoRa will oder braucht, kann hier den HTTPS POST // Request aus dem anderen Programmbeispiel einsetzen oder // eine ganz eigene Implementierung starten. // Achtung, LoRa-Übertragung erfolgt unverschlüsselt und ohne // Prüfsummen. Kann also mitgelesen und manipuliert werden. LoRa.beginPacket(); LoRa.print("s="); LoRa.print(signalwert); LoRa.print("&m="); LoRa.print(mac); LoRa.endPacket(); digitalWrite(LED_GPIO_PIN, HIGH); // noch ein paar Daten als Debug auf der seriellen Schnittstelle Serial.print(signalwert); Serial.print(" / MAC: "); Serial.println(mac); signalwert = 0; } }