Merge pull request #66 from cyberman54/master

Push master 1.3.6 to development
This commit is contained in:
Verkehrsrot 2018-06-02 16:32:34 +02:00 committed by GitHub
commit c922bafa2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 346 additions and 333 deletions

View File

@ -1,7 +1,5 @@
# ESP32-Paxcounter # ESP32-Paxcounter
**Wifi & Bluetooth driven, LoRaWAN enabled, battery powered mini Paxcounter built on cheap ESP32 boards** **Wifi & Bluetooth driven, LoRaWAN enabled, battery powered mini Paxcounter built on cheap ESP32 LoRa IoT boards**
---> check branch "development" for latest alpha version <---
<img src="img/Paxcounter-title.jpg"> <img src="img/Paxcounter-title.jpg">
@ -19,12 +17,14 @@ This can all be done with a single small and cheap ESP32 board for less than $20
# Hardware # Hardware
Currently supported IoT boards: Supported ESP32 based LoRa IoT boards:
- Heltec LoRa-32 {1} - Heltec LoRa-32 {1}
- TTGOv1 {1} - TTGOv1 {1}
- TTGOv2 {1}{4} - TTGOv2 {1}{4}
- TTGOv2.1 {1}
- Pycom LoPy {2} - Pycom LoPy {2}
- Pycom LoPy4 {2} - Pycom LoPy4 {2}
- Pycom FiPy {2}
- LoLin32 with [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora) {2}{3} - LoLin32 with [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora) {2}{3}
- LoLin32 Lite with [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora) {2}{3} - LoLin32 Lite with [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora) {2}{3}
@ -36,17 +36,7 @@ Hardware dependent settings (pinout etc.) are stored in board files in /hal dire
<b>3D printable cases</b> can be found (and, if wanted so, ordered) on Thingiverse, see <b>3D printable cases</b> can be found (and, if wanted so, ordered) on Thingiverse, see
<A HREF="https://www.thingiverse.com/thing:2670713">Heltec</A> and <A HREF="https://www.thingiverse.com/thing:2811127">TTGOv2</A>, for example.<br> <A HREF="https://www.thingiverse.com/thing:2670713">Heltec</A> and <A HREF="https://www.thingiverse.com/thing:2811127">TTGOv2</A>, for example.<br>
<b>Power consumption</b>: <b>Power consumption</b> was metered at around 1000mW, depending on board (i.e. has display or not) and user settings in paxcounter.conf. If you are limited on battery, you may want to save around 30% power by disabling bluetooth (commenting out line *#define BLECOUNTER* in paxcounter.conf).
- Heltec ~720mW
- TTGOv1 TBD
- TTGOv2 ~990mW
- LoPy with expansion board: ~690mW
- LoPy pure, without expansion board: TBD
- LoLin32 with [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora): TBD
- LoLin32 Lite with [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora): TBD
These results where metered with software version 1.2.97 while continuously scanning wifi and ble, no LoRa TXing, OLED display (if present) on, 5V USB powered.
# Preparing # Preparing
@ -69,9 +59,9 @@ Use <A HREF="https://platformio.org/">PlatformIO</A> with your preferred IDE for
# Uploading # Uploading
To upload the code to your ESP32 board this needs to be switched from run to bootloader mode. Boards with USB bridge like Heltec and TTGO usually have an onboard logic which allows soft switching by the upload tool. In PlatformIO this happenes automatically.<p> To upload the code to your ESP32 board this needs to be switched from run to bootloader mode. Boards with USB bridge like Heltec and TTGO usually have an onboard logic which allows soft switching by the upload tool. In PlatformIO this happenes automatically.<p>
The LoPy/LoPy4 board needs to be set manually. See these The LoPy/LoPy4/FiPy board needs to be set manually. See these
<A HREF="https://www.thethingsnetwork.org/labs/story/program-your-lopy-from-the-arduino-ide-using-lmic">instructions</A> how to do it. Don't forget to press on board reset button after switching between run and bootloader mode.<p> <A HREF="https://www.thethingsnetwork.org/labs/story/program-your-lopy-from-the-arduino-ide-using-lmic">instructions</A> how to do it. Don't forget to press on board reset button after switching between run and bootloader mode.<p>
The original Pycom firmware is not needed, so there is no need to update it before flashing Paxcounter. Just flash the compiled paxcounter binary (.elf file) on your LoPy/LoPy4. If you later want to go back to the Pycom firmware, download the firmware from Pycom and flash it over. The original Pycom firmware is not needed, so there is no need to update it before flashing Paxcounter. Just flash the compiled paxcounter binary (.elf file) on your LoPy/LoPy4/FiPy. If you later want to go back to the Pycom firmware, download the firmware from Pycom and flash it over.
# Legal note # Legal note
@ -81,7 +71,7 @@ The original Pycom firmware is not needed, so there is no need to update it befo
(e.g. UK citizens may want to check [Data Protection Act 1998](https://ico.org.uk/media/1560691/wi-fi-location-analytics-guidance.pdf) and [GDPR 2018](https://ico.org.uk/for-organisations/guide-to-the-general-data-protection-regulation-gdpr/key-definitions/)) (e.g. UK citizens may want to check [Data Protection Act 1998](https://ico.org.uk/media/1560691/wi-fi-location-analytics-guidance.pdf) and [GDPR 2018](https://ico.org.uk/for-organisations/guide-to-the-general-data-protection-regulation-gdpr/key-definitions/))
(e.g. Citizens in the the Netherlands may want to read [this article](https://www.ivir.nl/publicaties/download/PrivacyInformatie_2016_6.pdf)) (e.g. Citizens in the the Netherlands may want to read [this article](https://www.ivir.nl/publicaties/download/PrivacyInformatie_2016_6.pdf) and [this article](https://autoriteitpersoonsgegevens.nl/nl/nieuws/europese-privacytoezichthouders-publiceren-opinie-eprivacyverordening))
Note: If you use this software you do this at your own risk. That means that you alone - not the authors of this software - are responsible for the legal compliance of an application using this or build from this software and/or usage of a device created using this software. You should take special care and get prior legal advice if you plan metering passengers in public areas and/or publish data drawn from doing so. Note: If you use this software you do this at your own risk. That means that you alone - not the authors of this software - are responsible for the legal compliance of an application using this or build from this software and/or usage of a device created using this software. You should take special care and get prior legal advice if you plan metering passengers in public areas and/or publish data drawn from doing so.
@ -89,6 +79,23 @@ Note: If you use this software you do this at your own risk. That means that you
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. 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.
# LED
Legend for mono color on board LED:
- Single Flash (50ms): seen a new Wifi or BLE device
- Quick blink (20ms on each 1/5 second): joining LoRaWAN network in progress or pending
- Small blink (10ms on each 1/2 second): LoRaWAN data transmit in progress or pending
- Long blink (200ms on each 2 seconds): LoRaWAN stack error
Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only):
- Green each blink: seen a new Wifi device
- Magenta each blink: seen a new BLE device
- Yellow quick blink: joining LoRaWAN network in progress or pending
- Blue blink: LoRaWAN data transmit in progress or pending
- Red long blink: LoRaWAN stack error
# Payload format description # Payload format description
FPort1: FPort1:
@ -144,7 +151,8 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0 = ADR off 0 = ADR off
1 = ADR on [default] 1 = ADR on [default]
note: set ADR to off, if device is moving, set to on, if not. Note: set ADR to off, if device is moving, set to on, if not.
If ADR is set to on, SF value is shown inverted on display.
0x08 do nothing 0x08 do nothing
@ -156,37 +164,37 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
1 = reset MAC counter to zero 1 = reset MAC counter to zero
2 = reset device to factory settings 2 = reset device to factory settings
0x0A set payload send cycle 0x0A set LoRaWAN payload send cycle
0 ... 255 payload send cycle in seconds/2 0 ... 255 payload send cycle in seconds/2
e.g. 120 -> payload is transmitted each 240 seconds [default] e.g. 120 -> payload is transmitted each 240 seconds [default]
0x0B set Wifi channel switch interval timer 0x0B set Wifi channel switch interval timer
0 ... 255 timeout for scanning 1 wifi channel in seconds/100 0 ... 255 duration for scanning a wifi channel in seconds/100
e.g. 50 -> each channel is scanned for 0,5 seconds [default] e.g. 50 -> each channel is scanned for 500 milliseconds [default]
0x0C set BLE scan cycle timer 0x0C set Bluetooth channel switch interval timer
0 ... 255 duration of a BLE scan cycle in seconds 0 ... 255 duration for scanning a bluetooth advertising channel in seconds/100
e.g. 11 -> 1 cycle runs for 11 seconds [default] e.g. 8 -> each channel is scanned for 80 milliseconds [default]
0x0D (NOT YET IMPLEMENTED) set BLE and WIFI vendorfilter mode 0x0D (NOT YET IMPLEMENTED) set BLE and WIFI vendorfilter mode
0 = disabled (use to count devices, not people) 0 = disabled (use to count devices, not people)
1 = enabled [default] 1 = enabled [default]
0x0E set BLE scan mode 0x0E set Bluetooth scanner
0 = disabled 0 = disabled
1 = enabled [default] 1 = enabled [default]
0x0F set WIFI antenna switch (works on LoPy/LoPy4 only) 0x0F set WIFI antenna switch (works on LoPy/LoPy4/FiPy only)
0 = internal antenna [default] 0 = internal antenna [default]
1 = external antenna 1 = external antenna
0x10 set RGB led luminosity (works on LoPy/LoPy4 and LoRaNode32 shield only) 0x10 set RGB led luminosity (works on LoPy/LoPy4/FiPy and LoRaNode32 shield only)
0 ... 100 percentage of luminosity (100% = full light) 0 ... 100 percentage of luminosity (100% = full light)
e.g. 50 -> 50% of luminosity [default] e.g. 50 -> 50% of luminosity [default]
@ -202,10 +210,10 @@ device answers with it's current configuration. The configuration is a C structu
byte 5: Display status (1=on, 0=off) byte 5: Display status (1=on, 0=off)
byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed) byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed)
bytes 7-8: RSSI limiter threshold value (negative) bytes 7-8: RSSI limiter threshold value (negative)
byte 9: Payload send cycle in seconds/2 (0..255) byte 9: Lora Payload send cycle in seconds/2 (0..255)
byte 10: Wifi channel switch interval in seconds/100 (0..255) byte 10: Wifi channel switch interval in seconds/100 (0..255)
byte 11: BLE scan cycle duration in seconds (0..255) byte 11: Bluetooth channel switch interval in seconds/100 (0..255)
byte 12: BLE scan mode (1=on, 0=0ff) byte 12: Bluetooth scanner status (1=on, 0=0ff)
byte 13: Wifi antenna switch (0=internal, 1=external) byte 13: Wifi antenna switch (0=internal, 1=external)
byte 14: Vendorfilter mode (0=disabled, 1=enabled) byte 14: Vendorfilter mode (0=disabled, 1=enabled)
byte 15: RGB LED luminosity (0..100 %) byte 15: RGB LED luminosity (0..100 %)
@ -219,15 +227,6 @@ device answers with it's current configuration. The configuration is a C structu
bytes 1-3: chip temperature in celsius (little endian format) bytes 1-3: chip temperature in celsius (little endian format)
# RGB Led color description
Description of the RGB LED color (LoPy/LoPy4 and Lolin32 only):
- Yellow quick blink: joining LoRaWAN network in progress or pending
- Blue blink: LoRaWAN data transmit (including waiting for receive windows) in progress or pending
- Green each blink: seen a new Wifi device
- Magenta each blink: seen a new BLE device
# License # License
Copyright 2018 Oliver Brandmueller <ob@sysadm.in> Copyright 2018 Oliver Brandmueller <ob@sysadm.in>

View File

@ -11,13 +11,15 @@
; ---> SELECT TARGET PLATFORM HERE! <--- ; ---> SELECT TARGET PLATFORM HERE! <---
[platformio] [platformio]
env_default = heltec_wifi_lora_32 env_default = heltec
;env_default = ttgov1 ;env_default = ttgov1
;env_default = ttgov2 ;env_default = ttgov2
;env_default = ttgov21
;env_default = lopy ;env_default = lopy
;env_default = lopy4 ;env_default = lopy4
;env_default = lolin32lite_lora ;env_default = fipy
;env_default = lolin32_lora ;env_default = lolin32lite
;env_default = lolin32
; ;
description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around. description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around.
@ -40,93 +42,109 @@ build_flags =
-D_lmic_config_h_ -D_lmic_config_h_
-include "src/paxcounter.conf" -include "src/paxcounter.conf"
[env:heltec_wifi_lora_32] [env:heltec]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = heltec_wifi_lora_32 board = heltec_wifi_lora_32
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 115200
lib_deps = lib_deps =
${common_env_data.lib_deps_display} ${common_env_data.lib_deps_display}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dheltec_wifi_lora_32
-include "src/hal/heltec.h" -include "src/hal/heltec.h"
[env:ttgov1] [env:ttgov1]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = esp32dev board = esp32dev
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 115200 upload_speed = 115200
lib_deps = lib_deps =
${common_env_data.lib_deps_display} ${common_env_data.lib_deps_display}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dttgov1
-include "src/hal/ttgov1.h" -include "src/hal/ttgov1.h"
[env:ttgov2] [env:ttgov2]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = esp32dev board = esp32dev
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 921600 upload_speed = 921600
lib_deps = lib_deps =
${common_env_data.lib_deps_display} ${common_env_data.lib_deps_display}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dttgov2
-include "src/hal/ttgov2.h" -include "src/hal/ttgov2.h"
[env:lopy] [env:ttgov21]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = esp32dev board = esp32dev
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 921600
lib_deps =
${common_env_data.lib_deps_display}
build_flags =
${common_env_data.build_flags}
-include "src/hal/ttgov21.h"
[env:fipy]
platform = espressif32@0.12.0
framework = arduino
board = esp32dev
monitor_speed = 115200
upload_speed = 921600
lib_deps =
${common_env_data.lib_deps_rgbled}
build_flags =
${common_env_data.build_flags}
-include "src/hal/fipy.h"
[env:lopy]
platform = espressif32@0.12.0
framework = arduino
board = esp32dev
monitor_speed = 115200
upload_speed = 921600 upload_speed = 921600
lib_deps = lib_deps =
${common_env_data.lib_deps_rgbled} ${common_env_data.lib_deps_rgbled}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dlopy
-include "src/hal/lopy.h" -include "src/hal/lopy.h"
[env:lopy4] [env:lopy4]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = esp32dev board = esp32dev
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 921600 upload_speed = 921600
lib_deps = lib_deps =
${common_env_data.lib_deps_rgbled} ${common_env_data.lib_deps_rgbled}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dlopy4
-include "src/hal/lopy4.h" -include "src/hal/lopy4.h"
[env:lolin32lite_lora] [env:lolin32lite]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = lolin32 board = lolin32
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 256000 upload_speed = 256000
lib_deps = lib_deps =
${common_env_data.lib_deps_rgbled} ${common_env_data.lib_deps_rgbled}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dlolin32lite_lora
-include "src/hal/lolin32lite_lora.h" -include "src/hal/lolin32lite_lora.h"
[env:lolin32_lora] [env:lolin32]
platform = espressif32 platform = espressif32@0.12.0
framework = arduino framework = arduino
board = lolin32 board = lolin32
monitor_baud = 115200 monitor_speed = 115200
upload_speed = 921600 upload_speed = 921600
lib_deps = lib_deps =
${common_env_data.lib_deps_rgbled} ${common_env_data.lib_deps_rgbled}
build_flags = build_flags =
${common_env_data.build_flags} ${common_env_data.build_flags}
-Dlolin32_lora
-include "src/hal/lolin32_lora.h" -include "src/hal/lolin32_lora.h"

View File

@ -5,7 +5,7 @@
#include <Arduino.h> #include <Arduino.h>
// Local logging tag // Local logging tag
static const char *TAG = "antenna"; static const char* TAG = "wifi";
typedef enum { typedef enum {
ANTENNA_INT = 0, ANTENNA_INT = 0,

View File

@ -17,7 +17,7 @@ https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner
#define BT_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] #define BT_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
// local Tag for logging // local Tag for logging
static const char *TAG = "bt_loop"; static const char* TAG = "bluetooth";
// defined in macsniff.cpp // defined in macsniff.cpp
bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type); bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type);
@ -88,35 +88,25 @@ static const char *btsig_gap_type(uint32_t gap_type) {
} }
} // btsig_gap_type } // btsig_gap_type
// using IRAM_:ATTR here to speed up callback function
static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) IRAM_ATTR static 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; esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param;
esp_err_t status;
ESP_LOGD(tag, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv, btsig_gap_type(*p->scan_rst.ble_adv)); ESP_LOGD(TAG, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv, btsig_gap_type(*p->scan_rst.ble_adv));
switch (event) switch (event)
{ {
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
{ // restart scan // restart scan
status = esp_ble_gap_start_scanning(cfg.blescantime); ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME));
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status);
}
}
break; break;
case ESP_GAP_BLE_SCAN_RESULT_EVT: case ESP_GAP_BLE_SCAN_RESULT_EVT:
{ // evaluate scan results
if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done
{ // restart scan { // restart scan
status = esp_ble_gap_start_scanning (cfg.blescantime); ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME));
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_start_scanning: rc=%d", status);
}
return; return;
} }
@ -126,27 +116,22 @@ static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa
ESP_LOGD(TAG, "Addr_type : %s", bt_addr_t_to_string(p->scan_rst.ble_addr_type)); ESP_LOGD(TAG, "Addr_type : %s", bt_addr_t_to_string(p->scan_rst.ble_addr_type));
ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi); ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi);
if (!( cfg.rssilimit == 0 ) || (p->scan_rst.rssi > cfg.rssilimit )) { // rssi is negative value 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); ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi, cfg.rssilimit);
break; break;
} }
#ifdef VENDORFILTER #ifdef VENDORFILTER
if (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) goto skip; if ((p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) || (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM)) {
if (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM) goto skip; ESP_LOGD(TAG, "BT device filtered");
break;
}
#endif #endif
// add this device and show new count total if it was not previously added // add this device and show new count total if it was not previously added
if (cfg.blescan) // count only if BLE scan is enabled
mac_add((uint8_t *) p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); mac_add((uint8_t *) p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
break;
skip:
ESP_LOGD(TAG, "BT device filtered");
break;
/* to be improved in vendorfilter if: /* to be improved in vendorfilter if:
@ -176,9 +161,7 @@ static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa
*/ */
} } // evaluate sniffed packet
}
break; break;
default: default:
@ -187,20 +170,12 @@ static void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa
} // gap_callback_handler } // gap_callback_handler
esp_err_t register_ble_functionality(void) esp_err_t register_ble_callback(void) {
{
esp_err_t status;
ESP_LOGI(TAG, "Register GAP callback"); ESP_LOGI(TAG, "Register GAP callback");
// This function is called to occur gap event, such as scan result. // This function is called to occur gap event, such as scan result.
//register the scan callback function to the gap module //register the scan callback function to the gap module
status = esp_ble_gap_register_callback(gap_callback_handler); ESP_ERROR_CHECK(esp_ble_gap_register_callback(&gap_callback_handler));
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_register_callback: rc=%d", status);
return ESP_FAIL;
}
static esp_ble_scan_params_t ble_scan_params = static esp_ble_scan_params_t ble_scan_params =
{ {
@ -214,85 +189,47 @@ esp_err_t register_ble_functionality(void)
#else #else
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
#endif #endif
.scan_interval = (uint16_t) (BLESCANINTERVAL / 0.625), // Time = N * 0.625 msec
.scan_interval = (uint16_t) (cfg.blescantime * 10 / 0.625), // Time = N * 0.625 msec
.scan_window = (uint16_t) (BLESCANWINDOW / 0.625) // Time = N * 0.625 msec .scan_window = (uint16_t) (BLESCANWINDOW / 0.625) // Time = N * 0.625 msec
}; };
ESP_LOGI(TAG, "Set GAP scan parameters"); ESP_LOGI(TAG, "Set GAP scan parameters");
// This function is called to set scan parameters. // This function is called to set scan parameters.
status = esp_ble_gap_set_scan_params(&ble_scan_params); ESP_ERROR_CHECK(esp_ble_gap_set_scan_params(&ble_scan_params));
if (status != ESP_OK)
{
ESP_LOGE(TAG, "esp_ble_gap_set_scan_params: rc=%d", status);
return ESP_FAIL;
}
return ESP_OK; return ESP_OK;
}
} // register_ble_callback
// Main start code running in its own Xtask void start_BLEscan(void){
void bt_loop(void * pvParameters) ESP_LOGI(TAG, "Initializing bluetooth scanner ...");
{
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
esp_err_t status;
// Initialize BT controller to allocate task and other resource. // Initialize BT controller to allocate task and other resource.
ESP_LOGI(TAG, "Enabling Bluetooth Controller");
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
bt_cfg.controller_task_stack_size = 8192; // double BT stack size bt_cfg.controller_task_stack_size = BLESTACKSIZE; // set BT stack size to value configured in paxcounter.conf
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BTDM));
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) // Init and alloc the resource for bluetooth stack, must be done prior to every bluetooth stuff
{ ESP_ERROR_CHECK(esp_bluedroid_init());
ESP_LOGE(TAG, "Bluetooth controller initialize failed"); ESP_ERROR_CHECK(esp_bluedroid_enable());
goto end;
}
// Enable BT controller // Register callback function for capturing bluetooth packets
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) ESP_ERROR_CHECK(register_ble_callback());
{
ESP_LOGE(TAG, "Bluetooth controller enable failed");
goto end;
}
//esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); // gives 30KB more RAM for heap ESP_LOGI(TAG, "Bluetooth scanner started");
} // start_BLEscan
// Init and alloc the resource for bluetooth, must be prior to every bluetooth stuff void stop_BLEscan(void){
ESP_LOGI(TAG, "Init Bluetooth stack"); ESP_LOGI(TAG, "Shutting down bluetooth scanner ...");
status = esp_bluedroid_init(); ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL));
if (status != ESP_OK) ESP_ERROR_CHECK(esp_bluedroid_disable());
{ ESP_ERROR_CHECK(esp_bluedroid_deinit());
ESP_LOGE(TAG, "%s init bluetooth failed\n", __func__); ESP_ERROR_CHECK(esp_bt_controller_disable());
goto end; ESP_ERROR_CHECK(esp_bt_controller_deinit());
} ESP_LOGI(TAG, "Bluetooth scanner stopped");
} // stop_BLEscan
// Enable bluetooth, must after esp_bluedroid_init()
status = esp_bluedroid_enable();
if (status != ESP_OK)
{
ESP_LOGE(TAG, "%s enable bluetooth failed\n", __func__);
goto end;
}
ESP_LOGI(TAG, "Register BLE functionality");
status = register_ble_functionality();
if (status != ESP_OK)
{
ESP_LOGE(TAG, "Register BLE functionality failed");
goto end;
}
while(1)
{
vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog
}
end:
ESP_LOGI(TAG, "Terminating BT logging task");
vTaskDelete(NULL);
} // bt_loop
#endif // BLECOUNTER #endif // BLECOUNTER

