mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-04 19:26:19 +00:00
feat(companion): follow live contacts — nav, geo-alert, ETA, quick-share
Builds on live location sharing: - Nearby "Navigate" now follows a moving live target: the navigate view re-reads the shared position every second and re-locates the entry by name for non-contact senders, so it no longer freezes or drops out (previously only refreshed for stored contacts entered via detail). - NavView gains a closing-speed / ETA line (EtaTracker), shown in the Nearby navigate view while approaching. - Geo Alert target can be a live contact, not just a waypoint: the engine re-reads the contact's latest [LOC] position each evaluation (keyed by pubkey prefix) so the geofence follows a moving person; alert wording switches to Near/Away. The picker cycles waypoints + verified live contacts (shown with an '@' prefix). Schema bumped 0xC0DE0014 -> 0x15. - Nearby marks a position-broadcasting node with the map's ♦ diamond (was a cryptic '*'/'~' prefix) and spells out "Sharing pos:" in detail. - Home Map page Hold-Enter is a one-shot position share: pushes to the Live Share target while auto-sharing is on, else opens the picker. Verified: WioTrackerL1_companion_solo_dual builds clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
44e522eec9
commit
dcc4379f63
@@ -1225,6 +1225,10 @@ public:
|
||||
_task->gotoDashboardConfig();
|
||||
return true;
|
||||
}
|
||||
if (c == KEY_CONTEXT_MENU && _page == HomePage::MAP) {
|
||||
_task->quickShareMyLocation();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -2129,10 +2133,20 @@ void UITask::loop() {
|
||||
// evaluator and the proximity beeper.
|
||||
bool UITask::geoAlertDistance(float& dist_m, float& radius_m) const {
|
||||
if (!_node_prefs || !_node_prefs->geo_alert_has_target) return false;
|
||||
int32_t tlat, tlon;
|
||||
if (_node_prefs->geo_alert_target_kind == 1) {
|
||||
// Live contact: follow the latest [LOC] position. No recent share → no
|
||||
// distance to evaluate (engine waits rather than using a stale fix).
|
||||
const LiveTrackStore::Entry* e =
|
||||
_livetrack.activeByKey(_node_prefs->geo_alert_key, (uint32_t)rtc_clock.getCurrentTime());
|
||||
if (!e) return false;
|
||||
tlat = e->lat_1e6; tlon = e->lon_1e6;
|
||||
} else {
|
||||
tlat = _node_prefs->geo_alert_lat_1e6; tlon = _node_prefs->geo_alert_lon_1e6;
|
||||
}
|
||||
int32_t lat, lon;
|
||||
if (!currentLocation(lat, lon)) return false;
|
||||
dist_m = geo::haversineKm(lat, lon, _node_prefs->geo_alert_lat_1e6,
|
||||
_node_prefs->geo_alert_lon_1e6) * 1000.0f;
|
||||
dist_m = geo::haversineKm(lat, lon, tlat, tlon) * 1000.0f;
|
||||
radius_m = (float)NodePrefs::geoAlertRadiusMeters(_node_prefs->geo_alert_radius_idx);
|
||||
return true;
|
||||
}
|
||||
@@ -2160,8 +2174,12 @@ void UITask::evaluateGeoAlert() {
|
||||
|
||||
void UITask::fireGeoAlert(bool arrived) {
|
||||
const char* lbl = _node_prefs->geo_alert_label[0] ? _node_prefs->geo_alert_label : "target";
|
||||
bool person = _node_prefs->geo_alert_target_kind == 1;
|
||||
char msg[40];
|
||||
snprintf(msg, sizeof(msg), arrived ? "Arrived: %s" : "Left: %s", lbl);
|
||||
// "Near/Away" reads naturally for a moving person; "Arrived/Left" for a place.
|
||||
snprintf(msg, sizeof(msg),
|
||||
arrived ? (person ? "Near: %s" : "Arrived: %s")
|
||||
: (person ? "Away: %s" : "Left: %s"), lbl);
|
||||
showAlert(msg, 3000);
|
||||
if (!isBuzzerQuiet())
|
||||
playMelody(arrived ? "geoarr:d=8,o=6,b=140:c,e,g" : "geolv:d=8,o=6,b=140:g,e,c");
|
||||
@@ -2277,6 +2295,22 @@ bool UITask::sendLocationShare(int32_t lat, int32_t lon) {
|
||||
return the_mesh.sendMessage(*c, rtc_clock.getCurrentTime(), 0, text, expected_ack, est_timeout) > 0;
|
||||
}
|
||||
|
||||
// One-shot "share my position" from the home Map page (Hold Enter). When live
|
||||
// sharing is already on, push an immediate [LOC] to the same target; otherwise
|
||||
// hand a [LOC] message to the recipient picker so the user chooses where it
|
||||
// goes (no accidental broadcast to a default channel).
|
||||
void UITask::quickShareMyLocation() {
|
||||
int32_t lat, lon;
|
||||
if (!currentLocation(lat, lon)) { showAlert("No GPS fix", 1000); return; }
|
||||
if (_node_prefs && _node_prefs->loc_share_enabled && sendLocationShare(lat, lon)) {
|
||||
showAlert("Position shared", 900);
|
||||
return;
|
||||
}
|
||||
char text[40];
|
||||
snprintf(text, sizeof(text), LOCATION_MSG_TAG "%.5f,%.5f", lat / 1e6, lon / 1e6);
|
||||
shareToMessage(text);
|
||||
}
|
||||
|
||||
void UITask::saveWaypoints() {
|
||||
DataStore* ds = the_mesh.getDataStore();
|
||||
if (!ds) return;
|
||||
|
||||
Reference in New Issue
Block a user