Merge branch 'apollo' of github.com:meshtastic/firmware into apollo

This commit is contained in:
Thomas Göttgens 2023-04-24 16:43:02 +02:00
commit 4b053ddd73
15 changed files with 202 additions and 43 deletions

View File

@ -105,7 +105,7 @@ lib_deps =
adafruit/Adafruit Unified Sensor@^1.1.9 adafruit/Adafruit Unified Sensor@^1.1.9
adafruit/Adafruit BMP280 Library@^2.6.6 adafruit/Adafruit BMP280 Library@^2.6.6
adafruit/Adafruit BME280 Library@^2.2.2 adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit BME680 Library@^2.0.1 https://github.com/meshtastic/BSEC-Arduino-library.git#452f9a7ffa8b53e1debe2c454fe375dfad98b507
adafruit/Adafruit MCP9808 Library@^2.0.0 adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0 adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0 adafruit/Adafruit INA219@^1.2.0

@ -1 +1 @@
Subproject commit ee6f408bb3c27b8ca820477cbb3a84ac6c8b0ffc Subproject commit ef2bc66bba41e8ef98ea893e46eb36a2da40cb5e

View File

@ -45,10 +45,10 @@ class ButtonThread : public concurrency::OSThread
ButtonThread() : OSThread("Button") ButtonThread() : OSThread("Button")
{ {
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
userButton = OneButton(BUTTON_PIN, true, true); userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
#ifdef INPUT_PULLUP_SENSE #ifdef INPUT_PULLUP_SENSE
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE); pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
#endif #endif
userButton.attachClick(userButtonPressed); userButton.attachClick(userButtonPressed);
userButton.setClickTicks(300); userButton.setClickTicks(300);
@ -57,7 +57,7 @@ class ButtonThread : public concurrency::OSThread
userButton.attachMultiClick(userButtonMultiPressed); userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop); userButton.attachLongPressStop(userButtonPressedLongStop);
wakeOnIrq(BUTTON_PIN, FALLING); wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
#endif #endif
#ifdef BUTTON_PIN_ALT #ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
@ -115,7 +115,9 @@ class ButtonThread : public concurrency::OSThread
{ {
// LOG_DEBUG("press!\n"); // LOG_DEBUG("press!\n");
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) || !moduleConfig.canned_message.enabled) { if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
#endif #endif

View File

@ -351,40 +351,39 @@ void Power::readPowerStatus()
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]); sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
auto newHeap = memGet.getFreeHeap(); auto newHeap = memGet.getFreeHeap();
std::string heapTopic = (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + "/2/heap/" + std::string(mac); std::string heapTopic =
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/heap/") + std::string(mac);
std::string heapString = std::to_string(newHeap); std::string heapString = std::to_string(newHeap);
mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false); mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false);
// auto fragHeap = memGet.getHeapFragmentation();
auto wifiRSSI = WiFi.RSSI(); auto wifiRSSI = WiFi.RSSI();
heapTopic = (*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + "/2/wifi/" + std::string(mac); std::string wifiTopic =
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/wifi/") + std::string(mac);
std::string wifiString = std::to_string(wifiRSSI); std::string wifiString = std::to_string(wifiRSSI);
mqtt->pubSub.publish(heapTopic.c_str(), wifiString.c_str(), false); mqtt->pubSub.publish(wifiTopic.c_str(), wifiString.c_str(), false);
} }
#endif #endif
#endif #endif
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row // If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 10 low readings in a
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days // row
#ifdef ARCH_NRF52
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) { if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) { if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) {
low_voltage_counter++; low_voltage_counter++;
LOG_DEBUG("Warning RAK4631 Low voltage counter: %d/10\n", low_voltage_counter); LOG_DEBUG("Low voltage counter: %d/10\n", low_voltage_counter);
if (low_voltage_counter > 10) { if (low_voltage_counter > 10) {
#ifdef ARCH_NRF52
// We can't trigger deep sleep on NRF52, it's freezing the board // We can't trigger deep sleep on NRF52, it's freezing the board
// powerFSM.trigger(EVENT_LOW_BATTERY);
LOG_DEBUG("Low voltage detected, but not triggering deep sleep\n"); LOG_DEBUG("Low voltage detected, but not triggering deep sleep\n");
#else
LOG_INFO("Low voltage detected, triggering deep sleep\n");
powerFSM.trigger(EVENT_LOW_BATTERY);
#endif
} }
} else { } else {
low_voltage_counter = 0; low_voltage_counter = 0;
} }
} }
#else
// If we have a battery at all and it is less than 10% full, force deep sleep
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB() && batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS)
powerFSM.trigger(EVENT_LOW_BATTERY);
#endif
} else { } else {
// No power sensing on this board - tell everyone else we have no idea what is happening // No power sensing on this board - tell everyone else we have no idea what is happening
const PowerStatus powerStatus3 = PowerStatus(OptUnknown, OptUnknown, OptUnknown, -1, -1); const PowerStatus powerStatus3 = PowerStatus(OptUnknown, OptUnknown, OptUnknown, -1, -1);
@ -538,7 +537,6 @@ bool Power::axpChipInit()
// Set up the charging voltage // Set up the charging voltage
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2); PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
} else if (PMU->getChipModel() == XPOWERS_AXP2101) { } else if (PMU->getChipModel() == XPOWERS_AXP2101) {
/*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/ /*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/

View File

@ -99,7 +99,7 @@ static void lsIdle()
LOG_INFO("wakeCause2 %d\n", wakeCause2); LOG_INFO("wakeCause2 %d\n", wakeCause2);
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
bool pressed = !digitalRead(BUTTON_PIN); bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#else #else
bool pressed = false; bool pressed = false;
#endif #endif

View File

@ -218,10 +218,10 @@ void setup()
// If the button is connected to GPIO 12, don't enable the ability to use // If the button is connected to GPIO 12, don't enable the ability to use
// meshtasticAdmin on the device. // meshtasticAdmin on the device.
pinMode(BUTTON_PIN, INPUT); pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT);
#ifdef BUTTON_NEED_PULLUP #ifdef BUTTON_NEED_PULLUP
gpio_pullup_en((gpio_num_t)BUTTON_PIN); gpio_pullup_en((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
delay(10); delay(10);
#endif #endif
@ -389,10 +389,7 @@ void setup()
// scanEInkDevice(); // scanEInkDevice();
#endif #endif
#if HAS_BUTTON // LED init
// Buttons & LED
buttonThread = new ButtonThread();
#endif
#ifdef LED_PIN #ifdef LED_PIN
pinMode(LED_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
@ -417,6 +414,11 @@ void setup()
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
router = new FloodingRouter(); router = new FloodingRouter();
#if HAS_BUTTON
// Buttons. Moved here cause we need NodeDB to be initialized
buttonThread = new ButtonThread();
#endif
playStartMelody(); playStartMelody();
// fixed screen override? // fixed screen override?

View File

@ -48,6 +48,12 @@ PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)
PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO) PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO)
PB_BIND(meshtastic_NeighborInfo, meshtastic_NeighborInfo, AUTO)
PB_BIND(meshtastic_Neighbor, meshtastic_Neighbor, AUTO)
PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO) PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO)

View File

@ -680,6 +680,25 @@ typedef struct _meshtastic_Compressed {
meshtastic_Compressed_data_t data; meshtastic_Compressed_data_t data;
} meshtastic_Compressed; } meshtastic_Compressed;
/* A single edge in the mesh */
typedef struct _meshtastic_Neighbor {
/* Node ID of neighbor */
uint32_t node_id;
/* SNR of last heard message */
float snr;
} meshtastic_Neighbor;
/* Full info on edges for a single node */
typedef struct _meshtastic_NeighborInfo {
/* The node ID of the node sending info on its neighbors */
uint32_t node_id;
/* Field to pass neighbor info for the next sending cycle */
uint32_t last_sent_by_id;
/* The list of out edges from this node */
pb_size_t neighbors_count;
meshtastic_Neighbor neighbors[10];
} meshtastic_NeighborInfo;
/* Device metadata response */ /* Device metadata response */
typedef struct _meshtastic_DeviceMetadata { typedef struct _meshtastic_DeviceMetadata {
/* Device firmware version string */ /* Device firmware version string */
@ -813,6 +832,8 @@ extern "C" {
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum #define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
#define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role #define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
#define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel #define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel
@ -832,6 +853,8 @@ extern "C" {
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}} #define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}} #define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
#define meshtastic_Neighbor_init_default {0, 0}
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} #define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0} #define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
@ -847,6 +870,8 @@ extern "C" {
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}} #define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
#define meshtastic_Neighbor_init_zero {0, 0}
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} #define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
@ -948,6 +973,11 @@ extern "C" {
#define meshtastic_ToRadio_xmodemPacket_tag 5 #define meshtastic_ToRadio_xmodemPacket_tag 5
#define meshtastic_Compressed_portnum_tag 1 #define meshtastic_Compressed_portnum_tag 1
#define meshtastic_Compressed_data_tag 2 #define meshtastic_Compressed_data_tag 2
#define meshtastic_Neighbor_node_id_tag 1
#define meshtastic_Neighbor_snr_tag 2
#define meshtastic_NeighborInfo_node_id_tag 1
#define meshtastic_NeighborInfo_last_sent_by_id_tag 2
#define meshtastic_NeighborInfo_neighbors_tag 3
#define meshtastic_DeviceMetadata_firmware_version_tag 1 #define meshtastic_DeviceMetadata_firmware_version_tag 1
#define meshtastic_DeviceMetadata_device_state_version_tag 2 #define meshtastic_DeviceMetadata_device_state_version_tag 2
#define meshtastic_DeviceMetadata_canShutdown_tag 3 #define meshtastic_DeviceMetadata_canShutdown_tag 3
@ -1157,6 +1187,20 @@ X(a, STATIC, SINGULAR, BYTES, data, 2)
#define meshtastic_Compressed_CALLBACK NULL #define meshtastic_Compressed_CALLBACK NULL
#define meshtastic_Compressed_DEFAULT NULL #define meshtastic_Compressed_DEFAULT NULL
#define meshtastic_NeighborInfo_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \
X(a, STATIC, REPEATED, MESSAGE, neighbors, 3)
#define meshtastic_NeighborInfo_CALLBACK NULL
#define meshtastic_NeighborInfo_DEFAULT NULL
#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor
#define meshtastic_Neighbor_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
X(a, STATIC, SINGULAR, FLOAT, snr, 2)
#define meshtastic_Neighbor_CALLBACK NULL
#define meshtastic_Neighbor_DEFAULT NULL
#define meshtastic_DeviceMetadata_FIELDLIST(X, a) \ #define meshtastic_DeviceMetadata_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \ X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \
X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \ X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \
@ -1184,6 +1228,8 @@ extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
extern const pb_msgdesc_t meshtastic_FromRadio_msg; extern const pb_msgdesc_t meshtastic_FromRadio_msg;
extern const pb_msgdesc_t meshtastic_ToRadio_msg; extern const pb_msgdesc_t meshtastic_ToRadio_msg;
extern const pb_msgdesc_t meshtastic_Compressed_msg; extern const pb_msgdesc_t meshtastic_Compressed_msg;
extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
extern const pb_msgdesc_t meshtastic_Neighbor_msg;
extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ /* Defines for backwards compatibility with code written before nanopb-0.4.0 */
@ -1201,6 +1247,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg #define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg #define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg #define meshtastic_Compressed_fields &meshtastic_Compressed_msg
#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg
#define meshtastic_Neighbor_fields &meshtastic_Neighbor_msg
#define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg #define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
@ -1211,6 +1259,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_LogRecord_size 81 #define meshtastic_LogRecord_size 81
#define meshtastic_MeshPacket_size 321 #define meshtastic_MeshPacket_size 321
#define meshtastic_MyNodeInfo_size 179 #define meshtastic_MyNodeInfo_size 179
#define meshtastic_NeighborInfo_size 142
#define meshtastic_Neighbor_size 11
#define meshtastic_NodeInfo_size 261 #define meshtastic_NodeInfo_size 261
#define meshtastic_Position_size 137 #define meshtastic_Position_size 137
#define meshtastic_QueueStatus_size 23 #define meshtastic_QueueStatus_size 23

View File

@ -85,6 +85,8 @@ typedef enum _meshtastic_PortNum {
/* Provides a traceroute functionality to show the route a packet towards /* Provides a traceroute functionality to show the route a packet towards
a certain destination would take on the mesh. */ a certain destination would take on the mesh. */
meshtastic_PortNum_TRACEROUTE_APP = 70, meshtastic_PortNum_TRACEROUTE_APP = 70,
/* Aggregates edge info for the network by sending out a list of each node's neighbors */
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
/* Private applications should use portnums >= 256. /* Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP" To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */ in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */

View File

@ -1,18 +1,26 @@
#include "BME680Sensor.h" #include "BME680Sensor.h"
#include "../mesh/generated/meshtastic/telemetry.pb.h" #include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "FSCommon.h"
#include "TelemetrySensor.h" #include "TelemetrySensor.h"
#include "configuration.h" #include "configuration.h"
#include <Adafruit_BME680.h>
BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {} BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {}
int32_t BME680Sensor::runOnce() int32_t BME680Sensor::runOnce()
{ {
LOG_INFO("Init sensor: %s\n", sensorName); LOG_INFO("Init sensor: %s with the BSEC Library\n", sensorName);
if (!hasSensor()) { if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
} }
status = bme680.begin(nodeTelemetrySensorsMap[sensorType]); bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire);
if (bme680.bsecStatus == BSEC_OK) {
bme680.setConfig(bsec_config_iaq);
loadState();
bme680.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
status = 1;
} else {
status = 0;
}
return initI2CSensor(); return initI2CSensor();
} }
@ -21,11 +29,76 @@ void BME680Sensor::setup() {}
bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement) bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
{ {
bme680.performReading(); bme680.run();
measurement->variant.environment_metrics.temperature = bme680.temperature; measurement->variant.environment_metrics.temperature = bme680.temperature;
measurement->variant.environment_metrics.relative_humidity = bme680.humidity; measurement->variant.environment_metrics.relative_humidity = bme680.humidity;
measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F; measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F;
measurement->variant.environment_metrics.gas_resistance = bme680.gas_resistance / 1000.0; measurement->variant.environment_metrics.gas_resistance = bme680.gasResistance / 1000.0;
// Check if we need to save state to filesystem (every STATE_SAVE_PERIOD ms)
updateState();
return true; return true;
} }
void BME680Sensor::loadState()
{
#ifdef FSCom
auto file = FSCom.open(bsecConfigFileName, FILE_O_READ);
if (file) {
file.read((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE);
file.close();
bme680.setState(bsecState);
LOG_INFO("%s state read from %s.\n", sensorName, bsecConfigFileName);
} else {
LOG_INFO("No %s state found (File: %s).\n", sensorName, bsecConfigFileName);
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}
void BME680Sensor::updateState()
{
#ifdef FSCom
bool update = false;
if (stateUpdateCounter == 0) {
/* First state update when IAQ accuracy is >= 3 */
if (bme680.iaqAccuracy >= 3) {
LOG_DEBUG("%s state update IAQ accuracy %u >= 3\n", sensorName, bme680.iaqAccuracy);
update = true;
stateUpdateCounter++;
} else {
LOG_DEBUG("%s not updated, IAQ accuracy is %u >= 3\n", sensorName, bme680.iaqAccuracy);
}
} else {
/* Update every STATE_SAVE_PERIOD minutes */
if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) {
LOG_DEBUG("%s state update every %d minutes\n", sensorName, STATE_SAVE_PERIOD);
update = true;
stateUpdateCounter++;
}
}
if (update) {
bme680.getState(bsecState);
std::string filenameTmp = bsecConfigFileName;
filenameTmp += ".tmp";
auto file = FSCom.open(bsecConfigFileName, FILE_O_WRITE);
if (file) {
LOG_INFO("%s state write to %s.\n", sensorName, bsecConfigFileName);
file.write((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE);
file.flush();
file.close();
// brief window of risk here ;-)
if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName))
LOG_WARN("Can't remove old state file\n");
if (!renameFile(filenameTmp.c_str(), bsecConfigFileName))
LOG_ERROR("Error: can't rename new state file\n");
} else {
LOG_INFO("Can't write %s state (File: %s).\n", sensorName, bsecConfigFileName);
}
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}

View File

@ -1,14 +1,38 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h" #include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h" #include "TelemetrySensor.h"
#include <Adafruit_BME680.h> #include <bsec.h>
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // That's 6 hours worth of millis()
const uint8_t bsec_config_iaq[] = {
#include <config/generic_33v_3s_4d/bsec_iaq.txt>
};
class BME680Sensor : virtual public TelemetrySensor class BME680Sensor : virtual public TelemetrySensor
{ {
private: private:
Adafruit_BME680 bme680; Bsec bme680;
protected: protected:
virtual void setup() override; virtual void setup() override;
const char *bsecConfigFileName = "/prefs/bsec.dat";
uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
uint16_t stateUpdateCounter = 0;
bsec_virtual_sensor_t sensorList[13] = {BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_STATIC_IAQ,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_STABILIZATION_STATUS,
BSEC_OUTPUT_RUN_IN_STATUS,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
BSEC_OUTPUT_GAS_PERCENTAGE};
void loadState();
void updateState();
public: public:
BME680Sensor(); BME680Sensor();

View File

@ -202,7 +202,7 @@ void cpuDeepSleep(uint32_t msecToWake)
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39. // Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
#if SOC_RTCIO_HOLD_SUPPORTED #if SOC_RTCIO_HOLD_SUPPORTED
uint64_t gpioMask = (1ULL << BUTTON_PIN); uint64_t gpioMask = (1ULL << config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#endif #endif
#ifdef BUTTON_NEED_PULLUP #ifdef BUTTON_NEED_PULLUP

View File

@ -92,12 +92,12 @@ void startAdv(void)
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
// IncludeService UUID // IncludeService UUID
Bluefruit.ScanResponse.addService(meshBleService); // Bluefruit.ScanResponse.addService(meshBleService);
Bluefruit.ScanResponse.addTxPower(); Bluefruit.ScanResponse.addTxPower();
Bluefruit.ScanResponse.addName(); Bluefruit.ScanResponse.addName();
// Include Name // Include Name
Bluefruit.Advertising.addName(); // Bluefruit.Advertising.addName();
Bluefruit.Advertising.addService(meshBleService); Bluefruit.Advertising.addService(meshBleService);
/* Start Advertising /* Start Advertising

View File

@ -309,7 +309,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
// assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK); // assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK);
#endif #endif
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
esp_sleep_enable_ext0_wakeup((gpio_num_t)BUTTON_PIN, LOW); // when user presses, this button goes low esp_sleep_enable_ext0_wakeup((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN),
LOW); // when user presses, this button goes low
#endif #endif
#if defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) #if defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC)
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high
@ -338,7 +339,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if (cause == ESP_SLEEP_WAKEUP_GPIO) if (cause == ESP_SLEEP_WAKEUP_GPIO)
LOG_INFO("Exit light sleep gpio: btn=%d\n", !digitalRead(BUTTON_PIN)); LOG_INFO("Exit light sleep gpio: btn=%d\n",
!digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
#endif #endif
return cause; return cause;

View File

@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 2 major = 2
minor = 1 minor = 1
build = 9 build = 10