Merge pull request #696 from cyberman54/development

Development
This commit is contained in:
Verkehrsrot 2020-12-29 00:33:23 +01:00 committed by GitHub
commit 6279589cda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 73 additions and 176 deletions

View File

@ -10,6 +10,7 @@
#include "display.h" #include "display.h"
#include "sds011read.h" #include "sds011read.h"
#include "sdcard.h" #include "sdcard.h"
#include "macsniff.h"
extern Ticker cyclicTimer; extern Ticker cyclicTimer;

View File

@ -2,7 +2,7 @@
#define _HASH_H #define _HASH_H
#include <Arduino.h> #include <Arduino.h>
#include <inttypes.h> #include <RokkitHash.h>
uint32_t IRAM_ATTR hash(const char *data, int len); uint32_t IRAM_ATTR hash(const char *data, int len);

View File

@ -14,7 +14,7 @@
#include "corona.h" #include "corona.h"
#endif #endif
uint16_t get_salt(void); uint32_t renew_salt(void);
uint64_t macConvert(uint8_t *paddr); uint64_t macConvert(uint8_t *paddr);
esp_err_t macQueueInit(void); esp_err_t macQueueInit(void);
void mac_process(void *pvParameters); void mac_process(void *pvParameters);

View File

@ -6,16 +6,6 @@
#include <MQTT.h> #include <MQTT.h>
#include <ETH.h> #include <ETH.h>
#define MQTT_ETHERNET 0 // select PHY: set 0 for Wifi, 1 for ethernet
#define MQTT_INTOPIC "paxin"
#define MQTT_OUTTOPIC "paxout"
#define MQTT_PORT 1883
#define MQTT_SERVER "paxcounter.cloud.shiftr.io"
#define MQTT_USER "public"
#define MQTT_PASSWD "public"
#define MQTT_RETRYSEC 20 // retry reconnect every 20 seconds
#define MQTT_KEEPALIVE 10 // keep alive interval in seconds
#ifndef MQTT_CLIENTNAME #ifndef MQTT_CLIENTNAME
#define MQTT_CLIENTNAME clientId #define MQTT_CLIENTNAME clientId
#endif #endif

View File

@ -79,6 +79,7 @@ lib_deps_sensors =
boschsensortec/BSEC Software Library @ 1.6.1480 boschsensortec/BSEC Software Library @ 1.6.1480
https://github.com/ricki-z/SDS011.git https://github.com/ricki-z/SDS011.git
lib_deps_basic = lib_deps_basic =
https://github.com/SukkoPera/Arduino-Rokkit-Hash.git
bblanchon/ArduinoJson @ ^6 bblanchon/ArduinoJson @ ^6
jchristensen/Timezone @ ^1.2.4 jchristensen/Timezone @ ^1.2.4
makuna/RTC @ ^2.3.5 makuna/RTC @ ^2.3.5

View File

