Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion protobufs
40 changes: 39 additions & 1 deletion src/gps/GPS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static struct uBloxGnssModelInfo {

#define GPS_SOL_EXPIRY_MS 5000 // in millis. give 1 second time to combine different sentences. NMEA Frequency isn't higher anyway
#define NMEA_MSG_GXGSA "GNGSA" // GSA message (GPGSA, GNGSA etc)
static constexpr uint32_t GPS_POSITION_UPDATE_REQUEST_INTERVAL_MS = 10 * 1000UL;

namespace
{
Expand Down Expand Up @@ -1380,6 +1381,37 @@ void GPS::up()
setPowerState(GPS_ACTIVE);
}

bool GPS::requestPositionUpdate()
{
if (!GPSInitFinished || config.position.fixed_position ||
config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
return false;
}

forwardPositionToPhone = true;
if (!enabled) {
LOG_INFO("GPS request: enable");
lastPositionUpdateRequest = millis();
enable();
} else if (powerState != GPS_ACTIVE) {
if (lastPositionUpdateRequest != 0 &&
Throttle::isWithinTimespanMs(lastPositionUpdateRequest, GPS_POSITION_UPDATE_REQUEST_INTERVAL_MS)) {
LOG_DEBUG("GPS request cooldown");
if (hasValidLocation)
positionModule->sendOurPositionToPhone();
forwardPositionToPhone = false;
return true;
}
LOG_INFO("GPS request");
lastPositionUpdateRequest = millis();
up();
} else {
lastPositionUpdateRequest = millis();
}
setIntervalFromNow(0);
return true;
}

// We've finished a GPS search cycle (lock or timeout). Enter a low power state, potentially.
void GPS::down()
{
Expand Down Expand Up @@ -1449,7 +1481,12 @@ void GPS::publishUpdate()
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p, gotTime);
newStatus.notifyObservers(&status);
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
positionModule->handleNewPosition();
if (forwardPositionToPhone && hasValidLocation) {
forwardPositionToPhone = false;
positionModule->sendOurPositionToPhone();
} else if (!forwardPositionToPhone) {
positionModule->handleNewPosition();
}
}
}
}
Expand Down Expand Up @@ -1570,6 +1607,7 @@ int32_t GPS::runOnce()
bool tooLong = scheduling.searchedTooLong();
if (tooLong && !gotLoc) {
LOG_WARN("Can't publish valid location: no GPS lock in time");
forwardPositionToPhone = false;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
// we didn't get a location during this ack window, therefore declare loss of lock
if (hasValidLocation) {
p = meshtastic_Position_init_default;
Expand Down
5 changes: 5 additions & 0 deletions src/gps/GPS.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ class GPS : private concurrency::OSThread
// Wake the GPS hardware - ready for an update
void up();

// Schedule an immediate GPS sampling cycle without changing configured intervals.
bool requestPositionUpdate();

// Let the GPS hardware save power between updates
void down();

Expand Down Expand Up @@ -212,6 +215,8 @@ class GPS : private concurrency::OSThread
bool hasValidLocation = false; // default to false, until we complete our first read

bool shouldPublish = false; // If we've changed GPS state, this will force a publish the next loop()
bool forwardPositionToPhone = false;
uint32_t lastPositionUpdateRequest = 0;

bool hasGPS = false; // Do we have a GPS we are talking to

Expand Down
6 changes: 6 additions & 0 deletions src/mesh/generated/meshtastic/admin.pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ typedef struct _meshtastic_AdminMessage {
meshtastic_SharedContact add_contact;
/* Initiate or respond to a key verification request */
meshtastic_KeyVerificationAdmin key_verification;
/* Request an immediate GPS sampling cycle. This does not change the
configured GPS or position broadcast intervals. Requests received
within 10 seconds are coalesced and use the most recent fix. */
bool request_position_update;
/* Tell the node to factory reset config everything; all device state and configuration will be returned to factory defaults and BLE bonds will be cleared. */
int32_t factory_reset_device;
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
Expand Down Expand Up @@ -667,6 +671,7 @@ extern "C" {
#define meshtastic_AdminMessage_commit_edit_settings_tag 65
#define meshtastic_AdminMessage_add_contact_tag 66
#define meshtastic_AdminMessage_key_verification_tag 67
#define meshtastic_AdminMessage_request_position_update_tag 70
#define meshtastic_AdminMessage_factory_reset_device_tag 94
#define meshtastic_AdminMessage_reboot_ota_seconds_tag 95
#define meshtastic_AdminMessage_exit_simulator_tag 96
Expand Down Expand Up @@ -729,6 +734,7 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_ed
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 65) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,add_contact,add_contact), 66) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,key_verification,key_verification), 67) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,request_position_update,request_position_update), 70) \
X(a, STATIC, ONEOF, INT32, (payload_variant,factory_reset_device,factory_reset_device), 94) \
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \
Expand Down
14 changes: 14 additions & 0 deletions src/modules/AdminModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,20 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
handleSendInputEvent(r->send_input_event);
break;
}
case meshtastic_AdminMessage_request_position_update_tag: {
#if !MESHTASTIC_EXCLUDE_GPS
if (gps && gps->requestPositionUpdate()) {
LOG_INFO("GPS update requested");
} else {
LOG_WARN("GPS update unavailable");
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
}
#else
LOG_WARN("GPS unavailable");
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
#endif
break;
}
#ifdef ARCH_PORTDUINO
case meshtastic_AdminMessage_exit_simulator_tag:
LOG_INFO("Exiting simulator");
Expand Down
19 changes: 19 additions & 0 deletions test/test_admin_radio/test_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <unity.h>
#include <vector>

#include "meshtastic/admin.pb.h"
#include "meshtastic/config.pb.h"
#include "support/AdminModuleTestShim.h"

Expand All @@ -53,6 +54,22 @@ class MockMeshService : public MeshService

static MockMeshService *mockMeshService;

static void test_request_position_update_admin_message_round_trip()
{
meshtastic_AdminMessage request = meshtastic_AdminMessage_init_zero;
request.which_payload_variant = meshtastic_AdminMessage_request_position_update_tag;
request.request_position_update = true;

uint8_t bytes[16];
size_t size = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_AdminMessage_msg, &request);
TEST_ASSERT_GREATER_THAN(0, size);

meshtastic_AdminMessage decoded = meshtastic_AdminMessage_init_zero;
TEST_ASSERT_TRUE(pb_decode_from_bytes(bytes, size, &meshtastic_AdminMessage_msg, &decoded));
TEST_ASSERT_EQUAL(meshtastic_AdminMessage_request_position_update_tag, decoded.which_payload_variant);
TEST_ASSERT_TRUE(decoded.request_position_update);
}

// -----------------------------------------------------------------------
// getRegion() tests
// -----------------------------------------------------------------------
Expand Down Expand Up @@ -1883,6 +1900,8 @@ void setup()

UNITY_BEGIN();

RUN_TEST(test_request_position_update_admin_message_round_trip);

// getRegion()
RUN_TEST(test_handleSetOwner_persistsLicensedChannelSanitation);
RUN_TEST(test_handleSetConfig_persistsLicensedFirstRegionIdentity);
Expand Down
Loading