View File

@ -5,7 +5,7 @@
#include <nvs_flash.h> #include <nvs_flash.h>
// Local logging tag // Local logging tag
static const char *TAG = "configmanager"; static const char* TAG = "flash";
nvs_handle my_handle; nvs_handle my_handle;
@ -27,7 +27,7 @@ void defaultConfig() {
cfg.rssilimit = 0; // threshold for rssilimiter, negative value! cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
cfg.sendcycle = SEND_SECS; // payload send cycle [seconds/2] cfg.sendcycle = SEND_SECS; // payload send 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.blescantime = BLESCANTIME; // BLE scan cycle duration [seconds] cfg.blescantime = BLESCANINTERVAL / 10; // BT channel scan cycle duration [seconds/100], default 1 (= 10ms)
cfg.blescan = 1; // 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.vendorfilter = 1; // 0=disabled, 1=enabled cfg.vendorfilter = 1; // 0=disabled, 1=enabled

View File

@ -44,16 +44,10 @@ typedef struct {
} configData_t; } configData_t;
extern configData_t cfg; extern configData_t cfg;
extern uint8_t mydata[];
extern uint64_t uptimecounter; extern uint64_t uptimecounter;
extern osjob_t sendjob; extern osjob_t sendjob;
extern char display_lora[], display_lmic[]; extern char display_lora[], display_lmic[];
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim; extern int countermode, screensaver, adrmode, lorasf, txpower, rlim;
extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters
extern bool joinstate;
extern std::set<uint16_t> macs; extern std::set<uint16_t> macs;
extern hw_timer_t * channelSwitch; // hardware timer used for wifi channel switching extern hw_timer_t * channelSwitch; // hardware timer used for wifi channel switching
#ifdef HAS_DISPLAY
extern HAS_DISPLAY u8x8;
#endif

