Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
15 changes: 15 additions & 0 deletions docs/cli_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ This document provides an overview of CLI commands that can be sent to MeshCore
**Parameters:**
- `epoch_seconds`: Unix epoch time

**Note:** The clock only moves forward. To set it back (e.g. after the clock was pushed into the future by a spoofed GPS time) use `time force <epoch_seconds>`.

---

### Send a flood advert
Expand Down Expand Up @@ -1042,6 +1044,19 @@ region save

---

#### GPS anti-spoofing guard (When built with `GPS_GUARD`)
With `GPS_GUARD`, a fix only updates the node position (and telemetry) after it passes plausibility checks: at least `GPS_GUARD_MIN_SATS` satellites, HDOP ≤ `GPS_GUARD_MAX_HDOP10`/10, inside the optional build-time region (`GPS_GUARD_LAT_MIN/MAX`, `GPS_GUARD_LON_MIN/MAX`), within `gps_fence` metres of the node's configured `lat`/`lon` (if set), no jump faster than `GPS_GUARD_MAX_SPEED_KMH`, and `GPS_GUARD_STABLE_FIXES` consistent fixes in a row.

GPS time is written to the clock only while such a fix is current, never earlier than the firmware build date, and — once the clock is valid — only within `GPS_GUARD_TIME_MAX_STEP` seconds for the first sync and within clock drift (`GPS_GUARD_TIME_DRIFT_BASE` s + `GPS_GUARD_TIME_DRIFT_PPM`) afterwards. Setting the clock manually (`time`, `clock sync`) resets that anchor.

**Sensor settings** (via `sensor get` / `sensor set`):
- `gps_fence`: geofence radius in metres around `lat`/`lon` (`0` = off). Default `GPS_GUARD_FENCE_M` (1000).
- `gps_ref`: reference position, shown as `lat;lon` (`lat,lon` is also accepted); follows `set lat`, `set lon` and `gps setloc`.
- `gps_guard` (read-only): status, e.g. `ok 7sat time ok +1s`, `rej region time rej nofix`, or `... ALERT gps-clk +3600s 75m` when a trusted fix has disagreed with the clock by the same offset for `GPS_GUARD_ALERT_MIN` minutes.
- `sensor set gps_time_accept 1`: while an alert is active, confirm that the GPS time is right and apply it to the clock.

---

### Sensors (When sensor support is compiled in)

#### View the list of sensors on this node
Expand Down
3 changes: 3 additions & 0 deletions examples/simple_repeater/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
#if ENV_INCLUDE_GPS == 1
void applyGpsPrefs() {
sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0");
char ref[32];
snprintf(ref, sizeof(ref), "%.6f,%.6f", _prefs.node_lat, _prefs.node_lon);
sensors.setSettingValue("gps_ref", ref); // anti-spoofing reference (ignored if unsupported)
}
#endif

Expand Down
3 changes: 3 additions & 0 deletions examples/simple_room_server/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
#if ENV_INCLUDE_GPS == 1
void applyGpsPrefs() {
sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0");
char ref[32];
snprintf(ref, sizeof(ref), "%.6f,%.6f", _prefs.node_lat, _prefs.node_lon);
sensors.setSettingValue("gps_ref", ref); // anti-spoofing reference (ignored if unsupported)
}
#endif

Expand Down
3 changes: 3 additions & 0 deletions examples/simple_sensor/SensorMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
#if ENV_INCLUDE_GPS == 1
void applyGpsPrefs() {
sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0");
char ref[32];
snprintf(ref, sizeof(ref), "%.6f,%.6f", _prefs.node_lat, _prefs.node_lon);
sensors.setSettingValue("gps_ref", ref); // anti-spoofing reference (ignored if unsupported)
}
#endif
};
23 changes: 23 additions & 0 deletions src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
#endif

// Believe it or not, this std C function is busted on some platforms!
// Keeps the GPS anti-spoofing reference in sync with the configured node position
// (ignored by sensor managers that do not support it).
static void updateGpsReference(SensorManager* sensors, double lat, double lon) {
char ref[32];
snprintf(ref, sizeof(ref), "%.6f,%.6f", lat, lon);
sensors->setSettingValue("gps_ref", ref);
}

static uint32_t _atoi(const char* sp) {
uint32_t n = 0;
while (*sp && *sp >= '0' && *sp <= '9') {
Expand Down Expand Up @@ -211,6 +219,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
uint32_t curr = getRTCClock()->getCurrentTime();
if (sender_timestamp > curr) {
getRTCClock()->setCurrentTime(sender_timestamp + 1);
_sensors->setSettingValue("gps_time_reset", "1"); // manual clock set: reset GPS time anchor
uint32_t now = getRTCClock()->getCurrentTime();
DateTime dt = DateTime(now);
sprintf(reply, "OK - clock set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
Expand All @@ -225,11 +234,22 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
uint32_t now = getRTCClock()->getCurrentTime();
DateTime dt = DateTime(now);
sprintf(reply, "%02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
} else if (memcmp(command, "time force ", 11) == 0) { // set time, allowing it to go backwards
uint32_t secs = _atoi(&command[11]);
if (secs > 1700000000UL) {
getRTCClock()->setCurrentTime(secs);
_sensors->setSettingValue("gps_time_reset", "1"); // manual clock set: reset GPS time anchor
DateTime dt = DateTime(getRTCClock()->getCurrentTime());
sprintf(reply, "OK - clock forced: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
} else {
strcpy(reply, "ERR: invalid epoch");
}
} else if (memcmp(command, "time ", 5) == 0) { // set time (to epoch seconds)
uint32_t secs = _atoi(&command[5]);
uint32_t curr = getRTCClock()->getCurrentTime();
if (secs > curr) {
getRTCClock()->setCurrentTime(secs);
_sensors->setSettingValue("gps_time_reset", "1"); // manual clock set: reset GPS time anchor
uint32_t now = getRTCClock()->getCurrentTime();
DateTime dt = DateTime(now);
sprintf(reply, "OK - clock set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
Expand Down Expand Up @@ -393,6 +413,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
} else if (memcmp(command, "gps setloc", 10) == 0) {
_prefs->node_lat = _sensors->node_lat;
_prefs->node_lon = _sensors->node_lon;
updateGpsReference(_sensors, _prefs->node_lat, _prefs->node_lon);
savePrefs();
strcpy(reply, "ok");
} else if (memcmp(command, "gps advert", 10) == 0) {
Expand Down Expand Up @@ -549,10 +570,12 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
strcpy(reply, _prefs->disable_fwd ? "OK - repeat is now OFF" : "OK - repeat is now ON");
} else if (memcmp(config, "lat ", 4) == 0) {
_prefs->node_lat = atof(&config[4]);
updateGpsReference(_sensors, _prefs->node_lat, _prefs->node_lon);
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "lon ", 4) == 0) {
_prefs->node_lon = atof(&config[4]);
updateGpsReference(_sensors, _prefs->node_lat, _prefs->node_lon);
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "flood.max.unscoped ", 19) == 0) {
Expand Down
Loading