From c014824667e86da6796b549a4302bd25267aad0b Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Wed, 2 Sep 2020 11:21:56 +0200 Subject: [PATCH] CWA detection (experimental) --- include/sdcard.h | 7 +--- platformio.ini | 14 ++++---- src/blecsan.cpp | 21 ++++++----- src/coona.cpp | 85 --------------------------------------------- src/corona.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++ src/display.cpp | 16 ++++----- src/macsniff.cpp | 22 ++++++------ src/main.cpp | 2 +- src/paxcounter.conf | 13 +++---- src/sdcard.cpp | 4 +-- src/senddata.cpp | 4 +-- src/sensor.cpp | 4 +-- 12 files changed, 131 insertions(+), 142 deletions(-) delete mode 100644 src/coona.cpp create mode 100644 src/corona.cpp diff --git a/include/sdcard.h b/include/sdcard.h index fa358a71..d95e8336 100644 --- a/include/sdcard.h +++ b/include/sdcard.h @@ -15,11 +15,6 @@ #error HAS_SDCARD unknown card reader value, must be either 1 or 2 #endif #endif -// Pins for SD-card -#define SDCARD_CS (13) -#define SDCARD_MOSI (15) -#define SDCARD_MISO (2) -#define SDCARD_SCLK (14) #ifdef HAS_SDS011 #include "sds011read.h" @@ -45,7 +40,7 @@ #define SDCARD_FILE_HEADER "date, time, wifi, bluet" #define SDCARD_FILE_NAME "paxcount.%02d" #define SDCARD_FILE_HEADER "date, time, wifi, bluet" -#if (COUNT_CWA) +#if (COUNT_ENS) #define SDCARD_FILE_HEADER_CWA ",cwa" #endif diff --git a/platformio.ini b/platformio.ini index 246d5734..96c0a9ab 100644 --- a/platformio.ini +++ b/platformio.ini @@ -37,16 +37,16 @@ halfile = generic.h [platformio] ; upload firmware to board with usb cable -;default_envs = usb +default_envs = usb ; upload firmware to a jfrog bintray repository ;default_envs = ota ; use latest versions of libraries -default_envs = dev +;default_envs = dev description = Paxcounter is a device for metering passenger flows in realtime. It counts how many mobile devices are around. [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.9.996 +release_version = 2.0.1 ; 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 = 4 @@ -61,19 +61,19 @@ display_library = ; set by build.py and taken from hal file lib_deps_lora = MCCI LoRaWAN LMIC library@3.2.0 ; MCCI LMIC by Terrill Moore lib_deps_display = - OneBitDisplay@1.5.0 + OneBitDisplay@1.7.1 QRCode@0.0.1 BitBang_I2C@2.1.1 - TFT_eSPI@>=2.2.8 + TFT_eSPI@>=2.2.18 lib_deps_ledmatrix = Ultrathin_LED_Matrix@>=1.0.0 lib_deps_rgbled = - SmartLeds@>=1.2.0 + SmartLeds@>=1.2.1 lib_deps_gps = 1655@>=1.0.2 ; #1655 TinyGPSPlus by Mikal Hart lib_deps_sensors = Adafruit Unified Sensor@>=1.1.4 - Adafruit BME280 Library@>=2.0.2 + Adafruit BME280 Library@>=2.1.0 Adafruit BMP085 Library@>=1.1.0 BSEC Software Library@1.5.1474 https://github.com/ricki-z/SDS011.git diff --git a/src/blecsan.cpp b/src/blecsan.cpp index 0806776c..10dcc900 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -6,8 +6,10 @@ #define BT_BD_ADDR_HEX(addr) \ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] -// checking for CWAs we need this magic bytes: -static const char cwaMagicBytes[] = "\x03\x03\x6F\xfd"; +// UUID of Exposure Notification Service (ENS) +// see +// https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf +static const char ensMagicBytes[] = "\x03\x03\x6F\xfd"; // local Tag for logging static const char TAG[] = "bluetooth"; @@ -161,18 +163,15 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, // add this device and show new count total if it was not previously added mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); -#if (COUNT_CWA) - // we can call the cwa-functions now - // because we use the hashed max-value - // done in mac_add() +#if (COUNT_ENS) + // we can call the ens functions now using hashed max-value in mac_add() - // check for CWA-signature - if ( 0 == strncmp( (const char*)p->scan_rst.ble_adv, cwaMagicBytes , 4) ) { - cwa_mac_add( p->scan_rst.bda); - } + // check for ens signature + if (0 == strncmp((const char *)p->scan_rst.ble_adv, ensMagicBytes, 4)) { + cwa_mac_add(p->scan_rst.bda); + } #endif - /* to be improved in vendorfilter if: // you can search for elements in the payload using the // function esp_ble_resolve_adv_data() diff --git a/src/coona.cpp b/src/coona.cpp deleted file mode 100644 index 44020d84..00000000 --- a/src/coona.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// routines for counting the number of available Corona Warn Apps (CWA) - -// copied from https://github.com/kmetz/BLEExposureNotificationBeeper -// (c) by Kaspar Metz -// modified for use in the Paxcounter by AQ - -#if (COUNT_CWA) - -// Local logging tag -static const char TAG[] = __FILE__; - -#define BT_BD_ADDR_HEX(addr) \ - addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] - -#include "corona.h" - -// taken from macsniff.cpp -extern uint16_t salt; -extern uint16_t hashedmac; - -// When to forget old senders. -#define FORGET_AFTER_MINUTES 2 - -static std::map cwaSeenNotifiers; - - -/** - * Remove notifiers last seen over FORGET_AFTER_MINUTES ago. - */ -void cwa_clear() { - ESP_LOGD(TAG, "CWA: forget old notifier: %d", cwaSeenNotifiers.size()); - -//#ifdef SOME_FORM_OF_DEBUG - for (auto const ¬ifier : cwaSeenNotifiers) { - ESP_LOGI(TAG, "CWA forget <%X>", notifier.first); -// } - } -//#endif - /* clear everything, - * otherwise we will count the same device again - * as in the next cycle it will get a differetn hash-value - */ - cwaSeenNotifiers.clear(); -} - -/* return the numbers of active CWAs found - */ -uint16_t cwa_report(void) { - return cwaSeenNotifiers.size(); -} - -bool cwa_init(void) -{ - ESP_LOGD(TAG, "init of BLE-scanner for CWA"); - return true; - -} - -// similar to mac_add(), found in macsniff.cpp -// for comments pls. look into this function -bool cwa_mac_add(uint8_t* paddr) { - - // are we too early? - if ( hashedmac <= 0 ) - return false; // YES -> return - - bool added = false; - ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", - BT_BD_ADDR_HEX(paddr)); - - ESP_LOGD(TAG, "hasehd mac = %X, count = %d (total=%d)", hashedmac, cwaSeenNotifiers.count(hashedmac), cwaSeenNotifiers.size()); - added = !(cwaSeenNotifiers.count(hashedmac) > 0); - - // Count only if MAC was not yet seen - if (added) { - ESP_LOGD(TAG, "added device with active CWA"); - } - - cwaSeenNotifiers[hashedmac] = millis(); // last seen at .... - - // True if MAC WiFi/BLE was new - return added; -} - -#endif diff --git a/src/corona.cpp b/src/corona.cpp new file mode 100644 index 00000000..0ef136a2 --- /dev/null +++ b/src/corona.cpp @@ -0,0 +1,81 @@ +// routines for counting the number of devices which advertise Exposure +// Notification Service e.g. "Corona Warn App" in Germany + +// copied from https://github.com/kmetz/BLEExposureNotificationBeeper +// (c) by Kaspar Metz +// modified for use in the Paxcounter by AQ + +#if (COUNT_ENS) + +// Local logging tag +static const char TAG[] = __FILE__; + +#define BT_BD_ADDR_HEX(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + +#include "corona.h" + +// taken from macsniff.cpp +extern uint16_t salt; +extern uint16_t hashedmac; + +// When to forget old senders. +#define FORGET_AFTER_MINUTES 2 + +// array of timestamps for seen notifiers +static std::map cwaSeenNotifiers; + +// Remove notifiers last seen over FORGET_AFTER_MINUTES ago. +void cwa_clear() { + ESP_LOGD(TAG, "CWA: forget old notifier: %d", cwaSeenNotifiers.size()); + + /* + #ifdef SOME_FORM_OF_DEBUG + for (auto const ¬ifier : cwaSeenNotifiers) { + ESP_LOGD(TAG, "CWA forget <%X>", 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(); +} + +// return the total number of devices seen advertising ENS +uint16_t cwa_report(void) { return cwaSeenNotifiers.size(); } + +bool cwa_init(void) { + ESP_LOGD(TAG, "init BLE-scanner for ENS"); + return true; +} + +// similar to mac_add(), found in macsniff.cpp +// for comments pls. look into this function +bool cwa_mac_add(uint8_t *paddr) { + + // are we too early? + if (!hashedmac) + return false; // YES -> return + + bool added = false; + ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", + BT_BD_ADDR_HEX(paddr)); + + ESP_LOGD(TAG, "hashed ENS mac = %X, ENS count = %d (total=%d)", hashedmac, + cwaSeenNotifiers.count(hashedmac), cwaSeenNotifiers.size()); + added = !(cwaSeenNotifiers.count(hashedmac) > 0); + + // Count only if this ENS MAC was not yet seen + if (added) { + ESP_LOGD(TAG, "added device with active ENS"); + } + + cwaSeenNotifiers[hashedmac] = millis(); // last seen at .... + + // True if MAC WiFi/BLE was new + return added; +} + +#endif diff --git a/src/display.cpp b/src/display.cpp index 579956b9..84b21952 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -265,11 +265,10 @@ void dp_drawPage(time_t t, bool nextpage) { else dp_printf("WIFI:off"); if (cfg.blescan) -#if !(COUNT_CWA) +#if (!COUNT_ENS) dp_printf("BLTH:%-5d", macs_ble); #else - dp_printf("BLTH:%-5d", macs_ble); - dp_printf("(CWA:%d)", cwa_report()); + dp_printf(" CWA:%-5d", cwa_report()); #endif else dp_printf(" BLTH:off"); @@ -281,10 +280,10 @@ void dp_drawPage(time_t t, bool nextpage) { #elif ((!WIFICOUNTER) && (BLECOUNTER)) if (cfg.blescan) { dp_printf("BLTH:%-5d", macs_ble); -#if (COUNT_CWA) +#if (COUNT_ENS) dp_printf("(CWA:%d)", cwa_report()); -#endif - } else +#endif + } else dp_printf("BLTH:off"); #else dp_printf("Sniffer disabled"); @@ -357,7 +356,7 @@ void dp_drawPage(time_t t, bool nextpage) { #if (HAS_LORA) - // 3|NtwkID:000000 TXpw:aa + // 3|NetID:000000 PWR:aa // 4|DevAdd:00000000 DR:0 // 5|CHMsk:0000 Nonce:0000 // 6|CUp:000000 CDn:000000 @@ -365,8 +364,7 @@ void dp_drawPage(time_t t, bool nextpage) { dp_setFont(MY_FONT_SMALL); dp_setTextCursor(0, 3); - dp_printf("NetwID:%06X TXpw:%-2d", LMIC.netid & 0x001FFFFF, - LMIC.radio_txpow); + dp_printf("NetID:%06X PWR:%-2d", LMIC.netid & 0x001FFFFF, LMIC.radio_txpow); dp_println(); dp_printf("DevAdd:%08X DR:%1d", LMIC.devaddr, LMIC.datarate); dp_println(); diff --git a/src/macsniff.cpp b/src/macsniff.cpp index 3b6ee5d5..6b1df845 100644 --- a/src/macsniff.cpp +++ b/src/macsniff.cpp @@ -11,8 +11,8 @@ static const char TAG[] = __FILE__; // used here and in corona.cpp -uint16_t salt = -1; -uint16_t hashedmac = -1; // temporary buffer for generated hash value +uint16_t salt = 0; +uint16_t hashedmac = 0; // temporary buffer for generated hash value uint16_t get_salt(void) { salt = (uint16_t)random(65536); // get new 16bit random for salting hashes @@ -52,8 +52,8 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { 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 + int8_t beaconID; // beacon number in test monitor mode + 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. @@ -112,22 +112,22 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { payload.addAlarm(rssi, beaconID); SendPayload(BEACONPORT, prio_high); } - }; + }; } // added // Log scan result - ESP_LOGV(TAG, + ESP_LOGD(TAG, "%s %s RSSI %ddBi -> salted MAC %s -> Hash %04X -> WiFi:%d " "BLTH:%d " -#if (COUNT_CWA) - "(CWA:%d)" -#endif +#if (COUNT_ENS) + "(CWA:%d)" +#endif "-> %d Bytes left", added ? "new " : "known", sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff, - hashedmac, macs_wifi, macs_ble, -#if (COUNT_CWA) + hashedmac, macs_wifi, macs_ble, +#if (COUNT_ENS) cwa_report(), #endif getFreeRAM()); diff --git a/src/main.cpp b/src/main.cpp index ff0fa2cd..0018c53f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -313,7 +313,7 @@ void setup() { // initialize sensors #if (HAS_SENSORS) #if (HAS_SENSOR_1) -#if (COUNT_CWA) +#if (COUNT_ENS) ESP_LOGI(TAG, "init CWA-counter"); if ( cwa_init() ) strcat_P(features, " CWA"); diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 60bfc361..bc235dfa 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -16,7 +16,7 @@ // Set this to include BLE counting and vendor filter functions, or to switch off WIFI counting #define VENDORFILTER 1 // set to 0 if you want to count things, not people -#define BLECOUNTER 0 // set it to 1 if you want to use BLE count, at expense of power & memory +#define BLECOUNTER 1 // set it to 1 if you want to use BLE count, at expense of power & memory #define WIFICOUNTER 1 // set it to 0 if you want to switch off WIFI count // BLE scan parameters @@ -24,11 +24,12 @@ #define BLESCANWINDOW 80 // [milliseconds] scan window, see below, 3 .. 10240, default 80ms #define BLESCANINTERVAL 80 // [illiseconds] scan interval, see below, 3 .. 10240, default 80ms = 100% duty cycle -#define COUNT_CWA 0 // count found copies of the Corona Warn App (CWA) - // set to 0 if you do not want to count these apps +// Corona Exposure Notification Service(ENS) counter +#define COUNT_ENS 1 // count found number of devices which advertise Exposure Notification Service + // set to 0 if you do not want to count these devices // for additional sensors (added by some user) -#define HAS_SENSOR_1 0 // set to 1 if you want to count CWAs +#define HAS_SENSOR_1 1 // set to 1 if you want to count CWAs #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 @@ -82,8 +83,8 @@ #define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds] // settings for syncing time of node with a time source (network / gps / rtc / timeserver) -#define TIME_SYNC_LORAWAN 1 // set to 1 to use LORA network as time source, 0 means off [default = 1] -#define TIME_SYNC_LORASERVER 0 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] +#define TIME_SYNC_LORAWAN 0 // set to 1 to use LORA network as time source, 0 means off [default = 1] +#define TIME_SYNC_LORASERVER 1 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0] #define TIME_SYNC_INTERVAL 60 // sync time attempt each .. minutes from time source [default = 60], 0 means off #define TIME_SYNC_INTERVAL_RETRY 10 // retry time sync after lost sync each .. minutes [default = 10], 0 means off #define TIME_SYNC_SAMPLES 1 // number of time requests for averaging, max. 255 diff --git a/src/sdcard.cpp b/src/sdcard.cpp index 29f65f3a..57fc5b81 100644 --- a/src/sdcard.cpp +++ b/src/sdcard.cpp @@ -56,7 +56,7 @@ void sdcardWriteData(uint16_t noWifi, uint16_t noBle, __attribute__((unused)) ui fileSDCard.print(tempBuffer); sprintf(tempBuffer, "%d,%d", noWifi, noBle); fileSDCard.print(tempBuffer); -#if (COUNT_CWA) +#if (COUNT_ENS) sprintf(tempBuffer, ",%d", noBleCWA); fileSDCard.print(tempBuffer); #endif @@ -102,7 +102,7 @@ void createFile(void) { if (fileSDCard) { ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename); fileSDCard.print(SDCARD_FILE_HEADER); -#if (COUNT_CWA) +#if (COUNT_ENS) fileSDCard.print(SDCARD_FILE_HEADER_CWA); // for Corona-data (CWA) #endif #if (HAS_SDS011) diff --git a/src/senddata.cpp b/src/senddata.cpp index 34e9000b..13b42927 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -58,7 +58,7 @@ void SendPayload(uint8_t port, sendprio_t prio) { #if (HAS_SDCARD) if ( port == COUNTERPORT ) { sdcardWriteData(macs_wifi, macs_ble -#if (COUNT_CWA) +#if (COUNT_ENS) , cwa_report() #endif ); @@ -154,7 +154,7 @@ void sendData() { payload.reset(); payload.addSensor(sensor_read(1)); SendPayload(SENSOR1PORT, prio_normal); -#if (COUNT_CWA) +#if (COUNT_ENS) cwa_clear(); #endif break; diff --git a/src/sensor.cpp b/src/sensor.cpp index 230718ec..baebf9d1 100644 --- a/src/sensor.cpp +++ b/src/sensor.cpp @@ -2,7 +2,7 @@ #include "globals.h" #include "sensor.h" -#if (COUNT_CWA) +#if (COUNT_ENS) #include "payload.h" #include "corona.h" #include "macsniff.h" @@ -55,7 +55,7 @@ uint8_t *sensor_read(uint8_t sensor) { case 1: // insert user specific sensor data frames here */ -#if (COUNT_CWA) +#if (COUNT_ENS) payload.addCount( cwa_report(), MAC_SNIFF_BLE_CWA); #else buf[0] = length;