Merge branch 'meshtastic:master' into master

This commit is contained in:
Mictronics 2024-02-14 17:13:26 +01:00 committed by GitHub
commit f1e3f42aa5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 408 additions and 120 deletions

@ -1 +1 @@
Subproject commit 388fd79bf78df2c59dd0bdd029a382fa91b1cd88 Subproject commit 4432d3bfc155107e27079d96ddba16b52f2d9ea3

View File

@ -358,87 +358,98 @@ bool GPS::setup()
delay(1000); delay(1000);
} }
} }
// Disable Text Info messages
msglen = makeUBXPacket(0x06, 0x02, sizeof(_message_DISABLE_TXT_INFO), _message_DISABLE_TXT_INFO);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x02, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable text info messages.\n");
}
// ToDo add M10 tests for below // ToDo add M10 tests for below
if (strncmp(info.hwVersion, "00080000", 8) == 0) { if (strncmp(info.hwVersion, "00080000", 8) == 0) {
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8); msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8);
clearBuffer();
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n"); LOG_WARN("Unable to enable interference resistance.\n");
} }
clearBuffer();
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8); msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8);
clearBuffer();
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure extra settings.\n"); LOG_WARN("Unable to configure NAVX5_8 settings.\n");
} }
} else { } else {
msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7); msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x39, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable interference resistance.\n"); LOG_WARN("Unable to enable interference resistance.\n");
} }
msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5); msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to configure extra settings.\n"); LOG_WARN("Unable to configure NAVX5 settings.\n");
} }
} }
// ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid // Turn off unwanted NMEA messages, set update rate
msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ); msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x08, 400) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x08, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to set GPS update rate.\n"); LOG_WARN("Unable to set GPS update rate.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GLL.\n"); LOG_WARN("Unable to disable NMEA GLL.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to Enable NMEA GSA.\n"); LOG_WARN("Unable to Enable NMEA GSA.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA GSV.\n"); LOG_WARN("Unable to disable NMEA GSV.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA VTG.\n"); LOG_WARN("Unable to disable NMEA VTG.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA RMC.\n"); LOG_WARN("Unable to enable NMEA RMC.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA GGA.\n"); LOG_WARN("Unable to enable NMEA GGA.\n");
} }
clearBuffer();
if (uBloxProtocolVersion >= 18) { if (uBloxProtocolVersion >= 18) {
msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS); msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS);
clearBuffer();
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x86, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for GPS.\n"); LOG_WARN("Unable to enable powersaving for GPS.\n");
} }
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats. // For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
if (strncmp(info.hwVersion, "00080000", 8) == 0) { if (strncmp(info.hwVersion, "00080000", 8) == 0) {
msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA); msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA);
clearBuffer();
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x17, 400) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x17, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable NMEA 4.10.\n"); LOG_WARN("Unable to enable NMEA 4.10.\n");
} }
} }
@ -447,23 +458,23 @@ bool GPS::setup()
if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6 if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO); msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving ECO mode for Neo-6.\n"); LOG_WARN("Unable to enable powersaving ECO mode for Neo-6.\n");
} }
msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2); msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x3B, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving details for GPS.\n"); LOG_WARN("Unable to enable powersaving details for GPS.\n");
} }
msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID); msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x01, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable UBX-AID.\n"); LOG_WARN("Unable to disable UBX-AID.\n");
} }
} else { } else {
msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM); msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM);
_serial_gps->write(UBXscratch, msglen); _serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) { if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving mode for GPS.\n"); LOG_WARN("Unable to enable powersaving mode for GPS.\n");
} }
} }
@ -477,7 +488,96 @@ bool GPS::setup()
LOG_INFO("GNSS module configuration saved!\n"); LOG_INFO("GNSS module configuration saved!\n");
} }
} else { } else {
LOG_INFO("u-blox M10 hardware found, using defaults for now\n"); // LOG_INFO("u-blox M10 hardware found.\n");
delay(1000);
// First disable all NMEA messages in RAM layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_RAM), _message_VALSET_DISABLE_NMEA_RAM);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA messages for M10 GPS RAM.\n");
}
delay(250);
// Next disable unwanted NMEA messages in BBR layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_NMEA_BBR), _message_VALSET_DISABLE_NMEA_BBR);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable NMEA messages for M10 GPS BBR.\n");
}
delay(250);
// Disable Info txt messages in RAM layer
msglen =
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_RAM), _message_VALSET_DISABLE_TXT_INFO_RAM);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable Info messages for M10 GPS RAM.\n");
}
delay(250);
// Next disable Info txt messages in BBR layer
msglen =
makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_TXT_INFO_BBR), _message_VALSET_DISABLE_TXT_INFO_BBR);
clearBuffer();
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable Info messages for M10 GPS BBR.\n");
}
// Do M10 configuration for Power Management.
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_RAM), _message_VALSET_PM_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for M10 GPS RAM.\n");
}
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_PM_BBR), _message_VALSET_PM_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable powersaving for M10 GPS BBR.\n");
}
delay(250);
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_RAM), _message_VALSET_ITFM_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable Jamming detection M10 GPS RAM.\n");
}
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ITFM_BBR), _message_VALSET_ITFM_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable Jamming detection M10 GPS BBR.\n");
}
// Here is where the init commands should go to do further M10 initialization.
delay(250);
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_RAM), _message_VALSET_DISABLE_SBAS_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable SBAS M10 GPS RAM.\n");
}
delay(750); // will cause a receiver restart so wait a bit
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_DISABLE_SBAS_BBR), _message_VALSET_DISABLE_SBAS_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to disable SBAS M10 GPS BBR.\n");
}
delay(750); // will cause a receiver restart so wait a bit
// Done with initialization, Now enable wanted NMEA messages in BBR layer so they will survive a periodic sleep.
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_BBR), _message_VALSET_ENABLE_NMEA_BBR);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable messages for M10 GPS BBR.\n");
}
delay(250);
// Next enable wanted NMEA messages in RAM layer
msglen = makeUBXPacket(0x06, 0x8A, sizeof(_message_VALSET_ENABLE_NMEA_RAM), _message_VALSET_ENABLE_NMEA_RAM);
_serial_gps->write(UBXscratch, msglen);
if (getACK(0x06, 0x8A, 300) != GNSS_RESPONSE_OK) {
LOG_WARN("Unable to enable messages for M10 GPS RAM.\n");
}
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
} }
} }
didSerialInit = true; didSerialInit = true;
@ -547,10 +647,17 @@ void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime)
if (gnssModel == GNSS_MODEL_UBLOX) { if (gnssModel == GNSS_MODEL_UBLOX) {
uint8_t msglen; uint8_t msglen;
LOG_DEBUG("Sleep Time: %i\n", sleepTime); LOG_DEBUG("Sleep Time: %i\n", sleepTime);
for (int i = 0; i < 4; i++) { if (strncmp(info.hwVersion, "000A0000", 8) != 0) {
gps->_message_PMREQ[0 + i] = sleepTime >> (i * 8); // Encode the sleep time in millis into the packet for (int i = 0; i < 4; i++) {
gps->_message_PMREQ[0 + i] = sleepTime >> (i * 8); // Encode the sleep time in millis into the packet
}
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), gps->_message_PMREQ);
} else {
for (int i = 0; i < 4; i++) {
gps->_message_PMREQ_10[4 + i] = sleepTime >> (i * 8); // Encode the sleep time in millis into the packet
}
msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), gps->_message_PMREQ_10);
} }
msglen = gps->makeUBXPacket(0x02, 0x41, 0x08, gps->_message_PMREQ);
gps->_serial_gps->write(gps->UBXscratch, msglen); gps->_serial_gps->write(gps->UBXscratch, msglen);
} }
} else { } else {

View File

@ -106,6 +106,7 @@ class GPS : private concurrency::OSThread
static const uint8_t _message_NAVX5[]; static const uint8_t _message_NAVX5[];
static const uint8_t _message_NAVX5_8[]; static const uint8_t _message_NAVX5_8[];
static const uint8_t _message_NMEA[]; static const uint8_t _message_NMEA[];
static const uint8_t _message_DISABLE_TXT_INFO[];
static const uint8_t _message_1HZ[]; static const uint8_t _message_1HZ[];
static const uint8_t _message_GLL[]; static const uint8_t _message_GLL[];
static const uint8_t _message_GSA[]; static const uint8_t _message_GSA[];
@ -117,6 +118,21 @@ class GPS : private concurrency::OSThread
static const uint8_t _message_PMS[]; static const uint8_t _message_PMS[];
static const uint8_t _message_SAVE[]; static const uint8_t _message_SAVE[];
// VALSET Commands for M10
static const uint8_t _message_VALSET_PM[];
static const uint8_t _message_VALSET_PM_RAM[];
static const uint8_t _message_VALSET_PM_BBR[];
static const uint8_t _message_VALSET_ITFM_RAM[];
static const uint8_t _message_VALSET_ITFM_BBR[];
static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[];
static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[];
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[];
static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[];
static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[];
static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[];
static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[];
static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[];
meshtastic_Position p = meshtastic_Position_init_default; meshtastic_Position p = meshtastic_Position_init_default;
GPS() : concurrency::OSThread("GPS") {} GPS() : concurrency::OSThread("GPS") {}

View File

@ -1,16 +1,16 @@
// Power Management
uint8_t GPS::_message_PMREQ[] PROGMEM = { uint8_t GPS::_message_PMREQ[] PROGMEM = {
0x00, 0x00, // 4 bytes duration of request task 0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
0x00, 0x00, // (milliseconds) 0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1
0x02, 0x00, // Task flag bitfield
0x00, 0x00, // byte index 1 = sleep mode
}; };
uint8_t GPS::_message_PMREQ_10[] PROGMEM = { uint8_t GPS::_message_PMREQ_10[] PROGMEM = {
0x00, 0x00, // 4 bytes duration of request task 0x00, // version (0 for this version)
0x00, 0x00, // (milliseconds) 0x00, 0x00, 0x00, // Reserved 1
0x02, 0x00, // Task flag bitfield 0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds)
0x00, 0x00, // byte index 1 = sleep mode 0x06, 0x00, 0x00, 0x00, // Bitfield, set backup =1 and force =1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // wakeupSources 0x08, 0x00, 0x00, 0x00 // wakeupSources Wake on uartrx
}; };
const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = { const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = {
@ -46,6 +46,9 @@ const uint8_t GPS::_message_CFG_PM2[] PROGMEM = {
0x00, 0x00, 0x00, 0x00 // 0x64, 0x40, 0x01, 0x00 // reserved 11 0x00, 0x00, 0x00, 0x00 // 0x64, 0x40, 0x01, 0x00 // reserved 11
}; };
// Constallation setup, none required for Neo-6
// For Neo-7 GPS & SBAS
const uint8_t GPS::_message_GNSS_7[] = { const uint8_t GPS::_message_GNSS_7[] = {
0x00, // msgVer (0 for this version) 0x00, // msgVer (0 for this version)
0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0)
@ -272,6 +275,20 @@ const uint8_t GPS::_message_AID[] = {
0x00 // Reserved 0x00 // Reserved
}; };
// Turn off TEXT INFO Messages for all but M10 series
// B5 62 06 02 0A 00 01 00 00 00 03 03 00 03 03 00 1F 20
const uint8_t GPS::_message_DISABLE_TXT_INFO[] = {
0x01, // Protocol ID for NMEA
0x00, 0x00, 0x00, // Reserved
0x03, // I2C
0x03, // I/O Port 1
0x00, // I/O Port 2
0x03, // USB
0x03, // SPI
0x00 // Reserved
};
// The Power Management configuration allows the GPS module to operate in different power modes for optimized // The Power Management configuration allows the GPS module to operate in different power modes for optimized
// power consumption. The modes supported are: 0x00 = Full power: The module operates at full power with no power // power consumption. The modes supported are: 0x00 = Full power: The module operates at full power with no power
// saving. 0x01 = Balanced: The module dynamically adjusts the tracking behavior to balance power consumption. // saving. 0x01 = Balanced: The module dynamically adjusts the tracking behavior to balance power consumption.
@ -283,7 +300,7 @@ const uint8_t GPS::_message_AID[] = {
// is set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase // is set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase
// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, // and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise,
// it must be set to '0'. // it must be set to '0'.
// This command applies to M8 and higher products // This command applies to M8 products
const uint8_t GPS::_message_PMS[] = { const uint8_t GPS::_message_PMS[] = {
0x00, // Version (0) 0x00, // Version (0)
0x03, // Power setup value 3 = Agresssive 1Hz 0x03, // Power setup value 3 = Agresssive 1Hz
@ -297,4 +314,140 @@ const uint8_t GPS::_message_SAVE[] = {
0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections 0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections
0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded 0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded
0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash 0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash
}; };
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
// VALSET Commands for M10
// Please refer to the M10 Protocol Specification:
// https://content.u-blox.com/sites/default/files/u-blox-M10-SPG-5.10_InterfaceDescription_UBX-21035062.pdf
// Where the VALSET/VALGET/VALDEL commands are described in detail.
// and:
// https://content.u-blox.com/sites/default/files/u-blox-M10-ROM-5.10_ReleaseNotes_UBX-22001426.pdf
// for interesting insights.
/*
CFG-PM2 has been replaced by many CFG-PM commands
OPERATEMODE E1 2 (0 | 1 | 2)
POSUPDATEPERIOD U4 1000ms for M10 must be >= 5s try 5
ACQPERIOD U4 10 seems ok for M10 def ok
GRIDOFFSET U4 0 seems ok for M10 def ok
ONTIME U2 1 will try 1
MINACQTIME U1 0 will try 0 def ok
MAXACQTIME U1 stick with default of 0 def ok
DONOTENTEROFF L 1 stay at 1
WAITTIMEFIX L 1 stay with 1
UPDATEEPH L 1 changed to 1 for gps rework default is 1
EXTINTWAKE L 0 no ext ints
EXTINTBACKUP L 0 no ext ints
EXTINTINACTIVE L 0 no ext ints
EXTINTACTIVITY U4 0 no ext ints
LIMITPEAKCURRENT L 1 stay with 1
*/
// CFG-PMS has been removed
// Ram layer config message:
// b5 62 06 8a 26 00 00 01 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8b de
// BBR layer config message:
// b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0
// 10 01 8c 03
const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40,
0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0,
0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01};
/*
CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR
20410001 bbthreshold U1 3
20410002 cwthreshold U1 15
1041000d enable L 0 -> 1
20410010 ant E1 0
10410013 enable aux L 0 -> 1
b5 62 06 8a 0e 00 00 01 00 00 0d 00 41 10 01 13 00 41 10 01 63 c6
*/
const uint8_t GPS::_message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41,
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41,
0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01};
// Turn off all NMEA messages:
// Ram layer config message:
// b5 62 06 8a 22 00 00 01 00 00 c0 00 91 20 00 ca 00 91 20 00 c5 00 91 20 00 ac 00 91 20 00 b1 00 91 20 00 bb 00 91 20 00 40 8f
// Disable GLL, GSV, VTG messages in BBR layer
// BBR layer config message:
// b5 62 06 8a 13 00 00 02 00 00 ca 00 91 20 00 c5 00 91 20 00 b1 00 91 20 00 f8 4e
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_RAM[] = {
/*0x00, 0x01, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00 */
0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91,
0x20, 0x00, 0xac, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00, 0xbb, 0x00, 0x91, 0x20, 0x00};
const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5,
0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00};
// Turn off text info messages:
// Ram layer config message:
// b5 62 06 8a 09 00 00 01 00 00 07 00 92 20 06 59 50
// BBR layer config message:
// b5 62 06 8a 09 00 00 02 00 00 07 00 92 20 06 5a 58
// Turn NMEA GSA, GGA, RMC messages on:
// Ram layer config message:
// b5 62 06 8a 13 00 00 01 00 00 c0 00 91 20 01 bb 00 91 20 01 ac 00 91 20 01 e1 3b
// BBR layer config message:
// b5 62 06 8a 13 00 00 02 00 00 c0 00 91 20 01 bb 00 91 20 01 ac 00 91 20 01 e2 4d
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03};
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x01, 0xbb,
0x00, 0x91, 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
const uint8_t GPS::_message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x01, 0xbb,
0x00, 0x91, 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01};
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31,
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
const uint8_t GPS::_message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31,
0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00};
/*
Operational issues with the M10:
PowerSave doesn't work with SBAS, seems like you can have SBAS enabled, but it will never lock
onto the SBAS sats.
PowerSave doesn't work with BDS B1C, u-blox says use B1l instead.
BDS B1l cannot be enabled with BDS B1C or GLONASS L1OF, so GLONASS will work with B1C, but not B1l
So no powersave with GLONASS and BDS B1l enabled.
So disable GLONASS and use BDS B1l, which is part of the default M10 config.
GNSS configuration:
Default GNSS configuration is: GPS, Galileo, BDS B1l, with QZSS and SBAS enabled.
The PMREQ puts the receiver to sleep and wakeup re-acquires really fast and seems to not need
the PM config. Lets try without it.
PMREQ sort of works with SBAS, but the awake time is too short to re-acquire any SBAS sats.
The defination of "Got Fix" doesn't seem to include SBAS. Much more too this...
Even if it was, it can take minutes (up to 12.5),
even under good sat visability conditions to re-acquire the SBAS data.
Another effect fo the quick transition to sleep is that no other sats will be acquired so the
sat count will tend to remain at what the initial fix was.
*/
// GNSS disable SBAS as recommended by u-blox if using GNSS defaults and power save mode
/*
Ram layer config message:
b5 62 06 8a 0e 00 00 01 00 00 20 00 31 10 00 05 00 31 10 00 46 87
BBR layer config message:
b5 62 06 8a 0e 00 00 02 00 00 20 00 31 10 00 05 00 31 10 00 47 94
*/