19
src/hal/fipy.h Normal file
View File

@ -0,0 +1,19 @@
// Hardware related definitions for Pycom FiPy Board
#define CFG_sx1272_radio 1
#define HAS_LED NOT_A_PIN // FiPy has no on board LED, so we use RGB LED
#define HAS_RGB_LED 0 // WS2812B RGB LED on GPIO0
// Hardware pin definitions for Pycom FiPy board
#define PIN_SPI_SS 18
#define PIN_SPI_MOSI 27
#define PIN_SPI_MISO 19
#define PIN_SPI_SCK 5
#define RST LMIC_UNUSED_PIN
#define DIO0 23 // LoRa IRQ
#define DIO1 23 // workaround
#define DIO2 LMIC_UNUSED_PIN
// select WIFI antenna (internal = onboard / external = u.fl socket)
#define HAS_ANTENNA_SWITCH 21 // pin for switching wifi antenna
#define WIFI_ANTENNA 0 // 0 = internal, 1 = external

View File

@ -12,7 +12,7 @@
#define RST 18 #define RST 18
#define DIO0 23 // LoRa IRQ #define DIO0 23 // LoRa IRQ
#define DIO1 23 // workaround #define DIO1 23 // workaround
#define DIO2 LMIC_UNUSED_PIN // 23 workaround #define DIO2 LMIC_UNUSED_PIN
// select WIFI antenna (internal = onboard / external = u.fl socket) // select WIFI antenna (internal = onboard / external = u.fl socket)
#define HAS_ANTENNA_SWITCH 16 // pin for switching wifi antenna #define HAS_ANTENNA_SWITCH 16 // pin for switching wifi antenna

