commit
2657596646
42
README.md
42
README.md
@ -71,7 +71,7 @@ Note: If you use this software you do this at your own risk. That means that you
|
||||
|
||||
# Privacy disclosure
|
||||
|
||||
Paxcounter generates identifiers for sniffed MAC adresses and collects them temporary in the device's RAM for a configurable scan cycle time (default 240 seconds). After each scan cycle the collected identifiers are cleared. Identifiers are generated by salting and hashing MAC adresses. The random salt value changes after each scan cycle. Identifiers and MAC adresses are never transferred to the LoRaWAN network. No persistent storing of MAC adresses, identifiers or timestamps and no other kind of analytics than counting are implemented in this code. Wireless networks are not touched by this code, but MAC adresses from wireless devices as well within as not within wireless networks, regardless if encrypted or unencrypted, are sniffed and processed by this code. If the bluetooth option in the code is enabled, bluetooth MACs are scanned and processed by the included BLE stack, and counted by this code.
|
||||
Paxcounter generates identifiers for sniffed MAC adresses and collects them temporary in the device's RAM for a configurable scan cycle time (default 240 seconds). After each scan cycle the collected identifiers are cleared. Identifiers are generated by salting and hashing MAC adresses. The random salt value changes after each scan cycle. Identifiers and MAC adresses are never transferred to the LoRaWAN network. No persistent storing of MAC adresses, identifiers or timestamps and no other kind of analytics than counting are implemented in this code. Wireless networks are not touched by this code, but MAC adresses from wireless devices as well within as not within wireless networks, regardless if encrypted or unencrypted, are sniffed and processed by this code. If the bluetooth option in the code is enabled, bluetooth MACs are scanned and processed by the included BLE stack, then hashed and counted by this code.
|
||||
|
||||
# Payload format description
|
||||
|
||||
@ -140,31 +140,41 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||
1 = reset MAC counter to zero
|
||||
2 = reset device to factory settings
|
||||
|
||||
0x0A set Wifi scan cycle timer
|
||||
0x0A set Wifi scan cycle and payload transmit cycle
|
||||
|
||||
0 ... 255 duration of a wifi scan cycle in seconds/2
|
||||
e.g. 120 -> 1 cycle runs for 240 seconds
|
||||
0 ... 255 duration of a wifi scan cycle in seconds/2, after this payload is sent
|
||||
e.g. 120 -> 1 cycle runs for 240 seconds [default]
|
||||
|
||||
0x0B set Wifi channel switch interval timer
|
||||
|
||||
0 ... 255 timeout for scanning 1 wifi channel in seconds/100
|
||||
e.g. 50 -> each channel is scanned for 0,5 seconds
|
||||
e.g. 50 -> each channel is scanned for 0,5 seconds [default]
|
||||
|
||||
0x0C set BLE scan cycle timer
|
||||
|
||||
0 ... 255 duration of a BLE scan cycle in seconds
|
||||
e.g. 30 -> 1 cycle runs for 30 seconds
|
||||
e.g. 15 -> 1 cycle runs for 15 seconds [default]
|
||||
|
||||
0x0D set BLE scan mode
|
||||
0x0D set BLE scan cycle frequency
|
||||
|
||||
0 = disabled [default]
|
||||
1 = enabled
|
||||
run BLE scan once after 0 ... 255 full wifi scans
|
||||
e.g. 2 -> BLE scan runs once after each 2nd wifi scan [default]
|
||||
|
||||
0x0E set WIFI antenna switch (works on LoPy/LoPy4 only)
|
||||
0x0E set BLE scan mode
|
||||
|
||||
0 = disabled
|
||||
1 = enabled [default]
|
||||
|
||||
0x0F set WIFI antenna switch (works on LoPy/LoPy4 only)
|
||||
|
||||
0 = internal antenna [default]
|
||||
1 = external antenna
|
||||
|
||||
0x10 set RGB led luminosity (works on LoPy/LoPy4 and LoRaNode32 shield only)
|
||||
|
||||
0 ... 100 percentage of luminosity (100% = full light)
|
||||
e.g. 50 -> 50% of luminosity [default]
|
||||
|
||||
0x80 get device configuration
|
||||
|
||||
device answers with it's current configuration:
|
||||
@ -179,9 +189,11 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||
byte 9: Wifi scan cycle duration in seconds/2 (0..255)
|
||||
byte 10: Wifi channel switch interval in seconds/100 (0..255)
|
||||
byte 11: BLE scan cycle duration in seconds (0..255)
|
||||
byte 12: BLE scan mode (1=on, 0=0ff)
|
||||
byte 13: Wifi antenna switch (0=internal, 1=external)
|
||||
bytes 14-23: Software version (ASCII format)
|
||||
byte 12: BLE scan frequency, do once after (0..255) full wifi scans
|
||||
byte 13: BLE scan mode (1=on, 0=0ff)
|
||||
byte 14: Wifi antenna switch (0=internal, 1=external)
|
||||
byte 15: RGB LED luminosity (0..100 %)
|
||||
bytes 16-25: Software version (ASCII format)
|
||||
|
||||
0x81 get device uptime
|
||||
|
||||
@ -212,3 +224,7 @@ Copyright 2018 Klaus Wilting <verkehrsrot@arcor.de>
|
||||
NOTICE:
|
||||
Parts of the source files in this repository are made available under different licenses,
|
||||
see file <A HREF="https://github.com/cyberman54/ESP32-Paxcounter/blob/master/LICENSE">LICENSE.txt</A> in this repository. Refer to each individual source file for more details.
|
||||
|
||||
# Credits
|
||||
|
||||
Thanks to Charles Hallard (https://github.com/hallard) for major contributions to this project.
|
||||
|
@ -95,7 +95,7 @@ monitor_baud = 115200
|
||||
lib_deps =
|
||||
U8g2@>2.21.7
|
||||
ESP32 BLE Arduino@>=0.4.9
|
||||
; NeoPixelBus
|
||||
SmartLeds
|
||||
build_flags =
|
||||
;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
|
||||
@ -118,7 +118,7 @@ monitor_baud = 115200
|
||||
lib_deps =
|
||||
U8g2@>2.21.7
|
||||
ESP32 BLE Arduino@>=0.4.9
|
||||
; NeoPixelBus
|
||||
SmartLeds
|
||||
build_flags =
|
||||
;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
|
||||
@ -142,7 +142,7 @@ upload_speed = 256000
|
||||
lib_deps =
|
||||
U8g2
|
||||
ESP32 BLE Arduino@>=0.4.9
|
||||
; NeoPixelBus
|
||||
SmartLeds
|
||||
build_flags =
|
||||
;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
|
||||
@ -166,7 +166,7 @@ upload_speed = 921600
|
||||
lib_deps =
|
||||
U8g2
|
||||
ESP32 BLE Arduino@>=0.4.9
|
||||
; NeoPixelBus
|
||||
SmartLeds
|
||||
build_flags =
|
||||
;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
|
||||
@ -180,4 +180,3 @@ build_flags =
|
||||
-include "src/hal/lolin32_lora.h"
|
||||
;FreeRTOS single core operation, switches off core 1 (see arduino-esp32/cores/esp32/main.cpp)
|
||||
; -DCONFIG_FREERTOS_UNICORE
|
||||
|
||||
|
@ -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
|
@ -28,9 +28,12 @@ void defaultConfig() {
|
||||
cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
|
||||
cfg.wifiscancycle = SEND_SECS; // wifi scan cycle [seconds/2]
|
||||
cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
|
||||
cfg.blescancycle = BLESCANTIME; // BLE scan cycle [seconds]
|
||||
cfg.blescan = 0; // 0=disabled, 1=enabled
|
||||
cfg.blescantime = BLESCANTIME; // BLE scan cycle duration [seconds]
|
||||
cfg.blescancycle = BLESCANCYCLE; // do a BLE scan after [BLESCANCYCLE] full Wifi scan cycles
|
||||
cfg.blescan = 1; // 0=disabled, 1=enabled
|
||||
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 );
|
||||
}
|
||||
|
||||
@ -103,8 +106,11 @@ void saveConfig() {
|
||||
if( nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || flash8 != cfg.wifichancycle )
|
||||
nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle);
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK || flash8 != cfg.blescantime )
|
||||
nvs_set_i8(my_handle, "blescantime", cfg.blescantime);
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescancycle", &flash8) != ESP_OK || flash8 != cfg.blescancycle )
|
||||
nvs_set_i8(my_handle, "blescancycle", cfg.blescancycle);
|
||||
nvs_set_i8(my_handle, "blescantime", cfg.blescancycle);
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK || flash8 != cfg.blescan )
|
||||
nvs_set_i8(my_handle, "blescanmode", cfg.blescan);
|
||||
@ -112,6 +118,9 @@ void saveConfig() {
|
||||
if( nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != 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 )
|
||||
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
|
||||
|
||||
@ -236,11 +245,27 @@ void loadConfig() {
|
||||
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, "blescantime", &flash8) == ESP_OK ) {
|
||||
cfg.blescantime = flash8;
|
||||
ESP_LOGI(TAG, "blescantime = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "BLEscantime set to default %i", cfg.blescantime);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescancycle", &flash8) == ESP_OK ) {
|
||||
cfg.blescancycle = flash8;
|
||||
ESP_LOGI(TAG, "blescancycle = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "BLEscan cycle set to default %i", cfg.blescancycle);
|
||||
ESP_LOGI(TAG, "BLEscancycle set to default %i", cfg.blescancycle);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
// std::set for unified array functions
|
||||
#include <set>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
||||
// OLED Display
|
||||
#include <U8x8lib.h>
|
||||
@ -11,6 +13,12 @@
|
||||
#include <lmic.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
|
||||
typedef struct {
|
||||
int8_t lorasf; // 7-12, lora spreadfactor
|
||||
@ -22,9 +30,11 @@ typedef struct {
|
||||
int16_t rssilimit; // threshold for rssilimiter, negative value!
|
||||
int8_t wifiscancycle; // wifi scan cycle [seconds/2]
|
||||
int8_t wifichancycle; // wifi channel switch cycle [seconds/100]
|
||||
int8_t blescancycle; // BLE scan cycle [seconds]
|
||||
int8_t blescantime; // BLE scan cycle duration [seconds]
|
||||
int8_t blescancycle; // BLE scan frequency, once after [blescancycle] full wifi scans
|
||||
int8_t blescan; // 0=disabled, 1=enabled
|
||||
int8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4)
|
||||
int8_t rgblum; // RGB Led luminosity (0 100%)
|
||||
char version[10]; // Firmware version
|
||||
} configData_t;
|
||||
|
||||
@ -32,9 +42,9 @@ extern configData_t cfg;
|
||||
extern uint8_t mydata[];
|
||||
extern uint64_t uptimecounter;
|
||||
extern osjob_t sendjob;
|
||||
extern uint16_t macnum, blenum, salt;
|
||||
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim;
|
||||
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim, salt;
|
||||
extern bool joinstate;
|
||||
extern std::set<uint16_t> wifis;
|
||||
extern std::set<uint16_t> macs;
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
@ -45,4 +55,5 @@ extern std::set<uint16_t> macs;
|
||||
|
||||
#ifdef BLECOUNTER
|
||||
extern int scanTime;
|
||||
extern std::set<uint16_t> bles;
|
||||
#endif
|
@ -6,6 +6,7 @@
|
||||
|
||||
#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 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
|
||||
#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
|
||||
@ -30,4 +31,3 @@
|
||||
#define OLED_RST U8X8_PIN_NONE // Not reset pin
|
||||
#define OLED_SDA 21 // ESP32 GPIO21 (Pin21) -- OLED SDA
|
||||
#define OLED_SCL 22 // ESP32 GPIO22 (Pin22) -- OLED SCL
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
#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_LED NOT_A_PIN // Led os on same pin than Lora SS pin, to avoid pb, we don't use it
|
||||
// Anyway shield is on over the LoLin32 board, so we won't be able to see this LED
|
||||
#define HAS_LED 22 // ESP32 GPIO12 (pin22) On Board 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_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield
|
||||
#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_SDA 14 // ESP32 GPIO14 (Pin14) -- OLED SDA
|
||||
#define OLED_SCL 12 // ESP32 GPIO12 (Pin12) -- OLED SCL
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display 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
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
|
@ -79,10 +79,22 @@ void printKeys(void) {
|
||||
#endif // VERBOSE
|
||||
|
||||
void do_send(osjob_t* j){
|
||||
mydata[0] = (macnum & 0xff00) >> 8;
|
||||
mydata[1] = macnum & 0x00ff;
|
||||
mydata[2] = (blenum & 0xff00) >> 8;
|
||||
mydata[3] = blenum & 0x00ff;
|
||||
uint16_t data;
|
||||
// Total BLE+WIFI unique MACs seen
|
||||
data = (uint16_t) macs.size();
|
||||
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
|
||||
if (LMIC.opmode & OP_TXRXPEND) {
|
||||
@ -95,7 +107,6 @@ void do_send(osjob_t* j){
|
||||
ESP_LOGI(TAG, "Packet queued");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "PACKET QUEUED");
|
||||
set_onboard_led(1);
|
||||
}
|
||||
// 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)");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "TX COMPLETE");
|
||||
set_onboard_led(0);
|
||||
if (LMIC.txrxFlags & TXRX_ACK) {
|
||||
ESP_LOGI(TAG, "Received ack");
|
||||
u8x8.clearLine(7);
|
||||
@ -224,3 +234,4 @@ void onEvent (ev_t ev) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
141
src/macsniff.cpp
Normal file
141
src/macsniff.cpp
Normal 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.blescantime);
|
||||
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
28
src/macsniff.h
Normal 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 );
|
168
src/main.cpp
168
src/main.cpp
@ -25,6 +25,9 @@ Refer to LICENSE.txt file in repository for more details.
|
||||
#include "main.h"
|
||||
#include "globals.h"
|
||||
|
||||
// std::set for unified array functions
|
||||
#include <set>
|
||||
|
||||
// OLED driver
|
||||
#include <U8x8lib.h>
|
||||
|
||||
@ -42,11 +45,17 @@ configData_t cfg; // struct holds current device configuration
|
||||
osjob_t sendjob, initjob; // LMIC
|
||||
|
||||
// Initialize global variables
|
||||
uint16_t macnum = 0, blenum = 0, salt;
|
||||
int macnum = 0, salt;
|
||||
uint64_t uptimecounter = 0;
|
||||
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
|
||||
static volatile bool ButtonTriggered = false;
|
||||
@ -67,29 +76,19 @@ void eraseConfig(void);
|
||||
void saveConfig(void);
|
||||
void loadConfig(void);
|
||||
|
||||
/* begin LMIC specific parts ------------------------------------------------------------ */
|
||||
#ifdef HAS_LED
|
||||
void set_onboard_led(int st);
|
||||
#endif
|
||||
|
||||
// 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}
|
||||
};
|
||||
/* begin LMIC specific parts ------------------------------------------------------------ */
|
||||
|
||||
// defined in lorawan.cpp
|
||||
void gen_lora_deveui(uint8_t * pdeveui);
|
||||
void RevBytes(unsigned char* b, size_t c);
|
||||
|
||||
#ifdef VERBOSE
|
||||
void printKeys(void);
|
||||
#endif
|
||||
|
||||
// LMIC functions
|
||||
void onEvent(ev_t ev);
|
||||
void do_send(osjob_t* j);
|
||||
#endif // VERBOSE
|
||||
|
||||
// LMIC callback functions
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
static void lora_init (osjob_t* j) {
|
||||
// reset MAC state
|
||||
@ -125,8 +139,48 @@ static void lora_init (osjob_t* j) {
|
||||
// LMIC Task
|
||||
void lorawan_loop(void * pvParameters) {
|
||||
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
|
||||
|
||||
static bool led_state ;
|
||||
bool new_led_state ;
|
||||
|
||||
while(1) {
|
||||
uint16_t color;
|
||||
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);
|
||||
yield();
|
||||
}
|
||||
@ -159,12 +213,18 @@ void lorawan_loop(void * pvParameters) {
|
||||
void set_onboard_led(int st){
|
||||
#ifdef HAS_LED
|
||||
switch (st) {
|
||||
case 1: digitalWrite(HAS_LED, HIGH); break;
|
||||
case 0: digitalWrite(HAS_LED, LOW); break;
|
||||
#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 0: digitalWrite(HAS_LED, LOW); break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAS_BUTTON
|
||||
// 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
|
||||
@ -186,40 +246,43 @@ void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
|
||||
void wifi_sniffer_loop(void * pvParameters) {
|
||||
|
||||
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
|
||||
uint8_t channel = 1;
|
||||
uint8_t channel=0;
|
||||
int nloop=0, lorawait=0;
|
||||
|
||||
while (true) {
|
||||
nloop++;
|
||||
vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS);
|
||||
|
||||
nloop++; // acutal number of wifi loops, controls cycle when data is sent
|
||||
|
||||
vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS);
|
||||
yield();
|
||||
wifi_sniffer_set_channel(channel);
|
||||
channel = (channel % WIFI_CHANNEL_MAX) + 1;
|
||||
channel = (channel % WIFI_CHANNEL_MAX) + 1; // rotates variable channel 1..WIFI_CHANNEL_MAX
|
||||
wifi_sniffer_set_channel(channel);
|
||||
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
|
||||
if( nloop >= ((100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) ) {
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display on if enabled
|
||||
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
|
||||
u8x8.setCursor(0,4);
|
||||
u8x8.printf("MAC#: %-5i", macnum);
|
||||
do_send(&sendjob); // send payload
|
||||
if( nloop >= ( (100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) +1 ) {
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display on if enabled
|
||||
nloop=0; channel=0; // reset wifi scan + channel loop counter
|
||||
do_send(&sendjob); // Prepare and execute LoRaWAN data upload
|
||||
vTaskDelay(500/portTICK_PERIOD_MS);
|
||||
yield();
|
||||
|
||||
// clear counter if not in cumulative counter mode
|
||||
if (cfg.countermode != 1) {
|
||||
macs.clear(); // clear macs container
|
||||
salt = random(65536); // get new 16bit random for salting hashes
|
||||
macnum = 0;
|
||||
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
|
||||
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
|
||||
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
|
||||
}
|
||||
|
||||
// wait until payload is sent, while wifi scanning and mac counting task continues
|
||||
@ -238,11 +301,21 @@ void wifi_sniffer_loop(void * pvParameters) {
|
||||
|
||||
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();
|
||||
u8x8.setPowerSave(1 && cfg.screensaver); // set display off if screensaver is enabled
|
||||
}
|
||||
}
|
||||
} // end of send data cycle
|
||||
else {
|
||||
#ifdef BLECOUNTER // execute BLE count if BLE function is enabled
|
||||
if (nloop % (WIFI_CHANNEL_MAX * cfg.blescancycle) == 0 ) { // once after cfg.blescancycle Wifi scans, do a BLE scan
|
||||
if (cfg.blescan) // execute BLE count if BLE function is enabled
|
||||
BLECount();
|
||||
}
|
||||
#endif
|
||||
} // end of channel rotation loop
|
||||
} // end of infinite wifi scan loop
|
||||
}
|
||||
|
||||
/* end wifi specific parts ------------------------------------------------------------ */
|
||||
@ -336,6 +409,7 @@ void setup() {
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION);
|
||||
rgb_set_color(COLOR_NONE);
|
||||
|
||||
// system event handler for wifi task, needed for wifi_sniffer_init()
|
||||
esp_event_loop_init(NULL, NULL);
|
||||
@ -380,7 +454,7 @@ void setup() {
|
||||
antenna_init();
|
||||
#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
|
||||
|
||||
// initialize display
|
||||
|
35
src/main.h
35
src/main.h
@ -1,30 +1,35 @@
|
||||
// program version
|
||||
#define PROGVERSION "1.2.62" // use max 10 chars here!
|
||||
#define PROGVERSION "1.2.85" // use max 10 chars here!
|
||||
#define PROGNAME "PAXCNT"
|
||||
|
||||
// Verbose enables serial output
|
||||
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
||||
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
||||
|
||||
// set this to include BLE counting and vendor filter functions
|
||||
#define VENDORFILTER 1 // comment out if you want to count things, not people
|
||||
#define BLECOUNTER 1 // comment out if you don't want BLE count
|
||||
#define VENDORFILTER 1 // comment out if you want to count things, not people
|
||||
#define BLECOUNTER 1 // comment out if you don't want BLE count
|
||||
|
||||
// BLE scan time
|
||||
#define BLESCANTIME 30 // [seconds]
|
||||
#define BLESCANTIME 15 // [seconds]
|
||||
#define BLESCANCYCLE 2 // BLE scan once after each <BLECYCLE> wifi scans
|
||||
|
||||
// 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
|
||||
#define WIFI_CHANNEL_MIN 1 // start channel number where scan begings
|
||||
#define WIFI_CHANNEL_MAX 13 // total channel number to scan
|
||||
#define WIFI_MY_COUNTRY "EU" // for Wifi RF settings
|
||||
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
|
||||
#define WIFI_CHANNEL_MIN 1 // start channel number where scan begings
|
||||
#define WIFI_CHANNEL_MAX 13 // total channel number to scan
|
||||
#define WIFI_MY_COUNTRY "EU" // select locale for Wifi RF settings
|
||||
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
|
||||
|
||||
// Default LoRa Spreadfactor
|
||||
#define LORASFDEFAULT 9 // 7 ... 12
|
||||
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
|
||||
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
|
||||
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs
|
||||
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
|
||||
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
|
||||
|
||||
// Default RGB LED luminosity (in %)
|
||||
#define RGBLUMINOSITY 50 // 50%
|
||||
|
||||
// LMIC settings
|
||||
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored
|
||||
@ -99,10 +104,10 @@
|
||||
// implementation is optimized for speed on 32-bit processors using
|
||||
// fairly big lookup tables, but it takes up big amounts of flash on the
|
||||
// AVR architecture.
|
||||
// #define USE_ORIGINAL_AES
|
||||
#define USE_ORIGINAL_AES
|
||||
//
|
||||
// This selects the AES implementation written by Ideetroon for their
|
||||
// own LoRaWAN library. It also uses lookup tables, but smaller
|
||||
// byte-oriented ones, making it use a lot less flash space (but it is
|
||||
// also about twice as slow as the original).
|
||||
#define USE_IDEETRON_AES
|
||||
// #define USE_IDEETRON_AES
|
||||
|
@ -67,8 +67,9 @@ void set_reset(int val) {
|
||||
break;
|
||||
case 1: // reset MAC counter
|
||||
ESP_LOGI(TAG, "Remote command: reset MAC counter");
|
||||
macs.clear(); // clear macs container
|
||||
macnum = 0;
|
||||
macs.clear(); // clear all macs container
|
||||
wifis.clear(); // clear Wifi macs container
|
||||
bles.clear(); // clear BLE macs container
|
||||
salt = random(65536); // get new 16bit random for salting hashes
|
||||
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
|
||||
u8x8.clearLine(5);
|
||||
@ -103,9 +104,14 @@ void set_wifichancycle(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %i seconds", cfg.wifichancycle/100);
|
||||
};
|
||||
|
||||
void set_blescantime(int val) {
|
||||
cfg.blescantime = val;
|
||||
ESP_LOGI(TAG, "Remote command: set BLE scan time to %i seconds", cfg.blescantime);
|
||||
};
|
||||
|
||||
void set_blescancycle(int val) {
|
||||
cfg.blescancycle = val;
|
||||
ESP_LOGI(TAG, "Remote command: set Wifi channel cycle duration to %i seconds", cfg.blescancycle);
|
||||
ESP_LOGI(TAG, "Remote command: set BLE scan cycle to %i", cfg.blescancycle);
|
||||
};
|
||||
|
||||
void set_countmode(int val) {
|
||||
@ -180,6 +186,12 @@ void set_wifiant(int val) {
|
||||
#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) {
|
||||
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %i", val);
|
||||
switch_lora(cfg.lorasf, val);
|
||||
@ -237,9 +249,11 @@ cmd_t table[] = {
|
||||
{0x09, set_reset, false},
|
||||
{0x0a, set_wifiscancycle, true},
|
||||
{0x0b, set_wifichancycle, true},
|
||||
{0x0c, set_blescancycle, true},
|
||||
{0x0d, set_blescan, true},
|
||||
{0x0e, set_wifiant, true},
|
||||
{0x0c, set_blescantime, true},
|
||||
{0x0d, set_blescancycle, true},
|
||||
{0x0e, set_blescan, true},
|
||||
{0x0f, set_wifiant, true},
|
||||
{0x10, set_rgblum, true},
|
||||
{0x80, get_config, false},
|
||||
{0x81, get_uptime, false},
|
||||
{0x82, get_cputemp, false}
|
||||
|
87
src/rgb_led.cpp
Normal file
87
src/rgb_led.cpp
Normal 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
30
src/rgb_led.h
Normal 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);
|
2870
src/vendor_array.h
2870
src/vendor_array.h
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user