Merge pull request #47 from cyberman54/development

v1.3.2
This commit is contained in:
Verkehrsrot 2018-04-20 12:06:27 +02:00 committed by GitHub
commit 413b5f324e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 440 additions and 420 deletions

View File

@ -48,11 +48,13 @@ Hardware dependent settings (pinout etc.) are stored in board files in /hal dire
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.
# Building
# Preparing
Use <A HREF="https://platformio.org/">PlatformIO</A> with your preferred IDE for development and building this code.
Before compiling the code,
Before compiling the code, **create file loraconf.h in your local /src directory** using the template [loraconf.sample.h](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/loraconf.sample.h) and populate it with your personal APPEUI und APPKEY for the LoRaWAN network. If you're using popular <A HREF="https://thethingsnetwork.org">TheThingsNetwork</A> you can copy&paste the keys from TTN console or output of ttnctl.
- **edit paxcounter.conf** and taylor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use.
- **create file loraconf.h in your local /src directory** using the template [loraconf.sample.h](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/loraconf.sample.h) and populate it with your personal APPEUI und APPKEY for the LoRaWAN network. If you're using popular <A HREF="https://thethingsnetwork.org">TheThingsNetwork</A> you can copy&paste the keys from TTN console or output of ttnctl.
To join the network only method OTAA is supported, not ABP. The DEVEUI for OTAA will be derived from the device's MAC adress during device startup and is shown as well on the device's display (if it has one) as on the serial console for copying it to your LoRaWAN network server settings.
@ -60,6 +62,10 @@ If your device has a fixed DEVEUI enter this in your local loraconf.h file. Duri
If your device has silicon **Unique ID** which is stored in serial EEPROM Microchip 24AA02E64 you don't need to change anything. The Unique ID will be read during startup and DEVEUI will be generated from it, overriding settings in loraconf.h.
# Building
Use <A HREF="https://platformio.org/">PlatformIO</A> with your preferred IDE for development and building this code.
# 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>

View File

@ -31,14 +31,14 @@ build_flags =
; ---> NOTE: For production run set DEBUG_LEVEL level to NONE! <---
; otherwise device may crash in dense environments due to serial buffer overflow
;
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
;
; override lora settings from LMiC library in lmic/config.h and use main.h instead
-D_lmic_config_h_
-include "src/main.h"
-include "src/paxcounter.conf"
[env:heltec_wifi_lora_32]
platform = espressif32

View File