View File

@ -12,7 +12,7 @@
#define RST LMIC_UNUSED_PIN #define RST LMIC_UNUSED_PIN
#define DIO0 23 // LoRa IRQ #define DIO0 23 // LoRa IRQ
#define DIO1 23 // workaround #define DIO1 23 // workaround
#define DIO2 LMIC_UNUSED_PIN // 23 workaround #define DIO2 LMIC_UNUSED_PIN
// select WIFI antenna (internal = onboard / external = u.fl socket) // select WIFI antenna (internal = onboard / external = u.fl socket)
#define HAS_ANTENNA_SWITCH 21 // pin for switching wifi antenna #define HAS_ANTENNA_SWITCH 21 // pin for switching wifi antenna

27
src/hal/ttgov21.h Normal file
View File

@ -0,0 +1,27 @@
// Hardware related definitions for TTGO V2.1 Board
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
#define DISPLAY_FLIP 1 // rotated display
#define HAS_LED 23 // green on board LED_G3 (not in initial board version)
// disable brownout detection (needed on TTGOv2 for battery powered operation)
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
// re-define pin definitions of pins_arduino.h
#define PIN_SPI_SS 18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input
#define PIN_SPI_MOSI 27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
#define PIN_SPI_SCK 5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
// non arduino pin definitions
#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN
#define DIO0 26 // ESP32 GPIO26 <-> HPD13A IO0
#define DIO1 33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1
#define DIO2 32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display
#define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN
#define OLED_SDA 21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2
#define OLED_SCL 22 // ESP32 GPIO15 (Pin15) -- SD1306 D0

