diff --git a/README.md b/README.md index 22a73ff0..74f8a44c 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,11 @@ Target platform must be selected in [platformio.ini](https://github.com/cyberman Hardware dependent settings (pinout etc.) are stored in board files in /hal directory. If you want to use a ESP32 board which is not yet supported, use hal file generic.h and tailor pin mappings to your needs. Pull requests for new boards welcome.
3D printable cases can be found (and, if wanted so, ordered) on Thingiverse, see -Heltec, TTGOv2, TTGOv2.1, T-BEAM for example.
+Heltec, TTGOv2, TTGOv2.1, T-BEAM, +T-BEAM parts for example.
-Power consumption was metered at around 450 - 1000mW, depending on board 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). +Power consumption was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf. +By default bluetooth sniffing is disabled (line *#define BLECOUNTER* in paxcounter.conf is commented out). Enabling bluetooth costs 30% more power + 30% flash storage for the software stack. Proof of concept showed that for passenger flow metering wifi sniffing shows better results than bluetooth sniffing. If you enable bluetooth be aware that this goes on expense of wifi sniffing results, because then wifi and bt stack must share the 2,4 GHz RF ressources of ESP32. If you need to sniff wifi and bt in parallel and need best possible results, use two boards - one for wifi only and one for bt only - and add counted results. # Preparing @@ -150,7 +152,8 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering. **Port #1:** Paxcount data byte 1-2: Number of unique pax, first seen on Wifi - byte 3-4: Number of unique pax, first seen on Bluetooth [0 if BT disabled] + byte 3-4: Number of unique pax, first seen on Bluetooth [omited if BT disabled] + bytes 5-17: GPS data, if present, in same format as for Port #4 **Port #2:** Device status query result diff --git a/include/bme680mems.h b/include/bme680mems.h index 70dd8fec..a97e0605 100644 --- a/include/bme680mems.h +++ b/include/bme680mems.h @@ -3,29 +3,54 @@ #include "globals.h" #include -#include "bsec_integration.h" - -extern const uint8_t bsec_config_iaq[454]; +#include "../lib/Bosch-BSEC/src/bsec.h" extern bmeStatus_t bme_status; // Make struct for storing gps data globally available extern TaskHandle_t BmeTask; +// --- Bosch BSEC library configuration --- +// 3,3V supply voltage; 3s max time between sensor_control calls; 4 days +// calibration. Change this const if not applicable for your application (see +// BME680 datasheet) +const uint8_t bsec_config_iaq[454] = { + 1, 7, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 174, 1, 0, + 0, 48, 0, 1, 0, 137, 65, 0, 63, 205, 204, 204, 62, 0, 0, + 64, 63, 205, 204, 204, 62, 0, 0, 225, 68, 0, 192, 168, 71, 64, + 49, 119, 76, 0, 0, 0, 0, 0, 80, 5, 95, 0, 0, 0, 0, + 0, 0, 0, 0, 28, 0, 2, 0, 0, 244, 1, 225, 0, 25, 0, + 0, 128, 64, 0, 0, 32, 65, 144, 1, 0, 0, 112, 65, 0, 0, + 0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, + 215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 88, 0, 9, + 0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27, + 156, 62, 225, 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, 160, 191, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97, + 64, 65, 241, 99, 190, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121, + 71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 229, 0, 254, 0, 2, 1, 5, 48, + 117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4, + 144, 1, 64, 1, 64, 1, 144, 1, 48, 117, 48, 117, 48, 117, 48, + 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, + 100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48, + 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, + 100, 0, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, + 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, + 44, 1, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, + 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, + 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, + 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, + 255, 255, 255, 255, 255, 255, 220, 5, 220, 5, 220, 5, 255, 255, 255, + 255, 255, 255, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, + 239, 79, 0, 0}; + +// Helper functions declarations int bme_init(); void bme_loop(void *pvParameters); -int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len); -int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len); -void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, - float temperature, float humidity, float pressure, - float raw_temperature, float raw_humidity, float gas, - bsec_library_return_t bsec_status, float static_iaq, - float co2_equivalent, float breath_voc_equivalent); -uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer); -void state_save(const uint8_t *state_buffer, uint32_t length); -uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer); -void user_delay_ms(uint32_t period); -int64_t get_timestamp_us(); +int checkIaqSensorStatus(void); +void loadState(void); +void updateState(void); #endif \ No newline at end of file diff --git a/include/coexist_internal.h b/include/coexist_internal.h new file mode 100644 index 00000000..6b4c47cc --- /dev/null +++ b/include/coexist_internal.h @@ -0,0 +1,77 @@ +// Copyright 2018-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __COEXIST_INTERNAL_H__ +#define __COEXIST_INTERNAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + COEX_PREFER_WIFI = 0, + COEX_PREFER_BT, + COEX_PREFER_BALANCE, + COEX_PREFER_NUM, +} coex_prefer_t; + +/** + * @brief Init software coexist + * extern function for internal use. + * + * @return Init ok or failed. + */ +esp_err_t coex_init(void); + +/** + * @brief De-init software coexist + * extern function for internal use. + */ +void coex_deinit(void); + +/** + * @brief Pause software coexist + * extern function for internal use. + */ +void coex_pause(void); + +/** + * @brief Resume software coexist + * extern function for internal use. + */ +void coex_resume(void); + +/** + * @brief Get software coexist version string + * extern function for internal use. + * @return : version string + */ +const char *coex_version_get(void); + +/** + * @brief Coexist performance preference set from libbt.a + * extern function for internal use. + * + * @param prefer : the prefer enumeration value + * @return : ESP_OK - success, other - failed + */ +esp_err_t coex_preference_set(coex_prefer_t prefer); + +#ifdef __cplusplus +} +#endif + +#endif /* __COEXIST_INTERNAL_H__ */ \ No newline at end of file diff --git a/include/cyclic.h b/include/cyclic.h index e263a678..6e5df0cd 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -7,10 +7,15 @@ #include "spislave.h" #include +#ifdef HAS_BME +#include "bme680mems.h" +#endif + void doHousekeeping(void); void do_timesync(void); uint64_t uptime(void); void reset_counters(void); int redirect_log(const char *fmt, va_list args); +uint32_t getFreeRAM(); #endif \ No newline at end of file diff --git a/include/display.h b/include/display.h index 492af565..99379b58 100644 --- a/include/display.h +++ b/include/display.h @@ -2,6 +2,7 @@ #define _DISPLAY_H #include +#include "cyclic.h" extern uint8_t volatile DisplayState; extern HAS_DISPLAY u8x8; diff --git a/include/globals.h b/include/globals.h index fda41d0d..bff3fc78 100644 --- a/include/globals.h +++ b/include/globals.h @@ -8,6 +8,13 @@ #include #include #include +#include "Mallocator.h" +//#include "inc/bsec_datatypes.h" +#include "../lib/Bosch-BSEC/src/inc/bsec_datatypes.h" + +// sniffing types +#define MAC_SNIFF_WIFI 0 +#define MAC_SNIFF_BLE 1 // bits in payloadmask for filtering payload data #define GPS_DATA (0x01) @@ -49,6 +56,7 @@ typedef struct { uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data char version[10]; // Firmware version + uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor } configData_t; // Struct holding payload for data send queue @@ -67,14 +75,14 @@ typedef struct { } gpsStatus_t; typedef struct { -float iaq; // IAQ signal -uint8_t iaq_accuracy; // accuracy of IAQ signal -float temperature; // temperature signal -float humidity; // humidity signal -float pressure; // pressure signal -float raw_temperature; // raw temperature signal -float raw_humidity; // raw humidity signal -float gas; // raw gas sensor signal + float iaq; // IAQ signal + uint8_t iaq_accuracy; // accuracy of IAQ signal + float temperature; // temperature signal + float humidity; // humidity signal + float pressure; // pressure signal + float raw_temperature; // raw temperature signal + float raw_humidity; // raw humidity signal + float gas; // raw gas sensor signal } bmeStatus_t; // global variables @@ -82,26 +90,25 @@ extern configData_t cfg; // current device configuration extern char display_line6[], display_line7[]; // screen buffers extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, - batt_voltage; // display values -extern std::set macs; // temp storage for MACs -extern hw_timer_t *channelSwitch, *sendCycle; + batt_voltage; // display values +extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; +extern SemaphoreHandle_t I2Caccess; +extern std::set, Mallocator> macs; extern std::array::iterator it; extern std::array beacons; extern TaskHandle_t irqHandlerTask, wifiSwitchTask; +// application includes #include "led.h" #include "payload.h" +#include "blescan.h" #ifdef HAS_GPS #include "gpsread.h" #endif -#ifdef HAS_BME -#include "bme680mems.h" -#endif - #ifdef HAS_LORA #include "lorawan.h" #endif @@ -114,10 +121,6 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #include "button.h" #endif -#ifdef BLECOUNTER -#include "blescan.h" -#endif - #ifdef HAS_BATTERY_PROBE #include "battery.h" #endif @@ -130,4 +133,8 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #include "sensor.h" #endif +#ifdef HAS_BME +#include "bme680mems.h" +#endif + #endif \ No newline at end of file diff --git a/include/macsniff.h b/include/macsniff.h index 81e5a2ed..d41fc787 100644 --- a/include/macsniff.h +++ b/include/macsniff.h @@ -6,8 +6,8 @@ // Hash function for scrambling MAC addresses #include "hash.h" - #include "senddata.h" +#include "cyclic.h" #define MAC_SNIFF_WIFI 0 #define MAC_SNIFF_BLE 1 diff --git a/include/main.h b/include/main.h index 6bc1b377..af6ff496 100644 --- a/include/main.h +++ b/include/main.h @@ -4,6 +4,7 @@ #include // needed for reading ESP32 chip attributes #include // needed for Wifi event handler #include // needed for timers +#include // needed for showing coex sw version #include "globals.h" #include "wifiscan.h" diff --git a/include/mallocator.h b/include/mallocator.h new file mode 100644 index 00000000..7d32d409 --- /dev/null +++ b/include/mallocator.h @@ -0,0 +1,54 @@ +/* + +This Mallocator code was taken from: + +CppCon2014 Presentations +STL Features And Implementation Techniques +Stephan T. Lavavej + +https://github.com/CppCon/CppCon2014 + +*/ + + +#ifndef _MALLOCATOR_H +#define _MALLOCATOR_H + +#include // size_t, malloc, free +#include // bad_alloc, bad_array_new_length +#include "esp32-hal-psram.h" // ps_malloc + +template struct Mallocator { + typedef T value_type; + Mallocator() noexcept {} // default ctor not required + template Mallocator(const Mallocator &) noexcept {} + template bool operator==(const Mallocator &) const noexcept { + return true; + } + template bool operator!=(const Mallocator &) const noexcept { + return false; + } + + T *allocate(const size_t n) const { + if (n == 0) { + return nullptr; + } + if (n > static_cast(-1) / sizeof(T)) { + throw std::bad_array_new_length(); + } + +#ifndef BOARD_HAS_PSRAM + void *const pv = malloc(n * sizeof(T)); +#else + void *const pv = ps_malloc(n * sizeof(T)); +#endif + + if (!pv) { + throw std::bad_alloc(); + } + return static_cast(pv); + } + void deallocate(T *const p, size_t) const noexcept { free(p); } +}; + +#endif \ No newline at end of file diff --git a/include/payload.h b/include/payload.h index 0ae02705..24b5ece6 100644 --- a/include/payload.h +++ b/include/payload.h @@ -39,7 +39,7 @@ public: void reset(void); uint8_t getSize(void); uint8_t *getBuffer(void); - void addCount(uint16_t value1, uint16_t value2); + void addCount(uint16_t value, uint8_t sniffytpe); void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp, uint32_t mem, uint8_t reset1, uint8_t reset2); diff --git a/include/rcommand.h b/include/rcommand.h index 806f911a..269caf91 100644 --- a/include/rcommand.h +++ b/include/rcommand.h @@ -7,6 +7,7 @@ #include "lorawan.h" #include "macsniff.h" #include +#include "cyclic.h" // table of remote commands and assigned functions typedef struct { diff --git a/include/wifiscan.h b/include/wifiscan.h index d5e2f456..0e6962a2 100644 --- a/include/wifiscan.h +++ b/include/wifiscan.h @@ -7,9 +7,6 @@ // Hash function for scrambling MAC addresses #include "hash.h" -#define MAC_SNIFF_WIFI 0 -#define MAC_SNIFF_BLE 1 - void wifi_sniffer_init(void); void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); void switchWifiChannel(void * parameter); diff --git a/lib/Bosch-BSEC/bsec_integration.c b/lib/Bosch-BSEC/bsec_integration.c deleted file mode 100644 index 0dc5dc2d..00000000 --- a/lib/Bosch-BSEC/bsec_integration.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (C) 2017 Robert Bosch. All Rights Reserved. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchasers own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - */ - -/*! - * @file bsec_integration.c - * - * @brief - * Private part of the example for using of BSEC library. - */ - -/*! - * @addtogroup bsec_examples BSEC Examples - * @brief BSEC usage examples - * @{*/ - -/**********************************************************************************************************************/ -/* header files */ -/**********************************************************************************************************************/ - -#include -#include -#include - -#include "bsec_integration.h" - -/**********************************************************************************************************************/ -/* local macro definitions */ -/**********************************************************************************************************************/ - -#define NUM_USED_OUTPUTS 8 - -/**********************************************************************************************************************/ -/* global variable declarations */ -/**********************************************************************************************************************/ - -/* Global sensor APIs data structure */ -static struct bme680_dev bme680_g; - -/* Global temperature offset to be subtracted */ -static float bme680_temperature_offset_g = 0.0f; - -/**********************************************************************************************************************/ -/* functions */ -/**********************************************************************************************************************/ - -/*! - * @brief Virtual sensor subscription - * Please call this function before processing of data using bsec_do_steps function - * - * @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP) - * - * @return subscription result, zero when successful - */ -static bsec_library_return_t bme680_bsec_update_subscription(float sample_rate) -{ - bsec_sensor_configuration_t requested_virtual_sensors[NUM_USED_OUTPUTS]; - uint8_t n_requested_virtual_sensors = NUM_USED_OUTPUTS; - - bsec_sensor_configuration_t required_sensor_settings[BSEC_MAX_PHYSICAL_SENSOR]; - uint8_t n_required_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR; - - bsec_library_return_t status = BSEC_OK; - - /* note: Virtual sensors as desired to be added here */ - requested_virtual_sensors[0].sensor_id = BSEC_OUTPUT_IAQ; - requested_virtual_sensors[0].sample_rate = sample_rate; - requested_virtual_sensors[1].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE; - requested_virtual_sensors[1].sample_rate = sample_rate; - requested_virtual_sensors[2].sensor_id = BSEC_OUTPUT_RAW_PRESSURE; - requested_virtual_sensors[2].sample_rate = sample_rate; - requested_virtual_sensors[3].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY; - requested_virtual_sensors[3].sample_rate = sample_rate; - requested_virtual_sensors[4].sensor_id = BSEC_OUTPUT_RAW_GAS; - requested_virtual_sensors[4].sample_rate = sample_rate; - requested_virtual_sensors[5].sensor_id = BSEC_OUTPUT_RAW_TEMPERATURE; - requested_virtual_sensors[5].sample_rate = sample_rate; - requested_virtual_sensors[6].sensor_id = BSEC_OUTPUT_RAW_HUMIDITY; - requested_virtual_sensors[6].sample_rate = sample_rate; - requested_virtual_sensors[7].sensor_id = BSEC_OUTPUT_STATIC_IAQ; - requested_virtual_sensors[7].sample_rate = sample_rate; - - /* Call bsec_update_subscription() to enable/disable the requested virtual sensors */ - status = bsec_update_subscription(requested_virtual_sensors, n_requested_virtual_sensors, required_sensor_settings, - &n_required_sensor_settings); - - return status; -} - -/*! - * @brief Initialize the BME680 sensor and the BSEC library - * - * @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP) - * @param[in] temperature_offset device-specific temperature offset (due to self-heating) - * @param[in] bus_write pointer to the bus writing function - * @param[in] bus_read pointer to the bus reading function - * @param[in] sleep pointer to the system specific sleep function - * @param[in] state_load pointer to the system-specific state load function - * @param[in] config_load pointer to the system-specific config load function - * - * @return zero if successful, negative otherwise - */ -return_values_init bsec_iot_init(float sample_rate, float temperature_offset, bme680_com_fptr_t bus_write, - bme680_com_fptr_t bus_read, sleep_fct sleep, state_load_fct state_load, config_load_fct config_load) -{ - return_values_init ret = {BME680_OK, BSEC_OK}; - bsec_library_return_t bsec_status = BSEC_OK; - - uint8_t bsec_state[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0}; - uint8_t bsec_config[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0}; - uint8_t work_buffer[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0}; - int bsec_state_len, bsec_config_len; - - /* Fixed I2C configuration */ - bme680_g.dev_id = BME680_I2C_ADDR_PRIMARY; - bme680_g.intf = BME680_I2C_INTF; - /* User configurable I2C configuration */ - bme680_g.write = bus_write; - bme680_g.read = bus_read; - bme680_g.delay_ms = sleep; - - /* Initialize BME680 API */ - ret.bme680_status = bme680_init(&bme680_g); - if (ret.bme680_status != BME680_OK) - { - return ret; - } - - /* Initialize BSEC library */ - ret.bsec_status = bsec_init(); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - - /* Load library config, if available */ - bsec_config_len = config_load(bsec_config, sizeof(bsec_config)); - if (bsec_config_len != 0) - { - ret.bsec_status = bsec_set_configuration(bsec_config, bsec_config_len, work_buffer, sizeof(work_buffer)); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - } - - /* Load previous library state, if available */ - bsec_state_len = state_load(bsec_state, sizeof(bsec_state)); - if (bsec_state_len != 0) - { - ret.bsec_status = bsec_set_state(bsec_state, bsec_state_len, work_buffer, sizeof(work_buffer)); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - } - - /* Set temperature offset */ - bme680_temperature_offset_g = temperature_offset; - - /* Call to the function which sets the library with subscription information */ - ret.bsec_status = bme680_bsec_update_subscription(sample_rate); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - - return ret; -} - -/*! - * @brief Trigger the measurement based on sensor settings - * - * @param[in] sensor_settings settings of the BME680 sensor adopted by sensor control function - * @param[in] sleep pointer to the system specific sleep function - * - * @return none - */ -static void bme680_bsec_trigger_measurement(bsec_bme_settings_t *sensor_settings, sleep_fct sleep) -{ - uint16_t meas_period; - uint8_t set_required_settings; - int8_t bme680_status = BME680_OK; - - /* Check if a forced-mode measurement should be triggered now */ - if (sensor_settings->trigger_measurement) - { - /* Set sensor configuration */ - - bme680_g.tph_sett.os_hum = sensor_settings->humidity_oversampling; - bme680_g.tph_sett.os_pres = sensor_settings->pressure_oversampling; - bme680_g.tph_sett.os_temp = sensor_settings->temperature_oversampling; - bme680_g.gas_sett.run_gas = sensor_settings->run_gas; - bme680_g.gas_sett.heatr_temp = sensor_settings->heater_temperature; /* degree Celsius */ - bme680_g.gas_sett.heatr_dur = sensor_settings->heating_duration; /* milliseconds */ - - /* Select the power mode */ - /* Must be set before writing the sensor configuration */ - bme680_g.power_mode = BME680_FORCED_MODE; - /* Set the required sensor settings needed */ - set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL; - - /* Set the desired sensor configuration */ - bme680_status = bme680_set_sensor_settings(set_required_settings, &bme680_g); - - /* Set power mode as forced mode and trigger forced mode measurement */ - bme680_status = bme680_set_sensor_mode(&bme680_g); - - /* Get the total measurement duration so as to sleep or wait till the measurement is complete */ - bme680_get_profile_dur(&meas_period, &bme680_g); - - /* Delay till the measurement is ready. Timestamp resolution in ms */ - sleep((uint32_t)meas_period); - } - - /* Call the API to get current operation mode of the sensor */ - bme680_status = bme680_get_sensor_mode(&bme680_g); - /* When the measurement is completed and data is ready for reading, the sensor must be in BME680_SLEEP_MODE. - * Read operation mode to check whether measurement is completely done and wait until the sensor is no more - * in BME680_FORCED_MODE. */ - while (bme680_g.power_mode == BME680_FORCED_MODE) - { - /* sleep for 5 ms */ - sleep(5); - bme680_status = bme680_get_sensor_mode(&bme680_g); - } -} - -/*! - * @brief Read the data from registers and populate the inputs structure to be passed to do_steps function - * - * @param[in] time_stamp_trigger settings of the sensor returned from sensor control function - * @param[in] inputs input structure containing the information on sensors to be passed to do_steps - * @param[in] num_bsec_inputs number of inputs to be passed to do_steps - * @param[in] bsec_process_data process data variable returned from sensor_control - * - * @return none - */ -static void bme680_bsec_read_data(int64_t time_stamp_trigger, bsec_input_t *inputs, uint8_t *num_bsec_inputs, - int32_t bsec_process_data) -{ - static struct bme680_field_data data; - int8_t bme680_status = BME680_OK; - - /* We only have to read data if the previous call the bsec_sensor_control() actually asked for it */ - if (bsec_process_data) - { - bme680_status = bme680_get_sensor_data(&data, &bme680_g); - - if (data.status & BME680_NEW_DATA_MSK) - { - /* Pressure to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_PRESSURE) - { - /* Place presssure sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_PRESSURE; - inputs[*num_bsec_inputs].signal = data.pressure; - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - /* Temperature to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_TEMPERATURE) - { - /* Place temperature sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_TEMPERATURE; - #ifdef BME680_FLOAT_POINT_COMPENSATION - inputs[*num_bsec_inputs].signal = data.temperature; - #else - inputs[*num_bsec_inputs].signal = data.temperature / 100.0f; - #endif - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - - /* Also add optional heatsource input which will be subtracted from the temperature reading to - * compensate for device-specific self-heating (supported in BSEC IAQ solution)*/ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HEATSOURCE; - inputs[*num_bsec_inputs].signal = bme680_temperature_offset_g; - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - /* Humidity to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_HUMIDITY) - { - /* Place humidity sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HUMIDITY; - #ifdef BME680_FLOAT_POINT_COMPENSATION - inputs[*num_bsec_inputs].signal = data.humidity; - #else - inputs[*num_bsec_inputs].signal = data.humidity / 1000.0f; - #endif - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - /* Gas to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_GAS) - { - /* Check whether gas_valid flag is set */ - if(data.status & BME680_GASM_VALID_MSK) - { - /* Place sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_GASRESISTOR; - inputs[*num_bsec_inputs].signal = data.gas_resistance; - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - } - } - } -} - -/*! - * @brief This function is written to process the sensor data for the requested virtual sensors - * - * @param[in] bsec_inputs input structure containing the information on sensors to be passed to do_steps - * @param[in] num_bsec_inputs number of inputs to be passed to do_steps - * @param[in] output_ready pointer to the function processing obtained BSEC outputs - * - * @return none - */ -static void bme680_bsec_process_data(bsec_input_t *bsec_inputs, uint8_t num_bsec_inputs, output_ready_fct output_ready) -{ - /* Output buffer set to the maximum virtual sensor outputs supported */ - bsec_output_t bsec_outputs[BSEC_NUMBER_OUTPUTS]; - uint8_t num_bsec_outputs = 0; - uint8_t index = 0; - - bsec_library_return_t bsec_status = BSEC_OK; - - int64_t timestamp = 0; - float iaq = 0.0f; - uint8_t iaq_accuracy = 0; - float temp = 0.0f; - float raw_temp = 0.0f; - float raw_pressure = 0.0f; - float humidity = 0.0f; - float raw_humidity = 0.0f; - float raw_gas = 0.0f; - float static_iaq = 0.0f; - uint8_t static_iaq_accuracy = 0; - float co2_equivalent = 0.0f; - uint8_t co2_accuracy = 0; - float breath_voc_equivalent = 0.0f; - uint8_t breath_voc_accuracy = 0; - float comp_gas_value = 0.0f; - uint8_t comp_gas_accuracy = 0; - float gas_percentage = 0.0f; - uint8_t gas_percentage_acccuracy = 0; - - /* Check if something should be processed by BSEC */ - if (num_bsec_inputs > 0) - { - /* Set number of outputs to the size of the allocated buffer */ - /* BSEC_NUMBER_OUTPUTS to be defined */ - num_bsec_outputs = BSEC_NUMBER_OUTPUTS; - - /* Perform processing of the data by BSEC - Note: - * The number of outputs you get depends on what you asked for during bsec_update_subscription(). This is - handled under bme680_bsec_update_subscription() function in this example file. - * The number of actual outputs that are returned is written to num_bsec_outputs. */ - bsec_status = bsec_do_steps(bsec_inputs, num_bsec_inputs, bsec_outputs, &num_bsec_outputs); - - /* Iterate through the outputs and extract the relevant ones. */ - for (index = 0; index < num_bsec_outputs; index++) - { - switch (bsec_outputs[index].sensor_id) - { - case BSEC_OUTPUT_IAQ: - iaq = bsec_outputs[index].signal; - iaq_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_STATIC_IAQ: - static_iaq = bsec_outputs[index].signal; - static_iaq_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_CO2_EQUIVALENT: - co2_equivalent = bsec_outputs[index].signal; - co2_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: - breath_voc_equivalent = bsec_outputs[index].signal; - breath_voc_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: - temp = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_PRESSURE: - raw_pressure = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: - humidity = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_GAS: - raw_gas = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_TEMPERATURE: - raw_temp = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_HUMIDITY: - raw_humidity = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_COMPENSATED_GAS: - comp_gas_value = bsec_outputs[index].signal; - comp_gas_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_GAS_PERCENTAGE: - gas_percentage = bsec_outputs[index].signal; - gas_percentage_acccuracy = bsec_outputs[index].accuracy; - break; - default: - continue; - } - - /* Assume that all the returned timestamps are the same */ - timestamp = bsec_outputs[index].time_stamp; - } - - /* Pass the extracted outputs to the user provided output_ready() function. */ - output_ready(timestamp, iaq, iaq_accuracy, temp, humidity, raw_pressure, raw_temp, - raw_humidity, raw_gas, bsec_status, static_iaq, co2_equivalent, breath_voc_equivalent); - } -} - -/*! - * @brief Runs the main (endless) loop that queries sensor settings, applies them, and processes the measured data - * - * @param[in] sleep pointer to the system specific sleep function - * @param[in] get_timestamp_us pointer to the system specific timestamp derivation function - * @param[in] output_ready pointer to the function processing obtained BSEC outputs - * @param[in] state_save pointer to the system-specific state save function - * @param[in] save_intvl interval at which BSEC state should be saved (in samples) - * - * @return none - */ -void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready, - state_save_fct state_save, uint32_t save_intvl) -{ - /* Timestamp variables */ - int64_t time_stamp = 0; - int64_t time_stamp_interval_ms = 0; - - /* Allocate enough memory for up to BSEC_MAX_PHYSICAL_SENSOR physical inputs*/ - bsec_input_t bsec_inputs[BSEC_MAX_PHYSICAL_SENSOR]; - - /* Number of inputs to BSEC */ - uint8_t num_bsec_inputs = 0; - - /* BSEC sensor settings struct */ - bsec_bme_settings_t sensor_settings; - - /* Save state variables */ - uint8_t bsec_state[BSEC_MAX_STATE_BLOB_SIZE]; - uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE]; - uint32_t bsec_state_len = 0; - uint32_t n_samples = 0; - - bsec_library_return_t bsec_status = BSEC_OK; - - while (1) - { - /* get the timestamp in nanoseconds before calling bsec_sensor_control() */ - time_stamp = get_timestamp_us() * 1000; - - /* Retrieve sensor settings to be used in this time instant by calling bsec_sensor_control */ - bsec_sensor_control(time_stamp, &sensor_settings); - - /* Trigger a measurement if necessary */ - bme680_bsec_trigger_measurement(&sensor_settings, sleep); - - /* Read data from last measurement */ - num_bsec_inputs = 0; - bme680_bsec_read_data(time_stamp, bsec_inputs, &num_bsec_inputs, sensor_settings.process_data); - - /* Time to invoke BSEC to perform the actual processing */ - bme680_bsec_process_data(bsec_inputs, num_bsec_inputs, output_ready); - - /* Increment sample counter */ - n_samples++; - - /* Retrieve and store state if the passed save_intvl */ - if (n_samples >= save_intvl) - { - bsec_status = bsec_get_state(0, bsec_state, sizeof(bsec_state), work_buffer, sizeof(work_buffer), &bsec_state_len); - if (bsec_status == BSEC_OK) - { - state_save(bsec_state, bsec_state_len); - } - n_samples = 0; - } - - - /* Compute how long we can sleep until we need to call bsec_sensor_control() next */ - /* Time_stamp is converted from microseconds to nanoseconds first and then the difference to milliseconds */ - time_stamp_interval_ms = (sensor_settings.next_call - get_timestamp_us() * 1000) / 1000000; - if (time_stamp_interval_ms > 0) - { - sleep((uint32_t)time_stamp_interval_ms); - } - } -} - -/*! @}*/ - diff --git a/lib/Bosch-BSEC/bsec_integration.h b/lib/Bosch-BSEC/bsec_integration.h deleted file mode 100644 index 5155a001..00000000 --- a/lib/Bosch-BSEC/bsec_integration.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2017 Robert Bosch. All Rights Reserved. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchasers own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - */ - -/*! - * @file bsec_integration.h - * - * @brief - * Contains BSEC integration API - */ - -/*! - * @addtogroup bsec_examples BSEC Examples - * @brief BSEC usage examples - * @{*/ - -#ifndef __BSEC_INTEGRATION_H__ -#define __BSEC_INTEGRATION_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/**********************************************************************************************************************/ -/* header files */ -/**********************************************************************************************************************/ - -/* Use the following bme680 driver: https://github.com/BoschSensortec/BME680_driver/releases/tag/bme680_v3.5.1 */ -#include "bme680.h" -/* BSEC header files are available in the inc/ folder of the release package */ -#include "bsec_interface.h" -#include "bsec_datatypes.h" - - -/**********************************************************************************************************************/ -/* type definitions */ -/**********************************************************************************************************************/ - -/* function pointer to the system specific sleep function */ -typedef void (*sleep_fct)(uint32_t t_ms); - -/* function pointer to the system specific timestamp derivation function */ -typedef int64_t (*get_timestamp_us_fct)(); - -/* function pointer to the function processing obtained BSEC outputs */ -typedef void (*output_ready_fct)(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity, - float pressure, float raw_temperature, float raw_humidity, float gas, bsec_library_return_t bsec_status, - float static_iaq, float co2_equivalent, float breath_voc_equivalent); - -/* function pointer to the function loading a previous BSEC state from NVM */ -typedef uint32_t (*state_load_fct)(uint8_t *state_buffer, uint32_t n_buffer); - -/* function pointer to the function saving BSEC state to NVM */ -typedef void (*state_save_fct)(const uint8_t *state_buffer, uint32_t length); - -/* function pointer to the function loading the BSEC configuration string from NVM */ -typedef uint32_t (*config_load_fct)(uint8_t *state_buffer, uint32_t n_buffer); - -/* structure definitions */ - -/* Structure with the return value from bsec_iot_init() */ -typedef struct{ - /*! Result of API execution status */ - int8_t bme680_status; - /*! Result of BSEC library */ - bsec_library_return_t bsec_status; -}return_values_init; -/**********************************************************************************************************************/ -/* function declarations */ -/**********************************************************************************************************************/ - -/*! - * @brief Initialize the BME680 sensor and the BSEC library - * - * @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP) - * @param[in] temperature_offset device-specific temperature offset (due to self-heating) - * @param[in] bus_write pointer to the bus writing function - * @param[in] bus_read pointer to the bus reading function - * @param[in] sleep pointer to the system-specific sleep function - * @param[in] state_load pointer to the system-specific state load function - * - * @return zero if successful, negative otherwise - */ -return_values_init bsec_iot_init(float sample_rate, float temperature_offset, bme680_com_fptr_t bus_write, bme680_com_fptr_t bus_read, - sleep_fct sleep, state_load_fct state_load, config_load_fct config_load); - -/*! - * @brief Runs the main (endless) loop that queries sensor settings, applies them, and processes the measured data - * - * @param[in] sleep pointer to the system-specific sleep function - * @param[in] get_timestamp_us pointer to the system-specific timestamp derivation function - * @param[in] output_ready pointer to the function processing obtained BSEC outputs - * @param[in] state_save pointer to the system-specific state save function - * @param[in] save_intvl interval at which BSEC state should be saved (in samples) - * - * @return return_values_init struct with the result of the API and the BSEC library - */ -void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready, - state_save_fct state_save, uint32_t save_intvl); - -#ifdef __cplusplus -} -#endif - -#endif /* __BSEC_INTEGRATION_H__ */ - -/*! @}*/ - diff --git a/lib/Bosch-BSEC/README.md b/lib/Bosch-BSEC/src/bme680/README.md similarity index 100% rename from lib/Bosch-BSEC/README.md rename to lib/Bosch-BSEC/src/bme680/README.md diff --git a/lib/Bosch-BSEC/bme680.c b/lib/Bosch-BSEC/src/bme680/bme680.c similarity index 100% rename from lib/Bosch-BSEC/bme680.c rename to lib/Bosch-BSEC/src/bme680/bme680.c diff --git a/lib/Bosch-BSEC/bme680.h b/lib/Bosch-BSEC/src/bme680/bme680.h similarity index 100% rename from lib/Bosch-BSEC/bme680.h rename to lib/Bosch-BSEC/src/bme680/bme680.h diff --git a/lib/Bosch-BSEC/bme680_defs.h b/lib/Bosch-BSEC/src/bme680/bme680_defs.h similarity index 99% rename from lib/Bosch-BSEC/bme680_defs.h rename to lib/Bosch-BSEC/src/bme680/bme680_defs.h index 495edfe0..79fd7782 100644 --- a/lib/Bosch-BSEC/bme680_defs.h +++ b/lib/Bosch-BSEC/src/bme680/bme680_defs.h @@ -103,7 +103,7 @@ /** BME680 configuration macros */ /** Enable or un-comment the macro to provide floating point data output */ #ifndef BME680_FLOAT_POINT_COMPENSATION -/* #define BME680_FLOAT_POINT_COMPENSATION */ +//#define BME680_FLOAT_POINT_COMPENSATION #endif /** BME680 General config */ diff --git a/lib/Bosch-BSEC/src/bsec.cpp b/lib/Bosch-BSEC/src/bsec.cpp new file mode 100644 index 00000000..cf85d77f --- /dev/null +++ b/lib/Bosch-BSEC/src/bsec.cpp @@ -0,0 +1,498 @@ +/** + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bsec.cpp + * @date 31 Jan 2018 + * @version 1.0 + * + */ + +#include "bsec.h" + +TwoWire *Bsec::wireObj = NULL; +SPIClass *Bsec::spiObj = NULL; + +/** + * @brief Constructor + */ +Bsec::Bsec() { + nextCall = 0; + version.major = 0; + version.minor = 0; + version.major_bugfix = 0; + version.minor_bugfix = 0; + millisOverflowCounter = 0; + lastTime = 0; + bme680Status = BME680_OK; + outputTimestamp = 0; + _tempOffset = 0.0f; + status = BSEC_OK; + zeroOutputs(); +} + +/** + * @brief Function to initialize the BSEC library and the BME680 sensor + */ +void Bsec::begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, + bme680_com_fptr_t write, bme680_delay_fptr_t idleTask) { + _bme680.dev_id = devId; + _bme680.intf = intf; + _bme680.read = read; + _bme680.write = write; + _bme680.delay_ms = idleTask; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; + + beginCommon(); +} + +/** + * @brief Function to initialize the BSEC library and the BME680 sensor + */ +void Bsec::begin(uint8_t i2cAddr, TwoWire &i2c) { + _bme680.dev_id = i2cAddr; + _bme680.intf = BME680_I2C_INTF; + _bme680.read = Bsec::i2cRead; + _bme680.write = Bsec::i2cWrite; + _bme680.delay_ms = Bsec::delay_ms; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; + + Bsec::wireObj = &i2c; + Bsec::wireObj->begin(); + + beginCommon(); +} + +/** + * @brief Function to initialize the BSEC library and the BME680 sensor + */ +void Bsec::begin(uint8_t chipSelect, SPIClass &spi) { + _bme680.dev_id = chipSelect; + _bme680.intf = BME680_SPI_INTF; + _bme680.read = Bsec::spiTransfer; + _bme680.write = Bsec::spiTransfer; + _bme680.delay_ms = Bsec::delay_ms; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; + + pinMode(chipSelect, OUTPUT); + digitalWrite(chipSelect, HIGH); + Bsec::spiObj = &spi; + Bsec::spiObj->begin(); + + beginCommon(); +} + +/** + * @brief Common code for the begin function + */ +void Bsec::beginCommon(void) { + status = bsec_init(); + + getVersion(); + + bme680Status = bme680_init(&_bme680); +} + +/** + * @brief Function that sets the desired sensors and the sample rates + */ +void Bsec::updateSubscription(bsec_virtual_sensor_t sensorList[], + uint8_t nSensors, float sampleRate) { + bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS], + sensorSettings[BSEC_MAX_PHYSICAL_SENSOR]; + uint8_t nVirtualSensors = 0, nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR; + + for (uint8_t i = 0; i < nSensors; i++) { + virtualSensors[nVirtualSensors].sensor_id = sensorList[i]; + virtualSensors[nVirtualSensors].sample_rate = sampleRate; + nVirtualSensors++; + } + + status = bsec_update_subscription(virtualSensors, nVirtualSensors, + sensorSettings, &nSensorSettings); + return; +} + +/** + * @brief Callback from the user to trigger reading of data from the BME680, + * process and store outputs + */ +bool Bsec::run(void) { + bool newData = false; + /* Check if the time has arrived to call do_steps() */ + int64_t callTimeMs = getTimeMs(); + + if (callTimeMs >= nextCall) { + + bsec_bme_settings_t bme680Settings; + + int64_t callTimeNs = callTimeMs * INT64_C(1000000); + + status = bsec_sensor_control(callTimeNs, &bme680Settings); + if (status < BSEC_OK) + return false; + + nextCall = + bme680Settings.next_call / INT64_C(1000000); // Convert from ns to ms + + bme680Status = setBme680Config(bme680Settings); + if (bme680Status != BME680_OK) { + return false; + } + + bme680Status = bme680_set_sensor_mode(&_bme680); + if (bme680Status != BME680_OK) { + return false; + } + + /* Wait for measurement to complete */ + uint16_t meas_dur = 0; + + bme680_get_profile_dur(&meas_dur, &_bme680); + delay_ms(meas_dur); + + newData = readProcessData(callTimeNs, bme680Settings); + } + + return newData; +} + +/** + * @brief Function to get the state of the algorithm to save to non-volatile + * memory + */ +void Bsec::getState(uint8_t *state) { + uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; + uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE; + status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, + BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state); +} + +/** + * @brief Function to set the state of the algorithm from non-volatile memory + */ +void Bsec::setState(uint8_t *state) { + uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; + + status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, + BSEC_MAX_STATE_BLOB_SIZE); +} + +/** + * @brief Function to set the configuration of the algorithm from memory + */ +void Bsec::setConfig(const uint8_t *state) { + uint8_t workBuffer[BSEC_MAX_PROPERTY_BLOB_SIZE]; + + status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE, + workBuffer, sizeof(workBuffer)); +} + +/* Private functions */ + +/** + * @brief Get the version of the BSEC library + */ +void Bsec::getVersion(void) { bsec_get_version(&version); } + +/** + * @brief Read data from the BME680 and process it + */ +bool Bsec::readProcessData(int64_t currTimeNs, + bsec_bme_settings_t bme680Settings) { + bme680Status = bme680_get_sensor_data(&_data, &_bme680); + if (bme680Status != BME680_OK) { + return false; + } + + bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas + uint8_t nInputs = 0, nOutputs = 0; + + if (_data.status & BME680_NEW_DATA_MSK) { + if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) { + inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE; +#ifdef BME680_FLOAT_POINT_COMPENSATION + inputs[nInputs].signal = _data.temperature; +#else + inputs[nInputs].signal = _data.temperature / 100.0f; +#endif + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + /* Temperature offset from the real temperature due to external heat + * sources */ + inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE; + inputs[nInputs].signal = _tempOffset; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) { + inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY; +#ifdef BME680_FLOAT_POINT_COMPENSATION + inputs[nInputs].signal = _data.humidity; +#else + inputs[nInputs].signal = _data.humidity / 1000.0f; +#endif + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) { + inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE; + inputs[nInputs].signal = _data.pressure; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_GAS) { + inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR; + inputs[nInputs].signal = _data.gas_resistance; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + } + + if (nInputs > 0) { + nOutputs = BSEC_NUMBER_OUTPUTS; + bsec_output_t _outputs[BSEC_NUMBER_OUTPUTS]; + + status = bsec_do_steps(inputs, nInputs, _outputs, &nOutputs); + if (status != BSEC_OK) + return false; + + zeroOutputs(); + + if (nOutputs > 0) { + outputTimestamp = + _outputs[0].time_stamp / 1000000; // Convert from ns to ms + + for (uint8_t i = 0; i < nOutputs; i++) { + switch (_outputs[i].sensor_id) { + case BSEC_OUTPUT_IAQ: + iaqEstimate = _outputs[i].signal; + iaqAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_STATIC_IAQ: + staticIaq = _outputs[i].signal; + staticIaqAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_CO2_EQUIVALENT: + co2Equivalent = _outputs[i].signal; + co2Accuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: + breathVocEquivalent = _outputs[i].signal; + breathVocAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_RAW_TEMPERATURE: + rawTemperature = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_PRESSURE: + pressure = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_HUMIDITY: + rawHumidity = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_GAS: + gasResistance = _outputs[i].signal; + break; + case BSEC_OUTPUT_STABILIZATION_STATUS: + stabStatus = _outputs[i].signal; + break; + case BSEC_OUTPUT_RUN_IN_STATUS: + runInStatus = _outputs[i].signal; + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: + temperature = _outputs[i].signal; + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: + humidity = _outputs[i].signal; + break; + case BSEC_OUTPUT_COMPENSATED_GAS: + compGasValue = _outputs[i].signal; + compGasAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_GAS_PERCENTAGE: + gasPercentage = _outputs[i].signal; + gasPercentageAcccuracy = _outputs[i].accuracy; + break; + default: + break; + } + } + return true; + } + } + + return false; +} + +/** + * @brief Set the BME680 sensor's configuration + */ +int8_t Bsec::setBme680Config(bsec_bme_settings_t bme680Settings) { + _bme680.gas_sett.run_gas = bme680Settings.run_gas; + _bme680.tph_sett.os_hum = bme680Settings.humidity_oversampling; + _bme680.tph_sett.os_temp = bme680Settings.temperature_oversampling; + _bme680.tph_sett.os_pres = bme680Settings.pressure_oversampling; + _bme680.gas_sett.heatr_temp = bme680Settings.heater_temperature; + _bme680.gas_sett.heatr_dur = bme680Settings.heating_duration; + uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | + BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; + return bme680_set_sensor_settings(desired_settings, &_bme680); +} + +/** + * @brief Function to zero the outputs + */ +void Bsec::zeroOutputs(void) { + temperature = 0.0f; + pressure = 0.0f; + humidity = 0.0f; + gasResistance = 0.0f; + rawTemperature = 0.0f; + rawHumidity = 0.0f; + stabStatus = 0.0f; + runInStatus = 0.0f; + iaqEstimate = 0.0f; + iaqAccuracy = 0; + staticIaq = 0.0f; + staticIaqAccuracy = 0; + co2Equivalent = 0.0f; + co2Accuracy = 0; + breathVocEquivalent = 0.0f; + breathVocAccuracy = 0; + compGasValue = 0.0f; + compGasAccuracy = 0; + gasPercentage = 0.0f; + gasPercentageAcccuracy = 0; +} + +/** + * @brief Function to calculate an int64_t timestamp in milliseconds + */ +int64_t Bsec::getTimeMs(void) { + int64_t timeMs = millis(); + + if (lastTime > timeMs) { // An overflow occured + lastTime = timeMs; + millisOverflowCounter++; + } + + return timeMs + (millisOverflowCounter * 0xFFFFFFFF); +} + +/** + @brief Task that delays for a ms period of time + */ +void Bsec::delay_ms(uint32_t period) { + // Wait for a period amount of ms + // The system may simply idle, sleep or even perform background tasks + delay(period); +} + +/** + @brief Callback function for reading registers over I2C + */ +int8_t Bsec::i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, + uint16_t length) { + uint16_t i; + int8_t rslt = 0; + if (Bsec::wireObj) { + Bsec::wireObj->beginTransmission(devId); + Bsec::wireObj->write(regAddr); + rslt = Bsec::wireObj->endTransmission(); + Bsec::wireObj->requestFrom((int)devId, (int)length); + for (i = 0; (i < length) && Bsec::wireObj->available(); i++) { + regData[i] = Bsec::wireObj->read(); + } + } else { + rslt = -1; + } + return rslt; +} + +/** + * @brief Callback function for writing registers over I2C + */ +int8_t Bsec::i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, + uint16_t length) { + uint16_t i; + int8_t rslt = 0; + if (Bsec::wireObj) { + Bsec::wireObj->beginTransmission(devId); + Bsec::wireObj->write(regAddr); + for (i = 0; i < length; i++) { + Bsec::wireObj->write(regData[i]); + } + rslt = Bsec::wireObj->endTransmission(); + } else { + rslt = -1; + } + + return rslt; +} + +/** + * @brief Callback function for reading and writing registers over SPI + */ +int8_t Bsec::spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, + uint16_t length) { + int8_t rslt = 0; + if (Bsec::spiObj) { + Bsec::spiObj->beginTransaction( + SPISettings(4000000, MSBFIRST, SPI_MODE0)); // Can be upto 10MHz + + digitalWrite(devId, LOW); + + Bsec::spiObj->transfer( + regAddr); // Write the register address, ignore the return + for (uint16_t i = 0; i < length; i++) + regData[i] = Bsec::spiObj->transfer(regData[i]); + + digitalWrite(devId, HIGH); + Bsec::spiObj->endTransaction(); + } else { + rslt = -1; + } + + return rslt; + ; +} \ No newline at end of file diff --git a/lib/Bosch-BSEC/src/bsec.h b/lib/Bosch-BSEC/src/bsec.h new file mode 100644 index 00000000..bf2c0a61 --- /dev/null +++ b/lib/Bosch-BSEC/src/bsec.h @@ -0,0 +1,230 @@ +/** + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bsec.h + * @date 31 Jan 2018 + * @version 1.0 + * + */ + +#ifndef BSEC_CLASS_H +#define BSEC_CLASS_H + +/* Includes */ +#include "Arduino.h" +#include "Wire.h" +#include "SPI.h" +#include "inc/bsec_datatypes.h" +#include "inc/bsec_interface.h" +#include "bme680/bme680.h" + +/* BSEC class definition */ +class Bsec +{ +public: + /* Public variables */ + bsec_version_t version; // Stores the version of the BSEC algorithm + int64_t nextCall; // Stores the time when the algorithm has to be called next in ms + int8_t bme680Status; // Placeholder for the BME680 driver's error codes + bsec_library_return_t status; + float iaqEstimate, rawTemperature, pressure, rawHumidity, gasResistance, stabStatus, runInStatus, temperature, humidity, + staticIaq, co2Equivalent, breathVocEquivalent, compGasValue, gasPercentage; + uint8_t iaqAccuracy, staticIaqAccuracy, co2Accuracy, breathVocAccuracy, compGasAccuracy, gasPercentageAcccuracy; + int64_t outputTimestamp; // Timestamp in ms of the output + static TwoWire *wireObj; + static SPIClass *spiObj; + + /* Public APIs */ + /** + * @brief Constructor + */ + Bsec(); + + /** + * @brief Function to initialize the BSEC library and the BME680 sensor + * @param devId : Device identifier parameter for the read/write interface functions + * @param intf : Physical communication interface + * @param read : Pointer to the read function + * @param write : Pointer to the write function + * @param idleTask : Pointer to the idling task + */ + void begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask); + + /** + * @brief Function to initialize the BSEC library and the BME680 sensor + * @param i2cAddr : I2C address + * @param i2c : Pointer to the TwoWire object + */ + void begin(uint8_t i2cAddr, TwoWire &i2c); + + /** + * @brief Function to initialize the BSEC library and the BME680 sensor + * @param chipSelect : SPI chip select + * @param spi : Pointer to the SPIClass object + */ + void begin(uint8_t chipSelect, SPIClass &spi); + + /** + * @brief Function that sets the desired sensors and the sample rates + * @param sensorList : The list of output sensors + * @param nSensors : Number of outputs requested + * @param sampleRate : The sample rate of requested sensors + */ + void updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate = BSEC_SAMPLE_RATE_ULP); + + /** + * @brief Callback from the user to trigger reading of data from the BME680, process and store outputs + * @return true if there are new outputs. false otherwise + */ + bool run(void); + + /** + * @brief Function to get the state of the algorithm to save to non-volatile memory + * @param state : Pointer to a memory location that contains the state + */ + void getState(uint8_t *state); + + /** + * @brief Function to set the state of the algorithm from non-volatile memory + * @param state : Pointer to a memory location that contains the state + */ + void setState(uint8_t *state); + + /** + * @brief Function to set the configuration of the algorithm from memory + * @param state : Pointer to a memory location that contains the configuration + */ + void setConfig(const uint8_t *config); + + /** + * @brief Function to set the temperature offset + * @param tempOffset : Temperature offset in degree Celsius + */ + void setTemperatureOffset(float tempOffset) + { + _tempOffset = tempOffset; + } + + + /** + * @brief Function to calculate an int64_t timestamp in milliseconds + */ + int64_t getTimeMs(void); + + /** + * @brief Task that delays for a ms period of time + * @param period : Period of time in ms + */ + static void delay_ms(uint32_t period); + + /** + * @brief Callback function for reading registers over I2C + * @param devId : Library agnostic parameter to identify the device to communicate with + * @param regAddr : Register address + * @param regData : Pointer to the array containing the data to be read + * @param length : Length of the array of data + * @return Zero for success, non-zero otherwise + */ + static int8_t i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length); + + /** + * @brief Callback function for writing registers over I2C + * @param devId : Library agnostic parameter to identify the device to communicate with + * @param regAddr : Register address + * @param regData : Pointer to the array containing the data to be written + * @param length : Length of the array of data + * @return Zero for success, non-zero otherwise + */ + static int8_t i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length); + + /** + * @brief Callback function for reading and writing registers over SPI + * @param devId : Library agnostic parameter to identify the device to communicate with + * @param regAddr : Register address + * @param regData : Pointer to the array containing the data to be read or written + * @param length : Length of the array of data + * @return Zero for success, non-zero otherwise + */ + static int8_t spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length); + +private: + /* Private variables */ + struct bme680_dev _bme680; + struct bme680_field_data _data; + float _tempOffset; + // Global variables to help create a millisecond timestamp that doesn't overflow every 51 days. + // If it overflows, it will have a negative value. Something that should never happen. + uint32_t millisOverflowCounter; + uint32_t lastTime; + + /* Private APIs */ + /** + * @brief Get the version of the BSEC library + */ + void getVersion(void); + + /** + * @brief Read data from the BME680 and process it + * @param currTimeNs: Current time in ns + * @param bme680Settings: BME680 sensor's settings + * @return true if there are new outputs. false otherwise + */ + bool readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings); + + /** + * @brief Set the BME680 sensor's configuration + * @param bme680Settings: Settings to configure the BME680 + * @return BME680 return code. BME680_OK for success, failure otherwise + */ + int8_t setBme680Config(bsec_bme_settings_t bme680Settings); + + /** + * @brief Common code for the begin function + */ + void beginCommon(void); + + /** + * @brief Function to zero the outputs + */ + void zeroOutputs(void); +}; + +#endif diff --git a/lib/Bosch-BSEC/libalgobsec.a b/lib/Bosch-BSEC/src/esp32/libalgobsec.a similarity index 100% rename from lib/Bosch-BSEC/libalgobsec.a rename to lib/Bosch-BSEC/src/esp32/libalgobsec.a diff --git a/lib/Bosch-BSEC/bsec_datatypes.h b/lib/Bosch-BSEC/src/inc/bsec_datatypes.h similarity index 100% rename from lib/Bosch-BSEC/bsec_datatypes.h rename to lib/Bosch-BSEC/src/inc/bsec_datatypes.h diff --git a/lib/Bosch-BSEC/bsec_interface.h b/lib/Bosch-BSEC/src/inc/bsec_interface.h similarity index 100% rename from lib/Bosch-BSEC/bsec_interface.h rename to lib/Bosch-BSEC/src/inc/bsec_interface.h diff --git a/platformio.ini b/platformio.ini index 72fb93c1..21943a92 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,360 +1,343 @@ -; PlatformIO Project Configuration File -; -; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html - - -; ---> SELECT TARGET PLATFORM HERE! <--- -[platformio] -env_default = generic -;env_default = ebox -;env_default = eboxtube -;env_default = heltec -;env_default = heltecv2 -;env_default = ttgov1 -;env_default = ttgov2 -;env_default = ttgov21old -;env_default = ttgov21new -;env_default = ttgobeam_old -;env_default = ttgobeam_new -;env_default = lopy -;env_default = lopy4 -;env_default = fipy -;env_default = lolin32litelora -;env_default = lolin32lora -;env_default = lolin32lite -;env_default = octopus32 -;env_default = ebox, eboxtube, heltec, ttgobeam_old, ttgobeam_new, lopy4, lopy, ttgov21old, ttgov21new -; -description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around. - -[common] -; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.972 -; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! -; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 0 -; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA -upload_protocol = esptool -;upload_protocol = custom -extra_scripts = pre:build.py -keyfile = ota.conf -platform_espressif32 = espressif32@1.5.0 -;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#a7b1fe6 -board_build.partitions = min_spiffs.csv -monitor_speed = 115200 -lib_deps_lora = - MCCI LoRaWAN LMIC library@2.3.0 -lib_deps_display = - U8g2@>=2.25.0 -lib_deps_rgbled = - SmartLeds@>=1.1.3 -lib_deps_gps = - TinyGPSPlus@>=1.0.2 -lib_deps_basic = - ArduinoJson@^5.13.1 - Time@>=1.5 -lib_deps_all = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} - ${common.lib_deps_rgbled} - ${common.lib_deps_gps} -build_flags_basic = - -include "src/hal/${PIOENV}.h" - -include "src/paxcounter.conf" - -w - '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' - '-DCORE_DEBUG_LEVEL=${common.debug_level}' - '-DLOG_LOCAL_LEVEL=${common.debug_level}' - '-DBINTRAY_PACKAGE="${PIOENV}"' - '-DPROGVERSION="${common.release_version}"' -build_flags_sensors = - -Llib/Bosch-BSEC - -llibalgobsec.a -build_flags_all = - ${common.build_flags_basic} - ${common.build_flags_sensors} - -[env:ebox] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 115200 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:eboxtube] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 115200 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_rgbled} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:heltec] -platform = ${common.platform_espressif32} -framework = arduino -board = heltec_wifi_lora_32 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:heltecv2] -platform = ${common.platform_espressif32} -framework = arduino -board = heltec_wifi_lora_32 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:ttgov1] -platform = ${common.platform_espressif32} -framework = arduino -board = ttgo-lora32-v1 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 115200 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:ttgov2] -platform = ${common.platform_espressif32} -framework = arduino -board = ttgo-lora32-v1 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:ttgov21old] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:ttgov21new] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_display} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:ttgobeam_old] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_gps} -build_flags = - ${common.build_flags_all} - -mfix-esp32-psram-cache-issue -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:ttgobeam_new] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_gps} -build_flags = - ${common.build_flags_all} - -mfix-esp32-psram-cache-issue -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:fipy] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_rgbled} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:lopy] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_rgbled} - ${common.lib_deps_gps} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:lopy4] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_rgbled} - ${common.lib_deps_gps} -build_flags = - ${common.build_flags_basic} - -mfix-esp32-psram-cache-issue -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:lolin32litelora] -platform = ${common.platform_espressif32} -framework = arduino -board = lolin32 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_rgbled} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:lolin32lora] -platform = ${common.platform_espressif32} -framework = arduino -board = lolin32 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_rgbled} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:lolin32lite] -platform = ${common.platform_espressif32} -framework = arduino -board = lolin32 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_rgbled} -build_flags = - ${common.build_flags_basic} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:octopus32] -platform = ${common.platform_espressif32} -framework = arduino -board = featheresp32 -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = ${common.lib_deps_all} -build_flags = ${common.build_flags_all} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - -[env:generic] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = ${common.lib_deps_all} -build_flags = ${common.build_flags_all} -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} +; PlatformIO Project Configuration File +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + + +; ---> SELECT TARGET PLATFORM HERE! <--- +[platformio] +env_default = generic +;env_default = ebox +;env_default = eboxtube +;env_default = heltec +;env_default = heltecv2 +;env_default = ttgov1 +;env_default = ttgov2 +;env_default = ttgov21old +;env_default = ttgov21new +;env_default = ttgobeam +;env_default = lopy +;env_default = lopy4 +;env_default = fipy +;env_default = lolin32litelora +;env_default = lolin32lora +;env_default = lolin32lite +;env_default = octopus32 +;env_default = ebox, eboxtube, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new +; +description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around. + +[common] +; for release_version use max. 10 chars total, use any decimal format like "a.b.c" +release_version = 1.7.11 +; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! +; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose +debug_level = 0 +; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA +upload_protocol = esptool +;upload_protocol = custom +extra_scripts = pre:build.py +keyfile = ota.conf +platform_espressif32 = espressif32@1.6.0 +;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage +board_build.partitions = min_spiffs.csv +monitor_speed = 115200 +lib_deps_lora = + MCCI LoRaWAN LMIC library@^2.3.1 +lib_deps_display = + U8g2@>=2.25.0 +lib_deps_rgbled = + SmartLeds@>=1.1.3 +lib_deps_gps = + TinyGPSPlus@>=1.0.2 +lib_deps_basic = + ArduinoJson@^5.13.1 + Time@>=1.5 +lib_deps_all = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} + ${common.lib_deps_rgbled} + ${common.lib_deps_gps} +build_flags_basic = + -include "src/hal/${PIOENV}.h" + -include "src/paxcounter.conf" + -w + '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' + '-DCORE_DEBUG_LEVEL=${common.debug_level}' + '-DLOG_LOCAL_LEVEL=${common.debug_level}' + '-DBINTRAY_PACKAGE="${PIOENV}"' + '-DPROGVERSION="${common.release_version}"' +build_flags_sensors = + -Llib/Bosch-BSEC/src/esp32/ + -lalgobsec +build_flags_all = + ${common.build_flags_basic} + ${common.build_flags_sensors} + +[env:ebox] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +board_build.partitions = ${common.board_build.partitions} +upload_speed = 115200 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:eboxtube] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +board_build.partitions = ${common.board_build.partitions} +upload_speed = 115200 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_rgbled} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:heltec] +platform = ${common.platform_espressif32} +framework = arduino +board = heltec_wifi_lora_32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:heltecv2] +platform = ${common.platform_espressif32} +framework = arduino +board = heltec_wifi_lora_32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:ttgov1] +platform = ${common.platform_espressif32} +framework = arduino +board = ttgo-lora32-v1 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 115200 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:ttgov2] +platform = ${common.platform_espressif32} +framework = arduino +board = ttgo-lora32-v1 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:ttgov21old] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:ttgov21new] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_display} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:ttgobeam] +platform = ${common.platform_espressif32} +framework = arduino +board = ttgo-t-beam +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_gps} +; ${common.lib_deps_display} +build_flags = + ${common.build_flags_all} + -mfix-esp32-psram-cache-issue +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:fipy] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_rgbled} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:lopy] +platform = ${common.platform_espressif32} +framework = arduino +board = lopy +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_rgbled} + ${common.lib_deps_gps} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:lopy4] +platform = ${common.platform_espressif32} +framework = arduino +board = lopy4 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_rgbled} + ${common.lib_deps_gps} +build_flags = + ${common.build_flags_basic} + -mfix-esp32-psram-cache-issue +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:lolin32litelora] +platform = ${common.platform_espressif32} +framework = arduino +board = lolin32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_rgbled} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:lolin32lora] +platform = ${common.platform_espressif32} +framework = arduino +board = lolin32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_rgbled} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:lolin32lite] +platform = ${common.platform_espressif32} +framework = arduino +board = lolin32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_rgbled} +build_flags = + ${common.build_flags_basic} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:octopus32] +platform = ${common.platform_espressif32} +framework = arduino +board = featheresp32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = ${common.lib_deps_all} +build_flags = ${common.build_flags_all} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + +[env:generic] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = ${common.lib_deps_all} +build_flags = ${common.build_flags_all} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} \ No newline at end of file diff --git a/src/TTN/packed_converter.js b/src/TTN/packed_converter.js index 02f17cf3..7548e3ce 100644 --- a/src/TTN/packed_converter.js +++ b/src/TTN/packed_converter.js @@ -4,15 +4,22 @@ function Converter(decoded, port) { var converted = decoded; + var pax = 0; if (port === 1) { - converted.pax = converted.ble + converted.wifi; + if('wifi' in converted){ + pax += converted.wifi + } + + if('ble' in converted){ + pax += converted.ble + } + converted.pax = pax; } if (port === 2) { converted.voltage /= 1000; } - return converted; } \ No newline at end of file diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 938ab1fb..a99f44c6 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -5,12 +5,24 @@ function Decoder(bytes, port) { var decoded = {}; + if (bytes.length === 0) { + return {}; + } + if (port === 1) { - // only counter data, no gps + // only wifi counter data, no gps + if (bytes.length === 2) { + return decode(bytes, [uint16], ['wifi']); + } + // wifi + ble counter data, no gps if (bytes.length === 4) { return decode(bytes, [uint16, uint16], ['wifi', 'ble']); } - // combined counter and gps data + // combined wifi counter and gps data + if (bytes.length === 15) { + return decode(bytes, [uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); + } + // combined wifi + ble counter and gps data if (bytes.length === 17) { return decode(bytes, [uint16, uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); } @@ -46,6 +58,11 @@ function Decoder(bytes, port) { return decode(bytes, [float, uint16, ufloat, ufloat], ['temperature', 'pressure', 'humidity', 'air']); } + if (port === 8) { + // battery voltage + return decode(bytes, [uint16], ['voltage']); + } + } diff --git a/src/TTN/plain_decoder.js b/src/TTN/plain_decoder.js index 6534fb83..ec55dc2c 100644 --- a/src/TTN/plain_decoder.js +++ b/src/TTN/plain_decoder.js @@ -7,8 +7,11 @@ function Decoder(bytes, port) { if (port === 1) { var i = 0; - decoded.wifi = (bytes[i++] << 8) | bytes[i++]; - decoded.ble = (bytes[i++] << 8) | bytes[i++]; + if (bytes.length >= 2) { + decoded.wifi = (bytes[i++] << 8) | bytes[i++];} + + if (bytes.length >= 4) { + decoded.ble = (bytes[i++] << 8) | bytes[i++];} if (bytes.length > 4) { decoded.latitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); diff --git a/src/blecsan.cpp b/src/blecsan.cpp index 042d5f34..c4d10865 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -13,6 +13,7 @@ https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner #include #include #include // needed for BLE_ADDR types, do not remove +#include #define BT_BD_ADDR_HEX(addr) \ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] @@ -243,9 +244,16 @@ esp_err_t register_ble_callback(void) { } // register_ble_callback +#endif // BLECOUNTER + void start_BLEscan(void) { +#ifdef BLECOUNTER ESP_LOGI(TAG, "Initializing bluetooth scanner ..."); + ESP_ERROR_CHECK(esp_coex_preference_set( + (esp_coex_prefer_t) + ESP_COEX_PREFER_BALANCE)); // configure Wifi/BT coexist lib + // Initialize BT controller to allocate task and other resource. btStart(); ESP_ERROR_CHECK(esp_bluedroid_init()); @@ -255,15 +263,18 @@ void start_BLEscan(void) { ESP_ERROR_CHECK(register_ble_callback()); ESP_LOGI(TAG, "Bluetooth scanner started"); +#endif // BLECOUNTER } // start_BLEscan void stop_BLEscan(void) { +#ifdef BLECOUNTER ESP_LOGI(TAG, "Shutting down bluetooth scanner ..."); ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); ESP_ERROR_CHECK(esp_bluedroid_disable()); ESP_ERROR_CHECK(esp_bluedroid_deinit()); - btStop(); // disable & deinit bt_controller + btStop(); // disable bt_controller + ESP_ERROR_CHECK(esp_coex_preference_set(( + esp_coex_prefer_t)ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib ESP_LOGI(TAG, "Bluetooth scanner stopped"); -} // stop_BLEscan - #endif // BLECOUNTER +} // stop_BLEscan diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 6203d928..bb420db4 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -8,82 +8,97 @@ static const char TAG[] = "main"; bmeStatus_t bme_status; TaskHandle_t BmeTask; -float bme_offset = (float) BME_TEMP_OFFSET; +bsec_virtual_sensor_t sensorList[10] = { + BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + BSEC_OUTPUT_RAW_HUMIDITY, + BSEC_OUTPUT_RAW_GAS, + BSEC_OUTPUT_IAQ, + BSEC_OUTPUT_STATIC_IAQ, + BSEC_OUTPUT_CO2_EQUIVALENT, + BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, +}; -// --- Bosch BSEC library configuration --- -// 3,3V supply voltage; 3s max time between sensor_control calls; 4 days -// calibration. Change this const if not applicable for your application (see -// BME680 datasheet) -const uint8_t bsec_config_iaq[454] = { - 1, 7, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 174, 1, 0, - 0, 48, 0, 1, 0, 137, 65, 0, 63, 205, 204, 204, 62, 0, 0, - 64, 63, 205, 204, 204, 62, 0, 0, 225, 68, 0, 192, 168, 71, 64, - 49, 119, 76, 0, 0, 0, 0, 0, 80, 5, 95, 0, 0, 0, 0, - 0, 0, 0, 0, 28, 0, 2, 0, 0, 244, 1, 225, 0, 25, 0, - 0, 128, 64, 0, 0, 32, 65, 144, 1, 0, 0, 112, 65, 0, 0, - 0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, - 215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 88, 0, 9, - 0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27, - 156, 62, 225, 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, 160, 191, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97, - 64, 65, 241, 99, 190, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121, - 71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 254, 0, 2, 1, 5, 48, - 117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4, - 144, 1, 64, 1, 64, 1, 144, 1, 48, 117, 48, 117, 48, 117, 48, - 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, - 100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48, - 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, - 100, 0, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, - 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, - 44, 1, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, - 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, - 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, - 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, - 255, 255, 255, 255, 255, 255, 220, 5, 220, 5, 220, 5, 255, 255, 255, - 255, 255, 255, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, - 239, 79, 0, 0}; +uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; +uint16_t stateUpdateCounter = 0; + +Bsec iaqSensor; // initialize BME680 sensor int bme_init(void) { - // struct bme680_dev gas_sensor; - Wire.begin(HAS_BME, 400000); // I2C connect to BME680 sensor with 400 KHz + // return = 0 -> error / return = 1 -> success - // Call to the function which initializes the BSEC library - // Switch on low-power mode and provide no temperature offset + // block i2c bus access + if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == + pdTRUE) { + + Wire.begin(HAS_BME); + iaqSensor.begin(BME_ADDR, Wire); + + ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major, + iaqSensor.version.minor, iaqSensor.version.major_bugfix, + iaqSensor.version.minor_bugfix); + + iaqSensor.setConfig(bsec_config_iaq); + + if (checkIaqSensorStatus()) + ESP_LOGI(TAG, "BME680 sensor found and initialized"); + else { + ESP_LOGE(TAG, "BME680 sensor not found"); + goto error; + } + + loadState(); + + iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); + iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); + + if (checkIaqSensorStatus()) + ESP_LOGI(TAG, "BSEC subscription succesful"); + else { + ESP_LOGE(TAG, "BSEC subscription error"); + goto error; + } - return_values_init ret = - bsec_iot_init(BSEC_SAMPLE_RATE_LP, bme_offset, i2c_write, i2c_read, - user_delay_ms, state_load, config_load); - - if ((int)ret.bme680_status) { - ESP_LOGE(TAG, "Could not initialize BME680, error %d", - (int)ret.bme680_status); - } else if ((int)ret.bsec_status) { - ESP_LOGE(TAG, "Could not initialize BSEC library, error %d", - (int)ret.bsec_status); } else { - ESP_LOGI(TAG, "BME680 sensor found and initialized"); - return 1; + ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error"); + goto error; } + + xSemaphoreGive(I2Caccess); // release i2c bus access + return 1; + +error: + xSemaphoreGive(I2Caccess); // release i2c bus access return 0; -} -void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, - float temperature, float humidity, float pressure, - float raw_temperature, float raw_humidity, float gas, - bsec_library_return_t bsec_status, float static_iaq, - float co2_equivalent, float breath_voc_equivalent) { +} // bme_init() - bme_status.temperature = temperature; - bme_status.humidity = humidity; - bme_status.pressure = (pressure / 100.0); // conversion Pa -> hPa - bme_status.iaq = iaq; -} +// Helper function definitions +int checkIaqSensorStatus(void) { + int rslt = 1; // true = 1 = no error, false = 0 = error + + if (iaqSensor.status != BSEC_OK) { + rslt = 0; + if (iaqSensor.status < BSEC_OK) + ESP_LOGE(TAG, "BSEC error %d", iaqSensor.status); + else + ESP_LOGW(TAG, "BSEC warning %d", iaqSensor.status); + } + + if (iaqSensor.bme680Status != BME680_OK) { + rslt = 0; + if (iaqSensor.bme680Status < BME680_OK) + ESP_LOGE(TAG, "BME680 error %d", iaqSensor.bme680Status); + else + ESP_LOGW(TAG, "BME680 warning %d", iaqSensor.bme680Status); + } + + return rslt; +} // checkIaqSensorStatus() // loop function which reads and processes data based on sensor settings void bme_loop(void *pvParameters) { @@ -91,90 +106,68 @@ void bme_loop(void *pvParameters) { configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check #ifdef HAS_BME - // State is saved every 10.000 samples, which means every 10.000 * 3 secs = - // 500 minutes - bsec_iot_loop(user_delay_ms, get_timestamp_us, output_ready, state_save, - 10000); + // block i2c bus access + while (xSemaphoreTake(I2Caccess, portMAX_DELAY) == pdTRUE) { + + if (iaqSensor.run()) { // If new data is available + bme_status.raw_temperature = iaqSensor.rawTemperature; + bme_status.raw_humidity = iaqSensor.rawHumidity; + bme_status.temperature = iaqSensor.temperature; + bme_status.humidity = iaqSensor.humidity; + bme_status.pressure = + (iaqSensor.pressure / 100.0); // conversion Pa -> hPa + bme_status.iaq = iaqSensor.iaqEstimate; + bme_status.iaq_accuracy = iaqSensor.iaqAccuracy; + bme_status.gas = iaqSensor.gasResistance; + updateState(); + } + xSemaphoreGive(I2Caccess); // release i2c bus access + + } // while #endif + ESP_LOGE(TAG, "BME task ended"); vTaskDelete(BmeTask); // should never be reached + } // bme_loop() -int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len) { - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - uint16_t i; +void loadState(void) { + if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] == BSEC_MAX_STATE_BLOB_SIZE) { + // Existing state in NVS stored + ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); + memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); + iaqSensor.setState(bsecstate_buffer); + checkIaqSensorStatus(); + } else // no state stored + ESP_LOGI(TAG, + "no BSEC state stored in NVRAM, starting sensor with defaults"); +} - Wire.beginTransmission(dev_id); - Wire.write(reg_addr); - rslt = Wire.endTransmission(); +void updateState(void) { + bool update = false; - Wire.requestFrom((int)dev_id, (int)len); - for (i = 0; (i < len) && Wire.available(); i++) { - reg_data[i] = Wire.read(); + if (stateUpdateCounter == 0) { + // first state update when IAQ accuracy is >= 1 + if (iaqSensor.iaqAccuracy >= 1) { + update = true; + stateUpdateCounter++; + } + } else { + + /* Update every STATE_SAVE_PERIOD minutes */ + if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { + update = true; + stateUpdateCounter++; + } } - return rslt; -} - -int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len) { - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - uint16_t i; - - Wire.beginTransmission(dev_id); - Wire.write(reg_addr); - for (i = 0; i < len; i++) { - Wire.write(reg_data[i]); + if (update) { + iaqSensor.getState(bsecstate_buffer); + checkIaqSensorStatus(); + memcpy(cfg.bsecstate, bsecstate_buffer, BSEC_MAX_STATE_BLOB_SIZE); + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = BSEC_MAX_STATE_BLOB_SIZE; + ESP_LOGI(TAG, "saving BSEC state to NVRAM"); + saveConfig(); } - rslt = Wire.endTransmission(); - - return rslt; } -/*! - * @brief Load previous library state from non-volatile memory - * - * @param[in,out] state_buffer buffer to hold the loaded state string - * @param[in] n_buffer size of the allocated state buffer - * - * @return number of bytes copied to state_buffer - */ -uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer) { - // ... - // Load a previous library state from non-volatile memory, if available. - // - // Return zero if loading was unsuccessful or no state was available, - // otherwise return length of loaded state string. - // ... - return 0; -} - -/*! - * @brief Save library state to non-volatile memory - * - * @param[in] state_buffer buffer holding the state to be stored - * @param[in] length length of the state string to be stored - * - * @return none - */ -void state_save(const uint8_t *state_buffer, uint32_t length) { - // ... - // Save the string some form of non-volatile memory, if possible. - // ... -} - -uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer) { - - // Load a library config from non-volatile memory, if available. - // Return zero if loading was unsuccessful or no config was available, - // otherwise return length of loaded config string. - - memcpy(config_buffer, bsec_config_iaq, sizeof(bsec_config_iaq)); - return sizeof(bsec_config_iaq); -} - -void user_delay_ms(uint32_t period) { vTaskDelay(period / portTICK_PERIOD_MS); } - -int64_t get_timestamp_us() { return (int64_t)millis() * 1000; } - #endif // HAS_BME \ No newline at end of file diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 7222447f..dd4fdcbd 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -25,13 +25,15 @@ void defaultConfig() { cfg.blescantime = BLESCANINTERVAL / 10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) - cfg.blescan = 1; // 0=disabled, 1=enabled + cfg.blescan = 0; // 0=disabled, 1=enabled cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) cfg.vendorfilter = 1; // 0=disabled, 1=enabled cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) cfg.monitormode = 0; // 0=disabled, 1=enabled cfg.runmode = 0; // 0=normal, 1=update cfg.payloadmask = 0xFF; // all payload switched on + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { + 0}; // init BSEC state for BME680 sensor strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); } @@ -77,8 +79,15 @@ void saveConfig() { int8_t flash8 = 0; int16_t flash16 = 0; size_t required_size; + uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; char storedversion[10]; + if (nvs_get_blob(my_handle, "bsecstate", bsecstate_buffer, + &required_size) != ESP_OK || + memcmp(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE + 1) != 0) + nvs_set_blob(my_handle, "bsecstate", cfg.bsecstate, + BSEC_MAX_STATE_BLOB_SIZE + 1); + if (nvs_get_str(my_handle, "version", storedversion, &required_size) != ESP_OK || strcmp(storedversion, cfg.version) != 0) @@ -202,7 +211,14 @@ void loadConfig() { migrateVersion(); } - // overwrite defaults with valid values from NVRAM + // populate pre set defaults with current values from NVRAM + + if (nvs_get_blob(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { + nvs_get_blob(my_handle, "bsecstate", cfg.bsecstate, &required_size); + ESP_LOGI(TAG, "bsecstate = %d", + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]); + }; + if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { cfg.lorasf = flash8; ESP_LOGI(TAG, "lorasf = %d", flash8); @@ -317,9 +333,9 @@ void loadConfig() { if (nvs_get_i8(my_handle, "payloadmask", &flash8) == ESP_OK) { cfg.payloadmask = flash8; - ESP_LOGI(TAG, "payloadmask = %u", flash8); + ESP_LOGI(TAG, "payloadmask = %d", flash8); } else { - ESP_LOGI(TAG, "payloadmask set to default %u", cfg.payloadmask); + ESP_LOGI(TAG, "payloadmask set to default %d", cfg.payloadmask); saveConfig(); } diff --git a/src/cyclic.cpp b/src/cyclic.cpp index b0bc812d..13518cf5 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -26,48 +26,73 @@ void doHousekeeping() { // time sync once per TIME_SYNC_INTERVAL #ifdef TIME_SYNC_INTERVAL if (millis() >= nextTimeSync) { - nextTimeSync = millis() + TIME_SYNC_INTERVAL * - 60000; // set up next time sync period + nextTimeSync = + millis() + TIME_SYNC_INTERVAL * 60000; // set up next time sync period do_timesync(); } #endif // task storage debugging // - ESP_LOGD(TAG, "Wifiloop %d bytes left", - uxTaskGetStackHighWaterMark(wifiSwitchTask)); - ESP_LOGD(TAG, "IRQhandler %d bytes left", - uxTaskGetStackHighWaterMark(irqHandlerTask)); + ESP_LOGD(TAG, "Wifiloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(wifiSwitchTask), + eTaskGetState(wifiSwitchTask)); + ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(irqHandlerTask), + eTaskGetState(irqHandlerTask)); #ifdef HAS_GPS - ESP_LOGD(TAG, "Gpsloop %d bytes left", uxTaskGetStackHighWaterMark(GpsTask)); + ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask)); #endif #ifdef HAS_BME - ESP_LOGD(TAG, "Bmeloop %d bytes left", uxTaskGetStackHighWaterMark(BmeTask)); + ESP_LOGD(TAG, "Bmeloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(BmeTask), eTaskGetState(BmeTask)); #endif #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) - ESP_LOGD(TAG, "LEDloop %d bytes left", - uxTaskGetStackHighWaterMark(ledLoopTask)); + ESP_LOGD(TAG, "LEDloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(ledLoopTask), + eTaskGetState(ledLoopTask)); #endif // read battery voltage into global variable #ifdef HAS_BATTERY_PROBE batt_voltage = read_voltage(); - ESP_LOGI(TAG, "Measured Voltage: %dmV", batt_voltage); + ESP_LOGI(TAG, "Voltage: %dmV", batt_voltage); #endif - // check free memory - if (esp_get_minimum_free_heap_size() <= MEM_LOW) { +// display BME sensor data +#ifdef HAS_BME + ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f | IAQacc: %d", + bme_status.temperature, bme_status.iaq, bme_status.iaq_accuracy); +#endif + + // check free heap memory + if (ESP.getMinFreeHeap() <= 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()); + ESP.getMinFreeHeap(), ESP.getFreeHeap()); SendPayload(COUNTERPORT); // send data before clearing counters - reset_counters(); // clear macs container and reset all counters - get_salt(); // get new salt for salting hashes + reset_counters(); // clear macs container and reset all counters + get_salt(); // get new salt for salting hashes - if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again - do_reset(); // memory leak, reset device + if (ESP.getMinFreeHeap() <= MEM_LOW) // check again + do_reset(); // memory leak, reset device } + +// check free PSRAM memory +#ifdef BOARD_HAS_PSRAM + if (ESP.getMinFreePsram() <= MEM_LOW) { + ESP_LOGI(TAG, "PSRAM full, counter cleared"); + SendPayload(COUNTERPORT); // send data before clearing 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 + do_reset(); // memory leak, reset device + } +#endif + } // doHousekeeping() // uptime counter 64bit to prevent millis() rollover after 49 days @@ -80,6 +105,14 @@ uint64_t uptime() { return (uint64_t)high32 << 32 | low32; } +uint32_t getFreeRAM() { +#ifndef BOARD_HAS_PSRAM + return ESP.getFreeHeap(); +#else + return ESP.getFreePsram(); +#endif +} + void reset_counters() { macs.clear(); // clear all macs container macs_total = 0; // reset all counters @@ -89,7 +122,8 @@ void reset_counters() { void do_timesync() { #ifdef TIME_SYNC_INTERVAL -// sync time & date if we have valid gps time + +// sync time & date by GPS if we have valid gps time #ifdef HAS_GPS if (gps.time.isValid()) { setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), @@ -101,9 +135,14 @@ void do_timesync() { ESP_LOGI(TAG, "No valid GPS time"); } #endif // HAS_GPS + +// sync time by LoRa Network if network supports DevTimeReq +#ifdef LMIC_ENABLE_DeviceTimeReq // Schedule a network time request at the next possible time LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime); ESP_LOGI(TAG, "Network time request scheduled"); +#endif + #endif // TIME_SYNC_INTERVAL } // do_timesync() diff --git a/src/display.cpp b/src/display.cpp index ec187da4..861328fd 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -43,14 +43,14 @@ void init_display(const char *Productname, const char *Version) { u8x8.draw2x2String(0, 0, Productname); u8x8.setInverseFont(0); u8x8.draw2x2String(2, 2, Productname); - vTaskDelay(1500 / portTICK_PERIOD_MS); + delay(1500); u8x8.clear(); u8x8.setFlipMode(1); u8x8.setInverseFont(1); u8x8.draw2x2String(0, 0, Productname); u8x8.setInverseFont(0); u8x8.draw2x2String(2, 2, Productname); - vTaskDelay(1500 / portTICK_PERIOD_MS); + delay(1500); u8x8.setFlipMode(0); u8x8.clear(); @@ -81,7 +81,7 @@ void init_display(const char *Productname, const char *Version) { DisplayKey(buf, 8, true); #endif // HAS_LORA - vTaskDelay(3000 / portTICK_PERIOD_MS); + delay(3000); u8x8.clear(); u8x8.setPowerSave(!cfg.screenon); // set display off if disabled u8x8.draw2x2String(0, 0, "PAX:0"); @@ -98,99 +98,104 @@ void init_display(const char *Productname, const char *Version) { void refreshtheDisplay() { - // set display on/off according to current device configuration - if (DisplayState != cfg.screenon) { - DisplayState = cfg.screenon; - u8x8.setPowerSave(!cfg.screenon); - } + // block i2c bus access + if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == + pdTRUE) { - // if display is switched off we don't refresh it and save time - if (!DisplayState) - return; + // set display on/off according to current device configuration + if (DisplayState != cfg.screenon) { + DisplayState = cfg.screenon; + u8x8.setPowerSave(!cfg.screenon); + } - uint8_t msgWaiting; - char buff[16]; // 16 chars line buffer + // if display is switched off we don't refresh it and save time + if (!DisplayState) + return; - // update counter (lines 0-1) - 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 + uint8_t msgWaiting; + char buff[16]; // 16 chars line buffer + + // update counter (lines 0-1) + 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 // update Battery status (line 2) #ifdef HAS_BATTERY_PROBE - u8x8.setCursor(0, 2); - u8x8.printf(batt_voltage > 4000 ? "B:USB " : "B:%.1fV", - batt_voltage / 1000.0); + u8x8.setCursor(0, 2); + u8x8.printf("B:%.1fV", batt_voltage / 1000.0); #endif // update GPS status (line 2) #ifdef HAS_GPS - u8x8.setCursor(9, 2); - if (!gps.location.isValid()) // if no fix then display Sats value inverse - { - u8x8.setInverseFont(1); - u8x8.printf("Sats:%.2d", gps.satellites.value()); - u8x8.setInverseFont(0); - } else - u8x8.printf("Sats:%.2d", gps.satellites.value()); + u8x8.setCursor(9, 2); + if (!gps.location.isValid()) // if no fix then display Sats value inverse + { + u8x8.setInverseFont(1); + u8x8.printf("Sats:%.2d", gps.satellites.value()); + u8x8.setInverseFont(0); + } else + u8x8.printf("Sats:%.2d", gps.satellites.value()); #endif - // update bluetooth counter + LoRa SF (line 3) + // update bluetooth counter + LoRa SF (line 3) #ifdef BLECOUNTER - u8x8.setCursor(0, 3); - if (cfg.blescan) - u8x8.printf("BLTH:%-4d", macs_ble); - else - u8x8.printf("%s", "BLTH:off"); + u8x8.setCursor(0, 3); + if (cfg.blescan) + u8x8.printf("BLTH:%-4d", macs_ble); + else + u8x8.printf("%s", "BLTH:off"); #endif #ifdef HAS_LORA - u8x8.setCursor(11, 3); - 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); + u8x8.setCursor(11, 3); + 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); #endif // HAS_LORA - // update wifi counter + channel display (line 4) - u8x8.setCursor(0, 4); - u8x8.printf("WIFI:%-4d", macs_wifi); - u8x8.setCursor(11, 4); - u8x8.printf("ch:%02d", channel); + // update wifi counter + channel display (line 4) + u8x8.setCursor(0, 4); + u8x8.printf("WIFI:%-4d", macs_wifi); + u8x8.setCursor(11, 4); + u8x8.printf("ch:%02d", channel); - // update RSSI limiter status & free memory display (line 5) - u8x8.setCursor(0, 5); - u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); - u8x8.setCursor(10, 5); - u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); + // update RSSI limiter status & free memory display (line 5) + u8x8.setCursor(0, 5); + u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); + u8x8.setCursor(10, 5); + u8x8.printf("%4dKB", getFreeRAM() / 1024); #ifdef HAS_LORA - // update LoRa status display (line 6) - u8x8.setCursor(0, 6); - u8x8.printf("%-16s", display_line6); + // update LoRa status display (line 6) + u8x8.setCursor(0, 6); + u8x8.printf("%-16s", display_line6); - // update LMiC event display (line 7) - u8x8.setCursor(0, 7); - u8x8.printf("%-14s", display_line7); + // update LMiC event display (line 7) + u8x8.setCursor(0, 7); + u8x8.printf("%-14s", display_line7); - // update LoRa send queue display (line 7) - msgWaiting = uxQueueMessagesWaiting(LoraSendQueue); - if (msgWaiting) { - sprintf(buff, "%2d", msgWaiting); - u8x8.setCursor(14, 7); - u8x8.setInverseFont(1); - u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff); - u8x8.setInverseFont(0); - } else - u8x8.printf(" "); + // update LoRa send queue display (line 7) + msgWaiting = uxQueueMessagesWaiting(LoraSendQueue); + if (msgWaiting) { + sprintf(buff, "%2d", msgWaiting); + u8x8.setCursor(14, 7); + u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff); + } else + u8x8.printf(" "); #endif // HAS_LORA + xSemaphoreGive(I2Caccess); // release i2c bus access + } + } // refreshDisplay() #endif // HAS_DISPLAY \ No newline at end of file diff --git a/src/gpsread.cpp b/src/gpsread.cpp index e804630f..48f5a451 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -70,12 +70,12 @@ void gps_loop(void *pvParameters) { Wire.requestFrom(GPS_ADDR, 32); // caution: this is a blocking call while (Wire.available()) { gps.encode(Wire.read()); - vTaskDelay(2 / portTICK_PERIOD_MS); // 2ms delay according L76 datasheet + delay(2); // 2ms delay according L76 datasheet } #endif } // if - vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU + delay(2); // yield to CPU } // end of infinite loop diff --git a/src/hal/generic.h b/src/hal/generic.h index ad88536f..c4e6deb9 100644 --- a/src/hal/generic.h +++ b/src/hal/generic.h @@ -17,8 +17,8 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 #define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors diff --git a/src/hal/lopy.h b/src/hal/lopy.h index a7d92dad..be36175b 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -1,46 +1,35 @@ -// clang-format off - -#ifndef _LOPY_H -#define _LOPY_H - -#include - -// Hardware related definitions for Pycom LoPy Board (NOT LoPy4) - -#define HAS_LORA 1 // comment out if device shall not send data via LoRa -#define CFG_sx1272_radio 1 -#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED -#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 - -// Pins for LORA chip SPI interface come from board file, we need some -// additional definitions for LMIC -#define LORA_SCK 5 // GPIO5 - SX1276 SCK -#define LORA_MISO 19 // GPIO19 - SX1276 MISO -#define LORA_MOSI 27 // GPIO27 - SX1276 MOSI -#define LORA_CS 17 // GPIO17 - SX1276 CS -#define LORA_RST 18 // GPIO18 - SX1276 RST -#define LORA_IRQ 23 // GPIO23 - SX1276 IO0 -#define LORA_IO0 LORA_IRQ // alias -#define LORA_IO1 LORA_IRQ // tied by diode to IO0 -#define LORA_IO2 LORA_IRQ // tied by diode to IO0 - - -// select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH (16) // pin for switching wifi antenna -#define WIFI_ANTENNA 0 // 0 = internal, 1 = external - -// uncomment this only if your LoPy runs on a PYTRACK BOARD -#define HAS_GPS 1 -#define GPS_I2C GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -#define GPS_ADDR 0x10 - -// uncomment this only if your LoPy runs on a EXPANSION BOARD -//#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED -//#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED -//#define HAS_BUTTON (13) // user button on expansion board -//#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown -//#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 -//#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm -> expansion board 3.0 -//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 - -#endif +// clang-format off + +#ifndef _LOPY_H +#define _LOPY_H + +#include + +// Hardware related definitions for Pycom LoPy Board (NOT LoPy4) + +#define HAS_LORA 1 // comment out if device shall not send data via LoRa +#define CFG_sx1272_radio 1 +#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED +#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 + +// Note: Pins for LORA chip SPI interface come from board file pins_arduino.h + +// select WIFI antenna (internal = onboard / external = u.fl socket) +#define HAS_ANTENNA_SWITCH (16) // pin for switching wifi antenna +#define WIFI_ANTENNA 0 // 0 = internal, 1 = external + +// uncomment this only if your LoPy runs on a PYTRACK BOARD +#define HAS_GPS 1 +#define GPS_I2C GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +#define GPS_ADDR 0x10 + +// uncomment this only if your LoPy runs on a EXPANSION BOARD +//#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED +//#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED +//#define HAS_BUTTON (13) // user button on expansion board +//#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +//#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +//#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm -> expansion board 3.0 +//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 + +#endif diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 265ea171..badd4f8b 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -1,54 +1,44 @@ -// clang-format off - -#ifndef _LOPY4_H -#define _LOPY4_H - -#include - -// Hardware related definitions for Pycom LoPy4 Board - -#define HAS_LORA 1 // comment out if device shall not send data via LoRa - -#define HAS_SPI 1 // comment out if device shall not send data via SPI -// pin definitions for local wired SPI slave interface -#define SPI_MOSI GPIO_NUM_22 -#define SPI_MISO GPIO_NUM_33 -#define SPI_SCLK GPIO_NUM_26 -#define SPI_CS GPIO_NUM_36 - -#define CFG_sx1276_radio 1 -//#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED -#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 (P2) -#define BOARD_HAS_PSRAM // use extra 4MB extern RAM - -// Pins for LORA chip SPI interface come from board file, we need some -// additional definitions for LMIC -#define LORA_SCK 5 // GPIO5 - SX1276 SCK -#define LORA_MISO 19 // GPIO19 - SX1276 MISO -#define LORA_MOSI 27 // GPIO27 - SX1276 MOSI -#define LORA_CS 18 // GPIO18 - SX1276 CS -#define LORA_IRQ 23 // GPIO23 - SX1276 IO0 -#define LORA_IO0 LORA_IRQ // alias -#define LORA_IO1 LORA_IRQ // tied by diode to IO0 -#define LORA_IO2 LORA_IRQ // tied by diode to IO0 -#define LORA_RST NOT_A_PIN - -// select WIFI antenna (internal = onboard / external = u.fl socket) -#define HAS_ANTENNA_SWITCH (21) // pin for switching wifi antenna (P12) -#define WIFI_ANTENNA 0 // 0 = internal, 1 = external - -// uncomment this only if your LoPy runs on a PYTRACK BOARD -//#define HAS_GPS 1 -//#define GPS_I2C GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -//#define GPS_ADDR 0x10 - -// uncomment this only if your LoPy runs on a EXPANSION BOARD -#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED -#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED -#define HAS_BUTTON (13) // user button on expansion board -#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown -#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 -#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm -> expansion board 3.0 -//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 - +// clang-format off + +#ifndef _LOPY4_H +#define _LOPY4_H + +#include + +// Hardware related definitions for Pycom LoPy4 Board + +#define HAS_LORA 1 // comment out if device shall not send data via LoRa + +//#defin HAS_SPI 1 // comment out if device shall not send data via SPI +// pin definitions for local wired SPI slave interface +//#define SPI_MOSI GPIO_NUM_22 +//#define SPI_MISO GPIO_NUM_33 +//#define SPI_SCLK GPIO_NUM_26 +//#define SPI_CS GPIO_NUM_36 + +#define CFG_sx1276_radio 1 +//#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED +#define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 (P2) +#define BOARD_HAS_PSRAM // use extra 4MB extern RAM + +// Note: Pins for LORA chip SPI interface come from board file pins_arduino.h + +// select WIFI antenna (internal = onboard / external = u.fl socket) +#define HAS_ANTENNA_SWITCH (21) // pin for switching wifi antenna (P12) +#define WIFI_ANTENNA 0 // 0 = internal, 1 = external + +// uncomment this only if your LoPy runs on a PYTRACK BOARD +//#define HAS_GPS 1 +//#define GPS_I2C GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +//#define GPS_ADDR 0x10 + +// uncomment this only if your LoPy runs on a EXPANSION BOARD +#define HAS_LED (12) // use if LoPy is on Expansion Board, this has a user LED +#define LED_ACTIVE_LOW 1 // use if LoPy is on Expansion Board, this has a user LED +#define HAS_BUTTON (13) // user button on expansion board +#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +#define HAS_BATTERY_PROBE ADC1_GPIO39_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +#define BATT_FACTOR 2 // voltage divider 1MOhm/1MOhm -> expansion board 3.0 +//#define BATT_FACTOR 4 // voltage divider 115kOhm/56kOhm -> expansion board 2.0 + #endif \ No newline at end of file diff --git a/src/hal/octopus32.h b/src/hal/octopus32.h index a63b399b..288c286b 100644 --- a/src/hal/octopus32.h +++ b/src/hal/octopus32.h @@ -11,11 +11,9 @@ // disable brownout detection (avoid unexpected reset on some boards) #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -// enable only if device has these sensors, otherwise comment these lines -// BME680 sensor on I2C bus // Octopus32 has a pre-populated BME680 on i2c addr 0x76 #define HAS_BME GPIO_NUM_23, GPIO_NUM_22 // SDA, SCL -//#define HAS_BME 0x76 +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam.h similarity index 59% rename from src/hal/ttgobeam_new.h rename to src/hal/ttgobeam.h index 93f729a3..4b823e04 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam.h @@ -6,41 +6,37 @@ #include // Hardware related definitions for TTGO T-Beam board +// (only) for older T-Beam version T22_V05 eternal wiring LORA_IO1 to GPIO33 is needed! // // pinouts taken from http://tinymicros.com/wiki/TTGO_T-Beam -// -// enable only if device has these sensors, otherwise comment these lines -// BME680 sensor on I2C bus -// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 -// -//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -#define HAS_LED GPIO_NUM_14 // on board green LED - -// user defined sensors -//#define HAS_SENSORS 1 // comment out if device has user defined sensors +#define HAS_LED GPIO_NUM_14 // on board green LED, only new version TTGO-BEAM V07 +//#define HAS_LED GPIO_NUM_21 // on board green LED, only old verison TTGO-BEAM V05 #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define BOARD_HAS_PSRAM // use extra 4MB external RAM - -//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature - -#define HAS_BUTTON GPIO_NUM_39 // on board button "SW5" - +#define HAS_BUTTON GPIO_NUM_39 // on board button (next to reset) #define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define BATT_FACTOR 2 // voltage divider 100k/100k on board #define HAS_GPS 1 // use on board GPS #define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration -// Pins for LORA chip SPI interface, reset line and interrupt lines -#define LORA_SCK (5) -#define LORA_CS (18) -#define LORA_MISO (19) -#define LORA_MOSI (27) -#define LORA_RST (23) -#define LORA_IRQ (26) -#define LORA_IO1 (33) // for T-Beam T22_V05 and T22_V07, for other versions use ttgobeam_old.h -#define LORA_IO2 (32) +// enable only if device has these sensors, otherwise comment these lines +// BME680 sensor on I2C bus +//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND + +// display (if connected) +//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +//#define MY_OLED_SDA (21) +//#define MY_OLED_SCL (22) +//#define MY_OLED_RST U8X8_PIN_NONE +//#define DISPLAY_FLIP 1 // use if display is rotated + +// user defined sensors (if connected) +//#define HAS_SENSORS 1 // comment out if device has user defined sensors + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #endif \ No newline at end of file diff --git a/src/hal/ttgobeam_old.h b/src/hal/ttgobeam_old.h index e7d39287..4c5d1981 100644 --- a/src/hal/ttgobeam_old.h +++ b/src/hal/ttgobeam_old.h @@ -9,16 +9,21 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -// attention: Pin21 is also LED! set HAS_LED to NOT_A_PIN if using BME280 -// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 -//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -//#define HAS_LED NOT_A_PIN // on board green LED +#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND +#define HAS_LED NOT_A_PIN // on board green LED uses same GPIO as SDA! -#define HAS_LED GPIO_NUM_21 // on board green LED +// #define HAS_LED GPIO_NUM_21 // on board green LED // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors +//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +//#define MY_OLED_SDA (21) +//#define MY_OLED_SCL (22) +//#define MY_OLED_RST U8X8_PIN_NONE +//#define DISPLAY_FLIP 1 // use if display is rotated + #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define BOARD_HAS_PSRAM // use extra 4MB external RAM diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index f79e035e..a9192a2b 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -61,7 +61,7 @@ void IRAM_ATTR SendCycleIRQ() { #ifdef HAS_DISPLAY void IRAM_ATTR DisplayIRQ() { - xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL); + xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL); portYIELD_FROM_ISR(); } #endif diff --git a/src/led.cpp b/src/led.cpp index 8a90f9ec..a52315c5 100644 --- a/src/led.cpp +++ b/src/led.cpp @@ -190,7 +190,7 @@ void ledLoop(void *parameter) { previousLEDState = LEDState; } // give yield to CPU - vTaskDelay(2 / portTICK_PERIOD_MS); + delay(2); } // while(1) vTaskDelete(ledLoopTask); // shoud never be reached }; // ledloop() diff --git a/src/lmic_config.h b/src/lmic_config.h index 5197f046..a28f24a5 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -22,7 +22,7 @@ //#define LMIC_USE_INTERRUPTS //time sync via LoRaWAN network, is not yet supported by TTN (LoRaWAN spec v1.0.3) -#define LMIC_ENABLE_DeviceTimeReq 1 +//#define LMIC_ENABLE_DeviceTimeReq 1 // 16 μs per tick // LMIC requires ticks to be 15.5μs - 100 μs long @@ -34,7 +34,7 @@ // faster or slower. This causes the transceiver to be earlier switched on, // so consuming more power. You may sharpen (reduce) this value if you are // limited on battery. -#define CLOCK_ERROR_PROCENTAGE 20 +#define CLOCK_ERROR_PROCENTAGE 3 // Set this to 1 to enable some basic debug output (using printf) about // RF settings used during transmission and reception. Set to 2 to @@ -89,10 +89,12 @@ // 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 +//#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 +// +#define USE_MBEDTLS_AES diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 9102376c..05cab168 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -222,13 +222,6 @@ void onEvent(ev_t ev) { : PSTR("TX_COMPLETE")); sprintf(display_line6, " "); // clear previous lmic status - // if (LMIC.dataLen) { - // ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", - // LMIC.dataLen, (signed char)LMIC.rssi, (signed - // char)LMIC.snr); - // sprintf(display_line6, "RSSI %d SNR %d", (signed char)LMIC.rssi, - // (signed char)LMIC.snr); - if (LMIC.dataLen) { ESP_LOGI(TAG, "Received %d bytes of payload, RSSI -%d SNR %d", LMIC.dataLen, LMIC.rssi, LMIC.snr / 4); diff --git a/src/macsniff.cpp b/src/macsniff.cpp index 920ec091..b1e5ffcc 100644 --- a/src/macsniff.cpp +++ b/src/macsniff.cpp @@ -119,7 +119,8 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { "%d Bytes left", added ? "new " : "known", sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff, - hashedmac, macs_wifi, macs_ble, ESP.getFreeHeap()); + hashedmac, macs_wifi, macs_ble, getFreeRAM()); + #ifdef VENDORFILTER } else { // Very noisy diff --git a/src/main.cpp b/src/main.cpp index 4f28e064..609243f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,9 +35,14 @@ IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer looptask 1 1 arduino core -> runs the LMIC LoRa stack irqhandler 1 1 executes tasks triggered by irq gpsloop 1 2 reads data from GPS via serial or i2c -bmeloop 1 2 reads data from BME sensor via i2c +bmeloop 1 1 reads data from BME sensor via i2c IDLE 1 0 ESP32 arduino scheduler +Low priority numbers denote low priority tasks. + +Tasks using i2c bus all must have same priority, because using mutex semaphore +(irqhandler, bmeloop) + ESP32 hardware timers ========================== 0 Trigger display refresh @@ -55,12 +60,14 @@ char display_line6[16], display_line7[16]; // display buffers uint8_t volatile channel = 0; // channel rotation counter uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0, batt_voltage = 0; // globals for display - hw_timer_t *channelSwitch = NULL, *sendCycle = NULL, *homeCycle = NULL, *displaytimer = NULL; // irq tasks TaskHandle_t irqHandlerTask, wifiSwitchTask; +SemaphoreHandle_t I2Caccess; -std::set macs; // container holding unique MAC adress hashes +// container holding unique MAC address hashes with Memory Alloctor using PSRAM, +// if present +std::set, Mallocator> macs; // initialize payload encoder PayloadConvert payload(PAYLOAD_BUFFER_SIZE); @@ -75,6 +82,14 @@ void setup() { char features[100] = ""; + if (I2Caccess == NULL) // Check that semaphore has not already been created + { + I2Caccess = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use + // to manage the i2c bus + if ((I2Caccess) != NULL) + xSemaphoreGive((I2Caccess)); // Flag the i2c bus available for use + } + // disable brownout detection #ifdef DISABLE_BROWNOUT // register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4 @@ -105,8 +120,17 @@ void setup() { chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); - ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion()); - ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap()); + ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", + ESP.getHeapSize(), ESP.getFreeHeap()); +#ifdef BOARD_HAS_PSRAM + ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), + ESP.getFreePsram()); +#endif + ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", + ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); + ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), + ESP.getFlashChipSpeed()); + ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", esp_coex_version_get()); #ifdef HAS_GPS ESP_LOGI(TAG, "TinyGPS+ v%s", TinyGPSPlus::libraryVersion()); @@ -117,6 +141,12 @@ void setup() { // read (and initialize on first run) runtime settings from NVRAM loadConfig(); // includes initialize if necessary +#ifdef BOARD_HAS_PSRAM + assert(psramFound()); + ESP_LOGI(TAG, "PSRAM found and initialized"); + strcat_P(features, " PSRAM"); +#endif + // initialize leds #if (HAS_LED != NOT_A_PIN) pinMode(HAS_LED, OUTPUT); @@ -148,13 +178,6 @@ void setup() { antenna_select(cfg.wifiant); #endif -// switch off bluetooth, if not compiled -#ifdef BLECOUNTER - strcat_P(features, " BLE"); -#else - bool btstop = btStop(); -#endif - // initialize battery status #ifdef HAS_BATTERY_PROBE strcat_P(features, " BATT"); @@ -172,7 +195,27 @@ void setup() { } #endif - // initialize button +// start BLE scan callback if BLE function is enabled in NVRAM configuration +// or switch off bluetooth, if not compiled +#ifdef BLECOUNTER + strcat_P(features, " BLE"); + if (cfg.blescan) { + ESP_LOGI(TAG, "Starting Bluetooth..."); + start_BLEscan(); + } else + btStop(); +#else + // remove bluetooth stack to gain more free memory + ESP_ERROR_CHECK(esp_bluedroid_disable()); + ESP_ERROR_CHECK(esp_bluedroid_deinit()); + btStop(); + ESP_ERROR_CHECK(esp_bt_controller_deinit()); + ESP_ERROR_CHECK(esp_bt_mem_release(ESP_BT_MODE_BTDM)); + ESP_ERROR_CHECK(esp_coex_preference_set(( + esp_coex_prefer_t)ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib +#endif + +// initialize button #ifdef HAS_BUTTON strcat_P(features, " BTN_"); #ifdef BUTTON_PULLUP @@ -201,21 +244,6 @@ void setup() { } #endif -// initialize bme -#ifdef HAS_BME - strcat_P(features, " BME"); - if (bme_init()) { - ESP_LOGI(TAG, "Starting BMEloop..."); - xTaskCreatePinnedToCore(bme_loop, // task function - "bmeloop", // name of task - 4096, // stack size of task - (void *)1, // parameter of the task - 2, // priority of the task - &BmeTask, // task handle - 1); // CPU core - } -#endif - // initialize sensors #ifdef HAS_SENSORS strcat_P(features, " SENS"); @@ -290,14 +318,6 @@ void setup() { #endif #endif -// start BLE scan callback if BLE function is enabled in NVRAM configuration -#ifdef BLECOUNTER - if (cfg.blescan) { - ESP_LOGI(TAG, "Starting Bluetooth..."); - start_BLEscan(); - } -#endif - // start wifi in monitor mode and start channel rotation task on core 0 ESP_LOGI(TAG, "Starting Wifi..."); wifi_sniffer_init(); @@ -310,7 +330,7 @@ void setup() { ESP_LOGI(TAG, "Starting IRQ Handler..."); xTaskCreatePinnedToCore(irqHandler, // task function "irqhandler", // name of task - 2048, // stack size of task + 4096, // stack size of task (void *)1, // parameter of the task 1, // priority of the task &irqHandlerTask, // task handle @@ -326,6 +346,21 @@ void setup() { &wifiSwitchTask, // task handle 0); // CPU core + // initialize bme +#ifdef HAS_BME + strcat_P(features, " BME"); + if (bme_init()) { + ESP_LOGI(TAG, "Starting BMEloop..."); + xTaskCreatePinnedToCore(bme_loop, // task function + "bmeloop", // name of task + 2048, // stack size of task + (void *)1, // parameter of the task + 1, // priority of the task + &BmeTask, // task handle + 1); // CPU core + } +#endif + // start timer triggered interrupts ESP_LOGI(TAG, "Starting Interrupts..."); #ifdef HAS_DISPLAY @@ -352,7 +387,7 @@ void loop() { #ifdef HAS_LORA os_runloop_once(); // execute lmic scheduled jobs and events #endif - vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU + delay(2); // yield to CPU } vTaskDelete(NULL); // shoud never be reached diff --git a/src/mbedtls_aes.c b/src/mbedtls_aes.c new file mode 100644 index 00000000..0a40ed3c --- /dev/null +++ b/src/mbedtls_aes.c @@ -0,0 +1,28 @@ +/******************************************************************************* + * + * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x + * + * Copyright (c) 2018 Manuel Bleichenbacher + * + * Licensed under MIT License + * https://opensource.org/licenses/MIT + * + * AES encryption using ESP32's hardware AES unit. + *******************************************************************************/ + +#include "mbedtls/aes.h" +#include "lmic/oslmic.h" + +#if defined(USE_MBEDTLS_AES) + +void lmic_aes_encrypt(u1_t *data, u1_t *key) +{ + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, data, data); + mbedtls_aes_free(&ctx); +} + + +#endif \ No newline at end of file diff --git a/src/ota.cpp b/src/ota.cpp index bf9f30e2..4210b704 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -77,7 +77,7 @@ void start_ota_update() { while (i--) { ESP_LOGI(TAG, "Trying to connect to %s, attempt %u of %u", WIFI_SSID, WIFI_MAX_TRY - i, WIFI_MAX_TRY); - vTaskDelay(10000 / portTICK_PERIOD_MS); // wait for stable connect + delay(10000); // wait for stable connect if (WiFi.status() == WL_CONNECTED) { // we now have wifi connection and try to do an OTA over wifi update ESP_LOGI(TAG, "Connected to %s", WIFI_SSID); @@ -98,13 +98,13 @@ void start_ota_update() { // wifi did not connect ESP_LOGI(TAG, "Could not connect to %s", WIFI_SSID); display(1, " E", "no WiFi connect"); - vTaskDelay(5000 / portTICK_PERIOD_MS); + delay(5000); end: switch_LED(LED_OFF); ESP_LOGI(TAG, "Rebooting to %s firmware", (ret == 0) ? "new" : "current"); display(5, "**", ""); // mark line rebooting - vTaskDelay(5000 / portTICK_PERIOD_MS); + delay(5000); ESP.restart(); } // start_ota_update diff --git a/src/paxcounter.conf b/src/paxcounter.conf index a98832e8..007561c2 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -15,7 +15,7 @@ // 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, saves power & memory +#define BLECOUNTER 1 // activate if you want to use BLE count, at expense of memory // BLE scan parameters #define BLESCANTIME 0 // [seconds] scan duration, 0 means infinite [default], see note below @@ -72,9 +72,10 @@ // Settings for BME680 environmental sensor (if present) #define BME_TEMP_OFFSET 5.0f // Offset sensor on chip temp <-> ambient temp [default = 5°C] +#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // update every 360 minutes = 4 times a day // OTA settings -//#define USE_OTA 1 // Comment out to disable OTA update +#define USE_OTA 1 // Comment out to disable OTA update #define WIFI_MAX_TRY 5 // maximum number of wifi connect attempts for OTA update [default = 20] #define OTA_MAX_TRY 5 // maximum number of attempts for OTA download and write to flash [default = 3] #define OTA_MIN_BATT 3600 // minimum battery level for OTA [millivolt] diff --git a/src/payload.cpp b/src/payload.cpp index ea68b481..71534a24 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -18,11 +18,9 @@ uint8_t *PayloadConvert::getBuffer(void) { return buffer; } #if PAYLOAD_ENCODER == 1 -void PayloadConvert::addCount(uint16_t value1, uint16_t value2) { - buffer[cursor++] = highByte(value1); - buffer[cursor++] = lowByte(value1); - buffer[cursor++] = highByte(value2); - buffer[cursor++] = lowByte(value2); +void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { + buffer[cursor++] = highByte(value); + buffer[cursor++] = lowByte(value); } void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { @@ -135,10 +133,7 @@ void PayloadConvert::addButton(uint8_t value) { #elif PAYLOAD_ENCODER == 2 -void PayloadConvert::addCount(uint16_t value1, uint16_t value2) { - writeUint16(value1); - writeUint16(value2); -} +void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { writeUint16(value); } void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { writeUint8(rssi); @@ -286,21 +281,27 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, #elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4) -void PayloadConvert::addCount(uint16_t value1, uint16_t value2) { +void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { + switch(snifftype) { + case MAC_SNIFF_WIFI: #if (PAYLOAD_ENCODER == 3) - buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; + buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; #endif - buffer[cursor++] = - LPP_LUMINOSITY; // workaround since cayenne has no data type meter - buffer[cursor++] = highByte(value1); - buffer[cursor++] = lowByte(value1); + buffer[cursor++] = + LPP_LUMINOSITY; // workaround since cayenne has no data type meter + buffer[cursor++] = highByte(value); + buffer[cursor++] = lowByte(value); + break; + case MAC_SNIFF_BLE: #if (PAYLOAD_ENCODER == 3) - buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; + buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; #endif - buffer[cursor++] = - LPP_LUMINOSITY; // workaround since cayenne has no data type meter - buffer[cursor++] = highByte(value2); - buffer[cursor++] = lowByte(value2); + buffer[cursor++] = + LPP_LUMINOSITY; // workaround since cayenne has no data type meter + buffer[cursor++] = highByte(value); + buffer[cursor++] = lowByte(value); + break; + } } void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { @@ -317,7 +318,7 @@ void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { } void PayloadConvert::addVoltage(uint16_t value) { - uint16_t volt = value / 10; + uint16_t volt = value / 10; #if (PAYLOAD_ENCODER == 3) buffer[cursor++] = LPP_BATT_CHANNEL; #endif diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 44ddfd18..3b6bccc6 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -9,7 +9,7 @@ static const char TAG[] = "main"; void do_reset() { ESP_LOGI(TAG, "Remote command: restart device"); LMIC_shutdown(); - vTaskDelay(3000 / portTICK_PERIOD_MS); + delay(3000); esp_restart(); } @@ -79,13 +79,11 @@ void set_blescantime(uint8_t val[]) { cfg.blescantime = val[0]; 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[]) { @@ -193,14 +191,12 @@ void set_loraadr(uint8_t val[]) { void set_blescan(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val[0] ? "on" : "off"); cfg.blescan = val[0] ? 1 : 0; -#ifdef BLECOUNTER if (cfg.blescan) start_BLEscan(); else { macs_ble = 0; // clear BLE counter stop_BLEscan(); } -#endif } void set_wifiant(uint8_t val[]) { @@ -249,7 +245,7 @@ void get_status(uint8_t val[]) { #endif payload.reset(); payload.addStatus(voltage, uptime() / 1000, temperatureRead(), - ESP.getFreeHeap(), rtc_get_reset_reason(0), + getFreeRAM(), rtc_get_reset_reason(0), rtc_get_reset_reason(1)); SendPayload(STATUSPORT); }; diff --git a/src/senddata.cpp b/src/senddata.cpp index 7762222c..fe03be25 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -40,7 +40,21 @@ void sendCounter() { case COUNT_DATA: payload.reset(); - payload.addCount(macs_wifi, cfg.blescan ? macs_ble : 0); + payload.addCount(macs_wifi, MAC_SNIFF_WIFI); + if (cfg.blescan) + payload.addCount(macs_ble, MAC_SNIFF_BLE); + +#ifdef HAS_GPS + if (gps.location.isValid()) { // send GPS position only if we have a fix + gps_read(); + payload.addGPS(gps_status); + } else { + ESP_LOGD( + TAG, + "No valid GPS position. GPS data not appended to counter data."); + } +#endif + SendPayload(COUNTERPORT); // clear counter if not in cumulative counter mode if (cfg.countermode != 1) { diff --git a/src/sensor.cpp b/src/sensor.cpp index 147572d0..0892f4dd 100644 --- a/src/sensor.cpp +++ b/src/sensor.cpp @@ -31,6 +31,8 @@ uint8_t sensor_mask(uint8_t sensor_no) { return (uint8_t)MEMS_DATA; case 7: return (uint8_t)ALARM_DATA; + default: + return 0; } } diff --git a/src/spislave.cpp b/src/spislave.cpp index aefc06a4..5e9ebb1c 100644 --- a/src/spislave.cpp +++ b/src/spislave.cpp @@ -87,8 +87,7 @@ void spi_slave_task(void *param) { // wait until spi master clocks out the data, and read results in rx buffer ESP_LOGI(TAG, "Prepared SPI transaction for %zu byte(s)", transaction_size); ESP_LOG_BUFFER_HEXDUMP(TAG, txbuf, transaction_size, ESP_LOG_DEBUG); - esp_err_t ret = - spi_slave_transmit(HSPI_HOST, &spi_transaction, portMAX_DELAY); + ESP_ERROR_CHECK_WITHOUT_ABORT(spi_slave_transmit(HSPI_HOST, &spi_transaction, portMAX_DELAY)); ESP_LOG_BUFFER_HEXDUMP(TAG, rxbuf, transaction_size, ESP_LOG_DEBUG); ESP_LOGI(TAG, "Transaction finished with size %zu bits", spi_transaction.trans_len); diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index d6eaeb2d..dcd8ebc9 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -1,6 +1,8 @@ // Basic Config #include "globals.h" #include "wifiscan.h" +#include +#include "coexist_internal.h" // Local logging tag static const char TAG[] = "wifi"; @@ -27,7 +29,7 @@ typedef struct { // 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_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; @@ -49,6 +51,9 @@ void wifi_sniffer_init(void) { // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames + ESP_ERROR_CHECK(esp_coex_preference_set( + ESP_COEX_PREFER_BALANCE)); // configure Wifi/BT coexist lib + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country)); // set locales for RF and channels @@ -69,7 +74,7 @@ void switchWifiChannel(void *parameter) { channel = (channel % WIFI_CHANNEL_MAX) + 1; // rotate channel 1..WIFI_CHANNEL_MAX esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); - ESP_LOGD(TAG, "Wifi set channel %d", channel); + //ESP_LOGD(TAG, "Wifi set channel %d", channel); } vTaskDelete(NULL); // shoud never be reached }