View File

@ -12,46 +12,45 @@
/* Enum definitions */ /* Enum definitions */
/* Defines the device's role on the Mesh network */ /* Defines the device's role on the Mesh network */
typedef enum _meshtastic_Config_DeviceConfig_Role { typedef enum _meshtastic_Config_DeviceConfig_Role {
/* Client device role */ /* Description: App connected or stand alone messaging device.
Technical Details: Default Role */
meshtastic_Config_DeviceConfig_Role_CLIENT = 0, meshtastic_Config_DeviceConfig_Role_CLIENT = 0,
/* Client Mute device role /* Description: Device that does not forward packets from other devices. */
Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh. */
meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE = 1, meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE = 1,
/* Router device role. /* Description: Infrastructure node for extending network coverage by relaying messages. Visible in Nodes list.
Mesh packets will prefer to be routed over this node. This node will not be used by client apps. Technical Details: Mesh packets will prefer to be routed over this node. This node will not be used by client apps.
The wifi/ble radios and the oled screen will be put to sleep. The wifi radio and the oled screen will be put to sleep.
This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. */ This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. */
meshtastic_Config_DeviceConfig_Role_ROUTER = 2, meshtastic_Config_DeviceConfig_Role_ROUTER = 2,
/* Router Client device role /* Description: Combination of both ROUTER and CLIENT. Not for mobile devices. */
Mesh packets will prefer to be routed over this node. The Router Client can be used as both a Router and an app connected Client. */
meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3, meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3,
/* Repeater device role /* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list.
Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry
or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. */ or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. */
meshtastic_Config_DeviceConfig_Role_REPEATER = 4, meshtastic_Config_DeviceConfig_Role_REPEATER = 4,
/* Tracker device role /* Description: Broadcasts GPS position packets as priority.
Position Mesh packets will be prioritized higher and sent more frequently by default. Technical Details: Position Mesh packets will be prioritized higher and sent more frequently by default.
When used in conjunction with power.is_power_saving = true, nodes will wake up, When used in conjunction with power.is_power_saving = true, nodes will wake up,
send position, and then sleep for position.position_broadcast_secs seconds. */ send position, and then sleep for position.position_broadcast_secs seconds. */
meshtastic_Config_DeviceConfig_Role_TRACKER = 5, meshtastic_Config_DeviceConfig_Role_TRACKER = 5,
/* Sensor device role /* Description: Broadcasts telemetry packets as priority.
Telemetry Mesh packets will be prioritized higher and sent more frequently by default. Technical Details: Telemetry Mesh packets will be prioritized higher and sent more frequently by default.
When used in conjunction with power.is_power_saving = true, nodes will wake up, When used in conjunction with power.is_power_saving = true, nodes will wake up,
send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */ send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */
meshtastic_Config_DeviceConfig_Role_SENSOR = 6, meshtastic_Config_DeviceConfig_Role_SENSOR = 6,
/* TAK device role /* Description: Optimized for ATAK system communication, reduces routine broadcasts.
Used for nodes dedicated for connection to an ATAK EUD. Technical Details: Used for nodes dedicated for connection to an ATAK EUD.
Turns off many of the routine broadcasts to favor CoT packet stream Turns off many of the routine broadcasts to favor CoT packet stream
from the Meshtastic ATAK plugin -> IMeshService -> Node */ from the Meshtastic ATAK plugin -> IMeshService -> Node */
meshtastic_Config_DeviceConfig_Role_TAK = 7, meshtastic_Config_DeviceConfig_Role_TAK = 7,
/* Client Hidden device role /* Description: Device that only broadcasts as needed for stealth or power savings.
Used for nodes that "only speak when spoken to" Technical Details: Used for nodes that "only speak when spoken to"
Turns all of the routine broadcasts but allows for ad-hoc communication Turns all of the routine broadcasts but allows for ad-hoc communication
Still rebroadcasts, but with local only rebroadcast mode (known meshes only) Still rebroadcasts, but with local only rebroadcast mode (known meshes only)
Can be used for clandestine operation or to dramatically reduce airtime / power consumption */ Can be used for clandestine operation or to dramatically reduce airtime / power consumption */
meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8, meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8,
/* Lost and Found device role /* Description: Broadcasts location as message to default channel regularly for to assist with device recovery.
Used to automatically send a text message to the mesh Technical Details: Used to automatically send a text message to the mesh
with the current position of the device on a frequent interval: with the current position of the device on a frequent interval:
"I'm lost! Position: lat / long" */ "I'm lost! Position: lat / long" */
meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9 meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9
@ -313,6 +312,9 @@ typedef struct _meshtastic_Config_PositionConfig {
uint32_t gps_en_gpio; uint32_t gps_en_gpio;
/* Set where GPS is enabled, disabled, or not present */ /* Set where GPS is enabled, disabled, or not present */
meshtastic_Config_PositionConfig_GpsMode gps_mode; meshtastic_Config_PositionConfig_GpsMode gps_mode;
/* Set GPS precision in bits per channel, or 0 for disabled */
pb_size_t channel_precision_count;
uint32_t channel_precision[8];
} meshtastic_Config_PositionConfig; } meshtastic_Config_PositionConfig;
/* Power Config\ /* Power Config\
@ -580,7 +582,7 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0} #define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
@ -589,7 +591,7 @@ extern "C" {
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0} #define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
@ -621,6 +623,7 @@ extern "C" {
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11 #define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11
#define meshtastic_Config_PositionConfig_gps_en_gpio_tag 12 #define meshtastic_Config_PositionConfig_gps_en_gpio_tag 12
#define meshtastic_Config_PositionConfig_gps_mode_tag 13 #define meshtastic_Config_PositionConfig_gps_mode_tag 13
#define meshtastic_Config_PositionConfig_channel_precision_tag 14
#define meshtastic_Config_PowerConfig_is_power_saving_tag 1 #define meshtastic_Config_PowerConfig_is_power_saving_tag 1
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2 #define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3 #define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
@ -724,7 +727,8 @@ X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \ X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11) \ X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11) \
X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12) \ X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12) \
X(a, STATIC, SINGULAR, UENUM, gps_mode, 13) X(a, STATIC, SINGULAR, UENUM, gps_mode, 13) \
X(a, STATIC, REPEATED, UINT32, channel_precision, 14)
#define meshtastic_Config_PositionConfig_CALLBACK NULL #define meshtastic_Config_PositionConfig_CALLBACK NULL
#define meshtastic_Config_PositionConfig_DEFAULT NULL #define meshtastic_Config_PositionConfig_DEFAULT NULL
@ -830,7 +834,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
#define meshtastic_Config_LoRaConfig_size 80 #define meshtastic_Config_LoRaConfig_size 80
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20
#define meshtastic_Config_NetworkConfig_size 196 #define meshtastic_Config_NetworkConfig_size 196
#define meshtastic_Config_PositionConfig_size 62 #define meshtastic_Config_PositionConfig_size 110
#define meshtastic_Config_PowerConfig_size 40 #define meshtastic_Config_PowerConfig_size 40
#define meshtastic_Config_size 199 #define meshtastic_Config_size 199

View File

@ -316,7 +316,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
#define meshtastic_DeviceState_size 17062 #define meshtastic_DeviceState_size 17062
#define meshtastic_NodeInfoLite_size 153 #define meshtastic_NodeInfoLite_size 153
#define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_NodeRemoteHardwarePin_size 29
#define meshtastic_OEMStore_size 3246 #define meshtastic_OEMStore_size 3294
#define meshtastic_PositionLite_size 28 #define meshtastic_PositionLite_size 28
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -180,7 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define meshtastic_LocalConfig_size 469 #define meshtastic_LocalConfig_size 517
#define meshtastic_LocalModuleConfig_size 631 #define meshtastic_LocalModuleConfig_size 631
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -111,7 +111,7 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_RPI_PICO = 47, meshtastic_HardwareModel_RPI_PICO = 47,
/* Heltec Wireless Tracker with ESP32-S3 CPU, built-in GPS, and TFT /* Heltec Wireless Tracker with ESP32-S3 CPU, built-in GPS, and TFT
Newer V1.1, version is written on the PCB near the display. */ Newer V1.1, version is written on the PCB near the display. */
meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER_V1_1 = 48, meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER = 48,
/* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */ /* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */
meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49, meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49,
/* LilyGo T-Deck with ESP32-S3 CPU, Keyboard and IPS display */ /* LilyGo T-Deck with ESP32-S3 CPU, Keyboard and IPS display */

View File

@ -38,16 +38,11 @@ int32_t StoreForwardModule::runOnce()
// Only send packets if the channel is less than 25% utilized. // Only send packets if the channel is less than 25% utilized.
if (airTime->isTxAllowedChannelUtil(true)) { if (airTime->isTxAllowedChannelUtil(true)) {
storeForwardModule->sendPayload(this->busyTo, this->packetHistoryTXQueue_index); storeForwardModule->sendPayload(this->busyTo, this->packetHistoryTXQueue_index);
if (this->packetHistoryTXQueue_index == packetHistoryTXQueue_size) { if (this->packetHistoryTXQueue_index < packetHistoryTXQueue_size - 1) {
// Tell the client we're done sending this->packetHistoryTXQueue_index++;
meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero; } else {
sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_PING;
storeForwardModule->sendMessage(this->busyTo, sf);
LOG_INFO("*** S&F - Done. (ROUTER_PING)\n");
this->packetHistoryTXQueue_index = 0; this->packetHistoryTXQueue_index = 0;
this->busy = false; this->busy = false;
} else {
this->packetHistoryTXQueue_index++;
} }
} }
} else if ((millis() - lastHeartbeat > (heartbeatInterval * 1000)) && airTime->isTxAllowedChannelUtil(true)) { } else if ((millis() - lastHeartbeat > (heartbeatInterval * 1000)) && airTime->isTxAllowedChannelUtil(true)) {
@ -56,7 +51,7 @@ int32_t StoreForwardModule::runOnce()
meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero; meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero;
sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_HEARTBEAT; sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_HEARTBEAT;
sf.which_variant = meshtastic_StoreAndForward_heartbeat_tag; sf.which_variant = meshtastic_StoreAndForward_heartbeat_tag;
sf.variant.heartbeat.period = 300; sf.variant.heartbeat.period = heartbeatInterval;
sf.variant.heartbeat.secondary = 0; // TODO we always have one primary router for now sf.variant.heartbeat.secondary = 0; // TODO we always have one primary router for now
storeForwardModule->sendMessage(NODENUM_BROADCAST, sf); storeForwardModule->sendMessage(NODENUM_BROADCAST, sf);
} }
@ -101,10 +96,11 @@ void StoreForwardModule::populatePSRAM()
* *
* @param msAgo The number of milliseconds ago from which to start sending messages. * @param msAgo The number of milliseconds ago from which to start sending messages.
* @param to The recipient ID to send the messages to. * @param to The recipient ID to send the messages to.
* @param last_request_index The index in the packet history of the last request from this node.
*/ */
void StoreForwardModule::historySend(uint32_t msAgo, uint32_t to) void StoreForwardModule::historySend(uint32_t msAgo, uint32_t to, uint32_t last_request_index)
{ {
uint32_t queueSize = storeForwardModule->historyQueueCreate(msAgo, to); uint32_t queueSize = storeForwardModule->historyQueueCreate(msAgo, to, &last_request_index);
if (queueSize) { if (queueSize) {
LOG_INFO("*** S&F - Sending %u message(s)\n", queueSize); LOG_INFO("*** S&F - Sending %u message(s)\n", queueSize);
@ -118,6 +114,7 @@ void StoreForwardModule::historySend(uint32_t msAgo, uint32_t to)
sf.which_variant = meshtastic_StoreAndForward_history_tag; sf.which_variant = meshtastic_StoreAndForward_history_tag;
sf.variant.history.history_messages = queueSize; sf.variant.history.history_messages = queueSize;
sf.variant.history.window = msAgo; sf.variant.history.window = msAgo;
sf.variant.history.last_request = last_request_index;
storeForwardModule->sendMessage(to, sf); storeForwardModule->sendMessage(to, sf);
} }
@ -125,15 +122,18 @@ void StoreForwardModule::historySend(uint32_t msAgo, uint32_t to)
* Creates a new history queue with messages that were received within the specified time frame. * Creates a new history queue with messages that were received within the specified time frame.
* *
* @param msAgo The number of milliseconds ago to start the history queue. * @param msAgo The number of milliseconds ago to start the history queue.
* @param to The maximum number of messages to include in the history queue. * @param to The NodeNum of the recipient.
* @param last_request_index The index in the packet history of the last request from this node.
* @return The ID of the newly created history queue. * @return The ID of the newly created history queue.
*/ */
uint32_t StoreForwardModule::historyQueueCreate(uint32_t msAgo, uint32_t to) uint32_t StoreForwardModule::historyQueueCreate(uint32_t msAgo, uint32_t to, uint32_t *last_request_index)
{ {
this->packetHistoryTXQueue_size = 0; this->packetHistoryTXQueue_size = 0;
// If our history was cleared, ignore what the client is telling us
uint32_t last_index = *last_request_index >= this->packetHistoryCurrent ? 0 : *last_request_index;
for (int i = 0; i < this->packetHistoryCurrent; i++) { for (int i = last_index; i < this->packetHistoryCurrent; i++) {
/* /*
LOG_DEBUG("SF historyQueueCreate\n"); LOG_DEBUG("SF historyQueueCreate\n");
LOG_DEBUG("SF historyQueueCreate - time %d\n", this->packetHistory[i].time); LOG_DEBUG("SF historyQueueCreate - time %d\n", this->packetHistory[i].time);
@ -141,16 +141,11 @@ uint32_t StoreForwardModule::historyQueueCreate(uint32_t msAgo, uint32_t to)
LOG_DEBUG("SF historyQueueCreate - math %d\n", (millis() - msAgo)); LOG_DEBUG("SF historyQueueCreate - math %d\n", (millis() - msAgo));
*/ */
if (this->packetHistory[i].time && (this->packetHistory[i].time < (millis() - msAgo))) { if (this->packetHistory[i].time && (this->packetHistory[i].time < (millis() - msAgo))) {
LOG_DEBUG("*** SF historyQueueCreate - Time matches - ok\n"); /* Copy the messages that were received by the router in the last msAgo
/*
Copy the messages that were received by the router in the last msAgo
to the packetHistoryTXQueue structure. to the packetHistoryTXQueue structure.
Client not interested in packets from itself and only in broadcast packets or packets towards it. */
TODO: The condition (this->packetHistory[i].to & NODENUM_BROADCAST) == to) is not tested since if (this->packetHistory[i].from != to &&
I don't have an easy way to target a specific user. Will need to do this soon. (this->packetHistory[i].to == NODENUM_BROADCAST || this->packetHistory[i].to == to)) {
*/
if ((this->packetHistory[i].to & NODENUM_BROADCAST) == NODENUM_BROADCAST ||
((this->packetHistory[i].to & NODENUM_BROADCAST) == to)) {
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].to = this->packetHistory[i].to; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].to = this->packetHistory[i].to;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].from = this->packetHistory[i].from; this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].from = this->packetHistory[i].from;
@ -159,9 +154,10 @@ uint32_t StoreForwardModule::historyQueueCreate(uint32_t msAgo, uint32_t to)
memcpy(this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload, this->packetHistory[i].payload, memcpy(this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload, this->packetHistory[i].payload,
meshtastic_Constants_DATA_PAYLOAD_LEN); meshtastic_Constants_DATA_PAYLOAD_LEN);
this->packetHistoryTXQueue_size++; this->packetHistoryTXQueue_size++;
*last_request_index = i + 1; // Set to one higher such that we don't send the same message again
LOG_DEBUG("*** PacketHistoryStruct time=%d\n", this->packetHistory[i].time); LOG_DEBUG("*** PacketHistoryStruct time=%d, msg=%s\n", this->packetHistory[i].time,
LOG_DEBUG("*** PacketHistoryStruct msg=%s\n", this->packetHistory[i].payload); this->packetHistory[i].payload);
} }
} }
} }
@ -177,15 +173,20 @@ void StoreForwardModule::historyAdd(const meshtastic_MeshPacket &mp)
{ {
const auto &p = mp.decoded; const auto &p = mp.decoded;
this->packetHistory[this->packetHistoryCurrent].time = millis(); if (this->packetHistoryCurrent < this->records) {
this->packetHistory[this->packetHistoryCurrent].to = mp.to; this->packetHistory[this->packetHistoryCurrent].time = millis();
this->packetHistory[this->packetHistoryCurrent].channel = mp.channel; this->packetHistory[this->packetHistoryCurrent].to = mp.to;
this->packetHistory[this->packetHistoryCurrent].from = mp.from; this->packetHistory[this->packetHistoryCurrent].channel = mp.channel;
this->packetHistory[this->packetHistoryCurrent].payload_size = p.payload.size; this->packetHistory[this->packetHistoryCurrent].from = mp.from;
memcpy(this->packetHistory[this->packetHistoryCurrent].payload, p.payload.bytes, meshtastic_Constants_DATA_PAYLOAD_LEN); this->packetHistory[this->packetHistoryCurrent].payload_size = p.payload.size;
memcpy(this->packetHistory[this->packetHistoryCurrent].payload, p.payload.bytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
this->packetHistoryCurrent++; this->packetHistoryCurrent++;
this->packetHistoryMax++; this->packetHistoryMax++;
} else {
// TODO: Overwrite the oldest message in the history buffer when it is full.
LOG_WARN("*** S&F - PSRAM Full. Packet is not added to the history.\n");
}
} }
meshtastic_MeshPacket *StoreForwardModule::allocReply() meshtastic_MeshPacket *StoreForwardModule::allocReply()
@ -213,10 +214,19 @@ void StoreForwardModule::sendPayload(NodeNum dest, uint32_t packetHistory_index)
// TODO: Make this configurable. // TODO: Make this configurable.
p->want_ack = false; p->want_ack = false;
p->decoded.payload.size = meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero;
this->packetHistoryTXQueue[packetHistory_index].payload_size; // You must specify how many bytes are in the reply sf.which_variant = meshtastic_StoreAndForward_text_tag;
memcpy(p->decoded.payload.bytes, this->packetHistoryTXQueue[packetHistory_index].payload, sf.variant.text.size = this->packetHistoryTXQueue[packetHistory_index].payload_size;
memcpy(sf.variant.text.bytes, this->packetHistoryTXQueue[packetHistory_index].payload,
this->packetHistoryTXQueue[packetHistory_index].payload_size); this->packetHistoryTXQueue[packetHistory_index].payload_size);
if (this->packetHistoryTXQueue[packetHistory_index].to == NODENUM_BROADCAST) {
sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_BROADCAST;
} else {
sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_TEXT_DIRECT;
}
p->decoded.payload.size =
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_StoreAndForward_msg, &sf);
service.sendToMesh(p); service.sendToMesh(p);
} }
@ -387,7 +397,9 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
LOG_INFO("*** S&F - Busy. Try again shortly.\n"); LOG_INFO("*** S&F - Busy. Try again shortly.\n");
} else { } else {
if ((p->which_variant == meshtastic_StoreAndForward_history_tag) && (p->variant.history.window > 0)) { if ((p->which_variant == meshtastic_StoreAndForward_history_tag) && (p->variant.history.window > 0)) {
storeForwardModule->historySend(p->variant.history.window * 60000, getFrom(&mp)); // window is in minutes // window is in minutes
storeForwardModule->historySend(p->variant.history.window * 60000, getFrom(&mp),
p->variant.history.last_request);
} else { } else {
storeForwardModule->historySend(historyReturnWindow * 60000, getFrom(&mp)); // defaults to 4 hours storeForwardModule->historySend(historyReturnWindow * 60000, getFrom(&mp)); // defaults to 4 hours
} }
@ -406,8 +418,7 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp,
case meshtastic_StoreAndForward_RequestResponse_CLIENT_PONG: case meshtastic_StoreAndForward_RequestResponse_CLIENT_PONG:
if (is_server) { if (is_server) {
LOG_INFO("*** StoreAndForward_RequestResponse_CLIENT_PONG\n"); LOG_INFO("*** StoreAndForward_RequestResponse_CLIENT_PONG\n");
// The Client is alive, update NodeDB // NodeDB is already updated
nodeDB.updateFrom(mp);
} }
break; break;
@ -546,9 +557,7 @@ StoreForwardModule::StoreForwardModule()
} }
// Client // Client
} } else {
if ((config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT) ||
(config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT)) {
is_client = true; is_client = true;
LOG_INFO("*** Initializing Store & Forward Module in Client mode\n"); LOG_INFO("*** Initializing Store & Forward Module in Client mode\n");
} }