View File

@ -1,26 +1,28 @@
/************************************************************ /************************************************************
* LMIC LoRaWAN configuration * LMIC LoRaWAN configuration
* *
* Read the values from TTN console (or whatever applies) * Read the values from TTN console (or whatever applies), insert them here,
* and rename this file to src/loraconf.h
*
* Note that DEVEUI, APPEUI and APPKEY should all be specified in MSB format.
* (This is different from standard LMIC-Arduino which expects DEVEUI and APPEUI in LSB format.)
* Set your DEVEUI here, if you have one. You can leave this untouched,
* then the DEVEUI will be generated during runtime from device's MAC adress
* and will be displayed on device's screen as well as on serial console.
*
* NOTE: Use MSB format (as displayed in TTN console, so you can cut & paste from there)
* For TTN, APPEUI in MSB format always starts with 0x70, 0xB3, 0xD5
*
* Note: If using a board with Microchip 24AA02E64 Uinique ID for deveui,
* the DEVEUI will be overwriten by the one contained in the Microchip module
* *
************************************************************/ ************************************************************/
#include <Arduino.h> #include <Arduino.h>
/*
// Set your DEVEUI here, if you have one. You can leave this untouched,
// then the DEVEUI will be generated during runtime from device's MAC adress
// Note: Use same format as in TTN console (cut & paste, for your convenience)
// *** Take care : If Using a board with Microchip 24AA02E64 Uinique ID for deveui, **
// *** this DEVEUI will be overwriten by the one contained in the Microchip module ***
static const u1_t DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u1_t DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Note: Use msb format for APPEUI as in TTN console (cut & paste, for your convenience)
// For TTN, APPEUI always starts with 0x70, 0xB3, 0xD5
static const u1_t APPEUI[8]={ 0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u1_t APPEUI[8]={ 0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00 };
// Note: Use msb format for APPEUI as in TTN console (cut & paste, for your convenience)
static const u1_t APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u1_t APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
*/

View File

@ -11,7 +11,7 @@
#endif #endif
// Local logging Tag // Local logging Tag
static const char *TAG = "lorawan"; static const char* TAG = "lora";
// functions defined in rcommand.cpp // functions defined in rcommand.cpp
void rcommand(uint8_t cmd, uint8_t arg); void rcommand(uint8_t cmd, uint8_t arg);
@ -79,8 +79,6 @@ void get_hard_deveui(uint8_t *pdeveui) {
// Display a key // Display a key
void printKey(const char * name, const uint8_t * key, uint8_t len, bool lsb) { void printKey(const char * name, const uint8_t * key, uint8_t len, bool lsb) {
uint8_t start=lsb?len:0;
uint8_t end = lsb?0:len;
const uint8_t * p ; const uint8_t * p ;
char keystring[len+1] = "", keybyte[3]; char keystring[len+1] = "", keybyte[3];
for (uint8_t i=0; i<len ; i++) { for (uint8_t i=0; i<len ; i++) {
@ -108,38 +106,43 @@ void printKeys(void) {
#endif // VERBOSE #endif // VERBOSE
void do_send(osjob_t* j){ void do_send(osjob_t* j){
uint8_t mydata[4];
// Sum of unique WIFI MACs seen // Check if there is a pending TX/RX job running
mydata[0] = (macs_wifi & 0xff00) >> 8;
mydata[1] = macs_wifi & 0xff;
#ifdef BLECOUNTER
// Sum of unique BLE MACs seen
mydata[2] = (macs_ble & 0xff00) >> 8;
mydata[3] = macs_ble & 0xff;
#else
mydata[2] = 0;
mydata[3] = 0;
#endif
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) { if (LMIC.opmode & OP_TXRXPEND) {
ESP_LOGI(TAG, "OP_TXRXPEND, not sending"); ESP_LOGI(TAG, "OP_TXRXPEND, not sending");
sprintf(display_lmic, "LORA BUSY"); sprintf(display_lmic, "LORA BUSY");
goto end;
}
// prepare payload with sum of unique WIFI MACs seen
static uint8_t mydata[4];
mydata[0] = (macs_wifi & 0xff00) >> 8;
mydata[1] = macs_wifi & 0xff;
if (cfg.blescan) {
// append sum of unique BLE MACs seen to payload
mydata[2] = (macs_ble & 0xff00) >> 8;
mydata[3] = macs_ble & 0xff;
} else { } else {
mydata[2] = 0;
mydata[3] = 0;
}
// Prepare upstream data transmission at the next possible time. // Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata), (cfg.countermode & 0x02)); LMIC_setTxData2(1, mydata, sizeof(mydata), (cfg.countermode & 0x02));
ESP_LOGI(TAG, "Packet queued"); ESP_LOGI(TAG, "Packet queued");
sprintf(display_lmic, "PACKET QUEUED"); sprintf(display_lmic, "PACKET QUEUED");
// clear counter if not in cumulative counter mode // clear counter if not in cumulative counter mode
if (cfg.countermode != 1) { if (cfg.countermode != 1) {
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes reset_salt(); // get new salt for salting hashes
} ESP_LOGI(TAG, "Counter cleared (countermode = %d)", cfg.countermode);
} }
// Schedule next transmission // Schedule next transmission
end:
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(cfg.sendcycle * 2), do_send); os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(cfg.sendcycle * 2), do_send);
} // do_send() } // do_send()
@ -164,12 +167,13 @@ void onEvent (ev_t ev) {
case EV_JOINED: case EV_JOINED:
joinstate=true;
strcpy_P(buff, PSTR("JOINED")); strcpy_P(buff, PSTR("JOINED"));
sprintf(display_lora, " "); // clear previous lmic status message from display
// Disable link check validation (automatically enabled // Disable link check validation (automatically enabled
// during join, but not supported by TTN at this time). // during join, but not supported by TTN at this time). -> do we need this?
LMIC_setLinkCheckMode(0); LMIC_setLinkCheckMode(0);
// set data rate adaptation // set data rate adaptation
LMIC_setAdrMode(cfg.adrmode); LMIC_setAdrMode(cfg.adrmode);
// Set data rate and transmit power (note: txpower seems to be ignored by the library) // Set data rate and transmit power (note: txpower seems to be ignored by the library)
@ -182,7 +186,7 @@ void onEvent (ev_t ev) {
case EV_TXCOMPLETE: case EV_TXCOMPLETE:
strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") : PSTR("TX COMPLETE")); strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") : PSTR("TX COMPLETE"));
sprintf(display_lora, ""); // erase previous LoRa message from display sprintf(display_lora, " "); // clear previous lmic status message from display
if (LMIC.dataLen) { if (LMIC.dataLen) {
ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4); ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4);

View File

@ -3,13 +3,11 @@
#include "globals.h" #include "globals.h"
#ifdef VENDORFILTER #ifdef VENDORFILTER
#include <array>
#include <algorithm>
#include "vendor_array.h" #include "vendor_array.h"
#endif #endif
// Local logging tag // Local logging tag
static const char *TAG = "macsniff"; static const char* TAG = "wifi";
static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL}; static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL};
@ -102,16 +100,17 @@ void wifi_sniffer_set_channel(uint8_t channel) {
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
} }
void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) { // using IRAM_:ATTR here to speed up callback function
IRAM_ATTR 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_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr; const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
if (( cfg.rssilimit == 0 ) || (ppkt->rx_ctrl.rssi > cfg.rssilimit )) { // rssi is negative value if ((cfg.rssilimit) && (ppkt->rx_ctrl.rssi < cfg.rssilimit )) { // rssi is negative value
ESP_LOGI(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi, cfg.rssilimit);
} else {
uint8_t *p = (uint8_t *) hdr->addr2; uint8_t *p = (uint8_t *) hdr->addr2;
mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI) ; mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI) ;
} else {
ESP_LOGI(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi, cfg.rssilimit);
} }
} }

View File

@ -39,7 +39,7 @@ Refer to LICENSE.txt file in repository for more details.
// Initialize global variables // Initialize global variables
configData_t cfg; // struct holds current device configuration configData_t cfg; // struct holds current device configuration
osjob_t sendjob, initjob; // LMIC jobs osjob_t sendjob; // LMIC job handler
uint64_t uptimecounter = 0; // timer global for uptime counter uint64_t uptimecounter = 0; // timer global for uptime counter
uint8_t DisplayState = 0; // globals for state machine uint8_t DisplayState = 0; // globals for state machine
uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0; // MAC counters globals for display uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0; // MAC counters globals for display
@ -50,8 +50,6 @@ led_states previousLEDState = LED_ON; // This will force LED to be off at boo
unsigned long LEDBlinkStarted = 0; // When (in millis() led blink started) unsigned long LEDBlinkStarted = 0; // When (in millis() led blink started)
uint16_t LEDBlinkDuration = 0; // How long the blink need to be uint16_t LEDBlinkDuration = 0; // How long the blink need to be
uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color
bool joinstate = false; // LoRa network joined? global flag
bool blinkdone = true; // flag for state machine for blinking LED once
hw_timer_t * displaytimer = NULL; // configure hardware timer used for cyclic display refresh hw_timer_t * displaytimer = NULL; // configure hardware timer used for cyclic display refresh
hw_timer_t * channelSwitch = NULL; // configure hardware timer used for wifi channel switching hw_timer_t * channelSwitch = NULL; // configure hardware timer used for wifi channel switching
@ -63,9 +61,7 @@ std::set<uint16_t> macs; // associative container holds total of unique MAC adre
static volatile int ButtonPressed = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0; static volatile int ButtonPressed = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0;
// local Tag for logging // local Tag for logging
static const char *TAG = "paxcnt"; static const char* TAG = "main";
// Note: Log level control seems not working during runtime,
// so we need to switch loglevel by compiler build option in platformio.ini
#ifndef VERBOSE #ifndef VERBOSE
int redirect_log(const char * fmt, va_list args) { int redirect_log(const char * fmt, va_list args) {
@ -128,32 +124,19 @@ const lmic_pinmap lmic_pins = {
.dio = {DIO0, DIO1, DIO2} .dio = {DIO0, DIO1, DIO2}
}; };
// LoRaWAN Initjob
static void lora_init (osjob_t* j) {
// reset MAC state
LMIC_reset();
// This tells LMIC to make the receive windows bigger, in case your clock is 1% faster or slower.
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
// start joining
LMIC_startJoining();
}
// LMIC FreeRTos Task // LMIC FreeRTos 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 uint16_t lorawait = 0; //static uint16_t lorawait = 0;
while(1) { while(1) {
// execute LMIC jobs // execute LMIC jobs
os_runloop_once(); os_runloop_once();
// indicate LMIC state on LEDs if present
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED)
led_loop();
#endif
/* /*
// check if payload is sent // check if payload is sent
while(LMIC.opmode & OP_TXRXPEND) { while(LMIC.opmode & OP_TXRXPEND) {
@ -169,12 +152,13 @@ void lorawan_loop(void * pvParameters) {
vTaskDelay(1000/portTICK_PERIOD_MS); vTaskDelay(1000/portTICK_PERIOD_MS);
} }
*/ */
vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog
} }
} }
/* end LMIC specific parts --------------------------------------------------------------- */
/* end LMIC specific parts --------------------------------------------------------------- */
/* beginn hardware specific parts -------------------------------------------------------- */ /* beginn hardware specific parts -------------------------------------------------------- */
@ -255,8 +239,6 @@ uint64_t uptime() {
// Print a key on display // Print a key on display
void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) { void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) {
uint8_t start=lsb?len:0;
uint8_t end = lsb?0:len;
const uint8_t * p ; const uint8_t * p ;
for (uint8_t i=0; i<len ; i++) { for (uint8_t i=0; i<len ; i++) {
p = lsb ? key+len-i-1 : key+i; p = lsb ? key+len-i-1 : key+i;
@ -327,12 +309,17 @@ uint64_t uptime() {
if (cfg.blescan) if (cfg.blescan)
u8x8.printf("BLTH:%-4d", macs_ble); u8x8.printf("BLTH:%-4d", macs_ble);
else else
u8x8.printf("%-16s", "BLTH:off"); u8x8.printf("%s", "BLTH:off");
#endif #endif
// update LoRa SF display (line 3) // update LoRa SF display (line 3)
u8x8.setCursor(11,3); u8x8.setCursor(11,3);
u8x8.printf("SF:%c%c", lora_datarate[LMIC.datarate * 2], lora_datarate[LMIC.datarate * 2 + 1]); u8x8.printf("SF:");
if (cfg.adrmode) // if ADR=on then display SF value inverse
u8x8.setInverseFont(1);
u8x8.printf("%c%c", lora_datarate[LMIC.datarate * 2], lora_datarate[LMIC.datarate * 2 + 1]);
if (cfg.adrmode) // switch off inverse if it was turned on
u8x8.setInverseFont(0);
// update wifi channel display (line 4) // update wifi channel display (line 4)
u8x8.setCursor(11,4); u8x8.setCursor(11,4);
@ -383,6 +370,7 @@ uint64_t uptime() {
#endif #endif
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) #if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED)
void blink_LED(uint16_t set_color, uint16_t set_blinkduration) { void blink_LED(uint16_t set_color, uint16_t set_blinkduration) {
LEDColor = set_color; // set color for RGB LED LEDColor = set_color; // set color for RGB LED
LEDBlinkDuration = set_blinkduration; // duration LEDBlinkDuration = set_blinkduration; // duration
@ -421,7 +409,7 @@ uint64_t uptime() {
// small blink 10ms on each 1/2sec (not when joining) // small blink 10ms on each 1/2sec (not when joining)
LEDState = ((millis() % 500) < 20) ? LED_ON : LED_OFF; LEDState = ((millis() % 500) < 20) ? LED_ON : LED_OFF;
// This should not happen so indicate a problem // This should not happen so indicate a problem
} else if ( LMIC.opmode & (OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0 ) { } else if ( LMIC.opmode & ((OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0 ) ) {
LEDColor = COLOR_RED; LEDColor = COLOR_RED;
// heartbeat long blink 200ms on each 2 seconds // heartbeat long blink 200ms on each 2 seconds
LEDState = ((millis() % 2000) < 200) ? LED_ON : LED_OFF; LEDState = ((millis() % 2000) < 200) ? LED_ON : LED_OFF;
@ -456,7 +444,6 @@ uint64_t uptime() {
#endif #endif
/* begin Aruino SETUP ------------------------------------------------------------ */ /* begin Aruino SETUP ------------------------------------------------------------ */
void setup() { void setup() {
@ -552,18 +539,19 @@ void setup() {
sprintf(display_lora, "Join wait"); sprintf(display_lora, "Join wait");
// setup Display IRQ, thanks to https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/ // setup display refresh trigger IRQ using esp32 hardware timer 0
// for explanation see https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
timerAttachInterrupt(displaytimer, &DisplayIRQ, true); // interrupt handler DisplayIRQ, triggered by edge timerAttachInterrupt(displaytimer, &DisplayIRQ, true); // interrupt handler DisplayIRQ, triggered by edge
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true); // reload interrupt after each trigger of display refresh cycle timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true); // reload interrupt after each trigger of display refresh cycle
timerAlarmEnable(displaytimer); // enable display interrupt timerAlarmEnable(displaytimer); // enable display interrupt
#endif #endif
// setup channel rotation IRQ, thanks to https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/ // setup channel rotation trigger IRQ using esp32 hardware timer 1
channelSwitch = timerBegin(1, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 1, count up channelSwitch = timerBegin(1, 80, true);
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true); // interrupt handler, triggered by edge timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); // reload interrupt after each trigger of channel switch cycle timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true);
timerAlarmEnable(channelSwitch); // enable channel switching interrupt timerAlarmEnable(channelSwitch);
// show compiled features // show compiled features
ESP_LOGI(TAG, "Features %s", features); ESP_LOGI(TAG, "Features %s", features);
@ -573,45 +561,49 @@ ESP_LOGI(TAG, "Features %s", features);
printKeys(); printKeys();
#endif #endif
os_init(); // setup LMIC // initialize LoRaWAN LMIC run-time environment
LMIC_reset(); // Reset the MAC state. Session and pending data transfers will be discarded. os_init();
os_setCallback(&initjob, lora_init); // setup initial job & join network // reset LMIC MAC state
LMIC_reset();
// This tells LMIC to make the receive windows bigger, in case your clock is 1% faster or slower.
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
wifi_sniffer_init(); // setup wifi in monitor mode and start MAC counting // start lmic runloop in rtos task on core 1 (note: arduino main loop runs on core 1, too)
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
// initialize salt value using esp_random() called by random() in arduino-esp32 core
// note: do this *after* wifi has started, since gets it's seed from RF noise
reset_salt(); // get new 16bit for salting hashes
// run wifi task on core 0 and lora task on core 1 and bt task on core 0
ESP_LOGI(TAG, "Starting Lora task on core 1"); ESP_LOGI(TAG, "Starting Lora task on core 1");
xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, ( void * ) 1, ( 5 | portPRIVILEGE_BIT ), NULL, 1); xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, ( void * ) 1, ( 5 | portPRIVILEGE_BIT ), NULL, 1);
// start wifi in monitor mode and start channel rotation task on core 0
ESP_LOGI(TAG, "Starting Wifi task on core 0"); ESP_LOGI(TAG, "Starting Wifi task on core 0");
wifi_sniffer_init();
// initialize salt value using esp_random() called by random() in arduino-esp32 core
// note: do this *after* wifi has started, since function gets it's seed from RF noise
reset_salt(); // get new 16bit for salting hashes
xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 2048, ( void * ) 1, 1, NULL, 0); xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 2048, ( void * ) 1, 1, NULL, 0);
// start BLE scan callback if BLE function is enabled in NVRAM configuration
#ifdef BLECOUNTER #ifdef BLECOUNTER
if (cfg.blescan) { // start BLE task only if BLE function is enabled in NVRAM configuration if (cfg.blescan) {
ESP_LOGI(TAG, "Starting Bluetooth task on core 0"); start_BLEscan();
xTaskCreatePinnedToCore(bt_loop, "btscan", 4096, ( void * ) 1, 1, NULL, 0);
} }
#endif #endif
// Finally: kickoff first sendjob and join, then send initial payload "0000" // kickoff sendjob -> joins network and rescedules sendjob for cyclic transmitting payload
uint8_t mydata[] = "0000";
do_send(&sendjob); do_send(&sendjob);
} }
/* end Aruino SETUP ------------------------------------------------------------ */ /* end Arduino SETUP ------------------------------------------------------------ */
/* begin Arduino main loop ------------------------------------------------------ */
/* begin Aruino LOOP ------------------------------------------------------------ */
// Arduino main moop, runs on core 1
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
void loop() { void loop() {
// simple state machine for controlling display, LED, button, etc. while (1) {
// simple state machine for controlling uptime, display, LED, button, memory.
uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit) uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit)
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) #if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED)
@ -627,7 +619,9 @@ void loop() {
#endif #endif
// check free memory // check free memory
if (ESP.getFreeHeap() <= MEM_LOW) { if (esp_get_minimum_free_heap_size() <= MEM_LOW) {
ESP_LOGI(TAG, "Memory full, counter cleared (heap low water mark = %d Bytes / free heap = %d bytes)", \
esp_get_minimum_free_heap_size(), ESP.getFreeHeap());
do_send(&sendjob); // send count do_send(&sendjob); // send count
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes reset_salt(); // get new salt for salting hashes
@ -635,6 +629,7 @@ void loop() {
vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(10/portTICK_PERIOD_MS); // reset watchdog
} // end of infinite main loop
} }
/* end Aruino LOOP ------------------------------------------------------------ */ /* end Arduino main loop ------------------------------------------------------------ */

View File

@ -1,6 +1,6 @@
// program version - note: increment version after modifications to configData_t struct!! // program version - note: increment version after modifications to configData_t struct!!
#define PROGVERSION "1.3.4" // use max 10 chars here! #define PROGVERSION "1.3.6" // use max 10 chars here!
#define PROGNAME "PAXCNT" #define PROGNAME "PAXCNT"
//--- Declarations --- //--- Declarations ---
@ -41,4 +41,7 @@ void wifi_sniffer_set_channel(uint8_t channel);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
// defined in blescan.cpp // defined in blescan.cpp
void bt_loop(void *ignore); #ifdef BLECOUNTER
void start_BLEscan(void);
void stop_BLEscan(void);
#endif

View File

@ -7,23 +7,25 @@
// set this to include BLE counting and vendor filter functions // set this to include BLE counting and vendor filter functions
#define VENDORFILTER 1 // comment out if you want to count things, not people #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 BLECOUNTER 1 // comment out if you don't want BLE count, saves power & memory
// BLE scan parameters // BLE scan parameters
#define BLESCANTIME 11 // [seconds] scan duration, see note below #define BLESTACKSIZE 8192 // stack size for esp_bt_controller
#define BLESCANWINDOW 10 // [milliseconds] scan window, see below, 3 .. 10240, default 10 #define BLESCANTIME 0 // [seconds] scan duration, 0 means infinite [default], see note below
#define BLESCANINTERVAL 10 // [milliseconds] how long to wait between scans, 3 .. 10240, default 10 #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
/* Note: guide for setting bluetooth parameters /* Note: guide for setting bluetooth parameters
* *
* |< Scan Window > |< Scan Window > |< Scan Window > | * |< Scan Window > |< Scan Window > | ... |< Scan Window > |
* |< Scan Interval >|< Scan Interval >|< Scan Interval >| * |< Scan Interval >|< Scan Interval >| ... |< Scan Interval >|
* |< Scan duration >| * |< Scan duration >|
* *
* Scan duration sets how long scanning should be going on, interrupting a wifi scan cycle. * Scan duration sets how long scanning should be going on, before starting a new scan cycle. 0 means infinite (default).
* Scan window sets how much of the interval should be occupied by scanning. * Scan window sets how much of the interval should be occupied by scanning. Should be >= BLESCANINTERVAL.
* Scan interval is how long scanning should be done on each channel. BLE uses 3 channels for advertising. * Scan interval is how long scanning should be done on each channel. BLE uses 3 channels for advertising.
* -> Adjust these values with power consumption in mind if power is limited. * -> Adjust these values with power consumption in mind if power is limited.
* -> Scan interval can be changed during runtime by remote comammand.
*/ */
// WiFi scan parameters // WiFi scan parameters

View File

@ -10,7 +10,7 @@
#include <hal/hal.h> #include <hal/hal.h>
// Local logging tag // Local logging tag
static const char *TAG = "rcommand"; static const char* TAG = "main";
// table of remote commands and assigned functions // table of remote commands and assigned functions
typedef struct { typedef struct {
@ -91,7 +91,15 @@ void set_wifichancycle(uint8_t val) {
void set_blescantime(uint8_t val) { void set_blescantime(uint8_t val) {
cfg.blescantime = val; cfg.blescantime = val;
ESP_LOGI(TAG, "Remote command: set BLE scan time to %d seconds", cfg.blescantime); ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds", cfg.blescantime/float(100));
#ifdef BLECOUNTER
// stop & restart BLE scan task to apply new parameter
if (cfg.blescan)
{
stop_BLEscan();
start_BLEscan();
}
#endif
}; };
void set_countmode(uint8_t val) { void set_countmode(uint8_t val) {
@ -142,14 +150,20 @@ void set_loraadr(uint8_t val) {
}; };
void set_blescan(uint8_t val) { void set_blescan(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set BLE scan mode to %s", val ? "on" : "off"); ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val ? "on" : "off");
switch (val) { switch (val) {
case 0: case 0:
cfg.blescan = 0; cfg.blescan = 0;
macs_ble = 0; // clear BLE counter macs_ble = 0; // clear BLE counter
#ifdef BLECOUNTER
stop_BLEscan();
#endif
break; break;
default: default:
cfg.blescan = 1; cfg.blescan = 1;
#ifdef BLECOUNTER
start_BLEscan();
#endif
break; break;
} }
}; };