Merge pull request #17 from cyberman54/hallard-master

v1.2.8 - thanks to Charles Hallard for contribution!
This commit is contained in:
Verkehrsrot 2018-04-02 14:49:42 +02:00 committed by GitHub
commit 2a23f66050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1942 additions and 1658 deletions

View File

@ -165,6 +165,11 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0 = internal antenna [default] 0 = internal antenna [default]
1 = external antenna 1 = external antenna
0x0F set RGB led luminosity (works on LoPy/LoPy4 and LoRaNode32 shield only)
0 ... 100 percentage of luminosity (100% = full light)
e.g. 40 -> 40% of luminosity
0x80 get device configuration 0x80 get device configuration
device answers with it's current configuration: device answers with it's current configuration:
@ -181,7 +186,8 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
byte 11: BLE scan cycle duration in seconds (0..255) byte 11: BLE scan cycle duration in seconds (0..255)
byte 12: BLE scan mode (1=on, 0=0ff) byte 12: BLE scan mode (1=on, 0=0ff)
byte 13: Wifi antenna switch (0=internal, 1=external) byte 13: Wifi antenna switch (0=internal, 1=external)
bytes 14-23: Software version (ASCII format) byte 14: RGB LED luminosity (0..100 %)
bytes 15-24: Software version (ASCII format)
0x81 get device uptime 0x81 get device uptime

View File

@ -95,7 +95,7 @@ monitor_baud = 115200
lib_deps = lib_deps =
U8g2@>2.21.7 U8g2@>2.21.7
ESP32 BLE Arduino@>=0.4.9 ESP32 BLE Arduino@>=0.4.9
; NeoPixelBus SmartLeds
build_flags = build_flags =
;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework ;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
@ -118,7 +118,7 @@ monitor_baud = 115200
lib_deps = lib_deps =
U8g2@>2.21.7 U8g2@>2.21.7
ESP32 BLE Arduino@>=0.4.9 ESP32 BLE Arduino@>=0.4.9
; NeoPixelBus SmartLeds
build_flags = build_flags =
;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework ;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
@ -142,7 +142,7 @@ upload_speed = 256000
lib_deps = lib_deps =
U8g2 U8g2
ESP32 BLE Arduino@>=0.4.9 ESP32 BLE Arduino@>=0.4.9
; NeoPixelBus SmartLeds
build_flags = build_flags =
;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework ;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
@ -166,7 +166,7 @@ upload_speed = 921600
lib_deps = lib_deps =
U8g2 U8g2
ESP32 BLE Arduino@>=0.4.9 ESP32 BLE Arduino@>=0.4.9
; NeoPixelBus SmartLeds
build_flags = build_flags =
;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework ;set log level, we need build_flag for this, otherwise we can't use ESP_LOGx in arduino framework
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
@ -180,4 +180,3 @@ build_flags =
-include "src/hal/lolin32_lora.h" -include "src/hal/lolin32_lora.h"
;FreeRTOS single core operation, switches off core 1 (see arduino-esp32/cores/esp32/main.cpp) ;FreeRTOS single core operation, switches off core 1 (see arduino-esp32/cores/esp32/main.cpp)
; -DCONFIG_FREERTOS_UNICORE ; -DCONFIG_FREERTOS_UNICORE

View File

@ -1,32 +0,0 @@
// Basic Config
#include "globals.h"
#ifdef BLECOUNTER
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
// Local logging tag
static const char *TAG = "blecount";
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
}
};
void BLECount() {
u8x8.clearLine(3);
u8x8.drawString(0,3,"BLE Scan...");
BLEDevice::init(PROGNAME);
BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
BLEScanResults foundDevices = pBLEScan->start(cfg.blescancycle);
u8x8.clearLine(3);
u8x8.setCursor(0,3);
blenum=foundDevices.getCount();
u8x8.printf("BLE#: %-5i",blenum);
}
#endif

View File