@ -46,10 +46,10 @@ Adafruit_BMP085 bmp; // I2C
void setBMEIRQ() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); } void setBMEIRQ() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); }
// initialize MEMS sensor // initialize MEMS sensor
// return = 0 -> error / return = 1 -> success
int bme_init(void) { int bme_init(void) {
// return = 0 -> error / return = 1 -> success int rc = 0;
int rc = 1;
#ifdef HAS_BME680 #ifdef HAS_BME680
// block i2c bus access // block i2c bus access
@ -63,76 +63,33 @@ int bme_init(void) {
iaqSensor.version.minor_bugfix); iaqSensor.version.minor_bugfix);
iaqSensor.setConfig(bsec_config_iaq); iaqSensor.setConfig(bsec_config_iaq);
if (checkIaqSensorStatus())
ESP_LOGI(TAG, "BME680 sensor found and initialized");
else {
ESP_LOGE(TAG, "BME680 sensor not found");
rc = 0;
goto finish;
}
loadState(); loadState();
iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET);
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
if (checkIaqSensorStatus()) rc = checkIaqSensorStatus();
ESP_LOGI(TAG, "BSEC subscription succesful");
else { } else
ESP_LOGE(TAG, "BSEC subscription error");
rc = 0;
goto finish;
}
} else {
ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error"); ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error");
rc = 0;
goto finish;
}
#elif defined HAS_BME280 #elif defined HAS_BME280
bool status;
// block i2c bus access
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
rc = bme.begin(BME280_ADDR);
status = bme.begin(BME280_ADDR); } else
if (!status) {
ESP_LOGE(TAG, "BME280 sensor not found");
rc = 0;
goto finish;
}
ESP_LOGI(TAG, "BME280 sensor found and initialized");
} else {
ESP_LOGE(TAG, "I2c bus busy - BME280 initialization error"); ESP_LOGE(TAG, "I2c bus busy - BME280 initialization error");
rc = 0;
goto finish;
}
#elif defined HAS_BMP180 #elif defined HAS_BMP180
bool status;
// block i2c bus access
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
// Wire.begin(21, 22); // Wire.begin(21, 22);
status = bmp.begin(); rc = bmp.begin();
if (!status) { } else
ESP_LOGE(TAG, "BMP180 sensor not found");
rc = 0;
goto finish;
}
ESP_LOGI(TAG, "BMP180 sensor found and initialized");
} else {
ESP_LOGE(TAG, "I2c bus busy - BMP180 initialization error"); ESP_LOGE(TAG, "I2c bus busy - BMP180 initialization error");
rc = 0;
goto finish;
}
#endif #endif
finish:
I2C_MUTEX_UNLOCK(); // release i2c bus access I2C_MUTEX_UNLOCK(); // release i2c bus access
if (rc) if (rc)
bmecycler.attach(BMECYCLE, setBMEIRQ); bmecycler.attach(BMECYCLE, setBMEIRQ); // start cyclic data transmit
return rc; return rc;
} // bme_init() } // bme_init()

View File

