diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 783791f0ba..4fc84fa780 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -6,4 +6,4 @@
"platformio.platformio-ide",
"trunk.io"
],
-}
\ No newline at end of file
+}
diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini
index 62da1c2ae0..c315c50f25 100644
--- a/arch/esp32/esp32.ini
+++ b/arch/esp32/esp32.ini
@@ -1,6 +1,7 @@
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]
extends = arduino_base
+custom_esp32_kind = esp32
platform = platformio/espressif32@6.7.0
platform_packages =
framework-arduinoespressif32@https://github.com/espressif/arduino-esp32#3.0.0
diff --git a/arch/esp32/esp32c3.ini b/arch/esp32/esp32c3.ini
index 619fdb28aa..2ba3036d0b 100644
--- a/arch/esp32/esp32c3.ini
+++ b/arch/esp32/esp32c3.ini
@@ -1,5 +1,6 @@
[esp32c3_base]
extends = esp32_base
+custom_esp32_kind = esp32c3
monitor_speed = 115200
monitor_filters = esp32_c3_exception_decoder
diff --git a/arch/esp32/esp32s2.ini b/arch/esp32/esp32s2.ini
index df66de2edd..40fdc461aa 100644
--- a/arch/esp32/esp32s2.ini
+++ b/arch/esp32/esp32s2.ini
@@ -1,5 +1,6 @@
[esp32s2_base]
extends = esp32_base
+custom_esp32_kind = esp32s2
build_src_filter =
${esp32_base.build_src_filter} - - -
diff --git a/arch/esp32/esp32s3.ini b/arch/esp32/esp32s3.ini
index a18d4af5bb..ede5f22fae 100644
--- a/arch/esp32/esp32s3.ini
+++ b/arch/esp32/esp32s3.ini
@@ -1,5 +1,6 @@
[esp32s3_base]
extends = esp32_base
+custom_esp32_kind = esp32s3
monitor_speed = 115200
diff --git a/bin/platformio-custom.py b/bin/platformio-custom.py
index e5820b3cec..fd516916da 100644
--- a/bin/platformio-custom.py
+++ b/bin/platformio-custom.py
@@ -62,7 +62,21 @@ def esp32_create_combined_bin(source, target, env):
import esptool
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
- env.Append(LINKFLAGS=["--specs=nano.specs", "-u", "_printf_float"])
+
+ esp32_kind = env.GetProjectOption("custom_esp32_kind")
+ if esp32_kind == "esp32":
+ # Free up some IRAM by removing auxiliary SPI flash chip drivers.
+ # Wrapped stub symbols are defined in src/platform/esp32/iram-quirk.c.
+ env.Append(
+ LINKFLAGS=[
+ "-Wl,--wrap=esp_flash_chip_gd",
+ "-Wl,--wrap=esp_flash_chip_issi",
+ "-Wl,--wrap=esp_flash_chip_winbond",
+ ]
+ )
+ else:
+ # For newer ESP32 targets, using newlib nano works better.
+ env.Append(LINKFLAGS=["--specs=nano.specs", "-u", "_printf_float"])
# XXX
for lb in env.GetLibBuilders():
diff --git a/platformio.ini b/platformio.ini
index c6efc740da..f4306c2ea8 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -130,8 +130,10 @@ lib_deps =
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
adafruit/Adafruit MPU6050@^2.2.4
adafruit/Adafruit LIS3DH@^1.2.4
+ adafruit/Adafruit AHTX0@^2.0.5
lewisxhe/SensorLib@^0.2.0
adafruit/Adafruit LSM6DS@^4.7.2
mprograms/QMC5883LCompass@^1.2.0
adafruit/Adafruit VEML7700 Library@^2.1.6
- adafruit/Adafruit SHT4x Library@^1.0.4
\ No newline at end of file
+ adafruit/Adafruit SHT4x Library@^1.0.4
+ adafruit/Adafruit TSL2591 Library@^1.4.5
\ No newline at end of file
diff --git a/protobufs b/protobufs
index b5dc871a1b..a45a6154d0 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit b5dc871a1bfa2cc932126a4f490d9ef078476e4c
+Subproject commit a45a6154d0721027bf63f85cfc5abd9f6fab2422
diff --git a/src/PowerStatus.h b/src/PowerStatus.h
index 56d19b758c..592a033280 100644
--- a/src/PowerStatus.h
+++ b/src/PowerStatus.h
@@ -59,9 +59,18 @@ class PowerStatus : public Status
int getBatteryVoltageMv() const { return batteryVoltageMv; }
/**
- * Note: 0% battery means 'unknown/this board doesn't have a battery installed'
+ * Note: for boards with battery pin or PMU, 0% battery means 'unknown/this board doesn't have a battery installed'
*/
+#if defined(HAS_PMU) || defined(BATTERY_PIN)
uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 0; }
+#endif
+
+ /**
+ * Note: for boards without battery pin and PMU, 101% battery means 'the board is using external power'
+ */
+#if !defined(HAS_PMU) && !defined(BATTERY_PIN)
+ uint8_t getBatteryChargePercent() const { return getHasBattery() ? batteryChargePercent : 101; }
+#endif
bool matches(const PowerStatus *newStatus) const
{
diff --git a/src/configuration.h b/src/configuration.h
index 858f3167e7..2d0095e22e 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -128,8 +128,10 @@ along with this program. If not, see .
#define LPS22HB_ADDR_ALT 0x5D
#define SHT31_4x_ADDR 0x44
#define PMSA0031_ADDR 0x12
+#define AHT10_ADDR 0x38
#define RCWL9620_ADDR 0x57
#define VEML7700_ADDR 0x10
+#define TSL25911_ADDR 0x29
// -----------------------------------------------------------------------------
// ACCELEROMETER
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index 6c01b91000..a2ccb18a81 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -45,6 +45,8 @@ class ScanI2C
VEML7700,
RCWL9620,
NCP5623,
+ TSL2591,
+ AHT10,
} DeviceType;
// typedef uint8_t DeviceAddress;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 7828dfb586..d2a6e7848a 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -256,7 +256,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
type = BMP_280;
}
break;
-
+#ifndef HAS_NCP5623
+ case AHT10_ADDR:
+ LOG_INFO("AHT10 sensor found at address 0x%x\n", (uint8_t)addr.address);
+ type = AHT10;
+ break;
+#endif
case INA_ADDR:
case INA_ADDR_ALTERNATE:
case INA_ADDR_WAVESHARE_UPS:
@@ -337,6 +342,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found\n");
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found\n");
+ SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found\n");
default:
LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address);
@@ -369,4 +375,4 @@ TwoWire *ScanI2CTwoWire::fetchI2CBus(ScanI2C::DeviceAddress address) const
size_t ScanI2CTwoWire::countDevices() const
{
return foundDevices.size();
-}
+}
\ No newline at end of file
diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp
index 864b246a35..d60e3825c8 100644
--- a/src/gps/RTC.cpp
+++ b/src/gps/RTC.cpp
@@ -222,9 +222,8 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
*/
int32_t getTZOffset()
{
- time_t now;
+ time_t now = getTime(false);
struct tm *gmt;
- now = time(NULL);
gmt = gmtime(&now);
gmt->tm_isdst = -1;
return (int32_t)difftime(now, mktime(gmt));
@@ -265,4 +264,4 @@ time_t gm_mktime(struct tm *tm)
setenv("TZ", "UTC0", 1);
}
return res;
-}
+}
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index e7ffbeac00..849c03f92a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -534,7 +534,9 @@ void setup()
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700)
+ SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN)
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
+ SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
i2cScanner.reset();
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 0928caddf2..10a313e765 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -289,6 +289,9 @@ void NodeDB::installDefaultConfig()
meshtastic_Config_PositionConfig_PositionFlags_SPEED | meshtastic_Config_PositionConfig_PositionFlags_HEADING |
meshtastic_Config_PositionConfig_PositionFlags_DOP | meshtastic_Config_PositionConfig_PositionFlags_SATINVIEW);
+#ifdef RADIOMASTER_900_BANDIT_NANO
+ config.display.flip_screen = true;
+#endif
#ifdef T_WATCH_S3
config.display.screen_on_secs = 30;
config.display.wake_on_tap_or_motion = true;
diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp
index 2a69d6d56a..26d0d9525a 100644
--- a/src/mesh/PhoneAPI.cpp
+++ b/src/mesh/PhoneAPI.cpp
@@ -140,16 +140,18 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
*
* We assume buf is at least FromRadio_size bytes long.
*
- * Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
- * STATE_SEND_MY_INFO, // send our my info record
- * STATE_SEND_CHANNELS
- * STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client
- STATE_SEND_CONFIG,
- STATE_SEND_MODULE_CONFIG,
- STATE_SEND_METADATA,
- STATE_SEND_COMPLETE_ID,
- STATE_SEND_PACKETS // send packets or debug strings
+ * Our sending states progress in the following sequence (the client apps ASSUME THIS SEQUENCE, DO NOT CHANGE IT):
+ STATE_SEND_MY_INFO, // send our my info record
+ STATE_SEND_OWN_NODEINFO,
+ STATE_SEND_METADATA,
+ STATE_SEND_CHANNELS
+ STATE_SEND_CONFIG,
+ STATE_SEND_MODULE_CONFIG,
+ STATE_SEND_OTHER_NODEINFOS, // states progress in this order as the device sends to the client
+ STATE_SEND_COMPLETE_ID,
+ STATE_SEND_PACKETS // send packets or debug strings
*/
+
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available()) {
@@ -171,37 +173,32 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// app not to send locations on our behalf.
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag;
fromRadioScratch.my_info = myNodeInfo;
- state = STATE_SEND_METADATA;
+ state = STATE_SEND_OWN_NODEINFO;
service.refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon.
break;
- case STATE_SEND_METADATA:
- LOG_INFO("getFromRadio=STATE_SEND_METADATA\n");
- fromRadioScratch.which_payload_variant = meshtastic_FromRadio_metadata_tag;
- fromRadioScratch.metadata = getDeviceMetadata();
- state = STATE_SEND_NODEINFO;
- break;
-
- case STATE_SEND_NODEINFO: {
- LOG_INFO("getFromRadio=STATE_SEND_NODEINFO\n");
-
- if (nodeInfoForPhone.num != 0) {
- LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", nodeInfoForPhone.num, nodeInfoForPhone.last_heard,
- nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name);
+ case STATE_SEND_OWN_NODEINFO: {
+ LOG_INFO("getFromRadio=STATE_SEND_OWN_NODEINFO\n");
+ auto us = nodeDB->readNextMeshNode(readIndex);
+ if (us) {
+ nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(us);
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
fromRadioScratch.node_info = nodeInfoForPhone;
- // Stay in current state until done sending nodeinfos
- nodeInfoForPhone.num = 0; // We just consumed a nodeinfo, will need a new one next time
- } else {
- LOG_INFO("Done sending nodeinfos\n");
- state = STATE_SEND_CHANNELS;
- // Go ahead and send that ID right now
- return getFromRadio(buf);
+ // Should allow us to resume sending NodeInfo in STATE_SEND_OTHER_NODEINFOS
+ nodeInfoForPhone.num = 0;
}
+ state = STATE_SEND_METADATA;
break;
}
+ case STATE_SEND_METADATA:
+ LOG_INFO("getFromRadio=STATE_SEND_METADATA\n");
+ fromRadioScratch.which_payload_variant = meshtastic_FromRadio_metadata_tag;
+ fromRadioScratch.metadata = getDeviceMetadata();
+ state = STATE_SEND_CHANNELS;
+ break;
+
case STATE_SEND_CHANNELS:
LOG_INFO("getFromRadio=STATE_SEND_CHANNELS\n");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_channel_tag;
@@ -325,11 +322,30 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
config_state++;
// Advance when we have sent all of our ModuleConfig objects
if (config_state > (_meshtastic_AdminMessage_ModuleConfigType_MAX + 1)) {
- state = STATE_SEND_COMPLETE_ID;
+ // Clients sending special nonce don't want to see other nodeinfos
+ state = config_nonce == SPECIAL_NONCE ? STATE_SEND_COMPLETE_ID : STATE_SEND_OTHER_NODEINFOS;
config_state = 0;
}
break;
+ case STATE_SEND_OTHER_NODEINFOS: {
+ LOG_INFO("getFromRadio=STATE_SEND_OTHER_NODEINFOS\n");
+ if (nodeInfoForPhone.num != 0) {
+ LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", nodeInfoForPhone.num, nodeInfoForPhone.last_heard,
+ nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name);
+ fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag;
+ fromRadioScratch.node_info = nodeInfoForPhone;
+ // Stay in current state until done sending nodeinfos
+ nodeInfoForPhone.num = 0; // We just consumed a nodeinfo, will need a new one next time
+ } else {
+ LOG_INFO("Done sending nodeinfos\n");
+ state = STATE_SEND_COMPLETE_ID;
+ // Go ahead and send that ID right now
+ return getFromRadio(buf);
+ }
+ break;
+ }
+
case STATE_SEND_COMPLETE_ID:
LOG_INFO("getFromRadio=STATE_SEND_COMPLETE_ID\n");
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_config_complete_id_tag;
@@ -422,10 +438,11 @@ bool PhoneAPI::available()
case STATE_SEND_CONFIG:
case STATE_SEND_MODULECONFIG:
case STATE_SEND_METADATA:
+ case STATE_SEND_OWN_NODEINFO:
case STATE_SEND_COMPLETE_ID:
return true;
- case STATE_SEND_NODEINFO:
+ case STATE_SEND_OTHER_NODEINFOS:
if (nodeInfoForPhone.num == 0) {
auto nextNode = nodeDB->readNextMeshNode(readIndex);
if (nextNode) {
diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h
index 450649d7bc..49bf0e292b 100644
--- a/src/mesh/PhoneAPI.h
+++ b/src/mesh/PhoneAPI.h
@@ -6,6 +6,7 @@
// Make sure that we never let our packets grow too large for one BLE packet
#define MAX_TO_FROM_RADIO_SIZE 512
+#define SPECIAL_NONCE 69420
/**
* Provides our protobuf based API which phone/PC clients can use to talk to our device
@@ -20,13 +21,14 @@ class PhoneAPI
: public Observer // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
{
enum State {
- STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
- STATE_SEND_MY_INFO, // send our my info record
- STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
- STATE_SEND_CHANNELS, // Send all channels
- STATE_SEND_CONFIG, // Replacement for the old Radioconfig
- STATE_SEND_MODULECONFIG, // Send Module specific config
+ STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
+ STATE_SEND_MY_INFO, // send our my info record
+ STATE_SEND_OWN_NODEINFO,
STATE_SEND_METADATA,
+ STATE_SEND_CHANNELS, // Send all channels
+ STATE_SEND_CONFIG, // Replacement for the old Radioconfig
+ STATE_SEND_MODULECONFIG, // Send Module specific config
+ STATE_SEND_OTHER_NODEINFOS, // states progress in this order as the device sends to to the client
STATE_SEND_COMPLETE_ID,
STATE_SEND_PACKETS // send packets or debug strings
};
diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp
index 8c6c349fdd..5677e6edad 100644
--- a/src/mesh/RF95Interface.cpp
+++ b/src/mesh/RF95Interface.cpp
@@ -8,7 +8,10 @@
#include "PortduinoGlue.h"
#endif
-#define MAX_POWER 20
+#ifndef RF95_MAX_POWER
+#define RF95_MAX_POWER 20
+#endif
+
// if we use 20 we are limited to 1% duty cycle or hw might overheat. For continuous operation set a limit of 17
// In theory up to 27 dBm is possible, but the modules installed in most radios can cope with a max of 20. So BIG WARNING
// if you set power to something higher than 17 or 20 you might fry your board.
@@ -49,8 +52,8 @@ bool RF95Interface::init()
{
RadioLibInterface::init();
- if (power > MAX_POWER) // This chip has lower power limits than some
- power = MAX_POWER;
+ if (power > RF95_MAX_POWER) // This chip has lower power limits than some
+ power = RF95_MAX_POWER;
limitPower();
@@ -61,6 +64,13 @@ bool RF95Interface::init()
digitalWrite(RF95_TCXO, 1);
#endif
+ // enable PA
+#ifdef RF95_PA_EN
+#if defined(RF95_PA_DAC_EN)
+ dacWrite(RF95_PA_EN, RF95_PA_LEVEL);
+#endif
+#endif
+
/*
#define RF95_TXEN (22) // If defined, this pin should be set high prior to transmit (controls an external analog switch)
#define RF95_RXEN (23) // If defined, this pin should be set high prior to receive (controls an external analog switch)
@@ -71,6 +81,11 @@ bool RF95Interface::init()
digitalWrite(RF95_TXEN, 0);
#endif
+#ifdef RF95_FAN_EN
+ pinMode(RF95_FAN_EN, OUTPUT);
+ digitalWrite(RF95_FAN_EN, 1);
+#endif
+
#ifdef RF95_RXEN
pinMode(RF95_RXEN, OUTPUT);
digitalWrite(RF95_RXEN, 1);
@@ -146,10 +161,14 @@ bool RF95Interface::reconfigure()
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
- if (power > MAX_POWER) // This chip has lower power limits than some
- power = MAX_POWER;
+ if (power > RF95_MAX_POWER) // This chip has lower power limits than some
+ power = RF95_MAX_POWER;
+#ifdef USE_RF95_RFO
+ err = lora->setOutputPower(power, true);
+#else
err = lora->setOutputPower(power);
+#endif
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
@@ -235,5 +254,9 @@ bool RF95Interface::sleep()
setStandby(); // First cancel any active receiving/sending
lora->sleep();
+#ifdef RF95_FAN_EN
+ digitalWrite(RF95_FAN_EN, 0);
+#endif
+
return true;
}
\ No newline at end of file
diff --git a/src/mesh/RadioLibRF95.cpp b/src/mesh/RadioLibRF95.cpp
index 1fe7869a37..a202d4f4d9 100644
--- a/src/mesh/RadioLibRF95.cpp
+++ b/src/mesh/RadioLibRF95.cpp
@@ -42,7 +42,11 @@ int16_t RadioLibRF95::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_
state = setCodingRate(cr);
RADIOLIB_ASSERT(state);
+#ifdef USE_RF95_RFO
+ state = setOutputPower(power, true);
+#else
state = setOutputPower(power);
+#endif
RADIOLIB_ASSERT(state);
state = setGain(gain);
diff --git a/src/mesh/generated/meshtastic/atak.pb.h b/src/mesh/generated/meshtastic/atak.pb.h
index c094727ed3..5fd18f963b 100644
--- a/src/mesh/generated/meshtastic/atak.pb.h
+++ b/src/mesh/generated/meshtastic/atak.pb.h
@@ -73,6 +73,9 @@ typedef struct _meshtastic_GeoChat {
/* Uid recipient of the message */
bool has_to;
char to[120];
+ /* Callsign of the recipient for the message */
+ bool has_to_callsign;
+ char to_callsign[120];
} meshtastic_GeoChat;
/* ATAK Group
@@ -164,13 +167,13 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_TAKPacket_init_default {0, false, meshtastic_Contact_init_default, false, meshtastic_Group_init_default, false, meshtastic_Status_init_default, 0, {meshtastic_PLI_init_default}}
-#define meshtastic_GeoChat_init_default {"", false, ""}
+#define meshtastic_GeoChat_init_default {"", false, "", false, ""}
#define meshtastic_Group_init_default {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
#define meshtastic_Status_init_default {0}
#define meshtastic_Contact_init_default {"", ""}
#define meshtastic_PLI_init_default {0, 0, 0, 0, 0}
#define meshtastic_TAKPacket_init_zero {0, false, meshtastic_Contact_init_zero, false, meshtastic_Group_init_zero, false, meshtastic_Status_init_zero, 0, {meshtastic_PLI_init_zero}}
-#define meshtastic_GeoChat_init_zero {"", false, ""}
+#define meshtastic_GeoChat_init_zero {"", false, "", false, ""}
#define meshtastic_Group_init_zero {_meshtastic_MemberRole_MIN, _meshtastic_Team_MIN}
#define meshtastic_Status_init_zero {0}
#define meshtastic_Contact_init_zero {"", ""}
@@ -179,6 +182,7 @@ extern "C" {
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_GeoChat_message_tag 1
#define meshtastic_GeoChat_to_tag 2
+#define meshtastic_GeoChat_to_callsign_tag 3
#define meshtastic_Group_role_tag 1
#define meshtastic_Group_team_tag 2
#define meshtastic_Status_battery_tag 1
@@ -214,7 +218,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,chat,payload_variant.chat),
#define meshtastic_GeoChat_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, message, 1) \
-X(a, STATIC, OPTIONAL, STRING, to, 2)
+X(a, STATIC, OPTIONAL, STRING, to, 2) \
+X(a, STATIC, OPTIONAL, STRING, to_callsign, 3)
#define meshtastic_GeoChat_CALLBACK NULL
#define meshtastic_GeoChat_DEFAULT NULL
@@ -262,11 +267,11 @@ extern const pb_msgdesc_t meshtastic_PLI_msg;
/* Maximum encoded size of messages (where known) */
#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_TAKPacket_size
#define meshtastic_Contact_size 242
-#define meshtastic_GeoChat_size 323
+#define meshtastic_GeoChat_size 444
#define meshtastic_Group_size 4
#define meshtastic_PLI_size 31
#define meshtastic_Status_size 3
-#define meshtastic_TAKPacket_size 584
+#define meshtastic_TAKPacket_size 705
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h
index ffc18c30ba..7b544d714c 100644
--- a/src/mesh/generated/meshtastic/mesh.pb.h
+++ b/src/mesh/generated/meshtastic/mesh.pb.h
@@ -156,6 +156,9 @@ typedef enum _meshtastic_HardwareModel {
/* NRF52_PROMICRO_DIY
Promicro NRF52840 with SX1262/LLCC68, SSD1306 OLED and NEO6M GPS */
meshtastic_HardwareModel_NRF52_PROMICRO_DIY = 63,
+ /* RadioMaster 900 Bandit Nano, https://www.radiomasterrc.com/products/bandit-nano-expresslrs-rf-module
+ ESP32-D0WDQ6 With SX1276/SKY66122, SSD1306 OLED and No GPS */
+ meshtastic_HardwareModel_RADIOMASTER_900_BANDIT_NANO = 64,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index 7748dd6b37..f0ff9bed00 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -57,7 +57,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* Lite On LTR-390UV-01 UV Light Sensor */
meshtastic_TelemetrySensorType_LTR390UV = 21,
/* AMS TSL25911FN RGB Light Sensor */
- meshtastic_TelemetrySensorType_TSL25911FN = 22
+ meshtastic_TelemetrySensorType_TSL25911FN = 22,
+ /* AHT10 Integrated temperature and humidity sensor */
+ meshtastic_TelemetrySensorType_AHT10 = 23
} meshtastic_TelemetrySensorType;
/* Struct definitions */
@@ -168,8 +170,8 @@ extern "C" {
/* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
-#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL25911FN
-#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL25911FN+1))
+#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_AHT10
+#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_AHT10+1))
diff --git a/src/modules/AtakPluginModule.cpp b/src/modules/AtakPluginModule.cpp
index b460602ef7..59263415c8 100644
--- a/src/modules/AtakPluginModule.cpp
+++ b/src/modules/AtakPluginModule.cpp
@@ -87,6 +87,14 @@ void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtast
compressed.payload_variant.chat.to);
LOG_DEBUG("Compressed chat to: %d bytes\n", length);
}
+
+ if (t->payload_variant.chat.has_to_callsign) {
+ compressed.payload_variant.chat.has_to_callsign = true;
+ length =
+ unishox2_compress_simple(t->payload_variant.chat.to_callsign, strlen(t->payload_variant.chat.to_callsign),
+ compressed.payload_variant.chat.to_callsign);
+ LOG_DEBUG("Compressed chat to_callsign: %d bytes\n", length);
+ }
}
mp.decoded.payload.size = pb_encode_to_bytes(mp.decoded.payload.bytes, sizeof(mp.decoded.payload.bytes),
meshtastic_TAKPacket_fields, &compressed);
@@ -124,6 +132,14 @@ void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtast
uncompressed.payload_variant.chat.to);
LOG_DEBUG("Decompressed chat to: %d bytes\n", length);
}
+
+ if (t->payload_variant.chat.has_to_callsign) {
+ uncompressed.payload_variant.chat.has_to_callsign = true;
+ length =
+ unishox2_decompress_simple(t->payload_variant.chat.to_callsign, strlen(t->payload_variant.chat.to_callsign),
+ uncompressed.payload_variant.chat.to_callsign);
+ LOG_DEBUG("Decompressed chat to_callsign: %d bytes\n", length);
+ }
}
decompressedCopy->decoded.payload.size =
pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload),
diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp
index f770267086..78af7099a5 100644
--- a/src/modules/NodeInfoModule.cpp
+++ b/src/modules/NodeInfoModule.cpp
@@ -58,10 +58,15 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
meshtastic_MeshPacket *NodeInfoModule::allocReply()
{
+ if (!airTime->isTxAllowedChannelUtil(false)) {
+ ignoreRequest = true; // Mark it as ignored for MeshModule
+ LOG_DEBUG("Skip sending NodeInfo due to > 40 percent channel util.\n");
+ return NULL;
+ }
uint32_t now = millis();
// If we sent our NodeInfo less than 5 min. ago, don't send it again as it may be still underway.
if (lastSentToMesh && (now - lastSentToMesh) < (5 * 60 * 1000)) {
- LOG_DEBUG("Sending NodeInfo will be ignored since we just sent it.\n");
+ LOG_DEBUG("Skip sending NodeInfo since we just sent it less than 5 minutes ago.\n");
ignoreRequest = true; // Mark it as ignored for MeshModule
return NULL;
} else {
diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp
index 6a655e4b7c..5fadd531f9 100644
--- a/src/modules/PositionModule.cpp
+++ b/src/modules/PositionModule.cpp
@@ -211,11 +211,11 @@ meshtastic_MeshPacket *PositionModule::allocReply()
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
// devices can get time.
- if (getRTCQuality() < RTCQualityDevice) {
+ if (getRTCQuality() < RTCQualityGPS) {
LOG_INFO("Stripping time %u from position send\n", p.time);
p.time = 0;
} else {
- p.time = getValidTime(RTCQualityDevice);
+ p.time = getValidTime(RTCQualityGPS);
LOG_INFO("Providing time to mesh %u\n", p.time);
}
@@ -454,4 +454,4 @@ void PositionModule::handleNewPosition()
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index a3f63b0aac..5ecfe73289 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -18,6 +18,7 @@
#include
// Sensors
+#include "Sensor/AHT10.h"
#include "Sensor/BME280Sensor.h"
#include "Sensor/BME680Sensor.h"
#include "Sensor/BMP085Sensor.h"
@@ -28,6 +29,7 @@
#include "Sensor/SHT31Sensor.h"
#include "Sensor/SHT4XSensor.h"
#include "Sensor/SHTC3Sensor.h"
+#include "Sensor/TSL2591Sensor.h"
#include "Sensor/VEML7700Sensor.h"
BMP085Sensor bmp085Sensor;
@@ -39,8 +41,10 @@ SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
SHT31Sensor sht31Sensor;
VEML7700Sensor veml7700Sensor;
+TSL2591Sensor tsl2591Sensor;
SHT4XSensor sht4xSensor;
RCWL9620Sensor rcwl9620Sensor;
+AHT10Sensor aht10Sensor;
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -63,7 +67,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
*/
// moduleConfig.telemetry.environment_measurement_enabled = 1;
- // moduleConfig.telemetry.environment_screen_enabled = 1;
+ // moduleConfig.telemetry.environment_screen_enabled = 1;
// moduleConfig.telemetry.environment_update_interval = 45;
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
@@ -103,8 +107,12 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = ina260Sensor.runOnce();
if (veml7700Sensor.hasSensor())
result = veml7700Sensor.runOnce();
+ if (tsl2591Sensor.hasSensor())
+ result = tsl2591Sensor.runOnce();
if (rcwl9620Sensor.hasSensor())
result = rcwl9620Sensor.runOnce();
+ if (aht10Sensor.hasSensor())
+ result = aht10Sensor.runOnce();
}
return result;
} else {
@@ -287,10 +295,27 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
valid = valid && veml7700Sensor.getMetrics(&m);
hasSensor = true;
}
+ if (tsl2591Sensor.hasSensor()) {
+ valid = valid && tsl2591Sensor.getMetrics(&m);
+ hasSensor = true;
+ }
if (rcwl9620Sensor.hasSensor()) {
valid = valid && rcwl9620Sensor.getMetrics(&m);
hasSensor = true;
}
+ if (aht10Sensor.hasSensor()) {
+ if (!bmp280Sensor.hasSensor()) {
+ valid = valid && aht10Sensor.getMetrics(&m);
+ hasSensor = true;
+ } else {
+ // prefer bmp280 temp if both sensors are present, fetch only humidity
+ meshtastic_Telemetry m_ahtx;
+ LOG_INFO("AHTX0+BMP280 module detected: using temp from BMP280 and humy from AHTX0\n");
+ aht10Sensor.getMetrics(&m_ahtx);
+ m.variant.environment_metrics.relative_humidity = m_ahtx.variant.environment_metrics.relative_humidity;
+ }
+ }
+
valid = valid && hasSensor;
if (valid) {
diff --git a/src/modules/Telemetry/Sensor/AHT10.cpp b/src/modules/Telemetry/Sensor/AHT10.cpp
new file mode 100644
index 0000000000..985515bb6a
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/AHT10.cpp
@@ -0,0 +1,35 @@
+#include "AHT10.h"
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include "configuration.h"
+#include
+#include
+
+AHT10Sensor::AHT10Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_AHT10, "AHT10") {}
+
+int32_t AHT10Sensor::runOnce()
+{
+ LOG_INFO("Init sensor: %s\n", sensorName);
+ if (!hasSensor()) {
+ return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
+ }
+ aht10 = Adafruit_AHTX0();
+ status = aht10.begin(nodeTelemetrySensorsMap[sensorType].second, 0, nodeTelemetrySensorsMap[sensorType].first);
+
+ return initI2CSensor();
+}
+
+void AHT10Sensor::setup() {}
+
+bool AHT10Sensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ LOG_DEBUG("AHT10Sensor::getMetrics\n");
+
+ sensors_event_t humidity, temp;
+ aht10.getEvent(&humidity, &temp);
+
+ measurement->variant.environment_metrics.temperature = temp.temperature;
+ measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
+
+ return true;
+}
diff --git a/src/modules/Telemetry/Sensor/AHT10.h b/src/modules/Telemetry/Sensor/AHT10.h
new file mode 100644
index 0000000000..b2b7b47f36
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/AHT10.h
@@ -0,0 +1,17 @@
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class AHT10Sensor : public TelemetrySensor
+{
+ private:
+ Adafruit_AHTX0 aht10;
+
+ protected:
+ virtual void setup() override;
+
+ public:
+ AHT10Sensor();
+ virtual int32_t runOnce() override;
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+};
diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp
index f2c3804f4b..71da390433 100644
--- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp
+++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp
@@ -28,7 +28,7 @@ int32_t BME680Sensor::runOnce()
if (bme680.status == BSEC_OK) {
status = 1;
- if (!bme680.setConfig(bsec_config_iaq)) {
+ if (!bme680.setConfig(bsec_config)) {
checkStatus("setConfig");
status = 0;
}
diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.h b/src/modules/Telemetry/Sensor/BME680Sensor.h
index 351db50ab4..a5d2b5a484 100644
--- a/src/modules/Telemetry/Sensor/BME680Sensor.h
+++ b/src/modules/Telemetry/Sensor/BME680Sensor.h
@@ -8,7 +8,9 @@
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // That's 6 hours worth of millis()
-#include "bme680_iaq_33v_3s_4d/bsec_iaq.h"
+const uint8_t bsec_config[] = {
+#include "config/bme680/bme680_iaq_33v_3s_4d/bsec_iaq.txt"
+};
class BME680Sensor : public TelemetrySensor
{
diff --git a/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp b/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp
new file mode 100644
index 0000000000..0a3f5d685c
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/TSL2591Sensor.cpp
@@ -0,0 +1,38 @@
+#include "TSL2591Sensor.h"
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include "configuration.h"
+#include
+#include
+
+TSL2591Sensor::TSL2591Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_TSL25911FN, "TSL2591") {}
+
+int32_t TSL2591Sensor::runOnce()
+{
+ LOG_INFO("Init sensor: %s\n", sensorName);
+ if (!hasSensor()) {
+ return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
+ }
+ status = tsl.begin(nodeTelemetrySensorsMap[sensorType].second);
+
+ return initI2CSensor();
+}
+
+void TSL2591Sensor::setup()
+{
+ tsl.setGain(TSL2591_GAIN_MED); // 25x gain
+ tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
+}
+
+bool TSL2591Sensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ uint32_t lum = tsl.getFullLuminosity();
+ uint16_t ir, full;
+ ir = lum >> 16;
+ full = lum & 0xFFFF;
+
+ measurement->variant.environment_metrics.lux = tsl.calculateLux(full, ir);
+ LOG_INFO("Lux: %f\n", measurement->variant.environment_metrics.lux);
+
+ return true;
+}
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/TSL2591Sensor.h b/src/modules/Telemetry/Sensor/TSL2591Sensor.h
new file mode 100644
index 0000000000..a24d539756
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/TSL2591Sensor.h
@@ -0,0 +1,17 @@
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class TSL2591Sensor : public TelemetrySensor
+{
+ private:
+ Adafruit_TSL2591 tsl;
+
+ protected:
+ virtual void setup() override;
+
+ public:
+ TSL2591Sensor();
+ virtual int32_t runOnce() override;
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+};
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.c b/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.c
deleted file mode 100644
index 0b53283064..0000000000
--- a/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
-
-#include "bsec_iaq.h"
-
-const uint8_t bsec_config_iaq[1974] = {
- 0, 0, 4, 2, 189, 1, 0, 0, 0, 0, 0, 0, 158, 7, 0, 0, 176, 0, 1, 0, 0, 192, 168, 71, 64,
- 49, 119, 76, 0, 0, 97, 69, 0, 0, 97, 69, 137, 65, 0, 191, 205, 204, 204, 190, 0, 0, 64, 191, 225, 122,
- 148, 190, 10, 0, 3, 0, 0, 0, 96, 64, 23, 183, 209, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 205, 204, 204, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 128, 63,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 128, 63, 82, 73, 157, 188, 95, 41, 203, 61, 118, 224,
- 108, 63, 155, 230, 125, 63, 191, 14, 124, 63, 0, 0, 160, 65, 0, 0, 32, 66, 0, 0, 160, 65, 0, 0, 32,
- 66, 0, 0, 32, 66, 0, 0, 160, 65, 0, 0, 32, 66, 0, 0, 160, 65, 8, 0, 2, 0, 236, 81, 133, 66,
- 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, 215, 35, 59, 13, 0, 5, 0, 0, 0, 0, 0, 100,
- 35, 41, 29, 86, 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, 13, 5, 11, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0,
- 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
- 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 10, 10, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63,
- 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0,
- 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 0, 88, 1, 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, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 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, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 112, 23, 112, 23, 112, 23, 112, 23,
- 8, 7, 8, 7, 8, 7, 8, 7, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 112, 23, 112, 23, 112, 23, 112, 23, 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, 220, 5, 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, 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, 5, 10, 5,
- 0, 2, 0, 10, 0, 30, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 64, 1, 100, 0, 100, 0,
- 100, 0, 200, 0, 200, 0, 200, 0, 64, 1, 64, 1, 64, 1, 10, 0, 0, 0, 0, 0, 21, 122, 0, 0};
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.h b/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.h
deleted file mode 100644
index d693f1e6aa..0000000000
--- a/src/modules/Telemetry/Sensor/bme680_iaq_33v_3s_4d/bsec_iaq.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
-
-#include
-
-extern const uint8_t bsec_config_iaq[1974];
-
-#endif
\ No newline at end of file
diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h
index 45d533a760..824c11bdd3 100644
--- a/src/platform/esp32/architecture.h
+++ b/src/platform/esp32/architecture.h
@@ -145,6 +145,8 @@
#define HW_VENDOR meshtastic_HardwareModel_UNPHONE
#elif defined(WIPHONE)
#define HW_VENDOR meshtastic_HardwareModel_WIPHONE
+#elif defined(RADIOMASTER_900_BANDIT_NANO)
+#define HW_VENDOR meshtastic_HardwareModel_RADIOMASTER_900_BANDIT_NANO
#endif
// -----------------------------------------------------------------------------
diff --git a/src/platform/esp32/iram-quirk.c b/src/platform/esp32/iram-quirk.c
new file mode 100644
index 0000000000..813842138a
--- /dev/null
+++ b/src/platform/esp32/iram-quirk.c
@@ -0,0 +1,23 @@
+// Free up some precious space in the iram0_0_seg memory segment
+
+#include
+
+#include
+#include
+#include
+
+#define IRAM_SECTION section(".iram1.stub")
+
+IRAM_ATTR esp_err_t stub_probe(esp_flash_t *chip, uint32_t flash_id)
+{
+ return ESP_ERR_NOT_FOUND;
+}
+
+const spi_flash_chip_t stub_flash_chip __attribute__((IRAM_SECTION)) = {
+ .name = "stub",
+ .probe = stub_probe,
+};
+
+extern const spi_flash_chip_t __wrap_esp_flash_chip_gd __attribute__((IRAM_SECTION, alias("stub_flash_chip")));
+extern const spi_flash_chip_t __wrap_esp_flash_chip_issi __attribute__((IRAM_SECTION, alias("stub_flash_chip")));
+extern const spi_flash_chip_t __wrap_esp_flash_chip_winbond __attribute__((IRAM_SECTION, alias("stub_flash_chip")));
diff --git a/variants/heltec_v3/variant.h b/variants/heltec_v3/variant.h
index 70b122f584..2417b873d8 100644
--- a/variants/heltec_v3/variant.h
+++ b/variants/heltec_v3/variant.h
@@ -16,7 +16,7 @@
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
-#define ADC_MULTIPLIER 4.9
+#define ADC_MULTIPLIER 4.9 * 1.045
#define USE_SX1262
diff --git a/variants/heltec_wireless_tracker/variant.h b/variants/heltec_wireless_tracker/variant.h
index 167345e1a9..f0ee0631d0 100644
--- a/variants/heltec_wireless_tracker/variant.h
+++ b/variants/heltec_wireless_tracker/variant.h
@@ -27,13 +27,17 @@
#define SCREEN_TRANSITION_FRAMERATE 3 // fps
#define DISPLAY_FORCE_SMALL_FONTS
-#define VEXT_ENABLE_V05 3 // active HIGH, powers the lora antenna boost
+// pin 3 is Vext on v1.1 - HIGH enables LDO for Vext rail which goes to:
+// GPS UC6580: GPS V_DET(8), VDD_IO(7), DCDC_IN(21), pulls up RESETN(17), D_SEL(33) and BOOT_MODE(34) through 10kR
+// GPS LNA SW7125DE: VCC(4), pulls up SHDN(5) through 10kR
+// LED: VDD, LEDA (through diode)
+#define VEXT_ENABLE_V05 3 // active HIGH - powers the GPS, GPS LNA and OLED VDD/anode
#define BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
-#define ADC_MULTIPLIER 4.9
+#define ADC_MULTIPLIER 4.9 * 1.045
#define ADC_CTRL 2 // active HIGH, powers the voltage divider. Only on 1.1
#define ADC_CTRL_ENABLED HIGH
@@ -43,6 +47,8 @@
#define GPS_TX_PIN 34
#define PIN_GPS_RESET 35
#define PIN_GPS_PPS 36
+// #define PIN_GPS_EN 3 // Uncomment to power off the GPS with triple-click on Tracker v1.1, though we'll also lose the
+// display.
#define GPS_RESET_MODE LOW
#define GPS_UC6580
diff --git a/variants/heltec_wireless_tracker_V1_0/variant.h b/variants/heltec_wireless_tracker_V1_0/variant.h
index 84e77a6b95..1b4751a576 100644
--- a/variants/heltec_wireless_tracker_V1_0/variant.h
+++ b/variants/heltec_wireless_tracker_V1_0/variant.h
@@ -34,7 +34,7 @@
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
-#define ADC_MULTIPLIER 4.9
+#define ADC_MULTIPLIER 4.9 * 1.045
#undef GPS_RX_PIN
#undef GPS_TX_PIN
diff --git a/variants/heltec_wsl_v3/variant.h b/variants/heltec_wsl_v3/variant.h
index 917ea7fb9e..75cea538d0 100644
--- a/variants/heltec_wsl_v3/variant.h
+++ b/variants/heltec_wsl_v3/variant.h
@@ -11,7 +11,7 @@
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
-#define ADC_MULTIPLIER 4.9
+#define ADC_MULTIPLIER 4.9 * 1.045
#define USE_SX1262
diff --git a/variants/radiomaster_900_bandit_nano/platformio.ini b/variants/radiomaster_900_bandit_nano/platformio.ini
new file mode 100644
index 0000000000..d83c14de23
--- /dev/null
+++ b/variants/radiomaster_900_bandit_nano/platformio.ini
@@ -0,0 +1,15 @@
+[env:radiomaster_900_bandit_nano]
+extends = esp32_base
+board = esp32doit-devkit-v1
+board_level = extra
+build_flags =
+ ${esp32_base.build_flags}
+ -DRADIOMASTER_900_BANDIT_NANO
+ -DVTABLES_IN_FLASH=1
+ -DCONFIG_DISABLE_HAL_LOCKS=1
+ -O2
+ -Ivariants/radiomaster_900_bandit_nano
+board_build.f_cpu = 240000000L
+upload_protocol = esptool
+lib_deps =
+ ${esp32_base.lib_deps}
\ No newline at end of file
diff --git a/variants/radiomaster_900_bandit_nano/variant.h b/variants/radiomaster_900_bandit_nano/variant.h
new file mode 100644
index 0000000000..bd66877333
--- /dev/null
+++ b/variants/radiomaster_900_bandit_nano/variant.h
@@ -0,0 +1,84 @@
+/*
+ Initial settings and work by https://github.com/uberhalit and re-work by https://github.com/gjelsoe
+ Unit provided by Radio Master RC
+ https://radiomasterrc.com/products/bandit-nano-expresslrs-rf-module with 0.96" OLED display
+*/
+
+/*
+ I2C SDA and SCL.
+*/
+#define I2C_SDA 14
+#define I2C_SCL 12
+
+/*
+ No GPS - but free solder pads are available inside the case.
+*/
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+
+/*
+ Pin connections from ESP32-D0WDQ6 to SX1276.
+*/
+#define LORA_DIO0 22
+#define LORA_DIO1 21
+#define LORA_SCK 18
+#define LORA_MISO 19
+#define LORA_MOSI 23
+#define LORA_CS 4
+#define LORA_RESET 5
+#define LORA_TXEN 33
+
+/*
+ This unit has a FAN built-in.
+ FAN is active at 250mW on it's ExpressLRS Firmware.
+*/
+#define RF95_FAN_EN 2
+
+/*
+ LED PIN setup.
+*/
+#define LED_PIN 15
+
+/*
+ Five way button when using ADC.
+ 2.632V, 2.177V, 1.598V, 1.055V, 0V
+
+ Possible ADC Values:
+ { UP, DOWN, LEFT, RIGHT, ENTER, IDLE }
+ 3227, 0 ,1961, 2668, 1290, 4095
+*/
+#define BUTTON_PIN 39
+#define BUTTON_NEED_PULLUP
+
+#define SCREEN_ROTATE
+
+/*
+ No External notification.
+*/
+#undef EXT_NOTIFY_OUT
+
+/*
+ Remapping PIN Names.
+ Note, that this unit uses RFO
+*/
+#define USE_RF95
+#define USE_RF95_RFO
+#define RF95_CS LORA_CS
+#define RF95_DIO1 LORA_DIO1
+#define RF95_TXEN LORA_TXEN
+#define RF95_RESET LORA_RESET
+#define RF95_MAX_POWER 12
+
+/*
+ This module has Skyworks SKY66122 controlled by dacWrite
+ power rangeing from 100mW to 1000mW.
+
+ Mapping of PA_LEVEL to Power output: GPIO26/dacWrite
+ 168 -> 100mW -> 2.11v
+ 148 -> 250mW -> 1.87v
+ 128 -> 500mW -> 1.63v
+ 90 -> 1000mW -> 1.16v
+*/
+#define RF95_PA_EN 26
+#define RF95_PA_DAC_EN
+#define RF95_PA_LEVEL 90
\ No newline at end of file
diff --git a/variants/station-g2/variant.h b/variants/station-g2/variant.h
index f781ceb24e..8f0b4b220c 100755
--- a/variants/station-g2/variant.h
+++ b/variants/station-g2/variant.h
@@ -40,6 +40,7 @@ Board Information: https://wiki.uniteng.com/en/meshtastic/station-g2
#define SX126X_MAX_POWER 19
#endif
+/*
#define BATTERY_PIN 4 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_CHANNEL ADC1_GPIO4_CHANNEL
#define ADC_MULTIPLIER 4
@@ -50,3 +51,4 @@ Board Information: https://wiki.uniteng.com/en/meshtastic/station-g2
#define BAT_NOBATVOLT 4460
#define CELL_TYPE_LION // same curve for liion/lipo
#define NUM_CELLS 2
+*/
diff --git a/variants/trackerd/variant.h b/variants/trackerd/variant.h
index bd8017d8c2..c4dfb9e936 100644
--- a/variants/trackerd/variant.h
+++ b/variants/trackerd/variant.h
@@ -20,16 +20,34 @@
#define LORA_DIO1 33
#define LORA_DIO2 32 // Not really used
-#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
-
-// Battery
-// The battery sense is hooked to pin A0 (4)
-// it is defined in the anlaolgue pin section of this file
-// and has 12 bit resolution
-// #define BATTERY_SENSE_SAMPLES 15 // Set the number of samples, It has an effect of increasing sensitivity.
-#define BATTERY_SENSE_RESOLUTION_BITS 12
-#define BATTERY_SENSE_RESOLUTION 4096.0
-#undef AREF_VOLTAGE
-#define AREF_VOLTAGE 3.0
-#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
-#define ADC_MULTIPLIER (2.0F)
\ No newline at end of file
+#undef BAT_MEASURE_ADC_UNIT
+#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
+#define ADC_MULTIPLIER 1.34 // tracked resistance divider is 100k+470k, so it can not fillfull well on esp32 adc
+#define ADC_CHANNEL ADC1_GPIO35_CHANNEL
+#define ADC_ATTENUATION ADC_ATTEN_DB_12 // lower dB for high resistance voltage divider
+
+#undef GPS_RX_PIN
+#undef GPS_TX_PIN
+#undef PIN_GPS_PPS
+
+#define PIN_GPS_EN 12
+#define GPS_EN_ACTIVE 1
+
+#define GPS_TX_PIN 10
+#define GPS_RX_PIN 9
+
+#define PIN_GPS_RESET 25
+// #define PIN_GPS_REINIT 25
+#define GPS_RESET_MODE 1
+
+#define GPS_L76K
+
+#undef PIN_LED1
+#undef PIN_LED2
+#undef PIN_LED3
+
+#define PIN_LED1 13
+#define PIN_LED2 15
+#define PIN_LED3 2
+
+#define ledOff(pin) pinMode(pin, INPUT)
\ No newline at end of file
diff --git a/version.properties b/version.properties
index aa4d2c2078..700044e6ff 100644
--- a/version.properties
+++ b/version.properties
@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 3
-build = 11
+build = 12