@ -29,8 +29,10 @@ void defaultConfig() {
cfg.wifiscancycle = SEND_SECS; // wifi scan cycle [seconds/2] cfg.wifiscancycle = SEND_SECS; // wifi scan cycle [seconds/2]
cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
cfg.blescancycle = BLESCANTIME; // BLE scan cycle [seconds] cfg.blescancycle = BLESCANTIME; // BLE scan cycle [seconds]
cfg.blescan = 0; // 0=disabled, 1=enabled cfg.blescan = 1; // 0=disabled, 1=enabled
cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4)
cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0 100%)
strncpy( cfg.version, PROGVERSION, sizeof(cfg.version)-1 ); strncpy( cfg.version, PROGVERSION, sizeof(cfg.version)-1 );
} }
@ -112,6 +114,9 @@ void saveConfig() {
if( nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != cfg.wifiant ) if( nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != cfg.wifiant )
nvs_set_i8(my_handle, "wifiant", cfg.wifiant); nvs_set_i8(my_handle, "wifiant", cfg.wifiant);
if( nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK || flash8 != cfg.rgblum )
nvs_set_i8(my_handle, "rgblum", cfg.rgblum);
if( nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit ) if( nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit )
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
@ -236,6 +241,14 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK ) {
cfg.rgblum = flash8;
ESP_LOGI(TAG, "rgbluminosity = %i", flash8);
} else {
ESP_LOGI(TAG, "RGB luminosity set to default %i", cfg.rgblum);
saveConfig();
}
if( nvs_get_i8(my_handle, "blescancycle", &flash8) == ESP_OK ) { if( nvs_get_i8(my_handle, "blescancycle", &flash8) == ESP_OK ) {
cfg.blescancycle = flash8; cfg.blescancycle = flash8;
ESP_LOGI(TAG, "blescancycle = %i", flash8); ESP_LOGI(TAG, "blescancycle = %i", flash8);

View File

@ -3,6 +3,8 @@
// std::set for unified array functions // std::set for unified array functions
#include <set> #include <set>
#include <array>
#include <algorithm>
// OLED Display // OLED Display
#include <U8x8lib.h> #include <U8x8lib.h>
@ -11,6 +13,12 @@
#include <lmic.h> #include <lmic.h>
#include <hal/hal.h> #include <hal/hal.h>
#ifdef HAS_RGB_LED
#include <SmartLeds.h>
#endif
#include "rgb_led.h"
#include "macsniff.h"
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
typedef struct { typedef struct {
int8_t lorasf; // 7-12, lora spreadfactor int8_t lorasf; // 7-12, lora spreadfactor
@ -25,6 +33,7 @@ typedef struct {
int8_t blescancycle; // BLE scan cycle [seconds] int8_t blescancycle; // BLE scan cycle [seconds]
int8_t blescan; // 0=disabled, 1=enabled int8_t blescan; // 0=disabled, 1=enabled
int8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) int8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4)
int8_t rgblum; // RGB Led luminosity (0 100%)
char version[10]; // Firmware version char version[10]; // Firmware version
} configData_t; } configData_t;
@ -32,9 +41,9 @@ extern configData_t cfg;
extern uint8_t mydata[]; extern uint8_t mydata[];
extern uint64_t uptimecounter; extern uint64_t uptimecounter;
extern osjob_t sendjob; extern osjob_t sendjob;
extern uint16_t macnum, blenum, salt; extern int countermode, screensaver, adrmode, lorasf, txpower, rlim, salt;
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim;
extern bool joinstate; extern bool joinstate;
extern std::set<uint16_t> wifis;
extern std::set<uint16_t> macs; extern std::set<uint16_t> macs;
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
@ -45,4 +54,5 @@ extern std::set<uint16_t> macs;
#ifdef BLECOUNTER #ifdef BLECOUNTER
extern int scanTime; extern int scanTime;
extern std::set<uint16_t> bles;
#endif #endif

View File

@ -6,6 +6,7 @@
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
#define HAS_LED NOT_A_PIN // Led os on same pin than Lora SS pin, to avoid pb, we don't use it #define HAS_LED NOT_A_PIN // Led os on same pin than Lora SS pin, to avoid pb, we don't use it
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
// Anyway shield is on over the LoLin32 board, so we won't be able to see this LED // Anyway shield is on over the LoLin32 board, so we won't be able to see this LED
#define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED #define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED
#define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield #define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield
@ -30,4 +31,3 @@
#define OLED_RST U8X8_PIN_NONE // Not reset pin #define OLED_RST U8X8_PIN_NONE // Not reset pin
#define OLED_SDA 21 // ESP32 GPIO21 (Pin21) -- OLED SDA #define OLED_SDA 21 // ESP32 GPIO21 (Pin21) -- OLED SDA
#define OLED_SCL 22 // ESP32 GPIO22 (Pin22) -- OLED SCL #define OLED_SCL 22 // ESP32 GPIO22 (Pin22) -- OLED SCL

View File

@ -5,8 +5,8 @@
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
#define HAS_LED NOT_A_PIN // Led os on same pin than Lora SS pin, to avoid pb, we don't use it #define HAS_LED 22 // ESP32 GPIO12 (pin22) On Board LED
// Anyway shield is on over the LoLin32 board, so we won't be able to see this LED #define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
#define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED #define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED
#define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield #define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield
#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown #define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown
@ -30,4 +30,3 @@
#define OLED_RST U8X8_PIN_NONE // Not reset pin #define OLED_RST U8X8_PIN_NONE // Not reset pin
#define OLED_SDA 14 // ESP32 GPIO14 (Pin14) -- OLED SDA #define OLED_SDA 14 // ESP32 GPIO14 (Pin14) -- OLED SDA
#define OLED_SCL 12 // ESP32 GPIO12 (Pin12) -- OLED SCL #define OLED_SCL 12 // ESP32 GPIO12 (Pin12) -- OLED SCL

View File

@ -4,6 +4,7 @@
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
#define HAS_LED GPIO_NUM_2 // white LED on board #define HAS_LED GPIO_NUM_2 // white LED on board
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
#define HAS_BUTTON GPIO_NUM_0 // button "PRG" on board #define HAS_BUTTON GPIO_NUM_0 // button "PRG" on board
// re-define pin definitions of pins_arduino.h // re-define pin definitions of pins_arduino.h

View File

@ -79,10 +79,22 @@ void printKeys(void) {
#endif // VERBOSE #endif // VERBOSE
void do_send(osjob_t* j){ void do_send(osjob_t* j){
mydata[0] = (macnum & 0xff00) >> 8; uint16_t data;
mydata[1] = macnum & 0x00ff; // Total BLE+WIFI unique MACs seen
mydata[2] = (blenum & 0xff00) >> 8; data = (uint16_t) macs.size();
mydata[3] = blenum & 0x00ff; mydata[0] = (data & 0xff00) >> 8;
mydata[1] = data & 0xff;
// Sum of unique BLE MACs seen
data = (uint16_t) bles.size();
mydata[2] = (data & 0xff00) >> 8;
mydata[3] = data & 0xff;
// Sum of unique WIFI MACs seen
// TBD ?
//data = (uint16_t) wifis.size();
//mydata[4] = (data & 0xff00) >> 8;
//mydata[5] = data & 0xff;
// Check if there is not a current TX/RX job running // Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) { if (LMIC.opmode & OP_TXRXPEND) {
@ -95,7 +107,6 @@ void do_send(osjob_t* j){
ESP_LOGI(TAG, "Packet queued"); ESP_LOGI(TAG, "Packet queued");
u8x8.clearLine(7); u8x8.clearLine(7);
u8x8.drawString(0, 7, "PACKET QUEUED"); u8x8.drawString(0, 7, "PACKET QUEUED");
set_onboard_led(1);
} }
// Next TX is scheduled after TX_COMPLETE event. // Next TX is scheduled after TX_COMPLETE event.
} }
@ -162,7 +173,6 @@ void onEvent (ev_t ev) {
ESP_LOGI(TAG, "EV_TXCOMPLETE (includes waiting for RX windows)"); ESP_LOGI(TAG, "EV_TXCOMPLETE (includes waiting for RX windows)");
u8x8.clearLine(7); u8x8.clearLine(7);
u8x8.drawString(0, 7, "TX COMPLETE"); u8x8.drawString(0, 7, "TX COMPLETE");
set_onboard_led(0);
if (LMIC.txrxFlags & TXRX_ACK) { if (LMIC.txrxFlags & TXRX_ACK) {
ESP_LOGI(TAG, "Received ack"); ESP_LOGI(TAG, "Received ack");
u8x8.clearLine(7); u8x8.clearLine(7);
@ -224,3 +234,4 @@ void onEvent (ev_t ev) {
break; break;
} }
} }

141
src/macsniff.cpp Normal file
View File

@ -0,0 +1,141 @@
// Basic Config
#include "main.h"
#include "globals.h"
#ifdef BLECOUNTER
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#endif
#ifdef VENDORFILTER
#include <array>
#include <algorithm>
#include "vendor_array.h"
#endif
// Local logging tag
static const char *TAG = "macsniff";
static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL};
uint16_t currentScanDevice = 0;
bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
char counter [6]; // uint16_t -> 2 byte -> 5 decimals + '0' terminator -> 6 chars
char macbuf [21]; // uint64_t -> 8 byte -> 20 decimals + '0' terminator -> 21 chars
char typebuff[8];
uint64_t addr2int;
uint32_t vendor2int;
uint16_t hashedmac;
std::pair<std::set<uint16_t>::iterator, bool> newmac;
addr2int = ( (uint64_t)paddr[0] ) | ( (uint64_t)paddr[1] << 8 ) | ( (uint64_t)paddr[2] << 16 ) | \
( (uint64_t)paddr[3] << 24 ) | ( (uint64_t)paddr[4] << 32 ) | ( (uint64_t)paddr[5] << 40 );
#ifdef VENDORFILTER
vendor2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[1] << 8 ) | ( (uint32_t)paddr[0] << 16 );
// No vendor filter for BLE
if ( (sniff_type==MAC_SNIFF_BLE) || std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) {
#endif
// salt and hash MAC, and if new unique one, store identifier in container and increment counter on display
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization
addr2int |= (uint64_t) salt << 48; // prepend 16-bit salt to 48-bit MAC
snprintf(macbuf, 21, "%llx", addr2int); // convert unsigned 64-bit salted MAC to 16 digit hex string
hashedmac = rokkit(macbuf, 5); // hash MAC string, use 5 chars to fit hash in uint16_t container
newmac = macs.insert(hashedmac); // add hashed MAC to total container if new unique
if (sniff_type == MAC_SNIFF_WIFI ) {
newmac = wifis.insert(hashedmac); // add hashed MAC to wifi container if new unique
strcpy(typebuff, "WiFi");
} else if (sniff_type == MAC_SNIFF_BLE ) {
newmac = bles.insert(hashedmac); // add hashed MAC to BLE container if new unique
strcpy(typebuff, "BLE ");
}
if (newmac.second) { // first time seen this WIFI or BLE MAC
snprintf(counter, 6, "%i", macs.size()); // convert 16-bit MAC counter to decimal counter value
u8x8.draw2x2String(0, 0, counter);
ESP_LOGI(TAG, "%s RSSI %04d -> Hash %04x -> #%05i", typebuff, rssi, hashedmac, macs.size());
} else { // already seen WIFI or BLE MAC
ESP_LOGI(TAG, "%s RSSI %04d -> already seen", typebuff, rssi);
}
#ifdef VENDORFILTER
} else {
// Very noisy
//ESP_LOGI(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X", paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]);
}
#endif
// True if MAC WiFi/BLE was new
return newmac.second;
}
#ifdef BLECOUNTER
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
uint8_t *p = (uint8_t *) advertisedDevice.getAddress().getNative();
// Current devices seen on this scan session
currentScanDevice++;
mac_add(p, advertisedDevice.getRSSI(), MAC_SNIFF_BLE);
u8x8.setCursor(12,3);
u8x8.printf("%d", currentScanDevice);
}
};
void BLECount() {
int blenum = 0; // Total device seen on this scan session
currentScanDevice = 0; // Set 0 seen device on this scan session
u8x8.clearLine(3);
u8x8.drawString(0,3,"BLE Scan...");
BLEDevice::init(PROGNAME);
BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
BLEScanResults foundDevices = pBLEScan->start(cfg.blescancycle);
blenum=foundDevices.getCount();
u8x8.clearLine(3);
u8x8.setCursor(0,3);
u8x8.printf("BLE#: %-5i %-3i",bles.size(), blenum);
}
#endif
void wifi_sniffer_init(void) {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
wifi_promiscuous_filter_t filter = {.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg
ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country)); // set locales for RF and channels
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set MAC frame filter
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode
}
void wifi_sniffer_set_channel(uint8_t channel) {
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
}
void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) {
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;
if (( cfg.rssilimit == 0 ) || (ppkt->rx_ctrl.rssi > cfg.rssilimit )) { // rssi is negative value
uint8_t *p = (uint8_t *) hdr->addr2;
mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI) ;
} else {
ESP_LOGI(TAG, "WiFi RSSI %04d -> ignoring (limit: %i)", ppkt->rx_ctrl.rssi, cfg.rssilimit);
}
yield();
}

28
src/macsniff.h Normal file
View File

@ -0,0 +1,28 @@
// ESP32 Functions
#include <esp_wifi.h>
#define MAC_SNIFF_WIFI 0
#define MAC_SNIFF_BLE 1
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;
void BLECount();
void wifi_sniffer_init(void);
void wifi_sniffer_set_channel(uint8_t channel);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
// function defined in rokkithash.cpp
uint32_t rokkit(const char * , int );

View File

@ -25,6 +25,9 @@ Refer to LICENSE.txt file in repository for more details.
#include "main.h" #include "main.h"
#include "globals.h" #include "globals.h"
// std::set for unified array functions
#include <set>
// OLED driver // OLED driver
#include <U8x8lib.h> #include <U8x8lib.h>
@ -42,11 +45,17 @@ configData_t cfg; // struct holds current device configuration
osjob_t sendjob, initjob; // LMIC osjob_t sendjob, initjob; // LMIC
// Initialize global variables // Initialize global variables
uint16_t macnum = 0, blenum = 0, salt; int macnum = 0, salt;
uint64_t uptimecounter = 0; uint64_t uptimecounter = 0;
bool joinstate = false; bool joinstate = false;
std::set<uint16_t> macs; // associative container holds filtered MAC adresses std::set<uint16_t> macs; // associative container holds total of unique MAC adress hashes (Wifi + BLE)
std::set<uint16_t> wifis; // associative container holds unique Wifi MAC adress hashes
#ifdef BLECOUNTER
std::set<uint16_t> bles; // associative container holds unique BLE MAC adresses hashes
int scanTime;
#endif
// this variable will be changed in the ISR, and read in main loop // this variable will be changed in the ISR, and read in main loop
static volatile bool ButtonTriggered = false; static volatile bool ButtonTriggered = false;
@ -67,29 +76,19 @@ void eraseConfig(void);
void saveConfig(void); void saveConfig(void);
void loadConfig(void); void loadConfig(void);
/* begin LMIC specific parts ------------------------------------------------------------ */ #ifdef HAS_LED
void set_onboard_led(int st);
#endif
// LMIC enhanced Pin mapping /* begin LMIC specific parts ------------------------------------------------------------ */
const lmic_pinmap lmic_pins = {
.mosi = PIN_SPI_MOSI,
.miso = PIN_SPI_MISO,
.sck = PIN_SPI_SCK,
.nss = PIN_SPI_SS,
.rxtx = LMIC_UNUSED_PIN,
.rst = RST,
.dio = {DIO0, DIO1, DIO2}
};
// defined in lorawan.cpp // defined in lorawan.cpp
void gen_lora_deveui(uint8_t * pdeveui); void gen_lora_deveui(uint8_t * pdeveui);
void RevBytes(unsigned char* b, size_t c); void RevBytes(unsigned char* b, size_t c);
#ifdef VERBOSE #ifdef VERBOSE
void printKeys(void); void printKeys(void);
#endif #endif // VERBOSE
// LMIC functions
void onEvent(ev_t ev);
void do_send(osjob_t* j);
// LMIC callback functions // LMIC callback functions
void os_getDevKey (u1_t *buf) { void os_getDevKey (u1_t *buf) {
@ -112,6 +111,21 @@ void os_getDevEui (u1_t* buf) {
gen_lora_deveui(buf); // generate DEVEUI from device's MAC gen_lora_deveui(buf); // generate DEVEUI from device's MAC
} }
// LMIC enhanced Pin mapping
const lmic_pinmap lmic_pins = {
.mosi = PIN_SPI_MOSI,
.miso = PIN_SPI_MISO,
.sck = PIN_SPI_SCK,
.nss = PIN_SPI_SS,
.rxtx = LMIC_UNUSED_PIN,
.rst = RST,
.dio = {DIO0, DIO1, DIO2}
};
// LMIC functions
void onEvent(ev_t ev);
void do_send(osjob_t* j);
// LoRaWAN Initjob // LoRaWAN Initjob
static void lora_init (osjob_t* j) { static void lora_init (osjob_t* j) {
// reset MAC state // reset MAC state
@ -125,8 +139,48 @@ static void lora_init (osjob_t* j) {
// LMIC Task // LMIC Task
void lorawan_loop(void * pvParameters) { void lorawan_loop(void * pvParameters) {
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
static bool led_state ;
bool new_led_state ;
while(1) { while(1) {
uint16_t color;
os_runloop_once(); os_runloop_once();
// All follow is Led management
// Let join at the begining of if sequence,
// is prior to send because joining state send data
if ( LMIC.opmode & (OP_JOINING | OP_REJOIN) ) {
color = COLOR_YELLOW;
// Joining Quick blink 20ms on each 1/5 second
new_led_state = ((millis() % 200) < 20) ? HIGH : LOW;
// Small blink 10ms on each 1/2sec (not when joining)
} else if (LMIC.opmode & (OP_TXDATA | OP_TXRXPEND)) {
color = COLOR_BLUE;
new_led_state = ((millis() % 500) < 20) ? HIGH : LOW;
// This should not happen so indicate a pb
} else if ( LMIC.opmode & (OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0 ) {
color = COLOR_RED;
// Heartbeat long blink 200ms on each 2 seconds
new_led_state = ((millis() % 2000) < 200) ? HIGH : LOW;
} else {
rgb_set_color(COLOR_NONE);
}
// led need to change state ?
// avoid digitalWrite() for nothing
if (led_state != new_led_state) {
if (new_led_state == HIGH) {
set_onboard_led(1);
rgb_set_color(color);
} else {
set_onboard_led(0);
rgb_set_color(COLOR_NONE);
}
led_state = new_led_state;
}
vTaskDelay(10/portTICK_PERIOD_MS); vTaskDelay(10/portTICK_PERIOD_MS);
yield(); yield();
} }
@ -159,12 +213,18 @@ void lorawan_loop(void * pvParameters) {
void set_onboard_led(int st){ void set_onboard_led(int st){
#ifdef HAS_LED #ifdef HAS_LED
switch (st) { switch (st) {
#ifdef LED_ACTIVE_LOW
case 1: digitalWrite(HAS_LED, LOW); break;
case 0: digitalWrite(HAS_LED, HIGH); break;
#else
case 1: digitalWrite(HAS_LED, HIGH); break; case 1: digitalWrite(HAS_LED, HIGH); break;
case 0: digitalWrite(HAS_LED, LOW); break; case 0: digitalWrite(HAS_LED, LOW); break;
#endif
} }
#endif #endif
}; };
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
// Button Handling, board dependent -> perhaps to be moved to hal/<$board.h> // Button Handling, board dependent -> perhaps to be moved to hal/<$board.h>
// IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855 // IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855
@ -190,35 +250,49 @@ void wifi_sniffer_loop(void * pvParameters) {
int nloop=0, lorawait=0; int nloop=0, lorawait=0;
while (true) { while (true) {
nloop++; nloop++; // acutal number of wifi loops
// execute BLE count if BLE function is enabled
#ifdef BLECOUNTER
// Once 2 full Wifi Channels scan, do a BLE scan
if (nloop % (WIFI_CHANNEL_MAX*2) == 0 ) {
// execute BLE count if BLE function is enabled
if (cfg.blescan)
BLECount();
}
#endif
vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS); vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS);
yield(); yield();
wifi_sniffer_set_channel(channel); wifi_sniffer_set_channel(channel);
channel = (channel % WIFI_CHANNEL_MAX) + 1; channel = (channel % WIFI_CHANNEL_MAX) + 1;
ESP_LOGI(TAG, "Wifi set channel %d", channel);
u8x8.setCursor(0,5);
u8x8.printf(!cfg.rssilimit ? "RLIM: off" : "RLIM: %4i", cfg.rssilimit);
u8x8.setCursor(11,5);
u8x8.printf("ch:%02i", channel);
u8x8.setCursor(0,4);
u8x8.printf("MAC#: %-5i", wifis.size());
// duration of one wifi scan loop reached? then send data and begin new scan cycle // duration of one wifi scan loop reached? then send data and begin new scan cycle
if( nloop >= ((100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) ) { if( nloop >= ((100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) ) {
u8x8.setPowerSave(!cfg.screenon); // set display on if enabled u8x8.setPowerSave(!cfg.screenon); // set display on if enabled
nloop = 0; // reset wlan sniffing loop counter nloop = 0; // reset wlan sniffing loop counter
// execute BLE count if BLE function is enabled
#ifdef BLECOUNTER
if (cfg.blescan)
BLECount();
#endif
// Prepare and execute LoRaWAN data upload // Prepare and execute LoRaWAN data upload
u8x8.setCursor(0,4);
u8x8.printf("MAC#: %-5i", macnum);
do_send(&sendjob); // send payload do_send(&sendjob); // send payload
vTaskDelay(500/portTICK_PERIOD_MS); vTaskDelay(500/portTICK_PERIOD_MS);
yield(); yield();
// clear counter if not in cumulative counter mode // clear counter if not in cumulative counter mode
if (cfg.countermode != 1) { if (cfg.countermode != 1) {
macs.clear(); // clear macs container macs.clear(); // clear all macs container
wifis.clear(); // clear Wifi macs couner
#ifdef BLECOUNTER
bles.clear(); // clear BLE macs counter
#endif
salt = random(65536); // get new 16bit random for salting hashes salt = random(65536); // get new 16bit random for salting hashes
macnum = 0;
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
} }
@ -238,7 +312,9 @@ void wifi_sniffer_loop(void * pvParameters) {
u8x8.clearLine(6); u8x8.clearLine(6);
if (cfg.screenon && cfg.screensaver) vTaskDelay(2000/portTICK_PERIOD_MS); // pause for displaying results if (cfg.screenon && cfg.screensaver) {
vTaskDelay(2000/portTICK_PERIOD_MS); // pause for displaying results
}
yield(); yield();
u8x8.setPowerSave(1 && cfg.screensaver); // set display off if screensaver is enabled u8x8.setPowerSave(1 && cfg.screensaver); // set display off if screensaver is enabled
} }
@ -336,6 +412,7 @@ void setup() {
#endif #endif
ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION); ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION);
rgb_set_color(COLOR_NONE);
// system event handler for wifi task, needed for wifi_sniffer_init() // system event handler for wifi task, needed for wifi_sniffer_init()
esp_event_loop_init(NULL, NULL); esp_event_loop_init(NULL, NULL);
@ -380,7 +457,7 @@ void setup() {
antenna_init(); antenna_init();
#endif #endif
// initialize salt value using esp_random() called by random in arduino-esp32 core // initialize salt value using esp_random() called by random() in arduino-esp32 core
salt = random(65536); // get new 16bit random for salting hashes salt = random(65536); // get new 16bit random for salting hashes
// initialize display // initialize display

View File

@ -1,5 +1,5 @@
// program version // program version
#define PROGVERSION "1.2.62" // use max 10 chars here! #define PROGVERSION "1.2.8" // use max 10 chars here!
#define PROGNAME "PAXCNT" #define PROGNAME "PAXCNT"
// Verbose enables serial output // Verbose enables serial output
@ -10,10 +10,11 @@
#define BLECOUNTER 1 // comment out if you don't want BLE count #define BLECOUNTER 1 // comment out if you don't want BLE count
// BLE scan time // BLE scan time
#define BLESCANTIME 30 // [seconds] #define BLESCANTIME 15 // [seconds]
// WiFi Sniffer cycle interval // WiFi Sniffer cycle interval
#define SEND_SECS 120 // [seconds/2] -> 240 sec. #define SEND_SECS 120 // [seconds/2] -> 240 sec.
//#define SEND_SECS 30 // [seconds/2] -> 60 sec.
// WiFi sniffer config // WiFi sniffer config
#define WIFI_CHANNEL_MIN 1 // start channel number where scan begings #define WIFI_CHANNEL_MIN 1 // start channel number where scan begings
@ -26,6 +27,9 @@
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy #define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands #define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
// Default RGB LED luminosity (in %)
#define RGBLUMINOSITY 50 // 50%
// LMIC settings // LMIC settings
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored // define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored
// define hardware specifics settings in platformio.ini as build_flag for hardware environment // define hardware specifics settings in platformio.ini as build_flag for hardware environment
@ -99,10 +103,10 @@
// implementation is optimized for speed on 32-bit processors using // implementation is optimized for speed on 32-bit processors using
// fairly big lookup tables, but it takes up big amounts of flash on the // fairly big lookup tables, but it takes up big amounts of flash on the
// AVR architecture. // AVR architecture.
// #define USE_ORIGINAL_AES #define USE_ORIGINAL_AES
// //
// This selects the AES implementation written by Ideetroon for their // This selects the AES implementation written by Ideetroon for their
// own LoRaWAN library. It also uses lookup tables, but smaller // own LoRaWAN library. It also uses lookup tables, but smaller
// byte-oriented ones, making it use a lot less flash space (but it is // byte-oriented ones, making it use a lot less flash space (but it is
// also about twice as slow as the original). // also about twice as slow as the original).
#define USE_IDEETRON_AES // #define USE_IDEETRON_AES

View File

@ -67,8 +67,9 @@ void set_reset(int val) {
break; break;
case 1: // reset MAC counter case 1: // reset MAC counter
ESP_LOGI(TAG, "Remote command: reset MAC counter"); ESP_LOGI(TAG, "Remote command: reset MAC counter");
macs.clear(); // clear macs container macs.clear(); // clear all macs container
macnum = 0; wifis.clear(); // clear Wifi macs container
bles.clear(); // clear BLE macs container
salt = random(65536); // get new 16bit random for salting hashes salt = random(65536); // get new 16bit random for salting hashes
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
u8x8.clearLine(5); u8x8.clearLine(5);
@ -180,6 +181,12 @@ void set_wifiant(int val) {
#endif #endif
}; };
void set_rgblum(int val) {
// Avoid wrong parameters
cfg.rgblum = (val>=0 && val<=100) ? (uint8_t) val : RGBLUMINOSITY;
ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum);
};
void set_lorapower(int val) { void set_lorapower(int val) {
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %i", val); ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %i", val);
switch_lora(cfg.lorasf, val); switch_lora(cfg.lorasf, val);
@ -240,6 +247,7 @@ cmd_t table[] = {
{0x0c, set_blescancycle, true}, {0x0c, set_blescancycle, true},
{0x0d, set_blescan, true}, {0x0d, set_blescan, true},
{0x0e, set_wifiant, true}, {0x0e, set_wifiant, true},
{0x0f, set_rgblum, true},
{0x80, get_config, false}, {0x80, get_config, false},
{0x81, get_uptime, false}, {0x81, get_uptime, false},
{0x82, get_cputemp, false} {0x82, get_cputemp, false}

87
src/rgb_led.cpp Normal file
View File

@ -0,0 +1,87 @@
// Basic Config
#include "main.h"
#include "globals.h"
#ifdef HAS_RGB_LED
// RGB Led instance
SmartLed rgb_led(LED_WS2812, 1, HAS_RGB_LED);
// Luminosity from 0 to 100%
uint8_t rgb_luminosity = 50 ;
float rgb_CalcColor(float p, float q, float t)
{
if (t < 0.0f)
t += 1.0f;
if (t > 1.0f)
t -= 1.0f;
if (t < 1.0f / 6.0f)
return p + (q - p) * 6.0f * t;
if (t < 0.5f)
return q;
if (t < 2.0f / 3.0f)
return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f);
return p;
}
// ------------------------------------------------------------------------
// Hue, Saturation, Lightness color members
// HslColor using H, S, L values (0.0 - 1.0)
// L should be limited to between (0.0 - 0.5)
// ------------------------------------------------------------------------
RGBColor rgb_hsl2rgb(float h, float s, float l)
{
RGBColor RGB_color;
float r;
float g;
float b;
if (s == 0.0f || l == 0.0f)
{
r = g = b = l; // achromatic or black
}
else
{
float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
float p = 2.0f * l - q;
r = rgb_CalcColor(p, q, h + 1.0f / 3.0f);
g = rgb_CalcColor(p, q, h);
b = rgb_CalcColor(p, q, h - 1.0f / 3.0f);
}
RGB_color.R = (uint8_t)(r * 255.0f);
RGB_color.G = (uint8_t)(g * 255.0f);
RGB_color.B = (uint8_t)(b * 255.0f);
return RGB_color;
}
void rgb_set_color(uint16_t hue) {
if (hue == COLOR_NONE) {
// Off
rgb_led[0] = Rgb(0,0,0);
} else {
// see http://www.workwithcolor.com/blue-color-hue-range-01.htm
// H (is color from 0..360) should be between 0.0 and 1.0
// S is saturation keep it to 1
// L is brightness should be between 0.0 and 0.5
// rgb_luminosity is between 0 and 100 (percent)
RGBColor target = rgb_hsl2rgb( hue / 360.0f, 1.0f, 0.005f * cfg.rgblum);
//uint32_t color = target.R<<16 | target.G<<8 | target.B;
rgb_led[0] = Rgb(target.R, target.G, target.B);
}
// Show
rgb_led.show();
}
#else
// No RGB LED empty functions
void rgb_set_color(uint16_t hue) {}
#endif

30
src/rgb_led.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
// value for HSL color
// see http://www.workwithcolor.com/blue-color-hue-range-01.htm
#define COLOR_RED 0
#define COLOR_ORANGE 30
#define COLOR_ORANGE_YELLOW 45
#define COLOR_YELLOW 60
#define COLOR_YELLOW_GREEN 90
#define COLOR_GREEN 120
#define COLOR_GREEN_CYAN 165
#define COLOR_CYAN 180
#define COLOR_CYAN_BLUE 210
#define COLOR_BLUE 240
#define COLOR_BLUE_MAGENTA 275
#define COLOR_MAGENTA 300
#define COLOR_PINK 350
#define COLOR_WHITE 360
#define COLOR_NONE 999
struct RGBColor
{
uint8_t R;
uint8_t G;
uint8_t B;
};
// Exported Functions
void rgb_set_color(uint16_t hue);

File diff suppressed because it is too large Load Diff

View File

@ -1,98 +0,0 @@
// Basic Config
#include "main.h"
#include "globals.h"
// ESP32 Functions
#include <esp_wifi.h>
#ifdef VENDORFILTER
#include <array>
#include <algorithm>
#include "vendor_array.h"
#endif
// Local logging tag
static const char *TAG = "wifisniffer";
// function defined in rokkithash.cpp
uint32_t rokkit(const char * , int );
static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL};
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;
extern void wifi_sniffer_init(void);
extern void wifi_sniffer_set_channel(uint8_t channel);
extern void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
void wifi_sniffer_init(void) {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
wifi_promiscuous_filter_t filter = {.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg
ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country)); // set locales for RF and channels
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set MAC frame filter
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode
}
void wifi_sniffer_set_channel(uint8_t channel) {
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
}
void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) {
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;
char counter [6]; // uint16_t -> 2 byte -> 5 decimals + '0' terminator -> 6 chars
char macbuf [21]; // uint64_t -> 8 byte -> 10 decimals + '0' terminator -> 21 chars
uint64_t addr2int;
uint32_t vendor2int;
uint16_t hashedmac;
std::pair<std::set<uint16_t>::iterator, bool> newmac;
if (( cfg.rssilimit == 0 ) || (ppkt->rx_ctrl.rssi > cfg.rssilimit )) { // rssi is negative value
addr2int = ( (uint64_t)hdr->addr2[0] ) | ( (uint64_t)hdr->addr2[1] << 8 ) | ( (uint64_t)hdr->addr2[2] << 16 ) | \
( (uint64_t)hdr->addr2[3] << 24 ) | ( (uint64_t)hdr->addr2[4] << 32 ) | ( (uint64_t)hdr->addr2[5] << 40 );
#ifdef VENDORFILTER // uses vendor array with prefiltered OUIs (no local nd no group MACs, bits 0+1 in 1st byte of OUI)
vendor2int = ( (uint32_t)hdr->addr2[2] ) | ( (uint32_t)hdr->addr2[1] << 8 ) | ( (uint32_t)hdr->addr2[0] << 16 );
if ( std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) {
#endif
// salt and hash MAC, and if new unique one, store identifier in container and increment counter on display
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization
addr2int |= (uint64_t) salt << 48; // prepend 16-bit salt to 48-bit MAC
snprintf(macbuf, 21, "%llx", addr2int); // convert unsigned 64-bit salted MAC to 16 digit hex string
hashedmac = rokkit(macbuf, 5); // hash MAC string, use 5 chars to fit hash in uint16_t container
newmac = macs.insert(hashedmac); // store hashed MAC only if first time seen
if (newmac.second) { // if first time seen MAC
macnum++; // increment MAC counter
snprintf(counter, 6, "%i", macnum); // convert 16-bit MAC counter to decimal counter value
u8x8.draw2x2String(0, 0, counter); // display counter
ESP_LOGI(TAG, "#%05i: RSSI %04d -> Hash %04x", macnum, ppkt->rx_ctrl.rssi, hashedmac);
}
#ifdef VENDORFILTER
}
#endif
} else
ESP_LOGI(TAG, "RSSI %04d -> ignoring (limit: %i)", ppkt->rx_ctrl.rssi, cfg.rssilimit);
yield();
}