@ -97,7 +97,6 @@ void doHousekeeping() {
"free heap = %d bytes)", "free heap = %d bytes)",
ESP.getMinFreeHeap(), ESP.getFreeHeap()); ESP.getMinFreeHeap(), ESP.getFreeHeap());
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
get_salt(); // get new salt for salting hashes
if (ESP.getMinFreeHeap() <= MEM_LOW) // check again if (ESP.getMinFreeHeap() <= MEM_LOW) // check again
do_reset(true); // memory leak, reset device do_reset(true); // memory leak, reset device
@ -108,7 +107,6 @@ void doHousekeeping() {
if (ESP.getMinFreePsram() <= MEM_LOW) { if (ESP.getMinFreePsram() <= MEM_LOW) {
ESP_LOGI(TAG, "PSRAM full, counter cleared"); ESP_LOGI(TAG, "PSRAM full, counter cleared");
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
get_salt(); // get new salt for salting hashes
if (ESP.getMinFreePsram() <= MEM_LOW) // check again if (ESP.getMinFreePsram() <= MEM_LOW) // check again
do_reset(true); // memory leak, reset device do_reset(true); // memory leak, reset device
@ -140,6 +138,7 @@ void reset_counters() {
macs.clear(); // clear all macs container macs.clear(); // clear all macs container
macs_wifi = 0; macs_wifi = 0;
macs_ble = 0; macs_ble = 0;
renew_salt(); // get new salt
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
dp_plotCurve(0, true); dp_plotCurve(0, true);
#endif #endif

View File

@ -36,55 +36,9 @@
#include "hash.h" #include "hash.h"
uint32_t IRAM_ATTR rokkit(const char *data, int len) { #ifdef ROKKIT_ENABLE_8BIT_OPTIMIZATIONS
uint32_t hash, tmp; #undef ROKKIT_ENABLE_8BIT_OPTIMIZATIONS
int rem; #endif
if (len <= 0 || data == 0)
return 0;
hash = len;
rem = len & 3;
len >>= 2;
/* Main loop */
while (len > 0) {
hash += *((uint16_t *)data);
tmp = (*((uint16_t *)(data + 2)) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2 * 2;
hash += hash >> 11;
len--;
}
/* Handle end cases */
switch (rem) {
case 3:
hash += *((uint16_t *)data);
hash ^= hash << 16;
hash ^= ((signed char)data[2]) << 18;
hash += hash >> 11;
break;
case 2:
hash += *((uint16_t *)data);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1:
hash += (signed char)*data;
hash ^= hash << 10;
hash += hash >> 1;
}
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}
uint32_t IRAM_ATTR hash(const char *data, int len) { uint32_t IRAM_ATTR hash(const char *data, int len) {
return rokkit(data, len); return rokkit(data, len);

View File

@ -284,14 +284,10 @@ esp_err_t lmic_init(void) {
// Pass OTA parameters to LMIC_setSession // Pass OTA parameters to LMIC_setSession
#else #else
// load saved session from RTC, if we have one // load saved session from RTC, if we have one
if (RTC_runmode == RUNMODE_WAKEUP) { if (RTC_runmode == RUNMODE_WAKEUP)
LoadLMICFromRTC(); LoadLMICFromRTC();
} if (!LMIC_startJoining())
// otherwise start join procedure if not already joined ESP_LOGI(TAG, "Already joined");
else {
if (!LMIC_startJoining())
ESP_LOGI(TAG, "Already joined");
}
#endif #endif
// start lmic loop task // start lmic loop task

View File

@ -9,10 +9,11 @@ static const char TAG[] = __FILE__;
QueueHandle_t MacQueue; QueueHandle_t MacQueue;
TaskHandle_t macProcessTask; TaskHandle_t macProcessTask;
uint16_t salt = 0; static uint32_t salt = renew_salt();
uint16_t get_salt(void) { uint32_t renew_salt(void) {
salt = (uint16_t)random(65536); // get new 16bit random for salting hashes salt = esp_random();
ESP_LOGV(TAG, "new salt = %04X", salt);
return salt; return salt;
} }
@ -101,9 +102,6 @@ void IRAM_ATTR mac_add(uint8_t *paddr, int8_t rssi, snifftype_t sniff_type) {
uint16_t mac_analyze(MacBuffer_t MacBuffer) { uint16_t mac_analyze(MacBuffer_t MacBuffer) {
if (salt == 0) // ensure we have salt (appears after radio is turned on)
return 0;
if ((cfg.rssilimit) && if ((cfg.rssilimit) &&
(MacBuffer.rssi < cfg.rssilimit)) { // rssi is negative value (MacBuffer.rssi < cfg.rssilimit)) { // rssi is negative value
ESP_LOGI(TAG, "%s RSSI %d -> ignoring (limit: %d)", ESP_LOGI(TAG, "%s RSSI %d -> ignoring (limit: %d)",
@ -126,8 +124,7 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
} }
}; };
char buff[10]; // temporary buffer for printf uint32_t *mac; // pointer to shortened 4 byte MAC
uint32_t *mac; // temporary buffer for shortened MAC
// 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. // but since it's uint32 we take 4 bytes to avoid 1st value to be 0.
@ -138,11 +135,15 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
// and increment counter on display // and increment counter on display
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization // https://en.wikipedia.org/wiki/MAC_Address_Anonymization
snprintf(buff, sizeof(buff), "%08X", // reversed 4 byte MAC added to current salt
*mac + (uint32_t)salt); // convert unsigned 32-bit salted MAC const uint32_t saltedmac = *mac + salt;
// to 8 digit hex string
uint16_t hashedmac = hash(&buff[3], 5); // hash MAC 8 digit -> 5 digit // hashed 4 byte MAC
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique // to save RAM, we use only lower 2 bytes of hash, since collisions don't
// matter in our use case
const uint16_t hashedmac = hash((const char *)&saltedmac, 4);
auto newmac = macs.insert(hashedmac); // add hashed MAC, if new unique
bool added = bool added =
newmac.second ? true : false; // true if hashed MAC is unique in container newmac.second ? true : false; // true if hashed MAC is unique in container
@ -183,7 +184,8 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
// Log scan result // Log scan result
ESP_LOGV(TAG, ESP_LOGV(TAG,
"%s %s RSSI %ddBi -> salted MAC %s -> Hash %04X -> WiFi:%d " "%s %s RSSI %ddBi -> MAC %0x:%0x:%0x:%0x:%0x:%0x -> salted %04X"
" -> hashed %04X -> WiFi:%d "
"BLTH:%d " "BLTH:%d "
#if (COUNT_ENS) #if (COUNT_ENS)
"(CWA:%d)" "(CWA:%d)"
@ -191,7 +193,9 @@ uint16_t mac_analyze(MacBuffer_t MacBuffer) {
"-> %d Bytes left", "-> %d Bytes left",
added ? "new " : "known", added ? "new " : "known",
MacBuffer.sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", MacBuffer.sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH",
MacBuffer.rssi, buff, hashedmac, macs_wifi, macs_ble, MacBuffer.rssi, MacBuffer.mac[0], MacBuffer.mac[1], MacBuffer.mac[2],
MacBuffer.mac[3], MacBuffer.mac[4], MacBuffer.mac[5], saltedmac,
hashedmac, macs_wifi, macs_ble,
#if (COUNT_ENS) #if (COUNT_ENS)
cwa_report(), cwa_report(),
#endif #endif

View File

@ -428,7 +428,7 @@ void setup() {
// initialize salt value using esp_random() called by random() in // initialize salt value using esp_random() called by random() in
// arduino-esp32 core. Note: do this *after* wifi has started, since // arduino-esp32 core. Note: do this *after* wifi has started, since
// function gets it's seed from RF noise // function gets it's seed from RF noise
get_salt(); // get new 16bit for salting hashes reset_counters();
// start state machine // start state machine
ESP_LOGI(TAG, "Starting Interrupt Handler..."); ESP_LOGI(TAG, "Starting Interrupt Handler...");
@ -451,8 +451,10 @@ void setup() {
#endif #endif
if (bme_init()) if (bme_init())
ESP_LOGI(TAG, "BME sensor initialized"); ESP_LOGI(TAG, "BME sensor initialized");
else else {
ESP_LOGE(TAG, "BME sensor could not be initialized"); ESP_LOGE(TAG, "BME sensor could not be initialized");
cfg.payloadmask &= ~MEMS_DATA; // switch off transmit of BME data
}
#endif #endif
// starting timers and interrupts // starting timers and interrupts

View File

@ -41,9 +41,13 @@ esp_err_t mqtt_init(void) {
int mqtt_connect(const char *my_host, const uint16_t my_port) { int mqtt_connect(const char *my_host, const uint16_t my_port) {
IPAddress mqtt_server_ip; IPAddress mqtt_server_ip;
const uint16_t hashed = hash(&ETH.macAddress()[0], 4); // hash MAC to 4 digits uint8_t mac[6];
char clientId[16]; char clientId[20];
snprintf(clientId, 16, "paxcounter_%d", hashed);
// hash 6 byte MAC to 4 byte hash
esp_eth_get_mac(mac);
const uint32_t hashedmac = hash((const char *)mac, 6);
snprintf(clientId, 20, "paxcounter_%08x", hashedmac);
ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME); ESP_LOGI(TAG, "MQTT name is %s", MQTT_CLIENTNAME);

View File

@ -121,3 +121,15 @@
#define CAYENNE_DEVICECONFIG 11 // device period configuration #define CAYENNE_DEVICECONFIG 11 // device period configuration
#define CAYENNE_SENSORREAD 13 // sensor period configuration #define CAYENNE_SENSORREAD 13 // sensor period configuration
#define CAYENNE_SENSORENABLE 14 // sensor enable configuration #define CAYENNE_SENSORENABLE 14 // sensor enable configuration
// MQTT settings, only needed if MQTT is used (#define HAS_MQTT in board hal file)
#define MQTT_ETHERNET 0 // select PHY: set 0 for Wifi, 1 for ethernet
#define MQTT_INTOPIC "paxin"
#define MQTT_OUTTOPIC "paxout"
#define MQTT_PORT 1883
#define MQTT_SERVER "public.cloud.shiftr.io"
#define MQTT_USER "public"
#define MQTT_PASSWD "public"
#define MQTT_RETRYSEC 20 // retry reconnect every 20 seconds
#define MQTT_KEEPALIVE 10 // keep alive interval in seconds
//#define MQTT_CLIENTNAME "my_paxcounter" // generated by default

View File

@ -18,7 +18,6 @@ void set_reset(uint8_t val[]) {
case 1: // reset MAC counter case 1: // reset MAC counter
ESP_LOGI(TAG, "Remote command: reset MAC counter"); ESP_LOGI(TAG, "Remote command: reset MAC counter");
reset_counters(); // clear macs reset_counters(); // clear macs
get_salt(); // get new salt
break; break;
case 2: // reset device to factory settings case 2: // reset device to factory settings
ESP_LOGI(TAG, "Remote command: reset device to factory settings"); ESP_LOGI(TAG, "Remote command: reset device to factory settings");
@ -119,7 +118,6 @@ void set_countmode(uint8_t val[]) {
return; return;
} }
reset_counters(); // clear macs reset_counters(); // clear macs
get_salt(); // get new salt
} }
void set_screensaver(uint8_t val[]) { void set_screensaver(uint8_t val[]) {

View File

@ -84,24 +84,15 @@ void do_after_reset(void) {
void enter_deepsleep(const uint64_t wakeup_sec = 60, void enter_deepsleep(const uint64_t wakeup_sec = 60,
gpio_num_t wakeup_gpio = GPIO_NUM_MAX) { gpio_num_t wakeup_gpio = GPIO_NUM_MAX) {
// don't go to sleep while unjoined ESP_LOGI(TAG, "Preparing to sleep...");
#if (HAS_LORA)
if (!LMIC.devaddr) {
ESP_LOGI(TAG, "Can't go to sleep while joining");
return;
}
#endif
RTC_runmode = RUNMODE_SLEEP;
int i; int i;
// validate wake up pin, if we have // validate wake up pin, if we have
if (!GPIO_IS_VALID_GPIO(wakeup_gpio)) if (!GPIO_IS_VALID_GPIO(wakeup_gpio))
wakeup_gpio = GPIO_NUM_MAX; wakeup_gpio = GPIO_NUM_MAX;
ESP_LOGI(TAG, "Preparing to sleep...");
RTC_runmode = RUNMODE_SLEEP;
// stop further enqueuing of senddata and MAC processing // stop further enqueuing of senddata and MAC processing
sendTimer.detach(); sendTimer.detach();
@ -125,27 +116,22 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
// wait a while (max 100 sec) to clear send queues // wait a while (max 100 sec) to clear send queues
ESP_LOGI(TAG, "Waiting until send queues are empty..."); ESP_LOGI(TAG, "Waiting until send queues are empty...");
for (i = 10; i > 0; i--) { for (i = 100; i > 0; i--) {
if (!allQueuesEmtpy()) if (allQueuesEmtpy())
vTaskDelay(pdMS_TO_TICKS(10000));
else
break; break;
vTaskDelay(pdMS_TO_TICKS(1000));
} }
if (i == 0)
goto Error;
// shutdown LMIC safely, waiting max 100 sec // shutdown LMIC safely, waiting max 100 sec
#if (HAS_LORA) #if (HAS_LORA)
ESP_LOGI(TAG, "Waiting until LMIC is idle..."); ESP_LOGI(TAG, "Waiting until LMIC is idle...");
for (i = 10; i > 0; i--) { for (i = 100; i > 0; i--) {
if ((LMIC.opmode & OP_TXRXPEND) || if ((LMIC.opmode & OP_TXRXPEND) ||
os_queryTimeCriticalJobs(sec2osticks(wakeup_sec))) os_queryTimeCriticalJobs(sec2osticks(wakeup_sec)))
vTaskDelay(pdMS_TO_TICKS(10000)); vTaskDelay(pdMS_TO_TICKS(1000));
else else
break; break;
} }
if (i == 0)
goto Error;
#endif // (HAS_LORA) #endif // (HAS_LORA)
// shutdown MQTT safely // shutdown MQTT safely
@ -165,10 +151,8 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
else else
break; break;
} }
if (i == 0)
goto Error;
// save LMIC state to RTC RAM // save LMIC state to RTC RAM
#if (HAS_LORA) #if (HAS_LORA)
SaveLMICToRTC(wakeup_sec); SaveLMICToRTC(wakeup_sec);
#endif // (HAS_LORA) #endif // (HAS_LORA)
@ -207,10 +191,6 @@ void enter_deepsleep(const uint64_t wakeup_sec = 60,
RTC_millis += millis(); RTC_millis += millis();
ESP_LOGI(TAG, "Going to sleep, good bye."); ESP_LOGI(TAG, "Going to sleep, good bye.");
esp_deep_sleep_start(); esp_deep_sleep_start();
Error:
ESP_LOGE(TAG, "Can't go to sleep. Resetting.");
do_reset(true);
} }
unsigned long long uptime() { return (RTC_millis + millis()); } unsigned long long uptime() { return (RTC_millis + millis()); }

View File

@ -115,7 +115,6 @@ void sendData() {
// 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
get_salt(); // get new salt for salting hashes
ESP_LOGI(TAG, "Counter cleared"); ESP_LOGI(TAG, "Counter cleared");
} }
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY