bsecstate load/save implemented; bugfix packed_decoder.js
This commit is contained in:
		
							parent
							
								
									184e1e7d84
								
							
						
					
					
						commit
						f26b7a545c
					
				| @ -47,8 +47,11 @@ const uint8_t bsec_config_iaq[454] = { | |||||||
|     255, 255, 255, 255, 255, 255, 255, 255, 255, 44,  1,   0,   0,   0,   0, |     255, 255, 255, 255, 255, 255, 255, 255, 255, 44,  1,   0,   0,   0,   0, | ||||||
|     239, 79,  0,   0}; |     239, 79,  0,   0}; | ||||||
| 
 | 
 | ||||||
|  | // Helper functions declarations
 | ||||||
| int bme_init(); | int bme_init(); | ||||||
| void bme_loop(void *pvParameters); | void bme_loop(void *pvParameters); | ||||||
| int checkIaqSensorStatus(void); | int checkIaqSensorStatus(void); | ||||||
|  | void loadState(void); | ||||||
|  | void updateState(void); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
| @ -7,6 +7,10 @@ | |||||||
| #include "spislave.h" | #include "spislave.h" | ||||||
| #include <lmic.h> | #include <lmic.h> | ||||||
| 
 | 
 | ||||||
|  | #ifdef HAS_BME | ||||||
|  | #include "bme680mems.h" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| void doHousekeeping(void); | void doHousekeeping(void); | ||||||
| void do_timesync(void); | void do_timesync(void); | ||||||
| uint64_t uptime(void); | uint64_t uptime(void); | ||||||
|  | |||||||
| @ -54,6 +54,7 @@ typedef struct { | |||||||
|   uint8_t runmode;       // 0=normal, 1=update
 |   uint8_t runmode;       // 0=normal, 1=update
 | ||||||
|   uint8_t payloadmask;   // bitswitches for payload data
 |   uint8_t payloadmask;   // bitswitches for payload data
 | ||||||
|   char version[10];      // Firmware version
 |   char version[10];      // Firmware version
 | ||||||
|  |   char bsecstate[BSEC_MAX_STATE_BLOB_SIZE+1]; // init BSEC state for BME680 sensor
 | ||||||
| } configData_t; | } configData_t; | ||||||
| 
 | 
 | ||||||
| // Struct holding payload for data send queue
 | // Struct holding payload for data send queue
 | ||||||
| @ -87,7 +88,7 @@ extern configData_t cfg;                      // current device configuration | |||||||
| extern char display_line6[], display_line7[]; // screen buffers
 | extern char display_line6[], display_line7[]; // screen buffers
 | ||||||
| extern uint8_t volatile channel;              // wifi channel rotation counter
 | extern uint8_t volatile channel;              // wifi channel rotation counter
 | ||||||
| extern uint16_t volatile macs_total, macs_wifi, macs_ble, | extern uint16_t volatile macs_total, macs_wifi, macs_ble, | ||||||
|     batt_voltage;                  // display values
 |     batt_voltage; // display values
 | ||||||
| extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; | extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; | ||||||
| extern SemaphoreHandle_t I2Caccess; | extern SemaphoreHandle_t I2Caccess; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
| 
 | 
 | ||||||
| ; ---> SELECT TARGET PLATFORM HERE! <--- | ; ---> SELECT TARGET PLATFORM HERE! <--- | ||||||
| [platformio] | [platformio] | ||||||
| ;env_default = generic | env_default = generic | ||||||
| ;env_default = ebox | ;env_default = ebox | ||||||
| ;env_default = eboxtube | ;env_default = eboxtube | ||||||
| ;env_default = heltec | ;env_default = heltec | ||||||
| @ -16,7 +16,7 @@ | |||||||
| ;env_default = ttgov21old | ;env_default = ttgov21old | ||||||
| ;env_default = ttgov21new | ;env_default = ttgov21new | ||||||
| ;env_default = ttgobeam_old | ;env_default = ttgobeam_old | ||||||
| env_default = ttgobeam_new | ;env_default = ttgobeam_new | ||||||
| ;env_default = lopy | ;env_default = lopy | ||||||
| ;env_default = lopy4 | ;env_default = lopy4 | ||||||
| ;env_default = fipy | ;env_default = fipy | ||||||
| @ -30,10 +30,10 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng | |||||||
| 
 | 
 | ||||||
| [common] | [common] | ||||||
| ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" | ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" | ||||||
| release_version = 1.7.03 | release_version = 1.7.06 | ||||||
| ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! | ; 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 | ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose | ||||||
| debug_level = 3 | debug_level = 0 | ||||||
| ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA | ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA | ||||||
| upload_protocol = esptool | upload_protocol = esptool | ||||||
| ;upload_protocol = custom | ;upload_protocol = custom | ||||||
|  | |||||||
| @ -18,7 +18,11 @@ function Decoder(bytes, port) { | |||||||
|         if (bytes.length === 4) { |         if (bytes.length === 4) { | ||||||
|             return decode(bytes, [uint16, uint16], ['wifi', 'ble']); |             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) { |         if (bytes.length === 17) { | ||||||
|             return decode(bytes, [uint16, uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); |             return decode(bytes, [uint16, uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -23,9 +23,12 @@ bsec_virtual_sensor_t sensorList[10] = { | |||||||
|     BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, |     BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0}; | ||||||
|  | uint16_t stateUpdateCounter = 0; | ||||||
|  | 
 | ||||||
| // initialize BME680 sensor
 | // initialize BME680 sensor
 | ||||||
| int bme_init(void) { | int bme_init(void) { | ||||||
| 
 |    | ||||||
|   // block i2c bus access
 |   // block i2c bus access
 | ||||||
|   if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == |   if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == | ||||||
|       pdTRUE) { |       pdTRUE) { | ||||||
| @ -46,6 +49,8 @@ int bme_init(void) { | |||||||
|       return 1; |       return 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     loadState(); | ||||||
|  | 
 | ||||||
|     iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); |     iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); | ||||||
|     iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); |     iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); | ||||||
| 
 | 
 | ||||||
| @ -99,7 +104,6 @@ void bme_loop(void *pvParameters) { | |||||||
|     // block i2c bus access
 |     // block i2c bus access
 | ||||||
|     if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == |     if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == | ||||||
|         pdTRUE) { |         pdTRUE) { | ||||||
| 
 |  | ||||||
|       if (iaqSensor.run()) { // If new data is available
 |       if (iaqSensor.run()) { // If new data is available
 | ||||||
|         bme_status.raw_temperature = iaqSensor.rawTemperature; |         bme_status.raw_temperature = iaqSensor.rawTemperature; | ||||||
|         bme_status.raw_humidity = iaqSensor.rawHumidity; |         bme_status.raw_humidity = iaqSensor.rawHumidity; | ||||||
| @ -111,7 +115,6 @@ void bme_loop(void *pvParameters) { | |||||||
|         bme_status.iaq_accuracy = iaqSensor.iaqAccuracy; |         bme_status.iaq_accuracy = iaqSensor.iaqAccuracy; | ||||||
|         bme_status.gas = iaqSensor.gasResistance; |         bme_status.gas = iaqSensor.gasResistance; | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|       xSemaphoreGive(I2Caccess); // release i2c bus access
 |       xSemaphoreGive(I2Caccess); // release i2c bus access
 | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -121,4 +124,43 @@ void bme_loop(void *pvParameters) { | |||||||
| 
 | 
 | ||||||
| } // bme_loop()
 | } // bme_loop()
 | ||||||
| 
 | 
 | ||||||
|  | void loadState(void) { | ||||||
|  |   if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] == BSEC_MAX_STATE_BLOB_SIZE) { | ||||||
|  |     // Existing state in NVS stored
 | ||||||
|  |     ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); | ||||||
|  |     memcpy(bsecState, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); | ||||||
|  |     iaqSensor.setState(bsecState); | ||||||
|  |     checkIaqSensorStatus(); | ||||||
|  |   } else // no state stored
 | ||||||
|  |     ESP_LOGI(TAG, | ||||||
|  |              "no BSEC state stored in NVRAM, starting sensor with defaults"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void updateState(void) { | ||||||
|  |   bool update = false; | ||||||
|  | 
 | ||||||
|  |   if (stateUpdateCounter == 0) { | ||||||
|  |     /* First state update when IAQ accuracy is >= 1 */ | ||||||
|  |     if (iaqSensor.iaqAccuracy >= 3) { | ||||||
|  |       update = true; | ||||||
|  |       stateUpdateCounter++; | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     /* Update every STATE_SAVE_PERIOD minutes */ | ||||||
|  |     if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { | ||||||
|  |       update = true; | ||||||
|  |       stateUpdateCounter++; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (update) { | ||||||
|  |     memcpy(bsecState, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); | ||||||
|  |     cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = BSEC_MAX_STATE_BLOB_SIZE; | ||||||
|  |     iaqSensor.getState(bsecState); | ||||||
|  |     checkIaqSensorStatus(); | ||||||
|  |     ESP_LOGI(TAG, "saving BSEC state to NVRAM"); | ||||||
|  |     saveConfig(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif // HAS_BME
 | #endif // HAS_BME
 | ||||||
| @ -32,6 +32,8 @@ void defaultConfig() { | |||||||
|   cfg.monitormode = 0;        // 0=disabled, 1=enabled
 |   cfg.monitormode = 0;        // 0=disabled, 1=enabled
 | ||||||
|   cfg.runmode = 0;            // 0=normal, 1=update
 |   cfg.runmode = 0;            // 0=normal, 1=update
 | ||||||
|   cfg.payloadmask = 0xFF;     // all payload switched on
 |   cfg.payloadmask = 0xFF;     // all payload switched on
 | ||||||
|  |   cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = { | ||||||
|  |       0}; // init BSEC state for BME680 sensor
 | ||||||
| 
 | 
 | ||||||
|   strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); |   strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); | ||||||
| } | } | ||||||
| @ -78,6 +80,12 @@ void saveConfig() { | |||||||
|     int16_t flash16 = 0; |     int16_t flash16 = 0; | ||||||
|     size_t required_size; |     size_t required_size; | ||||||
|     char storedversion[10]; |     char storedversion[10]; | ||||||
|  |     char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; | ||||||
|  | 
 | ||||||
|  |     if (nvs_get_str(my_handle, "bsecstate", bsecstate, &required_size) != | ||||||
|  |             ESP_OK || | ||||||
|  |         strcmp(bsecstate, cfg.bsecstate) != 0) | ||||||
|  |       nvs_set_str(my_handle, "bsecstate", cfg.bsecstate); | ||||||
| 
 | 
 | ||||||
|     if (nvs_get_str(my_handle, "version", storedversion, &required_size) != |     if (nvs_get_str(my_handle, "version", storedversion, &required_size) != | ||||||
|             ESP_OK || |             ESP_OK || | ||||||
| @ -202,7 +210,16 @@ void loadConfig() { | |||||||
|       migrateVersion(); |       migrateVersion(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // overwrite defaults with valid values from NVRAM
 |     // populate pre set defaults with current values from NVRAM
 | ||||||
|  | 
 | ||||||
|  |     char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; | ||||||
|  | 
 | ||||||
|  |     if (nvs_get_str(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { | ||||||
|  |       nvs_get_str(my_handle, "bsecstate", cfg.bsecstate, &required_size); | ||||||
|  |       ESP_LOGI(TAG, "bsecstate = %d", | ||||||
|  |                cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { |     if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { | ||||||
|       cfg.lorasf = flash8; |       cfg.lorasf = flash8; | ||||||
|       ESP_LOGI(TAG, "lorasf = %d", flash8); |       ESP_LOGI(TAG, "lorasf = %d", flash8); | ||||||
|  | |||||||
| @ -58,6 +58,7 @@ void doHousekeeping() { | |||||||
| // display BME sensor data if present
 | // display BME sensor data if present
 | ||||||
| #ifdef HAS_BME | #ifdef HAS_BME | ||||||
|   ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f", bme_status.temperature, bme_status.iaq); |   ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f", bme_status.temperature, bme_status.iaq); | ||||||
|  |   updateState(); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|   // check free heap memory
 |   // check free heap memory
 | ||||||
|  | |||||||
| @ -11,18 +11,18 @@ | |||||||
| 
 | 
 | ||||||
| // enable only if device has these sensors, otherwise comment these lines
 | // enable only if device has these sensors, otherwise comment these lines
 | ||||||
| // BME680 sensor on I2C bus
 | // BME680 sensor on I2C bus
 | ||||||
| #define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
 | //#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 BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND
 | ||||||
| 
 | 
 | ||||||
| #define HAS_LED GPIO_NUM_14 // on board green LED
 | #define HAS_LED GPIO_NUM_14 // on board green LED
 | ||||||
| 
 | 
 | ||||||
| // user defined sensors
 | // user defined sensors
 | ||||||
| //#define HAS_SENSORS 1 // comment out if device has 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 HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
 | ||||||
| #define MY_OLED_SDA (21) | //#define MY_OLED_SDA (21)
 | ||||||
| #define MY_OLED_SCL (22) | //#define MY_OLED_SCL (22)
 | ||||||
| #define MY_OLED_RST U8X8_PIN_NONE | //#define MY_OLED_RST U8X8_PIN_NONE
 | ||||||
| //#define DISPLAY_FLIP  1 // use if display is rotated
 | //#define DISPLAY_FLIP  1 // use if display is rotated
 | ||||||
| 
 | 
 | ||||||
| #define HAS_LORA 1       // comment out if device shall not send data via LoRa
 | #define HAS_LORA 1       // comment out if device shall not send data via LoRa
 | ||||||
|  | |||||||
| @ -72,6 +72,8 @@ | |||||||
| 
 | 
 | ||||||
| // Settings for BME680 environmental sensor (if present) | // Settings for BME680 environmental sensor (if present) | ||||||
| #define BME_TEMP_OFFSET                 5.0f    // Offset sensor on chip temp <-> ambient temp [default = 5°C] | #define BME_TEMP_OFFSET                 5.0f    // Offset sensor on chip temp <-> ambient temp [default = 5°C] | ||||||
|  | #define BSEC_MAX_STATE_BLOB_SIZE        134     // size of Bosch BME680 state data blob | ||||||
|  | #define STATE_SAVE_PERIOD               UINT32_C(360 * 60 * 1000) // update every 360 minutes = 4 times a day | ||||||
| 
 | 
 | ||||||
| // OTA settings | // OTA settings | ||||||
| #define USE_OTA                         1       // Comment out to disable OTA update | #define USE_OTA                         1       // Comment out to disable OTA update | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user