@ -233,8 +233,10 @@ esp_err_t register_ble_functionality(void)
// Main start code running in its own Xtask
void bt_loop(void *ignore)
void bt_loop(void * pvParameters)
{
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
esp_err_t status;
// Initialize BT controller to allocate task and other resource.

View File

@ -18,7 +18,7 @@ esp_err_t err;
// populate cfg vars with factory settings
void defaultConfig() {
cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in main.h
cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in paxcounter.conf
cfg.txpower = 15; // 2-15, lora tx power
cfg.adrmode = 1; // 0=disabled, 1=enabled
cfg.screensaver = 0; // 0=disabled, 1=enabled

View File

@ -3,8 +3,8 @@
// std::set for unified array functions
#include <set>
#include <array>
#include <algorithm>
//#include <array>
//#include <algorithm>
#ifdef HAS_DISPLAY
// OLED Display
@ -22,6 +22,7 @@
#include "rgb_led.h"
#include "macsniff.h"
#include "main.h"
// Struct holding devices's runtime configuration
typedef struct {
@ -45,18 +46,14 @@ typedef struct {
extern configData_t cfg;
extern uint8_t mydata[];
extern uint64_t uptimecounter;
extern uint32_t currentMillis ;
extern osjob_t sendjob;
extern char display_lora[], display_lmic[];
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim;
extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters
extern bool joinstate;
extern std::set<uint16_t> wifis;
extern std::set<uint16_t> macs;
#ifdef HAS_DISPLAY
extern HAS_DISPLAY u8x8;
#endif
#ifdef BLECOUNTER
extern int scanTime;
extern std::set<uint16_t> bles;
#endif

View File

@ -13,9 +13,6 @@
// Local logging Tag
static const char *TAG = "lorawan";
// function defined in main.cpp
void set_onboard_led(int state);
// functions defined in rcommand.cpp
void rcommand(int cmd, int arg);
void switch_lora(int sf, int tx);
@ -114,15 +111,13 @@ void do_send(osjob_t* j){
uint8_t mydata[4];
uint16_t data;
// Sum of unique WIFI MACs seen
data = (uint16_t) wifis.size();
mydata[0] = (data & 0xff00) >> 8;
mydata[1] = data & 0xff;
mydata[0] = (macs_wifi & 0xff00) >> 8;
mydata[1] = macs_wifi & 0xff;
#ifdef BLECOUNTER
// Sum of unique BLE MACs seen
data = (uint16_t) bles.size();
mydata[2] = (data & 0xff00) >> 8;
mydata[3] = data & 0xff;
mydata[2] = (macs_ble & 0xff00) >> 8;
mydata[3] = macs_ble & 0xff;
#else
mydata[2] = 0;
mydata[3] = 0;
@ -131,8 +126,8 @@ void do_send(osjob_t* j){
// Total BLE+WIFI unique MACs seen
// TBD ?
//data = (uint16_t) macs.size();
//mydata[4] = (data & 0xff00) >> 8;
//mydata[5] = data & 0xff;
//mydata[4] = (macs_total & 0xff00) >> 8;
//mydata[5] = macs_total & 0xff;
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
@ -167,7 +162,7 @@ void onEvent (ev_t ev) {
case EV_JOINED:
strcpy_P(buff, PSTR("JOINED"));
sprintf(display_lora, " "); // erase "Join Wait" message from display
sprintf(display_lora, ""); // erase "Join Wait" message from display
// Disable link check validation (automatically enabled
// during join, but not supported by TTN at this time).
LMIC_setLinkCheckMode(0);

View File

@ -13,10 +13,11 @@ static const char *TAG = "macsniff";
static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL};
// globals
uint16_t salt;
uint16_t salt_reset(void) {
salt = random(65536); // get new 16bit random for salting hashes
uint16_t reset_salt(void) {
salt = random(65536); // get new 16bit random for salting hashes and set global salt var
return salt;
}
@ -24,57 +25,49 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
char buff[16]; // temporary buffer for printf
bool added = false;
uint32_t addr2int;
uint32_t vendor2int;
uint16_t hashedmac;
uint32_t addr2int, vendor2int; // temporary buffer for MAC and Vendor OUI
uint16_t hashedmac; // temporary buffer for generated hash value
// only last 3 MAC Address bytes are used for MAC Address Anonymization
// 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
addr2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[3] << 8 ) | ( (uint32_t)paddr[4] << 16 ) | ( (uint32_t)paddr[5] << 24 );
#ifdef VENDORFILTER
vendor2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[1] << 8 ) | ( (uint32_t)paddr[0] << 16 );
// use OUI vendor filter list only on Wifi, not on BLE
if ( (sniff_type==MAC_SNIFF_BLE) || std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) {
if ( (sniff_type==MAC_SNIFF_BLE) || std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() )
{
#endif
// salt and hash MAC, and if new unique one, store identifier in container and increment counter on display
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization
addr2int += (uint32_t) salt; // add 16-bit salt to pseudo MAC
addr2int += (uint32_t)salt; // add 16-bit salt to pseudo MAC
snprintf(buff, sizeof(buff), "%08X", addr2int); // convert unsigned 32-bit salted MAC to 8 digit hex string
hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars to fit hash in uint16_t container
auto newmac = macs.insert(hashedmac); // add hashed MAC to total container if new unique
added = newmac.second ? true:false; // true if hashed MAC is unique in container
// Insert only if it was not found on global count
// Count only if MAC was not yet seen
if (added) {
if (sniff_type == MAC_SNIFF_WIFI ) {
rgb_set_color(COLOR_GREEN);
wifis.insert(hashedmac); // add hashed MAC to wifi container
macs_wifi++; // increment Wifi MACs counter
if (joinstate)
blink_LED(COLOR_GREEN, 50, 0);
}
#ifdef BLECOUNTER
else if (sniff_type == MAC_SNIFF_BLE ) {
rgb_set_color(COLOR_MAGENTA);
bles.insert(hashedmac); // add hashed MAC to BLE container
macs_ble++; // increment BLE Macs counter
if (joinstate)
blink_LED(COLOR_MAGENTA, 50, 0);
}
#endif
// Not sure user will have time to see the LED
// TBD do light off further in the code
rgb_set_color(COLOR_NONE);
}
// Log scan result
ESP_LOGI(TAG, "%s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d %s",
sniff_type==MAC_SNIFF_WIFI ? "WiFi":"BLTH",
rssi, buff, hashedmac,
(int) wifis.size(),
#ifdef BLECOUNTER
(int) bles.size(),
#else
0,
#endif
rssi, buff, hashedmac, macs_wifi, macs_ble,
added ? "new" : "known");
#ifdef VENDORFILTER

View File

@ -19,7 +19,7 @@ typedef struct {
uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */
} wifi_ieee80211_packet_t;
uint16_t salt_reset(void);
uint16_t reset_salt(void);
void wifi_sniffer_init(void);
void wifi_sniffer_set_channel(uint8_t channel);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);

View File

@ -24,9 +24,6 @@ Refer to LICENSE.txt file in repository for more details.
// Basic Config
#include "globals.h"
// std::set for unified array functions
#include <set>
// Does nothing and avoid any compilation error with I2C
#include <Wire.h>
@ -35,28 +32,26 @@ Refer to LICENSE.txt file in repository for more details.
#include <lmic.h>
#include <hal/hal.h>
// ESP32 Functions
// ESP32 lib Functions
#include <esp_event_loop.h> // needed for Wifi event handler
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
#include <esp32-hal-log.h> // needed for ESP_LOGx on arduino framework
configData_t cfg; // struct holds current device configuration
osjob_t sendjob, initjob; // LMIC
// Initialize global variables
char display_lora[16], display_lmic[16];
uint8_t channel = 0;
int macnum = 0;
uint64_t uptimecounter = 0;
bool joinstate = false;
configData_t cfg; // struct holds current device configuration
osjob_t sendjob, initjob; // LMIC jobs
uint64_t uptimecounter = 0; // timer global for uptime counter
uint32_t currentMillis = millis(); // timer global for state machine
uint32_t previousDisplaymillis = currentMillis; // Display refresh for state machine
uint8_t DisplayState = 0; // globals for state machine
uint16_t LEDBlinkduration = 0, LEDInterval = 0, color = COLOR_NONE; // state machine variables
uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0; // MAC counters globals for display
uint8_t channel = 0; // wifi channel rotation counter global for display
char display_lora[16], display_lmic[16]; // display buffers
enum states LEDState = LED_OFF, previousLEDState = LED_OFF; // LED state global for state machine
bool joinstate = false; // LoRa network joined? global flag
std::set<uint16_t> macs; // associative container holds total of unique MAC adress hashes (Wifi + BLE)
std::set<uint16_t> wifis; // associative container holds unique Wifi MAC adress hashes
#ifdef BLECOUNTER
std::set<uint16_t> bles; // associative container holds unique BLE MAC adresses hashes
int scanTime;
#endif
// this variable will be changed in the ISR, and read in main loop
static volatile bool ButtonTriggered = false;
@ -65,6 +60,7 @@ static volatile bool ButtonTriggered = false;
static const char *TAG = "paxcnt";
// Note: Log level control seems not working during runtime,
// so we need to switch loglevel by compiler build option in platformio.ini
#ifndef VERBOSE
int redirect_log(const char * fmt, va_list args) {
//do nothing
@ -72,22 +68,22 @@ int redirect_log(const char * fmt, va_list args) {
}
#endif
// defined in configmanager.cpp
void eraseConfig(void);
void saveConfig(void);
void loadConfig(void);
void blink_LED (uint16_t set_color, uint16_t set_blinkduration, uint16_t set_interval) {
color = set_color; // set color for RGB LED
LEDBlinkduration = set_blinkduration; // duration on
LEDInterval = set_interval; // duration off - on - off
LEDState = LED_ON; // start blink
}
#ifdef HAS_LED
void set_onboard_led(int st);
#endif
void reset_counters() {
macs.clear(); // clear all macs container
macs_total = 0; // reset all counters
macs_wifi = 0;
macs_ble = 0;
}
/* begin LMIC specific parts ------------------------------------------------------------ */
// defined in lorawan.cpp
void gen_lora_deveui(uint8_t * pdeveui);
void RevBytes(unsigned char* b, size_t c);
void get_hard_deveui(uint8_t *pdeveui);
#ifdef VERBOSE
void printKeys(void);
@ -133,10 +129,6 @@ const lmic_pinmap lmic_pins = {
.dio = {DIO0, DIO1, DIO2}
};
// LMIC functions
void onEvent(ev_t ev);
void do_send(osjob_t* j);
// LoRaWAN Initjob
static void lora_init (osjob_t* j) {
// reset MAC state
@ -149,48 +141,28 @@ static void lora_init (osjob_t* j) {
// LMIC FreeRTos Task
void lorawan_loop(void * pvParameters) {
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
static bool led_state;
bool new_led_state;
while(1) {
uint16_t color;
os_runloop_once();
// All follow is Led management
// Let join at the begining of if sequence,
// is prior to send because joining state send data
// LED indicators for viusalizing LoRaWAN state
if ( LMIC.opmode & (OP_JOINING | OP_REJOIN) ) {
color = COLOR_YELLOW;
// quick blink 20ms on each 1/5 second
new_led_state = ((millis() % 200) < 20) ? HIGH : LOW;
// 5 quick blinks 20ms on each 1/5 second while joining
blink_LED(COLOR_YELLOW, 20, 200);
// TX data pending
} else if (LMIC.opmode & (OP_TXDATA | OP_TXRXPEND)) {
color = COLOR_BLUE;
// small blink 10ms on each 1/2sec (not when joining)
new_led_state = ((millis() % 500) < 20) ? HIGH : LOW;
// 3 small blink 10ms on each 1/2sec (not when joining)
blink_LED(COLOR_BLUE, 10, 500);
// This should not happen so indicate a problem
} else if ( LMIC.opmode & (OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0 ) {
color = COLOR_RED;
// heartbeat long blink 200ms on each 2 seconds
new_led_state = ((millis() % 2000) < 200) ? HIGH : LOW;
// 5 heartbeat long blink 200ms on each 2 seconds
blink_LED(COLOR_RED, 200, 2000);
} else {
// led off
rgb_set_color(COLOR_NONE);
}
// led need to change state? avoid digitalWrite() for nothing
if (led_state != new_led_state) {
if (new_led_state == HIGH) {
set_onboard_led(1);
rgb_set_color(color);
} else {
set_onboard_led(0);
rgb_set_color(COLOR_NONE);
}
led_state = new_led_state;
blink_LED(COLOR_NONE, 0, 0);
}
vTaskDelay(10/portTICK_PERIOD_MS);
@ -218,21 +190,6 @@ void lorawan_loop(void * pvParameters) {
bool btstop = btStop();
#endif
void set_onboard_led(int st){
#ifdef HAS_LED
switch (st) {
#ifdef LED_ACTIVE_LOW
case 1: digitalWrite(HAS_LED, LOW); break;
case 0: digitalWrite(HAS_LED, HIGH); break;
#else
case 1: digitalWrite(HAS_LED, HIGH); break;
case 0: digitalWrite(HAS_LED, LOW); break;
#endif
}
#endif
};
#ifdef HAS_BUTTON
// Button Handling, board dependent -> perhaps to be moved to hal/<$board.h>
// IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855
@ -245,47 +202,32 @@ void set_onboard_led(int st){
/* begin wifi specific parts ---------------------------------------------------------- */
// defined in wifisniffer.cpp
void wifi_sniffer_init(void);
void wifi_sniffer_set_channel(uint8_t channel);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
// defined in blescan.cpp
void bt_loop(void *ignore);
// Sniffer Task
void sniffer_loop(void * pvParameters) {
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
channel=0;
char buff[16];
int nloop=0, lorawait=0;
while (true) {
while (1) {
nloop++; // actual number of wifi loops, controls cycle when data is sent
vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS);
yield();
channel = (channel % WIFI_CHANNEL_MAX) + 1; // rotates variable channel 1..WIFI_CHANNEL_MAX
wifi_sniffer_set_channel(channel);
ESP_LOGD(TAG, "Wifi set channel %d", channel);
// duration of one wifi scan loop reached? then send data and begin new scan cycle
if ( nloop >= ( (100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) +1 ) {
nloop=0; channel=0; // reset wifi scan + channel loop counter
do_send(&sendjob); // Prepare and execute LoRaWAN data upload
vTaskDelay(500/portTICK_PERIOD_MS);
yield();
// clear counter if not in cumulative counter mode
if (cfg.countermode != 1) {
macs.clear(); // clear all macs container
wifis.clear(); // clear Wifi macs couner
#ifdef BLECOUNTER
bles.clear(); // clear BLE macs counter
#endif
salt_reset(); // get new salt for salting hashes
reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes
}
// check if payload is sent
@ -302,19 +244,13 @@ void sniffer_loop(void * pvParameters) {
vTaskDelay(1000/portTICK_PERIOD_MS);
yield();
}
sprintf(display_lora, " "); // clear LoRa wait message fromd display
/*
// TBD: need to check if long 2000ms pause causes stack problems while scanning continues
if (cfg.screenon && cfg.screensaver) {
vTaskDelay(2000/portTICK_PERIOD_MS); // pause for displaying results
yield();
u8x8.setPowerSave(1 && cfg.screensaver); // set display off if screensaver is enabled
}
*/
sprintf(display_lora, ""); // clear LoRa wait message fromd display
} // end of send data cycle
vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS);
yield();
} // end of infinite wifi channel rotation loop
}
@ -330,8 +266,9 @@ uint64_t uptime() {
}
#ifdef HAS_DISPLAY
// Print a key on display
void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) {
// Print a key on display
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 ;
@ -340,9 +277,9 @@ void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) {
u8x8.printf("%02X", *p);
}
u8x8.printf("\n");
}
}
void init_display(const char *Productname, const char *Version) {
void init_display(const char *Productname, const char *Version) {
uint8_t buf[32];
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
@ -389,9 +326,101 @@ void init_display(const char *Productname, const char *Version) {
DisplayKey(buf, 8, true);
delay(5000);
u8x8.clear();
}
}
void refreshDisplay() {
// update counter display (lines 0-4)
char buff[16];
snprintf(buff, sizeof(buff), "PAX:%-4d", (int) macs.size()); // convert 16-bit MAC counter to decimal counter value
u8x8.draw2x2String(0, 0, buff); // display number on unique macs total Wifi + BLE
u8x8.setCursor(0,4);
u8x8.printf("WIFI:%-4d", macs_wifi);
#ifdef BLECOUNTER
u8x8.setCursor(0,3);
if (cfg.blescan)
u8x8.printf("BLTH:%-4d", macs_ble);
else
u8x8.printf("%-16s", "BLTH:off");
#endif
// update RSSI limiter status & wifi channel display (line 5)
u8x8.setCursor(0,5);
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
u8x8.setCursor(11,5);
u8x8.printf("ch:%02i", channel);
// update LoRa status display (line 6)
u8x8.setCursor(0,6);
u8x8.printf("%-16s", display_lora);
// update LMiC event display (line 7)
u8x8.setCursor(0,7);
u8x8.printf("%-16s", display_lmic);
}
void updateDisplay() {
// timed display refresh according to refresh cycle setting
if (currentMillis - previousDisplaymillis >= DISPLAYREFRESH_MS) {
refreshDisplay();
previousDisplaymillis += DISPLAYREFRESH_MS;
}
// set display on/off according to current device configuration
if (DisplayState != cfg.screenon) {
DisplayState = cfg.screenon;
u8x8.setPowerSave(!cfg.screenon);
}
} // updateDisplay()
#endif // HAS_DISPLAY
#ifdef HAS_BUTTON
void readButton() {
if (ButtonTriggered) {
ButtonTriggered = false;
ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults");
eraseConfig();
esp_restart();
}
}
#endif
#ifdef HAS_LED
void switchLED() {
// led need to change state? avoid digitalWrite() for nothing
if (LEDState != previousLEDState) {
#ifdef LED_ACTIVE_LOW
digitalWrite(HAS_LED, !LEDState);
#else
digitalWrite(HAS_LED, LEDState);
#endif
#ifdef HAS_RGB_LED
rgb_set_color(LEDState ? color : COLOR_NONE);
#endif
previousLEDState = LEDState;
}
}; // switchLED()
void switchLEDstate() {
// LEDInterval != 0 -> LED is currently blinking -> toggle if interval cycle time elapsed
// LEDInterval = 0 -> do one blink then turn off LED
if (LEDInterval) // LED is blinking, wait until time elapsed, then toggle
LEDState = ((currentMillis % LEDInterval) < LEDBlinkduration) ? LED_ON : LED_OFF;
else // only one blink
LEDState = (currentMillis < LEDBlinkduration) ? LED_ON : LED_OFF;
} // switchLEDstate()
#endif
/* begin Aruino SETUP ------------------------------------------------------------ */
void setup() {
@ -413,7 +442,6 @@ void setup() {
#endif
ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION);
rgb_set_color(COLOR_NONE);
// initialize system event handler for wifi task, needed for wifi_sniffer_init()
esp_event_loop_init(NULL, NULL);
@ -437,7 +465,7 @@ void setup() {
// initialize led if needed
#ifdef HAS_LED
pinMode(HAS_LED, OUTPUT);
digitalWrite(HAS_LED, LOW);
blink_LED(COLOR_NONE, 0, 0); // LED off
#endif
// initialize button handling if needed
@ -461,16 +489,17 @@ void setup() {
#ifdef HAS_DISPLAY
// initialize display
init_display(PROGNAME, PROGVERSION);
DisplayState = cfg.screenon;
u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
u8x8.draw2x2String(0, 0, "PAX:0");
u8x8.setCursor(0,4);
u8x8.printf("WIFI: 0");
u8x8.printf("WIFI:0");
#ifdef BLECOUNTER
u8x8.setCursor(0,3);
u8x8.printf("BLTH: 0");
u8x8.printf("BLTH:0");
#endif
u8x8.setCursor(0,5);
u8x8.printf(!cfg.rssilimit ? "RLIM: off" : "RLIM: %d", cfg.rssilimit);
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit);
sprintf(display_lora, "Join wait");
#endif
@ -485,17 +514,19 @@ wifi_sniffer_init(); // setup wifi in monitor mode and start MAC counting
// 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
salt_reset(); // get new 16bit for salting hashes
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");
xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, ( void * ) 1, ( 5 | portPRIVILEGE_BIT ), NULL, 1);
ESP_LOGI(TAG, "Starting Wifi task on core 0");
xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 16384, ( void * ) 1, 1, NULL, 0);
#ifdef BLECOUNTER
if (cfg.blescan) { // start BLE task only if BLE function is enabled in NVRAM configuration
ESP_LOGI(TAG, "Starting Bluetooth task on core 0");
xTaskCreatePinnedToCore(bt_loop, "btscan", 16384, NULL, 5, NULL, 0);
xTaskCreatePinnedToCore(bt_loop, "btscan", 16384, ( void * ) 1, 1, NULL, 0);
}
#endif
@ -513,56 +544,24 @@ do_send(&sendjob);
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
void loop() {
uptimecounter = uptime() / 1000; // count uptime seconds
// simple state machine for controlling display, LED, button, etc.
uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit)
currentMillis = millis(); // timebase for state machine in milliseconds (32bit)
#ifdef HAS_LED
switchLEDstate();
switchLED();
#endif
#ifdef HAS_BUTTON
readButton();
#endif
#ifdef HAS_DISPLAY
updateDisplay();
#endif
#ifdef HAS_BUTTON // ...then check if pressed
if (ButtonTriggered) {
ButtonTriggered = false;
ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults");
eraseConfig();
esp_restart();
}
#endif
#ifdef HAS_DISPLAY // ...then update mask
// set display on/off according to current device configuration
u8x8.setPowerSave(!cfg.screenon);
// update counter display (lines 0-4)
char buff[16];
snprintf(buff, sizeof(buff), "PAX:%-4d", (int) macs.size()); // convert 16-bit MAC counter to decimal counter value
u8x8.draw2x2String(0, 0, buff); // display number on unique macs total Wifi + BLE
u8x8.setCursor(0,4);
u8x8.printf("WIFI: %-4d", (int) wifis.size());
#ifdef BLECOUNTER
u8x8.setCursor(0,3);
if (cfg.blescan)
u8x8.printf("BLTH: %-4d", (int) bles.size());
else
u8x8.printf("%-16s", "BLTH: off");
#endif
// update wifi channel display (line 4)
u8x8.setCursor(11,4);
u8x8.printf("ch:%02i", channel);
// update RSSI limiter status display (line 5)
u8x8.setCursor(0,5);
u8x8.printf(!cfg.rssilimit ? "RLIM: off" : "RLIM: %-4d", cfg.rssilimit);
// update LoRa status display (line 6)
u8x8.setCursor(0,6);
u8x8.printf("%-16s", display_lora);
// update LMiC event display (line 7)
u8x8.setCursor(0,7);
u8x8.printf("%-16s", display_lmic);
#endif
vTaskDelay(1000/DISPLAYFPS/portTICK_PERIOD_MS);
}
/* end Aruino LOOP ------------------------------------------------------------ */

View File

@ -1,131 +1,40 @@
#pragma once
// program version - note: increment version after modifications to configData_t struct!!
#define PROGVERSION "1.3.01" // use max 10 chars here!
#define PROGVERSION "1.3.2" // use max 10 chars here!
#define PROGNAME "PAXCNT"
// Verbose enables serial output
#define VERBOSE 1 // comment out to silence the device, for mute use build option
//--- Declarations ---
// set this to include BLE counting and vendor filter functions
#define VENDORFILTER 1 // comment out if you want to count things, not people
#define BLECOUNTER 1 // comment out if you don't want BLE count
enum states {
LED_OFF,
LED_ON
};
// BLE scan parameters
#define BLESCANTIME 11 // [seconds] scan duration, see note below
#define BLESCANWINDOW 10 // [milliseconds] scan window, see below, 3 .. 10240, default 10
#define BLESCANINTERVAL 10 // [milliseconds] how long to wait between scans, 3 .. 10240, default 10
//--- Prototypes ---
/* Note: guide for setting bluetooth parameters
*
* |< Scan Window > |< Scan Window > |< Scan Window > |
* |< Scan Interval >|< Scan Interval >|< Scan Interval >|
* |< Scan duration >|
*
* Scan duration sets how long scanning should be going on, interrupting a wifi scan cycle.
* Scan window sets how much of the interval should be occupied by scanning.
* 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.
*/
// defined in main.cpp
void blink_LED (uint16_t set_color, uint16_t set_blinkduration, uint16_t set_interval);
void reset_counters();
// WiFi scan parameters
#define WIFI_CHANNEL_MIN 1 // start channel number where scan begings
#define WIFI_CHANNEL_MAX 13 // total channel number to scan
#define WIFI_MY_COUNTRY "EU" // select locale for Wifi RF settings
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
// defined in configmanager.cpp
void eraseConfig(void);
void saveConfig(void);
void loadConfig(void);
// LoRa payload send cycle
#define SEND_SECS 120 // [seconds/2] -> 240 sec.
//#define SEND_SECS 30 // [seconds/2] -> 60 sec.
// defined in lorawan.cpp
void onEvent(ev_t ev);
void do_send(osjob_t* j);
void gen_lora_deveui(uint8_t * pdeveui);
void RevBytes(unsigned char* b, size_t c);
void get_hard_deveui(uint8_t *pdeveui);
// Default LoRa Spreadfactor
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
// defined in wifisniffer.cpp
void wifi_sniffer_init(void);
void wifi_sniffer_set_channel(uint8_t channel);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
// Default RGB LED luminosity (in %)
#define RGBLUMINOSITY 30 // 30%
// defined in blescan.cpp
void bt_loop(void *ignore);
// OLED Display refresh cycle (in Milliseconds)
#define DISPLAYFPS 5 // [fps] -> 5 Frames per second ps = 200ms refreseh cycle
// LMIC settings
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored
// define hardware specifics settings in platformio.ini as build_flag for hardware environment
// Select frequency band here according to national regulations
#define CFG_eu868 1
//#define CFG_us915 1
// This is the SX1272/SX1273 radio, which is also used on the HopeRF
// RFM92 boards.
//#define CFG_sx1272_radio 1
// This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on
// the HopeRF RFM95 boards.
//#define CFG_sx1276_radio 1
// 16 μs per tick
// LMIC requires ticks to be 15.5μs - 100 μs long
#define US_PER_OSTICK_EXPONENT 4
#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT)
#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK)
// Set this to 1 to enable some basic debug output (using printf) about
// RF settings used during transmission and reception. Set to 2 to
// enable more verbose output. Make sure that printf is actually
// configured (e.g. on AVR it is not by default), otherwise using it can
// cause crashing.
//#define LMIC_DEBUG_LEVEL 1
// Enable this to allow using printf() to print to the given serial port
// (or any other Print object). This can be easy for debugging. The
// current implementation only works on AVR, though.
//#define LMIC_PRINTF_TO Serial
// Any runtime assertion failures are printed to this serial port (or
// any other Print object). If this is unset, any failures just silently
// halt execution.
#define LMIC_FAILURE_TO Serial
// Uncomment this to disable all code related to joining
//#define DISABLE_JOIN
// Uncomment this to disable all code related to ping
#define DISABLE_PING
// Uncomment this to disable all code related to beacon tracking.
// Requires ping to be disabled too
#define DISABLE_BEACONS
// Uncomment these to disable the corresponding MAC commands.
// Class A
//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap
//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param
//#define DISABLE_MCMD_SNCH_REQ // set new channel
// Class B
//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING
//#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON
// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the
// same on RX. This ensures that gateways can talk to nodes and vice
// versa, but gateways will not hear other gateways and nodes will not
// hear other nodes. By uncommenting this macro, this inversion is
// disabled and this node can hear other nodes. If two nodes both have
// this macro set, they can talk to each other (but they can no longer
// hear gateways). This should probably only be used when debugging
// and/or when talking to the radio directly (e.g. like in the "raw"
// example).
//#define DISABLE_INVERT_IQ_ON_RX
// This allows choosing between multiple included AES implementations.
// Make sure exactly one of these is uncommented.
//
// This selects the original AES implementation included LMIC. This
// implementation is optimized for speed on 32-bit processors using
// fairly big lookup tables, but it takes up big amounts of flash on the
// AVR architecture.
#define USE_ORIGINAL_AES
//
// This selects the AES implementation written by Ideetroon for their
// own LoRaWAN library. It also uses lookup tables, but smaller
// byte-oriented ones, making it use a lot less flash space (but it is
// also about twice as slow as the original).
// #define USE_IDEETRON_AES
// defined in main.cpp
void reset_counters(void);

129
src/paxcounter.conf Normal file
View File

@ -0,0 +1,129 @@
// ----- Paxcounter user config file ------
//
// --> adapt to your needs and use case <--
// Verbose enables serial output
#define VERBOSE 1 // comment out to silence the device, for mute use build option
// set this to include BLE counting and vendor filter functions
#define VENDORFILTER 1 // comment out if you want to count things, not people
#define BLECOUNTER 1 // comment out if you don't want BLE count
// BLE scan parameters
#define BLESCANTIME 11 // [seconds] scan duration, see note below
#define BLESCANWINDOW 10 // [milliseconds] scan window, see below, 3 .. 10240, default 10
#define BLESCANINTERVAL 10 // [milliseconds] how long to wait between scans, 3 .. 10240, default 10
/* Note: guide for setting bluetooth parameters
*
* |< Scan Window > |< Scan Window > |< Scan Window > |
* |< Scan Interval >|< Scan Interval >|< Scan Interval >|
* |< Scan duration >|
*
* Scan duration sets how long scanning should be going on, interrupting a wifi scan cycle.
* Scan window sets how much of the interval should be occupied by scanning.
* 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.
*/
// WiFi scan parameters
#define WIFI_CHANNEL_MIN 1 // start channel number where scan begings
#define WIFI_CHANNEL_MAX 13 // total channel number to scan
#define WIFI_MY_COUNTRY "EU" // select locale for Wifi RF settings
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
// LoRa payload send cycle
//#define SEND_SECS 120 // [seconds/2] -> 240 sec.
#define SEND_SECS 30 // [seconds/2] -> 60 sec.
// Default LoRa Spreadfactor
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
// Default RGB LED luminosity (in %)
#define RGBLUMINOSITY 30 // 30%
// OLED Display refresh cycle (in Milliseconds)
#define DISPLAYREFRESH_MS 40 // e.g. 40ms -> 1000/40 = 25 frames per second
// LMIC settings
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored
// define hardware specifics settings in platformio.ini as build_flag for hardware environment
// Select frequency band here according to national regulations
#define CFG_eu868 1
//#define CFG_us915 1
// This is the SX1272/SX1273 radio, which is also used on the HopeRF
// RFM92 boards.
//#define CFG_sx1272_radio 1
// This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on
// the HopeRF RFM95 boards.
//#define CFG_sx1276_radio 1
// 16 μs per tick
// LMIC requires ticks to be 15.5μs - 100 μs long
#define US_PER_OSTICK_EXPONENT 4
#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT)
#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK)
// Set this to 1 to enable some basic debug output (using printf) about
// RF settings used during transmission and reception. Set to 2 to
// enable more verbose output. Make sure that printf is actually
// configured (e.g. on AVR it is not by default), otherwise using it can
// cause crashing.
//#define LMIC_DEBUG_LEVEL 1
// Enable this to allow using printf() to print to the given serial port
// (or any other Print object). This can be easy for debugging. The
// current implementation only works on AVR, though.
//#define LMIC_PRINTF_TO Serial
// Any runtime assertion failures are printed to this serial port (or
// any other Print object). If this is unset, any failures just silently
// halt execution.
#define LMIC_FAILURE_TO Serial
// Uncomment this to disable all code related to joining
//#define DISABLE_JOIN
// Uncomment this to disable all code related to ping
#define DISABLE_PING
// Uncomment this to disable all code related to beacon tracking.
// Requires ping to be disabled too
#define DISABLE_BEACONS
// Uncomment these to disable the corresponding MAC commands.
// Class A
//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap
//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param
//#define DISABLE_MCMD_SNCH_REQ // set new channel
// Class B
//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING
//#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON
// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the
// same on RX. This ensures that gateways can talk to nodes and vice
// versa, but gateways will not hear other gateways and nodes will not
// hear other nodes. By uncommenting this macro, this inversion is
// disabled and this node can hear other nodes. If two nodes both have
// this macro set, they can talk to each other (but they can no longer
// hear gateways). This should probably only be used when debugging
// and/or when talking to the radio directly (e.g. like in the "raw"
// example).
//#define DISABLE_INVERT_IQ_ON_RX
// This allows choosing between multiple included AES implementations.
// Make sure exactly one of these is uncommented.
//
// This selects the original AES implementation included LMIC. This
// implementation is optimized for speed on 32-bit processors using
// fairly big lookup tables, but it takes up big amounts of flash on the
// AVR architecture.
#define USE_ORIGINAL_AES
//
// This selects the AES implementation written by Ideetroon for their
// own LoRaWAN library. It also uses lookup tables, but smaller
// byte-oriented ones, making it use a lot less flash space (but it is
// also about twice as slow as the original).
// #define USE_IDEETRON_AES

View File

@ -19,10 +19,6 @@ typedef struct {
const bool store;
} cmd_t;
// functions defined in configmanager.cpp
void eraseConfig(void);
void saveConfig(void);
// function defined in antenna.cpp
#ifdef HAS_ANTENNA_SWITCH
void antenna_select(const int8_t _ant);
@ -64,12 +60,8 @@ void set_reset(int val) {
break;
case 1: // reset MAC counter
ESP_LOGI(TAG, "Remote command: reset MAC counter");
macs.clear(); // clear all macs container
wifis.clear(); // clear Wifi macs container
#ifdef BLECOUNTER
bles.clear(); // clear BLE macs container
#endif
salt_reset(); // get new 16bit salt
reset_counters(); // clear macs
reset_salt(); // get new salt
sprintf(display_lora, "Reset counter");
break;
case 2: // reset device to factory settings
@ -152,9 +144,7 @@ void set_blescan(int val) {
switch (val) {
case 0:
cfg.blescan = 0;
#ifdef BLECOUNTER
bles.clear(); // clear BLE macs container
#endif
macs_ble = 0; // clear BLE counter
break;
default:
cfg.blescan = 1;
@ -212,7 +202,7 @@ void get_uptime (int val) {
ESP_LOGI(TAG, "Remote command: get uptime");
int size = sizeof(uptimecounter);
unsigned char *sendData = new unsigned char[size];
memcpy(sendData, (unsigned char*)&uptimecounter, size);
memcpy(sendData, (unsigned char*)&uptimecounter , size);
LMIC_setTxData2(RCMDPORT, sendData, size-1, 0); // send data unconfirmed on RCMD Port
delete sendData; // free memory
ESP_LOGI(TAG, "%i bytes queued in send queue", size-1);