View File

@ -13,7 +13,6 @@ struct PacketHistoryStruct {
uint32_t to; uint32_t to;
uint32_t from; uint32_t from;
uint8_t channel; uint8_t channel;
bool ack;
uint8_t payload[meshtastic_Constants_DATA_PAYLOAD_LEN]; uint8_t payload[meshtastic_Constants_DATA_PAYLOAD_LEN];
pb_size_t payload_size; pb_size_t payload_size;
}; };
@ -32,7 +31,7 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
uint32_t packetHistoryTXQueue_size = 0; uint32_t packetHistoryTXQueue_size = 0;
uint32_t packetHistoryTXQueue_index = 0; uint32_t packetHistoryTXQueue_index = 0;
uint32_t packetTimeMax = 5000; uint32_t packetTimeMax = 5000; // Interval between sending history packets as a server.
bool is_client = false; bool is_client = false;
bool is_server = false; bool is_server = false;
@ -41,7 +40,7 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
StoreForwardModule(); StoreForwardModule();
unsigned long lastHeartbeat = 0; unsigned long lastHeartbeat = 0;
uint32_t heartbeatInterval = 300; uint32_t heartbeatInterval = default_broadcast_interval_secs;
/** /**
Update our local reference of when we last saw that node. Update our local reference of when we last saw that node.
@ -49,9 +48,9 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
*/ */
void historyAdd(const meshtastic_MeshPacket &mp); void historyAdd(const meshtastic_MeshPacket &mp);
void statsSend(uint32_t to); void statsSend(uint32_t to);
void historySend(uint32_t msAgo, uint32_t to); void historySend(uint32_t msAgo, uint32_t to, uint32_t last_request_index = 0);
uint32_t historyQueueCreate(uint32_t msAgo, uint32_t to); uint32_t historyQueueCreate(uint32_t msAgo, uint32_t to, uint32_t *last_request_index);
/** /**
* Send our payload into the mesh * Send our payload into the mesh
@ -79,16 +78,16 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
void populatePSRAM(); void populatePSRAM();
// S&F Defaults // S&F Defaults
uint32_t historyReturnMax = 250; // 250 records uint32_t historyReturnMax = 25; // Return maximum of 25 records by default.
uint32_t historyReturnWindow = 240; // 4 hours uint32_t historyReturnWindow = 240; // Return history of last 4 hours by default.
uint32_t records = 0; // Calculated uint32_t records = 0; // Calculated
bool heartbeat = false; // No heartbeat. bool heartbeat = false; // No heartbeat.
// stats // stats
uint32_t requests = 0; uint32_t requests = 0; // Number of times any client sent a request to the S&F.
uint32_t requests_history = 0; uint32_t requests_history = 0; // Number of times the history was requested.
uint32_t retry_delay = 0; uint32_t retry_delay = 0; // If server is busy, retry after this delay (in ms).
protected: protected:
virtual int32_t runOnce() override; virtual int32_t runOnce() override;
@ -102,4 +101,4 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule<
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_StoreAndForward *p); virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_StoreAndForward *p);
}; };
extern StoreForwardModule *storeForwardModule; extern StoreForwardModule *storeForwardModule;

View File

@ -106,7 +106,7 @@
#elif defined(HELTEC_WSL_V3) #elif defined(HELTEC_WSL_V3)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WSL_V3 #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WSL_V3
#elif defined(HELTEC_WIRELESS_TRACKER) #elif defined(HELTEC_WIRELESS_TRACKER)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER_V1_1 #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER
#elif defined(HELTEC_WIRELESS_PAPER_V1_0) #elif defined(HELTEC_WIRELESS_PAPER_V1_0)
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER_V1_0 #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER_V1_0
#elif defined(HELTEC_WIRELESS_PAPER) #elif defined(HELTEC_WIRELESS_PAPER)