commit
7f20c198b9
@ -55,7 +55,6 @@ Depending on board hardware following features are supported:
|
||||
- OLED Display (shows detailed status)
|
||||
- RGB LED (shows colorized status)
|
||||
- Button (short press: flip display page / long press: send alarm message)
|
||||
- Silicon unique ID
|
||||
- Battery voltage monitoring (analog read / AXP192 / IP5306)
|
||||
- GPS (Generic serial NMEA, or Quectel L76 I2C)
|
||||
- Environmental sensors (Bosch BMP180/BME280/BME680 I2C; SDS011 serial)
|
||||
|
@ -18,10 +18,6 @@
|
||||
#include "mallocator.h"
|
||||
#include <bsec.h>
|
||||
|
||||
// sniffing types
|
||||
#define MAC_SNIFF_WIFI 0
|
||||
#define MAC_SNIFF_BLE 1
|
||||
|
||||
// bits in payloadmask for filtering payload data
|
||||
#define GPS_DATA (0x01)
|
||||
#define ALARM_DATA (0x02)
|
||||
@ -67,9 +63,9 @@
|
||||
|
||||
enum sendprio_t { prio_low, prio_normal, prio_high };
|
||||
enum timesource_t { _gps, _rtc, _lora, _unsynced };
|
||||
|
||||
enum snifftype_t { MAC_SNIFF_WIFI, MAC_SNIFF_BLE, MAC_SNIFF_BLE_ENS };
|
||||
enum runmode_t {
|
||||
RUNMODE_POWERCYCLE = 0,
|
||||
RUNMODE_POWERCYCLE,
|
||||
RUNMODE_NORMAL,
|
||||
RUNMODE_WAKEUP,
|
||||
RUNMODE_UPDATE
|
||||
@ -114,6 +110,13 @@ typedef struct {
|
||||
uint8_t Message[PAYLOAD_BUFFER_SIZE];
|
||||
} MessageBuffer_t;
|
||||
|
||||
// Struct for MAC processing queue
|
||||
typedef struct {
|
||||
uint8_t mac[6];
|
||||
int8_t rssi;
|
||||
snifftype_t sniff_type;
|
||||
} MacBuffer_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t latitude;
|
||||
int32_t longitude;
|
||||
@ -145,13 +148,14 @@ extern std::array<uint64_t, 0xff> beacons;
|
||||
extern configData_t cfg; // current device configuration
|
||||
extern char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer
|
||||
extern uint8_t volatile channel; // wifi channel rotation counter
|
||||
extern uint8_t volatile rf_load; // RF traffic indicator
|
||||
extern uint8_t batt_level; // display value
|
||||
extern uint16_t volatile macs_wifi, macs_ble; // display values
|
||||
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
|
||||
extern timesource_t timeSource;
|
||||
extern hw_timer_t *displayIRQ, *matrixDisplayIRQ, *ppsIRQ;
|
||||
extern SemaphoreHandle_t I2Caccess;
|
||||
extern TaskHandle_t irqHandlerTask, ClockTask;
|
||||
extern TaskHandle_t irqHandlerTask, ClockTask, macProcessTask;
|
||||
extern TimerHandle_t WifiChanTimer;
|
||||
extern Timezone myTZ;
|
||||
extern RTC_DATA_ATTR runmode_t RTC_runmode;
|
||||
|
@ -14,13 +14,12 @@
|
||||
#include "corona.h"
|
||||
#endif
|
||||
|
||||
#define MAC_SNIFF_WIFI 0
|
||||
#define MAC_SNIFF_BLE 1
|
||||
#define MAC_SNIFF_BLE_CWA 2
|
||||
|
||||
uint16_t get_salt(void);
|
||||
uint64_t macConvert(uint8_t *paddr);
|
||||
uint16_t mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type);
|
||||
esp_err_t macQueueInit(void);
|
||||
void mac_process(void *pvParameters);
|
||||
void IRAM_ATTR mac_add(uint8_t *paddr, int8_t rssi, snifftype_t sniff_type);
|
||||
uint16_t mac_analyze(MacBuffer_t MacBuffer);
|
||||
void printKey(const char *name, const uint8_t *key, uint8_t len, bool lsb);
|
||||
|
||||
#endif
|
||||
|
@ -46,7 +46,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
|
||||
|
||||
[common]
|
||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||
release_version = 2.0.3
|
||||
release_version = 2.0.4
|
||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||
debug_level = 3
|
||||
|
@ -6,14 +6,10 @@
|
||||
#define BT_BD_ADDR_HEX(addr) \
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
|
||||
|
||||
// UUID of Exposure Notification Service (ENS)
|
||||
// see
|
||||
// https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf
|
||||
static const char ensMagicBytes[] = "\x16\x6f\xfd";
|
||||
|
||||
// local Tag for logging
|
||||
static const char TAG[] = "bluetooth";
|
||||
|
||||
#ifdef VERBOSE
|
||||
const char *bt_addr_t_to_string(esp_ble_addr_type_t type) {
|
||||
switch (type) {
|
||||
case BLE_ADDR_TYPE_PUBLIC:
|
||||
@ -110,15 +106,24 @@ const char *btsig_gap_type(uint32_t gap_type) {
|
||||
return "Unknown type";
|
||||
}
|
||||
} // btsig_gap_type
|
||||
#endif
|
||||
|
||||
// using IRAM_:ATTR here to speed up callback function
|
||||
// using IRAM_ATTR here to speed up callback function
|
||||
IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event,
|
||||
esp_ble_gap_cb_param_t *param) {
|
||||
|
||||
esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param;
|
||||
|
||||
#if (COUNT_ENS)
|
||||
// UUID of Exposure Notification Service (ENS)
|
||||
// https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf
|
||||
static const char ensMagicBytes[] = "\x16\x6f\xfd";
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE
|
||||
ESP_LOGV(TAG, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv,
|
||||
btsig_gap_type(*p->scan_rst.ble_adv));
|
||||
#endif
|
||||
|
||||
switch (event) {
|
||||
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
|
||||
@ -138,42 +143,37 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event,
|
||||
if (p->scan_rst.search_evt ==
|
||||
ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device
|
||||
{ // evaluate sniffed packet
|
||||
#ifdef VERBOSE
|
||||
ESP_LOGV(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
BT_BD_ADDR_HEX(p->scan_rst.bda));
|
||||
ESP_LOGV(TAG, "Addr_type : %s",
|
||||
bt_addr_t_to_string(p->scan_rst.ble_addr_type));
|
||||
ESP_LOGV(TAG, "RSSI : %d", p->scan_rst.rssi);
|
||||
|
||||
if ((cfg.rssilimit) &&
|
||||
(p->scan_rst.rssi < cfg.rssilimit)) { // rssi is negative value
|
||||
ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi,
|
||||
cfg.rssilimit);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (VENDORFILTER)
|
||||
if ((p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) ||
|
||||
(p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM)) {
|
||||
#ifdef VERBOSE
|
||||
ESP_LOGV(TAG, "BT device filtered");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// hash and add this device and show new count total if it was not
|
||||
// previously added
|
||||
|
||||
#if (COUNT_ENS)
|
||||
uint16_t hashedmac =
|
||||
#endif
|
||||
|
||||
mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
|
||||
// add this device mac to processing queue
|
||||
|
||||
#if (COUNT_ENS)
|
||||
// check for ens signature
|
||||
if (cfg.enscount) {
|
||||
// check for ens signature
|
||||
if (NULL != strstr((const char *)p->scan_rst.ble_adv, ensMagicBytes))
|
||||
cwa_mac_add(hashedmac);
|
||||
if (strstr((const char *)p->scan_rst.ble_adv, ensMagicBytes) != NULL)
|
||||
mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi,
|
||||
MAC_SNIFF_BLE_ENS);
|
||||
else
|
||||
mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
|
||||
}
|
||||
#else
|
||||
mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
|
||||
#endif
|
||||
|
||||
/* to be improved in vendorfilter if:
|
||||
@ -186,8 +186,8 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event,
|
||||
// uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv,
|
||||
ESP_BLE_AD_TYPE_NAME_CMPL, &len);
|
||||
|
||||
filter BLE devices using their advertisements to get filter alternative to
|
||||
vendor OUI if vendorfiltering is on, we ...
|
||||
filter BLE devices using their advertisements to get filter alternative
|
||||
to vendor OUI if vendorfiltering is on, we ...
|
||||
- want to count: mobile phones and tablets
|
||||
- don't want to count: beacons, peripherals (earphones, headsets,
|
||||
printers), cars and machines see
|
||||
@ -211,13 +211,13 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event,
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} // switch
|
||||
} // gap_callback_handler
|
||||
|
||||
esp_err_t register_ble_callback(void) {
|
||||
ESP_LOGI(TAG, "Register GAP callback");
|
||||
|
||||
// This function is called to occur gap event, such as scan result.
|
||||
// This function is called when gap event occurs, such as scan result.
|
||||
// register the scan callback function to the gap module
|
||||
ESP_ERROR_CHECK(esp_ble_gap_register_callback(&gap_callback_handler));
|
||||
|
||||
|
@ -23,18 +23,13 @@ static std::map<uint16_t, unsigned long> cwaSeenNotifiers;
|
||||
|
||||
// Remove notifiers last seen over FORGET_AFTER_MINUTES ago.
|
||||
void cwa_clear() {
|
||||
/*
|
||||
|
||||
#ifdef SOME_FORM_OF_DEBUG
|
||||
ESP_LOGD(TAG, "CWA: forget old notifier: %d", cwaSeenNotifiers.size());
|
||||
for (auto const ¬ifier : cwaSeenNotifiers) {
|
||||
ESP_LOGD(TAG, "CWA forget <%X>", notifier.first);
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
#ifdef VERBOSE
|
||||
ESP_LOGV(TAG, "CWA: forget old notifier: %d", cwaSeenNotifiers.size());
|
||||
for (auto const ¬ifier : cwaSeenNotifiers) {
|
||||
ESP_LOGD(TAG, "CWA forget <%04X>", notifier.first);
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
// clear everything, otherwise we would count the same device again, as in the
|
||||
// next cycle it likely will advertise with a different hash-value
|
||||
cwaSeenNotifiers.clear();
|
||||
|
@ -40,6 +40,9 @@ void doHousekeeping() {
|
||||
ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d",
|
||||
uxTaskGetStackHighWaterMark(irqHandlerTask),
|
||||
eTaskGetState(irqHandlerTask));
|
||||
ESP_LOGD(TAG, "MACprocessor %d bytes left | Taskstate = %d",
|
||||
uxTaskGetStackHighWaterMark(macProcessTask),
|
||||
eTaskGetState(macProcessTask));
|
||||
#if (HAS_LORA)
|
||||
ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d",
|
||||
uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask));
|
||||
|
@ -311,6 +311,7 @@ void dp_drawPage(time_t t, bool nextpage) {
|
||||
dp_printf(" ");
|
||||
#endif
|
||||
dp_printf(" ch:%02d", channel);
|
||||
// dp_printf(" due:%02d", rf_load);
|
||||
dp_println();
|
||||
|
||||
// line 5: RSSI limiter + free memory
|
||||
|
@ -105,8 +105,4 @@
|
||||
#define LORA_IO1 (33)
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
// I2C config for Microchip 24AA02E64 DEVEUI unique address
|
||||
#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64
|
||||
#define MCP_24AA02E64_MAC_ADDRESS 0xF8 // Memory adress of unique deveui 64 bits
|
||||
|
||||
#endif
|
||||
|
@ -162,49 +162,7 @@ void os_getDevEui(u1_t *buf) {
|
||||
} else {
|
||||
gen_lora_deveui(buf); // generate DEVEUI from device's MAC
|
||||
}
|
||||
|
||||
// Get MCP 24AA02E64 hardware DEVEUI (override default settings if found)
|
||||
#ifdef MCP_24AA02E64_I2C_ADDRESS
|
||||
get_hard_deveui(buf);
|
||||
RevBytes(buf, 8); // swap bytes to LSB format
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void get_hard_deveui(uint8_t *pdeveui) {
|
||||
// read DEVEUI from Microchip 24AA02E64 2Kb serial eeprom if present
|
||||
#ifdef MCP_24AA02E64_I2C_ADDRESS
|
||||
|
||||
uint8_t i2c_ret;
|
||||
|
||||
// Init this just in case, no more to 100KHz
|
||||
Wire.begin(SDA, SCL, 100000);
|
||||
Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS);
|
||||
Wire.write(MCP_24AA02E64_MAC_ADDRESS);
|
||||
i2c_ret = Wire.endTransmission();
|
||||
|
||||
// check if device was seen on i2c bus
|
||||
if (i2c_ret == 0) {
|
||||
char deveui[32] = "";
|
||||
uint8_t data;
|
||||
|
||||
Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS);
|
||||
Wire.write(MCP_24AA02E64_MAC_ADDRESS);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(MCP_24AA02E64_I2C_ADDRESS, 8);
|
||||
while (Wire.available()) {
|
||||
data = Wire.read();
|
||||
sprintf(deveui + strlen(deveui), "%02X ", data);
|
||||
*pdeveui++ = data;
|
||||
}
|
||||
ESP_LOGI(TAG, "Serial EEPROM found, read DEVEUI %s", deveui);
|
||||
} else
|
||||
ESP_LOGI(TAG, "Could not read DEVEUI from serial EEPROM");
|
||||
|
||||
// Set back to 400KHz to speed up OLED
|
||||
Wire.setClock(400000);
|
||||
#endif // MCP 24AA02E64
|
||||
}
|
||||
|
||||
#if (VERBOSE)
|
||||
|
214
src/macsniff.cpp
214
src/macsniff.cpp
@ -10,6 +10,9 @@
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
QueueHandle_t MacQueue;
|
||||
TaskHandle_t macProcessTask;
|
||||
|
||||
uint16_t salt = 0;
|
||||
|
||||
uint16_t get_salt(void) {
|
||||
@ -43,103 +46,170 @@ uint64_t macConvert(uint8_t *paddr) {
|
||||
return (__builtin_bswap64(*mac) >> 16);
|
||||
}
|
||||
|
||||
uint16_t mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
|
||||
esp_err_t macQueueInit() {
|
||||
_ASSERT(MAC_QUEUE_SIZE > 0);
|
||||
MacQueue = xQueueCreate(MAC_QUEUE_SIZE, sizeof(MacBuffer_t));
|
||||
if (MacQueue == 0) {
|
||||
ESP_LOGE(TAG, "Could not create MAC processing queue. Aborting.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "MAC processing queue created, size %d Bytes",
|
||||
MAC_QUEUE_SIZE * sizeof(MacBuffer_t));
|
||||
|
||||
xTaskCreatePinnedToCore(mac_process, // task function
|
||||
"mac_process", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
1, // priority of the task
|
||||
&macProcessTask, // task handle
|
||||
1); // CPU core
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// sniffed MAC processing task
|
||||
void mac_process(void *pvParameters) {
|
||||
_ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
|
||||
|
||||
MacBuffer_t MacBuffer;
|
||||
|
||||
while (1) {
|
||||
|
||||
// fetch next or wait for incoming MAC from sniffing queue
|
||||
if (xQueueReceive(MacQueue, &MacBuffer, portMAX_DELAY) != pdTRUE) {
|
||||
ESP_LOGE(TAG, "Premature return from xQueueReceive() with no data!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// update traffic indicator
|
||||
rf_load = uxQueueMessagesWaiting(MacQueue);
|
||||
// process fetched mac
|
||||
mac_analyze(MacBuffer);
|
||||
}
|
||||
delay(2); // yield to CPU
|
||||
}
|
||||
|
||||
// enqueue message in MAC processing queue
|
||||
void IRAM_ATTR mac_add(uint8_t *paddr, int8_t rssi, snifftype_t sniff_type) {
|
||||
|
||||
MacBuffer_t MacBuffer;
|
||||
|
||||
MacBuffer.rssi = rssi;
|
||||
MacBuffer.sniff_type = sniff_type;
|
||||
memcpy(MacBuffer.mac, paddr, 6);
|
||||
|
||||
if (xQueueSendToBackFromISR(MacQueue, (void *)&MacBuffer, (TickType_t)0) !=
|
||||
pdPASS)
|
||||
ESP_LOGW(TAG, "Dense radio traffic, packet lost!");
|
||||
}
|
||||
|
||||
uint16_t mac_analyze(MacBuffer_t MacBuffer) {
|
||||
|
||||
if (salt == 0) // ensure we have salt (appears after radio is turned on)
|
||||
return 0;
|
||||
|
||||
uint16_t hashedmac = 0; // temporary buffer for generated hash value
|
||||
char buff[10]; // temporary buffer for printf
|
||||
bool added = false;
|
||||
int8_t beaconID; // beacon number in test monitor mode
|
||||
uint32_t *mac; // temporary buffer for shortened MAC
|
||||
if ((cfg.rssilimit) &&
|
||||
(MacBuffer.rssi < cfg.rssilimit)) { // rssi is negative value
|
||||
ESP_LOGI(TAG, "%s RSSI %d -> ignoring (limit: %d)",
|
||||
(MacBuffer.sniff_type == MAC_SNIFF_WIFI) ? "WIFI" : "BLTH",
|
||||
MacBuffer.rssi, cfg.rssilimit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// in beacon monitor mode check if seen MAC is a known beacon
|
||||
if (cfg.monitormode) {
|
||||
int8_t beaconID = isBeacon(macConvert(MacBuffer.mac));
|
||||
if (beaconID >= 0) {
|
||||
ESP_LOGI(TAG, "Beacon ID#%d detected", beaconID);
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_WHITE, 2000);
|
||||
#endif
|
||||
payload.reset();
|
||||
payload.addAlarm(MacBuffer.rssi, beaconID);
|
||||
SendPayload(BEACONPORT, prio_high);
|
||||
}
|
||||
};
|
||||
|
||||
#if (VENDORFILTER)
|
||||
uint32_t *oui; // temporary buffer for vendor OUI
|
||||
oui = (uint32_t *)MacBuffer.mac;
|
||||
// if we find OUI on vendor filter list we don't analyze and return early
|
||||
if (std::find(vendors.begin(), vendors.end(), __builtin_bswap32(*oui) >> 8) !=
|
||||
vendors.end())
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
char buff[10]; // temporary buffer for printf
|
||||
uint32_t *mac; // temporary buffer for shortened MAC
|
||||
|
||||
// only last 3 MAC Address bytes are used for MAC address anonymization
|
||||
// but since it's uint32 we take 4 bytes to avoid 1st value to be 0.
|
||||
// this gets MAC in msb (= reverse) order, but doesn't matter for hashing it.
|
||||
mac = (uint32_t *)(paddr + 2);
|
||||
mac = (uint32_t *)(MacBuffer.mac + 2);
|
||||
|
||||
#if (VENDORFILTER)
|
||||
uint32_t *oui; // temporary buffer for vendor OUI
|
||||
oui = (uint32_t *)paddr;
|
||||
// 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
|
||||
|
||||
// use OUI vendor filter list only on Wifi, not on BLE
|
||||
if ((sniff_type == MAC_SNIFF_BLE) ||
|
||||
std::find(vendors.begin(), vendors.end(), __builtin_bswap32(*oui) >> 8) !=
|
||||
vendors.end()) {
|
||||
#endif
|
||||
snprintf(buff, sizeof(buff), "%08X",
|
||||
*mac + (uint32_t)salt); // convert unsigned 32-bit salted MAC
|
||||
// to 8 digit hex string
|
||||
uint16_t hashedmac = rokkit(&buff[3], 5); // hash MAC 8 digit -> 5 digit
|
||||
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique
|
||||
bool added =
|
||||
newmac.second ? true : false; // true if hashed MAC is unique in container
|
||||
|
||||
// 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
|
||||
// Count only if MAC was not yet seen
|
||||
if (added) {
|
||||
|
||||
snprintf(buff, sizeof(buff), "%08X",
|
||||
*mac + (uint32_t)salt); // convert unsigned 32-bit salted MAC
|
||||
// to 8 digit hex string
|
||||
hashedmac = rokkit(&buff[3], 5); // hash MAC 8 digit -> 5 digit
|
||||
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique
|
||||
added = newmac.second ? true
|
||||
: false; // true if hashed MAC is unique in container
|
||||
switch (MacBuffer.sniff_type) {
|
||||
|
||||
// Count only if MAC was not yet seen
|
||||
if (added) {
|
||||
// increment counter and one blink led
|
||||
if (sniff_type == MAC_SNIFF_WIFI) {
|
||||
macs_wifi++; // increment Wifi MACs counter
|
||||
case MAC_SNIFF_WIFI:
|
||||
macs_wifi++; // increment Wifi MACs counter
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_GREEN, 50);
|
||||
blink_LED(COLOR_GREEN, 50);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
#if (BLECOUNTER)
|
||||
else if (sniff_type == MAC_SNIFF_BLE) {
|
||||
macs_ble++; // increment BLE Macs counter
|
||||
case MAC_SNIFF_BLE:
|
||||
macs_ble++; // increment BLE Macs counter
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_MAGENTA, 50);
|
||||
#endif
|
||||
}
|
||||
blink_LED(COLOR_MAGENTA, 50);
|
||||
#endif
|
||||
break;
|
||||
|
||||
// in beacon monitor mode check if seen MAC is a known beacon
|
||||
if (cfg.monitormode) {
|
||||
beaconID = isBeacon(macConvert(paddr));
|
||||
if (beaconID >= 0) {
|
||||
ESP_LOGI(TAG, "Beacon ID#%d detected", beaconID);
|
||||
#if (COUNT_ENS)
|
||||
case MAC_SNIFF_BLE_ENS:
|
||||
macs_ble++; // increment BLE Macs counter
|
||||
cwa_mac_add(hashedmac); // process ENS beacon
|
||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||
blink_LED(COLOR_WHITE, 2000);
|
||||
blink_LED(COLOR_WHITE, 50);
|
||||
#endif
|
||||
payload.reset();
|
||||
payload.addAlarm(rssi, beaconID);
|
||||
SendPayload(BEACONPORT, prio_high);
|
||||
}
|
||||
};
|
||||
break;
|
||||
|
||||
} // added
|
||||
#endif // COUNT_ENS
|
||||
#endif // BLECOUNTER
|
||||
|
||||
// Log scan result
|
||||
ESP_LOGV(TAG,
|
||||
"%s %s RSSI %ddBi -> salted MAC %s -> Hash %04X -> WiFi:%d "
|
||||
"BLTH:%d "
|
||||
} // switch
|
||||
} // added
|
||||
|
||||
// Log scan result
|
||||
ESP_LOGV(TAG,
|
||||
"%s %s RSSI %ddBi -> salted MAC %s -> Hash %04X -> WiFi:%d "
|
||||
"BLTH:%d "
|
||||
#if (COUNT_ENS)
|
||||
"(CWA:%d)"
|
||||
"(CWA:%d)"
|
||||
#endif
|
||||
"-> %d Bytes left",
|
||||
added ? "new " : "known",
|
||||
sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff,
|
||||
hashedmac, macs_wifi, macs_ble,
|
||||
"-> %d Bytes left",
|
||||
added ? "new " : "known",
|
||||
MacBuffer.sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH",
|
||||
MacBuffer.rssi, buff, hashedmac, macs_wifi, macs_ble,
|
||||
#if (COUNT_ENS)
|
||||
cwa_report(),
|
||||
cwa_report(),
|
||||
#endif
|
||||
getFreeRAM());
|
||||
getFreeRAM());
|
||||
|
||||
#if (VENDORFILTER)
|
||||
} else {
|
||||
// Very noisy
|
||||
// ESP_LOGD(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X",
|
||||
// paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// if a new and unique Wifi or BLE mac was counted, returs hash of this mac,
|
||||
// else 0
|
||||
return hashedmac;
|
||||
}
|
||||
// if an unknown Wifi or BLE mac was counted, return hash of this mac, else 0
|
||||
return (added ? hashedmac : 0);
|
||||
}
|
26
src/main.cpp
26
src/main.cpp
@ -35,9 +35,10 @@ IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||
lmictask 1 2 MCCI LMiC LORAWAN stack
|
||||
clockloop 1 4 generates realtime telegrams for external clock
|
||||
timesync_proc 1 3 processes realtime time sync requests
|
||||
irqhandler 1 1 cyclic tasks (i.e. displayrefresh) triggered by timers
|
||||
irqhandler 1 2 cyclic tasks (i.e. displayrefresh) triggered by timers
|
||||
gpsloop 1 1 reads data from GPS via serial or i2c
|
||||
lorasendtask 1 1 feeds data from lora sendqueue to lmcic
|
||||
macprocess 1 1 analyzes sniffed MACs
|
||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||
|
||||
Low priority numbers denote low priority tasks.
|
||||
@ -86,8 +87,9 @@ triggers pps 1 sec impulse
|
||||
|
||||
configData_t cfg; // struct holds current device configuration
|
||||
char lmic_event_msg[LMIC_EVENTMSG_LEN]; // display buffer for LMIC event message
|
||||
uint8_t volatile channel = 0; // channel rotation counter
|
||||
uint8_t batt_level = 0; // display value
|
||||
uint8_t volatile channel = 0; // channel rotation counter
|
||||
uint8_t volatile rf_load = 0; // RF traffic indicator
|
||||
uint16_t volatile macs_wifi = 0, macs_ble = 0; // globals for display
|
||||
|
||||
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *matrixDisplayIRQ = NULL;
|
||||
@ -285,6 +287,10 @@ void setup() {
|
||||
start_ota_update();
|
||||
#endif
|
||||
|
||||
// start mac processing task
|
||||
ESP_LOGI(TAG, "Starting MAC processor...");
|
||||
macQueueInit();
|
||||
|
||||
// start BLE scan callback if BLE function is enabled in NVRAM configuration
|
||||
// or switch off bluetooth, if not compiled
|
||||
#if (BLECOUNTER)
|
||||
@ -344,7 +350,7 @@ void setup() {
|
||||
strcat_P(features, " LORA");
|
||||
// kick off join, except we come from sleep
|
||||
_ASSERT(lora_stack_init(RTC_runmode == RUNMODE_WAKEUP ? false : true) ==
|
||||
ESP_OK);
|
||||
ESP_OK);
|
||||
#endif
|
||||
|
||||
// initialize SPI
|
||||
@ -490,12 +496,9 @@ void setup() {
|
||||
sendTimer.attach(cfg.sendcycle * 2, setSendIRQ);
|
||||
cyclicTimer.attach(HOMECYCLE, setCyclicIRQ);
|
||||
|
||||
#if (TIME_SYNC_INTERVAL)
|
||||
|
||||
#if (!(TIME_SYNC_LORAWAN) && !(TIME_SYNC_LORASERVER) && !defined HAS_GPS && \
|
||||
!defined HAS_RTC)
|
||||
#warning you did not specify a time source, time will not be synched
|
||||
#endif
|
||||
// only if we have a timesource we do timesync
|
||||
#if ((TIME_SYNC_LORAWAN) || (TIME_SYNC_LORASERVER) || (HAS_GPS) || \
|
||||
defined HAS_RTC)
|
||||
|
||||
#if (defined HAS_IF482 || defined HAS_DCF77)
|
||||
ESP_LOGI(TAG, "Starting Clock Controller...");
|
||||
@ -508,9 +511,10 @@ void setup() {
|
||||
|
||||
ESP_LOGI(TAG, "Starting Timekeeper...");
|
||||
_ASSERT(timepulse_init()); // setup pps timepulse
|
||||
timepulse_start(); // starts pps and cyclic time sync
|
||||
timepulse_start(); // starts pps and cyclic time sync
|
||||
strcat_P(features, " TIME");
|
||||
|
||||
#endif // TIME_SYNC_INTERVAL
|
||||
#endif // timesync
|
||||
|
||||
// show compiled features
|
||||
ESP_LOGI(TAG, "Features:%s", features);
|
||||
|
@ -14,10 +14,11 @@
|
||||
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed
|
||||
#define COUNTERMODE 0 // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
||||
|
||||
// Set this to include BLE counting and vendor filter functions, or to switch off WIFI counting
|
||||
// MAC sniffing parameters
|
||||
#define VENDORFILTER 0 // set to 0 if you want to scan all devices, not filtering smartphone OUIs
|
||||
#define BLECOUNTER 0 // set to 0 if you do not want to install the BLE sniffer
|
||||
#define WIFICOUNTER 1 // set to 0 if you do not want to install the WIFI sniffer
|
||||
#define MAC_QUEUE_SIZE 50 // size of MAC processing buffer (number of MACs) [default = 50]
|
||||
|
||||
// BLE scan parameters
|
||||
#define BLESCANTIME 0 // [seconds] scan duration, 0 means infinite [default], see note below
|
||||
@ -29,10 +30,9 @@
|
||||
// set to 0 if you do not want to enable this function
|
||||
|
||||
// for additional sensors (added by some user)
|
||||
#define HAS_SENSOR_1 0 // set to 1 if you want to transmit CWA counter
|
||||
#define HAS_SENSOR_2 0 // not used
|
||||
#define HAS_SENSOR_3 0 // not used
|
||||
#define HAS_SENSORS (HAS_SENSOR_1 || HAS_SENSOR_2 || HAS_SENSOR_3) // to simplify things
|
||||
#define HAS_SENSOR_1 0 // set to 1 to enable data transfer of user sensor #1 (also used as ENS counter) [default=0]
|
||||
#define HAS_SENSOR_2 0 // set to 1 to enable data transfer of user sensor #2 [default=0]
|
||||
#define HAS_SENSOR_3 0 // set to 1 to enable data transfer of user sensor #3 [default=0]
|
||||
|
||||
/* Note: guide for setting bluetooth parameters
|
||||
*
|
||||
|
@ -57,7 +57,7 @@ uint8_t *sensor_read(uint8_t sensor) {
|
||||
// note: Sensor1 fields are used for ENS count, if ENS detection enabled
|
||||
#if (COUNT_ENS)
|
||||
if (cfg.enscount)
|
||||
payload.addCount(cwa_report(), MAC_SNIFF_BLE_CWA);
|
||||
payload.addCount(cwa_report(), MAC_SNIFF_BLE_ENS);
|
||||
#else
|
||||
buf[0] = length;
|
||||
buf[1] = 0x01;
|
||||
|
@ -26,7 +26,7 @@ typedef struct {
|
||||
uint8_t payload[0]; // network data ended with 4 bytes csum (CRC32)
|
||||
} wifi_ieee80211_packet_t;
|
||||
|
||||
// using IRAM_:ATTR here to speed up callback function
|
||||
// using IRAM_ATTR here to speed up callback function
|
||||
IRAM_ATTR void wifi_sniffer_packet_handler(void *buff,
|
||||
wifi_promiscuous_pkt_type_t type) {
|
||||
|
||||
@ -35,16 +35,13 @@ IRAM_ATTR void wifi_sniffer_packet_handler(void *buff,
|
||||
(wifi_ieee80211_packet_t *)ppkt->payload;
|
||||
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
|
||||
|
||||
if ((cfg.rssilimit) &&
|
||||
(ppkt->rx_ctrl.rssi < cfg.rssilimit)) // rssi is negative value
|
||||
ESP_LOGD(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi,
|
||||
cfg.rssilimit);
|
||||
else // count seen MAC
|
||||
mac_add((uint8_t *)hdr->addr2, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI);
|
||||
// process seen MAC
|
||||
mac_add((uint8_t *)hdr->addr2, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI);
|
||||
}
|
||||
|
||||
// Software-timer driven Wifi channel rotation callback function
|
||||
void switchWifiChannel(TimerHandle_t xTimer) {
|
||||
// static uint8_t channel = 0; // channel rotation counter
|
||||
_ASSERT(xTimer != NULL);
|
||||
channel =
|
||||
(channel % WIFI_CHANNEL_MAX) + 1; // rotate channel 1..WIFI_CHANNEL_MAX
|
||||
|
Loading…
Reference in New Issue
Block a user