diff --git a/protobufs b/protobufs index 388fd79bf..4432d3bfc 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 388fd79bf78df2c59dd0bdd029a382fa91b1cd88 +Subproject commit 4432d3bfc155107e27079d96ddba16b52f2d9ea3 diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 02bca211b..addde4edd 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -358,87 +358,98 @@ bool GPS::setup() 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 if (strncmp(info.hwVersion, "00080000", 8) == 0) { msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_8), _message_JAM_8); + clearBuffer(); _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"); } - clearBuffer(); + msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5_8), _message_NAVX5_8); + clearBuffer(); _serial_gps->write(UBXscratch, msglen); - if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to configure extra settings.\n"); + if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to configure NAVX5_8 settings.\n"); } } else { msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM_6_7), _message_JAM_6_7); _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"); } msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5); _serial_gps->write(UBXscratch, msglen); - if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to configure extra settings.\n"); + if (getACK(0x06, 0x23, 500) != GNSS_RESPONSE_OK) { + 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); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GLL), _message_GLL); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA); _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"); } - clearBuffer(); + if (uBloxProtocolVersion >= 18) { msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS); + clearBuffer(); _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"); } // For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats. if (strncmp(info.hwVersion, "00080000", 8) == 0) { msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA); + clearBuffer(); _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"); } } @@ -447,23 +458,23 @@ bool GPS::setup() if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode is only for Neo-6 msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO); _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"); } - msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2); + msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2); _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"); } msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_AID), _message_AID); _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"); } } else { msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM); _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"); } } @@ -477,7 +488,96 @@ bool GPS::setup() LOG_INFO("GNSS module configuration saved!\n"); } } 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; @@ -547,10 +647,17 @@ void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime) if (gnssModel == GNSS_MODEL_UBLOX) { uint8_t msglen; LOG_DEBUG("Sleep Time: %i\n", sleepTime); - for (int i = 0; i < 4; i++) { - gps->_message_PMREQ[0 + i] = sleepTime >> (i * 8); // Encode the sleep time in millis into the packet + if (strncmp(info.hwVersion, "000A0000", 8) != 0) { + 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); } } else { diff --git a/src/gps/GPS.h b/src/gps/GPS.h index 15c355add..77e1d8042 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -106,6 +106,7 @@ class GPS : private concurrency::OSThread static const uint8_t _message_NAVX5[]; static const uint8_t _message_NAVX5_8[]; 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_GLL[]; 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_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; GPS() : concurrency::OSThread("GPS") {} diff --git a/src/gps/ubx.h b/src/gps/ubx.h index 4fff51d52..28f9573bf 100644 --- a/src/gps/ubx.h +++ b/src/gps/ubx.h @@ -1,16 +1,16 @@ +// Power Management + uint8_t GPS::_message_PMREQ[] PROGMEM = { - 0x00, 0x00, // 4 bytes duration of request task - 0x00, 0x00, // (milliseconds) - 0x02, 0x00, // Task flag bitfield - 0x00, 0x00, // byte index 1 = sleep mode + 0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds) + 0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1 }; uint8_t GPS::_message_PMREQ_10[] PROGMEM = { - 0x00, 0x00, // 4 bytes duration of request task - 0x00, 0x00, // (milliseconds) - 0x02, 0x00, // Task flag bitfield - 0x00, 0x00, // byte index 1 = sleep mode - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // wakeupSources + 0x00, // version (0 for this version) + 0x00, 0x00, 0x00, // Reserved 1 + 0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds) + 0x06, 0x00, 0x00, 0x00, // Bitfield, set backup =1 and force =1 + 0x08, 0x00, 0x00, 0x00 // wakeupSources Wake on uartrx }; 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 }; +// Constallation setup, none required for Neo-6 + +// For Neo-7 GPS & SBAS const uint8_t GPS::_message_GNSS_7[] = { 0x00, // msgVer (0 for this version) 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 }; +// 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 // 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. @@ -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 // 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'. -// This command applies to M8 and higher products +// This command applies to M8 products const uint8_t GPS::_message_PMS[] = { 0x00, // Version (0) 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 0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded 0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash -}; \ No newline at end of file +}; + +// 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 +*/ \ No newline at end of file diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 4047f7367..445ef7e1b 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -12,46 +12,45 @@ /* Enum definitions */ /* Defines the device's role on the Mesh network */ 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, - /* Client Mute device role - Same as a client except packets will not hop over this node, does not contribute to routing packets for mesh. */ + /* Description: Device that does not forward packets from other devices. */ meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE = 1, - /* Router device role. - 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. + /* Description: Infrastructure node for extending network coverage by relaying messages. Visible in Nodes list. + Technical Details: Mesh packets will prefer to be routed over this node. This node will not be used by client apps. + 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. */ meshtastic_Config_DeviceConfig_Role_ROUTER = 2, - /* Router Client device role - 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. */ + /* Description: Combination of both ROUTER and CLIENT. Not for mobile devices. */ meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3, - /* Repeater device role - Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry + /* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list. + 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. */ meshtastic_Config_DeviceConfig_Role_REPEATER = 4, - /* Tracker device role - Position Mesh packets will be prioritized higher and sent more frequently by default. + /* Description: Broadcasts GPS position packets as priority. + 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, send position, and then sleep for position.position_broadcast_secs seconds. */ meshtastic_Config_DeviceConfig_Role_TRACKER = 5, - /* Sensor device role - Telemetry Mesh packets will be prioritized higher and sent more frequently by default. + /* Description: Broadcasts telemetry packets as priority. + 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, send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */ meshtastic_Config_DeviceConfig_Role_SENSOR = 6, - /* TAK device role - Used for nodes dedicated for connection to an ATAK EUD. + /* Description: Optimized for ATAK system communication, reduces routine broadcasts. + Technical Details: Used for nodes dedicated for connection to an ATAK EUD. Turns off many of the routine broadcasts to favor CoT packet stream from the Meshtastic ATAK plugin -> IMeshService -> Node */ meshtastic_Config_DeviceConfig_Role_TAK = 7, - /* Client Hidden device role - Used for nodes that "only speak when spoken to" + /* Description: Device that only broadcasts as needed for stealth or power savings. + Technical Details: Used for nodes that "only speak when spoken to" Turns all of the routine broadcasts but allows for ad-hoc communication Still rebroadcasts, but with local only rebroadcast mode (known meshes only) Can be used for clandestine operation or to dramatically reduce airtime / power consumption */ meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8, - /* Lost and Found device role - Used to automatically send a text message to the mesh + /* Description: Broadcasts location as message to default channel regularly for to assist with device recovery. + Technical Details: Used to automatically send a text message to the mesh with the current position of the device on a frequent interval: "I'm lost! Position: lat / long" */ meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9 @@ -313,6 +312,9 @@ typedef struct _meshtastic_Config_PositionConfig { uint32_t gps_en_gpio; /* Set where GPS is enabled, disabled, or not present */ 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; /* Power Config\ @@ -580,7 +582,7 @@ extern "C" { /* Initializer values for message structs */ #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_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_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} @@ -589,7 +591,7 @@ extern "C" { #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_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_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} @@ -621,6 +623,7 @@ extern "C" { #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_mode_tag 13 +#define meshtastic_Config_PositionConfig_channel_precision_tag 14 #define meshtastic_Config_PowerConfig_is_power_saving_tag 1 #define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2 #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_interval_secs, 11) \ 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_DEFAULT NULL @@ -830,7 +834,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; #define meshtastic_Config_LoRaConfig_size 80 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #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_size 199 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index e017be9a2..bca305c14 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -316,7 +316,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; #define meshtastic_DeviceState_size 17062 #define meshtastic_NodeInfoLite_size 153 #define meshtastic_NodeRemoteHardwarePin_size 29 -#define meshtastic_OEMStore_size 3246 +#define meshtastic_OEMStore_size 3294 #define meshtastic_PositionLite_size 28 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 7d39da01f..644d965ab 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -180,7 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_LocalConfig_size 469 +#define meshtastic_LocalConfig_size 517 #define meshtastic_LocalModuleConfig_size 631 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index d109c2f3c..6c3a9729f 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -111,7 +111,7 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_RPI_PICO = 47, /* Heltec Wireless Tracker with ESP32-S3 CPU, built-in GPS, and TFT 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 */ meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49, /* LilyGo T-Deck with ESP32-S3 CPU, Keyboard and IPS display */ diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp index 6b2c079cc..93472b8b1 100644 --- a/src/modules/esp32/StoreForwardModule.cpp +++ b/src/modules/esp32/StoreForwardModule.cpp @@ -38,16 +38,11 @@ int32_t StoreForwardModule::runOnce() // Only send packets if the channel is less than 25% utilized. if (airTime->isTxAllowedChannelUtil(true)) { storeForwardModule->sendPayload(this->busyTo, this->packetHistoryTXQueue_index); - if (this->packetHistoryTXQueue_index == packetHistoryTXQueue_size) { - // Tell the client we're done sending - meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero; - sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_PING; - storeForwardModule->sendMessage(this->busyTo, sf); - LOG_INFO("*** S&F - Done. (ROUTER_PING)\n"); + if (this->packetHistoryTXQueue_index < packetHistoryTXQueue_size - 1) { + this->packetHistoryTXQueue_index++; + } else { this->packetHistoryTXQueue_index = 0; this->busy = false; - } else { - this->packetHistoryTXQueue_index++; } } } else if ((millis() - lastHeartbeat > (heartbeatInterval * 1000)) && airTime->isTxAllowedChannelUtil(true)) { @@ -56,7 +51,7 @@ int32_t StoreForwardModule::runOnce() meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero; sf.rr = meshtastic_StoreAndForward_RequestResponse_ROUTER_HEARTBEAT; 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 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 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) { 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.variant.history.history_messages = queueSize; sf.variant.history.window = msAgo; + sf.variant.history.last_request = last_request_index; 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. * * @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. */ -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; + // 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 - 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)); */ 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. - - TODO: The condition (this->packetHistory[i].to & NODENUM_BROADCAST) == to) is not tested since - I don't have an easy way to target a specific user. Will need to do this soon. - */ - if ((this->packetHistory[i].to & NODENUM_BROADCAST) == NODENUM_BROADCAST || - ((this->packetHistory[i].to & NODENUM_BROADCAST) == to)) { + Client not interested in packets from itself and only in broadcast packets or packets towards it. */ + if (this->packetHistory[i].from != to && + (this->packetHistory[i].to == NODENUM_BROADCAST || this->packetHistory[i].to == to)) { 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].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, meshtastic_Constants_DATA_PAYLOAD_LEN); 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 msg=%s\n", this->packetHistory[i].payload); + LOG_DEBUG("*** PacketHistoryStruct time=%d, msg=%s\n", this->packetHistory[i].time, + this->packetHistory[i].payload); } } } @@ -177,15 +173,20 @@ void StoreForwardModule::historyAdd(const meshtastic_MeshPacket &mp) { const auto &p = mp.decoded; - this->packetHistory[this->packetHistoryCurrent].time = millis(); - this->packetHistory[this->packetHistoryCurrent].to = mp.to; - this->packetHistory[this->packetHistoryCurrent].channel = mp.channel; - this->packetHistory[this->packetHistoryCurrent].from = mp.from; - this->packetHistory[this->packetHistoryCurrent].payload_size = p.payload.size; - memcpy(this->packetHistory[this->packetHistoryCurrent].payload, p.payload.bytes, meshtastic_Constants_DATA_PAYLOAD_LEN); + if (this->packetHistoryCurrent < this->records) { + this->packetHistory[this->packetHistoryCurrent].time = millis(); + this->packetHistory[this->packetHistoryCurrent].to = mp.to; + this->packetHistory[this->packetHistoryCurrent].channel = mp.channel; + this->packetHistory[this->packetHistoryCurrent].from = mp.from; + 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->packetHistoryMax++; + this->packetHistoryCurrent++; + 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() @@ -213,10 +214,19 @@ void StoreForwardModule::sendPayload(NodeNum dest, uint32_t packetHistory_index) // TODO: Make this configurable. p->want_ack = false; - p->decoded.payload.size = - this->packetHistoryTXQueue[packetHistory_index].payload_size; // You must specify how many bytes are in the reply - memcpy(p->decoded.payload.bytes, this->packetHistoryTXQueue[packetHistory_index].payload, + meshtastic_StoreAndForward sf = meshtastic_StoreAndForward_init_zero; + sf.which_variant = meshtastic_StoreAndForward_text_tag; + 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); + 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); } @@ -387,7 +397,9 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, LOG_INFO("*** S&F - Busy. Try again shortly.\n"); } else { 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 { 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: if (is_server) { LOG_INFO("*** StoreAndForward_RequestResponse_CLIENT_PONG\n"); - // The Client is alive, update NodeDB - nodeDB.updateFrom(mp); + // NodeDB is already updated } break; @@ -546,9 +557,7 @@ StoreForwardModule::StoreForwardModule() } // Client - } - if ((config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT) || - (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT)) { + } else { is_client = true; LOG_INFO("*** Initializing Store & Forward Module in Client mode\n"); } diff --git a/src/modules/esp32/StoreForwardModule.h b/src/modules/esp32/StoreForwardModule.h index 806f0a836..b04d9ef84 100644 --- a/src/modules/esp32/StoreForwardModule.h +++ b/src/modules/esp32/StoreForwardModule.h @@ -13,7 +13,6 @@ struct PacketHistoryStruct { uint32_t to; uint32_t from; uint8_t channel; - bool ack; uint8_t payload[meshtastic_Constants_DATA_PAYLOAD_LEN]; pb_size_t payload_size; }; @@ -32,7 +31,7 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule< uint32_t packetHistoryTXQueue_size = 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_server = false; @@ -41,7 +40,7 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule< StoreForwardModule(); 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. @@ -49,9 +48,9 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule< */ void historyAdd(const meshtastic_MeshPacket &mp); 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 @@ -79,16 +78,16 @@ class StoreForwardModule : private concurrency::OSThread, public ProtobufModule< void populatePSRAM(); // S&F Defaults - uint32_t historyReturnMax = 250; // 250 records - uint32_t historyReturnWindow = 240; // 4 hours + uint32_t historyReturnMax = 25; // Return maximum of 25 records by default. + uint32_t historyReturnWindow = 240; // Return history of last 4 hours by default. uint32_t records = 0; // Calculated bool heartbeat = false; // No heartbeat. // stats - uint32_t requests = 0; - uint32_t requests_history = 0; + uint32_t requests = 0; // Number of times any client sent a request to the S&F. + 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: 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); }; -extern StoreForwardModule *storeForwardModule; +extern StoreForwardModule *storeForwardModule; \ No newline at end of file diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index ffff90c75..9fa4a5dd7 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -106,7 +106,7 @@ #elif defined(HELTEC_WSL_V3) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WSL_V3 #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) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER_V1_0 #elif defined(HELTEC_WIRELESS_PAPER)