mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-04 03:06:12 +00:00
feat(nav): navigate to / save a location shared in a message
Locations already travel as plain text ({loc} expands to "lat,lon"), so any
message carrying coordinates can now be acted on. In the fullscreen message
view, the context-menu (Hold Enter) gains Navigate and Save waypoint
entries whenever the message contains a coordinate — alongside Reply.
- geo::parseLatLon: shared scanner for an embedded "lat,lon" (the {loc}
format), with an optional [WAY] tag that supplies a label. Range-checked,
requires a decimal point to avoid matching plain integer pairs. Will also
back the waypoint-share feature later.
- QuickMsgScreen: Navigate opens NavView inline (To/Hdg/distance, honouring
the global Units setting) over the message, back returns to it; Save
waypoint stores the point (label from [WAY], else auto-named). Works in
both DM and channel histories, and on incoming or outgoing messages.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,9 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
@@ -58,4 +61,52 @@ static inline void fmtDist(char* buf, int n, float km, bool imperial) {
|
||||
}
|
||||
}
|
||||
|
||||
// Tag marking a shared waypoint inside a message: "[WAY]<lat>,<lon> <label>".
|
||||
// A plain {loc} expansion ("<lat>,<lon>") parses too — the tag just adds intent
|
||||
// and a label, and keeps the text readable on apps/firmware that don't know it.
|
||||
#define WAYPOINT_MSG_TAG "[WAY]"
|
||||
|
||||
// Scan a message for an embedded "lat,lon" location (decimal degrees, the same
|
||||
// text {loc} emits). If a WAYPOINT_MSG_TAG precedes it, the trailing text is
|
||||
// taken as the label. Returns true and fills lat/lon (1e6-scaled) on a valid,
|
||||
// in-range coordinate; label (optional) gets the trimmed tag suffix or "".
|
||||
static inline bool parseLatLon(const char* text, int32_t& lat_1e6, int32_t& lon_1e6,
|
||||
char* label = nullptr, int label_n = 0) {
|
||||
if (label && label_n > 0) label[0] = '\0';
|
||||
if (!text) return false;
|
||||
|
||||
const char* tag = strstr(text, WAYPOINT_MSG_TAG);
|
||||
const char* scan = tag ? tag + strlen(WAYPOINT_MSG_TAG) : text;
|
||||
|
||||
for (const char* p = scan; *p; p++) {
|
||||
if (*p != '-' && *p != '+' && *p != '.' && !isdigit((unsigned char)*p)) continue;
|
||||
char* end = nullptr;
|
||||
double la = strtod(p, &end);
|
||||
if (end == p) continue;
|
||||
if (!memchr(p, '.', end - p)) continue; // require a decimal point (skip "5,6")
|
||||
const char* q = end;
|
||||
while (*q == ' ') q++;
|
||||
if (*q != ',') { p = end - 1; continue; }
|
||||
q++;
|
||||
while (*q == ' ') q++;
|
||||
char* end2 = nullptr;
|
||||
double lo = strtod(q, &end2);
|
||||
if (end2 == q) continue;
|
||||
if (la < -90.0 || la > 90.0 || lo < -180.0 || lo > 180.0) continue;
|
||||
|
||||
lat_1e6 = (int32_t)lroundf((float)(la * 1e6));
|
||||
lon_1e6 = (int32_t)lroundf((float)(lo * 1e6));
|
||||
if (label && label_n > 0 && tag) { // label only from a tagged share
|
||||
const char* s = end2;
|
||||
while (*s == ' ') s++;
|
||||
int n = 0;
|
||||
while (s[n] && n < label_n - 1) { label[n] = s[n]; n++; }
|
||||
while (n > 0 && label[n - 1] == ' ') n--; // trim trailing spaces
|
||||
label[n] = '\0';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace geo
|
||||
|
||||
Reference in New Issue
Block a user