mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-23 03:41:27 +00:00
vanilla dev sync
This commit is contained in:
1 parent
7662decca5
commit
2e0f765036
12 files changed
+301
-13
No files matched your search
@@ -1016,6 +1016,40 @@ config ZEPHCORE_GPS_SAT_DIAG
|
||||
available — this option only adds the per-constellation evidence to
|
||||
its report.
|
||||
|
||||
config ZEPHCORE_GPS_REAPPLY
|
||||
bool "Re-send GNSS module settings after every GPS power-on"
|
||||
depends on GNSS
|
||||
default y
|
||||
help
|
||||
CASIC receivers (Quectel L76K/L76KB, Air530Z) keep the sentence
|
||||
selection (PCAS03) and constellation set (PCAS04) in RAM only: nothing
|
||||
here sends PCAS00 to save them, so a supply cut returns the module to
|
||||
its factory GPS + BeiDou. Configuration otherwise runs once, at boot,
|
||||
so a board whose gps off / duty-cycle standby really removes power
|
||||
would lose GLONASS after its first sleep (upstream MeshCore #3201
|
||||
re-sends PCAS04 on every start for the same reason).
|
||||
|
||||
With this on, about one second after each power-on the settings that
|
||||
are lost with power are written again, blind, one sentence at a time
|
||||
with the boot sequence's settle gaps, over the GNSS UART from the main
|
||||
thread (never through modem_chat, whose blocking scripts are unsafe
|
||||
right after a power restore): PCAS03, PCAS11 (the nav mode, when set)
|
||||
and PCAS04 last; on generic-NMEA boards, whose module is unknown,
|
||||
MediaTek's PMTK353 constellations, EASY (PMTK869) and AIC (PMTK286)
|
||||
first. Both constellation commands restart their own chip's engine; on
|
||||
a module that kept its settings that is one restart per wake, taken
|
||||
over leaving one that lost them searching GPS-only. UBX stays
|
||||
boot-only: CFG-CFG saves it to the module's flash, and repeating it
|
||||
would wear that flash.
|
||||
|
||||
No board list: every GNSS board gets it, and it is inert where it is
|
||||
not needed: receivers ignore the other families' sentences, and one
|
||||
that only went to standby (Wio Tracker L1's WAKEUP pin) is simply told
|
||||
what it already has. Costs under 130 UART bytes per wake.
|
||||
|
||||
Turn it off in a board.conf only with a reason, e.g. a CASIC board
|
||||
proven to lose fixes to the navigation restart PCAS04 triggers.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "WiFi OTA Update"
|
||||
|
||||
@@ -641,4 +641,14 @@ bool ZephyrBoard::isExternalPowered()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ZephyrBoard::hasUsbPowerDetect() const
|
||||
{
|
||||
return IS_ENABLED(CONFIG_SOC_SERIES_NRF52);
|
||||
}
|
||||
|
||||
bool ZephyrBoard::isUsbPowered()
|
||||
{
|
||||
return hasUsbPowerDetect() && isExternalPowered();
|
||||
}
|
||||
|
||||
} /* namespace mesh */
|
||||
@@ -33,6 +33,10 @@ public:
|
||||
void clearBootloaderMagic(); /* Clear stale GPREGRET values at startup */
|
||||
uint8_t getStartupReason() const override;
|
||||
bool isExternalPowered() override; /* nRF52: VBUS present (USB/charger); else false */
|
||||
/* `power`: nRF52's VBUS detect is a USB-power detect; other platforms
|
||||
* keep upstream's "n/a". No board reports a charger line yet. */
|
||||
bool hasUsbPowerDetect() const override;
|
||||
bool isUsbPowered() override;
|
||||
|
||||
/* get pwrmgt.*: upstream's power-management getters. */
|
||||
uint16_t getBootVoltage() override { return _boot_mv; }
|
||||
|
||||
@@ -56,6 +56,7 @@ static gps_event_callback_t gps_event_cb = NULL;
|
||||
#define GPS_ACTION_TIMEOUT BIT(1) /* Acquisition timeout → go to standby */
|
||||
#define GPS_ACTION_FIX_DONE BIT(2) /* Got enough good fixes → go to standby */
|
||||
#define GPS_ACTION_FIX BIT(3) /* A validated fix for gps_fix_cb (fix_pending) */
|
||||
#define GPS_ACTION_REAPPLY BIT(4) /* Next module re-send step (gps_reapply_step) */
|
||||
static atomic_t pending_gps_actions;
|
||||
|
||||
/* GPS Power Management State Machine */
|
||||
@@ -122,6 +123,42 @@ static void gps_start_acquiring(void);
|
||||
static K_WORK_DELAYABLE_DEFINE(gps_wake_work, gps_wake_work_fn);
|
||||
static K_WORK_DELAYABLE_DEFINE(gps_timeout_work, gps_timeout_work_fn);
|
||||
|
||||
#if HAS_GPS_UART && defined(CONFIG_ZEPHCORE_GPS_REAPPLY)
|
||||
/* CONFIG_ZEPHCORE_GPS_REAPPLY: after each power-on, wait for the module
|
||||
* to boot, then hand the main thread one sentence per step. */
|
||||
#define GPS_REAPPLY_BOOT_MS 1000 /* module boot is ~300 ms; margin for slow rails */
|
||||
static uint8_t gps_reapply_step;
|
||||
static uint32_t gps_reapply_count; /* completed re-sends, `gps diag` ra: */
|
||||
static void gps_reapply_work_fn(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
|
||||
if (gps_current_state != GPS_STATE_ACQUIRING) {
|
||||
return;
|
||||
}
|
||||
atomic_or(&pending_gps_actions, GPS_ACTION_REAPPLY);
|
||||
if (gps_event_cb) {
|
||||
gps_event_cb();
|
||||
}
|
||||
}
|
||||
static K_WORK_DELAYABLE_DEFINE(gps_reapply_work, gps_reapply_work_fn);
|
||||
|
||||
static void gps_reapply_start(void)
|
||||
{
|
||||
gps_reapply_step = 0;
|
||||
k_work_reschedule(&gps_reapply_work, K_MSEC(GPS_REAPPLY_BOOT_MS));
|
||||
}
|
||||
|
||||
static void gps_reapply_cancel(void)
|
||||
{
|
||||
k_work_cancel_delayable(&gps_reapply_work);
|
||||
atomic_and(&pending_gps_actions, ~GPS_ACTION_REAPPLY);
|
||||
}
|
||||
#else
|
||||
static inline void gps_reapply_start(void) { }
|
||||
static inline void gps_reapply_cancel(void) { }
|
||||
#endif
|
||||
|
||||
#else
|
||||
static gps_enable_callback_t gps_enable_cb = NULL;
|
||||
#endif
|
||||
@@ -490,6 +527,7 @@ static void gps_go_to_standby(void)
|
||||
* VBACKUP charger keeps the receiver's V_BCKP domain alive, so ephemeris/
|
||||
* RTC survive the cut and re-acquisition is a warm/hot start, not cold.
|
||||
* Other non-GPIO boards: software sleep via UART commands (PMTK + UBX). */
|
||||
gps_reapply_cancel();
|
||||
gps_module_power(false);
|
||||
|
||||
/* Module is off/asleep — release the UART until the next wake
|
||||
@@ -497,10 +535,10 @@ static void gps_go_to_standby(void)
|
||||
gps_uart_set_power(false);
|
||||
gps_hold_sleep_lock(false);
|
||||
|
||||
/* NOTE: gnss_configured stays true — L76K retains PCAS settings in
|
||||
* flash across power cycles. Re-running gps_module_configure() after GPIO
|
||||
* wake would call modem_chat_run_script() before the chip has booted,
|
||||
* risking a deadlock (modem_chat blocks on system work queue). */
|
||||
/* NOTE: gnss_configured stays true, gps_module_configure() is boot-only:
|
||||
* after a power restore modem_chat_run_script() would reach a chip that
|
||||
* has not booted yet (deadlock risk, see gps_wake_work_fn). What a power
|
||||
* cut loses on CASIC parts is re-sent by gps_reapply_start() instead. */
|
||||
|
||||
/* Schedule next wake (event-driven, no polling!) */
|
||||
k_work_schedule(&gps_wake_work, K_MSEC(wake_interval));
|
||||
@@ -509,11 +547,12 @@ static void gps_go_to_standby(void)
|
||||
/* Wake GPS and start acquiring.
|
||||
* GPIO boards: hardware power-on.
|
||||
* Non-GPIO boards: UART wake byte (wakes L76K from standby, ZOE-M8Q from backup).
|
||||
* Does NOT call gps_module_configure() — constellation/fix-rate settings persist
|
||||
* in L76K flash across power cycles. Calling modem_chat_run_script() here
|
||||
* Does NOT call gps_module_configure(). Calling modem_chat_run_script() here
|
||||
* would deadlock: the chip needs ~300ms to boot after GPIO power restore,
|
||||
* but modem_chat blocks the calling thread waiting for the system work
|
||||
* queue which may be processing stale UART data. */
|
||||
* queue which may be processing stale UART data. CASIC settings are NOT
|
||||
* persisted (no PCAS00, see the air530z driver), so they are re-sent blind
|
||||
* a second after power-on (CONFIG_ZEPHCORE_GPS_REAPPLY). */
|
||||
static void gps_start_acquiring(void)
|
||||
{
|
||||
LOG_INF("GPS: Waking for %s", gps_repeater_mode ? "time sync" : "position fix");
|
||||
@@ -526,6 +565,7 @@ static void gps_start_acquiring(void)
|
||||
* goes out, so the first NMEA sentences aren't lost. */
|
||||
gps_uart_set_power(true);
|
||||
gps_module_power(true);
|
||||
gps_reapply_start();
|
||||
|
||||
/* Schedule the standby timeout — unless always-on (interval 0), where the
|
||||
* GPS stays in continuous acquisition and never sleeps. Every duty window
|
||||
@@ -824,8 +864,8 @@ void gps_enable(bool enable)
|
||||
* lock, and the first (longer) acquire window unless always-on. */
|
||||
gps_start_acquiring();
|
||||
|
||||
/* gps_module_configure() runs once at boot (see gps_manager_init path).
|
||||
* L76K retains PCAS settings in flash across power cycles.
|
||||
/* gps_module_configure() runs once at boot (see gps_manager_init path);
|
||||
* gps_start_acquiring() re-sends the CASIC settings a power cut loses.
|
||||
* Do NOT call modem_chat_run_script() here — the chip needs
|
||||
* ~300ms to boot after GPIO power restore and calling it
|
||||
* immediately deadlocks the main thread. */
|
||||
@@ -836,6 +876,7 @@ void gps_enable(bool enable)
|
||||
/* Cancel any pending work */
|
||||
k_work_cancel_delayable(&gps_wake_work);
|
||||
k_work_cancel_delayable(&gps_timeout_work);
|
||||
gps_reapply_cancel();
|
||||
|
||||
/* Power off GPS — warm standby if VRTC available (Arduino sleep_gps),
|
||||
* full power off otherwise. Warm standby preserves ephemeris/RTC
|
||||
@@ -1046,6 +1087,56 @@ void gps_get_state_info(struct gps_state_info *info)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAS_GNSS
|
||||
/* Parsed-sentence count from the GNSS driver (see gps_module_cfg.cpp). */
|
||||
extern "C" uint32_t zephcore_gnss_rx_count(void) __attribute__((weak));
|
||||
#endif
|
||||
|
||||
void gps_format_diagnostics(char *out, size_t out_size)
|
||||
{
|
||||
if (out_size == 0) {
|
||||
return;
|
||||
}
|
||||
#if HAS_GNSS
|
||||
/* Upstream's keys, where this port has the same quantity: en = module
|
||||
* powered and searching (standby is off/asleep), ok = checksum-valid
|
||||
* sentences (the driver parses nothing else), fa = age of the last
|
||||
* validated fix. */
|
||||
k_mutex_lock(&gps_mutex, K_FOREVER);
|
||||
bool fix = current_pos.valid;
|
||||
unsigned sats = current_pos.satellites;
|
||||
k_mutex_unlock(&gps_mutex);
|
||||
|
||||
char fix_age[11];
|
||||
if (last_fix_uptime_ms > 0) {
|
||||
snprintf(fix_age, sizeof(fix_age), "%lu",
|
||||
(unsigned long)(uint32_t)(k_uptime_get() - last_fix_uptime_ms));
|
||||
} else {
|
||||
snprintf(fix_age, sizeof(fix_age), "never");
|
||||
}
|
||||
|
||||
char ok[16] = "";
|
||||
if (zephcore_gnss_rx_count != NULL) {
|
||||
snprintf(ok, sizeof(ok), " ok:%lu", (unsigned long)zephcore_gnss_rx_count());
|
||||
}
|
||||
|
||||
/* ZephCore addition: completed CASIC re-sends (CONFIG_ZEPHCORE_GPS_REAPPLY),
|
||||
* one per power-on that stayed up past GPS_REAPPLY_BOOT_MS. */
|
||||
char ra[16] = "";
|
||||
#if HAS_GPS_UART && defined(CONFIG_ZEPHCORE_GPS_REAPPLY)
|
||||
snprintf(ra, sizeof(ra), " ra:%lu", (unsigned long)gps_reapply_count);
|
||||
#endif
|
||||
|
||||
snprintf(out, out_size, "en:%u%s sat:%u fix:%u fa:%s bc:%lu sc:%lu%s",
|
||||
gps_current_state == GPS_STATE_ACQUIRING ? 1U : 0U,
|
||||
ok, sats, fix ? 1U : 0U, fix_age,
|
||||
(unsigned long)gps_power_on_count,
|
||||
(unsigned long)gps_power_off_count, ra);
|
||||
#else
|
||||
snprintf(out, out_size, "en:0 sat:0 fix:0");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Process pending GPS state transitions — called from main thread.
|
||||
* Work handlers on the system work queue set flags + signal the main
|
||||
* thread via gps_event_cb(). The main thread then calls this function,
|
||||
@@ -1089,5 +1180,18 @@ void gps_process_event(void)
|
||||
gps_go_to_standby();
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_GPS_UART && defined(CONFIG_ZEPHCORE_GPS_REAPPLY)
|
||||
/* After the transitions: a standby above has already cancelled it. */
|
||||
if ((actions & GPS_ACTION_REAPPLY) && gps_current_state == GPS_STATE_ACQUIRING) {
|
||||
uint32_t gap_ms = gps_module_reapply_step(gps_reapply_step++);
|
||||
|
||||
if (gap_ms > 0) {
|
||||
k_work_reschedule(&gps_reapply_work, K_MSEC(gap_ms));
|
||||
} else {
|
||||
gps_reapply_count++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -53,6 +53,12 @@ void gps_set_diag(bool on);
|
||||
* succeeds; reports "never run" if configuration has not happened yet. */
|
||||
void gps_get_diag_report(char *buf, size_t len);
|
||||
|
||||
/* `gps diag` (upstream's LocationProvider::formatDiagnostics): module on,
|
||||
* NMEA sentences parsed, satellites, fix, fix age in ms, module power-on /
|
||||
* power-off counts. Upstream's UART byte and bad-checksum counters have no
|
||||
* source behind the GNSS API and are left out. */
|
||||
void gps_format_diagnostics(char *out, size_t out_size);
|
||||
|
||||
/* GPS enable callback - called when GPS is enabled/disabled (for power management) */
|
||||
typedef void (*gps_enable_callback_t)(bool enabled);
|
||||
void gps_set_enable_callback(gps_enable_callback_t cb);
|
||||
|
||||
@@ -84,6 +84,9 @@ void gps_sat_tally(uint8_t out[5]);
|
||||
void gps_power_control(bool on, bool keep_vrtc = false);
|
||||
/* The power line or rail if the board has one, else the UART sleep commands. */
|
||||
void gps_module_power(bool on, bool keep_vrtc = true);
|
||||
/* gps_module_power() calls, for `gps diag` (upstream's bc/sc). */
|
||||
extern uint32_t gps_power_on_count;
|
||||
extern uint32_t gps_power_off_count;
|
||||
/* Suspend/resume the GNSS UART (nRF UARTE: releases HFCLK). */
|
||||
void gps_uart_set_power(bool on);
|
||||
#if HAS_GPS_POWER_CONTROL
|
||||
@@ -95,6 +98,12 @@ void gps_dump_gpio_states(void);
|
||||
void gps_module_configure(void);
|
||||
/* Re-run the UART configuration when `set gps diag 1` asked for it. */
|
||||
void gps_diag_maybe_reconfigure(void);
|
||||
#if HAS_GPS_UART && defined(CONFIG_ZEPHCORE_GPS_REAPPLY)
|
||||
/* CONFIG_ZEPHCORE_GPS_REAPPLY: write the step-th re-sent setting blind
|
||||
* (see the list in gps_module_cfg.cpp). Returns the ms to wait before the
|
||||
* next step, 0 when that was the last. */
|
||||
uint32_t gps_module_reapply_step(uint8_t step);
|
||||
#endif
|
||||
void gps_uart_dump_hw_state(void);
|
||||
#if HAS_GPS_UART
|
||||
extern const struct device *const gps_uart_dev;
|
||||
|
||||
@@ -29,9 +29,9 @@ static bool gps_diag_on = false;
|
||||
* 3. The script completion callback competes with NMEA processing
|
||||
*
|
||||
* Safe to call at boot because the driver init already ran and the chip
|
||||
* is powered and outputting NMEA. After power cycles, the L76K retains
|
||||
* constellation + fix rate settings in internal flash (PCAS commands
|
||||
* persist). So we only need to configure once. */
|
||||
* is powered and outputting NMEA. PCAS settings are NOT persisted (nothing
|
||||
* sends PCAS00), so what a power cut loses is re-sent blind after every
|
||||
* power-on instead (gps_module_reapply_step, CONFIG_ZEPHCORE_GPS_REAPPLY). */
|
||||
static bool gnss_configured = false;
|
||||
|
||||
/* ========== Configuration Diagnostics ==========
|
||||
@@ -567,6 +567,65 @@ void gps_module_configure(void)
|
||||
gnss_configured = true;
|
||||
}
|
||||
|
||||
#if HAS_GPS_UART && defined(CONFIG_ZEPHCORE_GPS_REAPPLY)
|
||||
/* The boot-time settings a power cut loses (see the Kconfig help). One
|
||||
* sentence per step, written with gps_uart_send() directly and no settle
|
||||
* sleep: the caller waits each entry's gap with a work item, so the main
|
||||
* thread only spends the UART time.
|
||||
*
|
||||
* Kept boot-only on purpose:
|
||||
* - UBX: already saved to BBR + flash by CFG-CFG at boot, and repeating it
|
||||
* would rewrite the module's flash on every wake;
|
||||
* - PCAS02 (1 Hz is the default) and PCAS06 (a query, no state).
|
||||
*
|
||||
* Both constellation commands restart their chip's navigation engine, and a
|
||||
* sentence written into a restarting engine is lost, so each is followed by
|
||||
* the boot sequence's restart settle: PMTK353 first, PCAS04 last. Each only
|
||||
* restarts its own family's chip (the other ignores it). On a MediaTek part
|
||||
* that merely slept this costs one engine restart per wake, accepted
|
||||
* (architect, 2026-09-27): one that lost power is otherwise left searching
|
||||
* GPS-only, which is slower than a restart with every constellation. The
|
||||
* PMTK sentences go only where the module is unknown (the generic-NMEA
|
||||
* path); an API-driver board's module is known CASIC. */
|
||||
struct reapply_cmd {
|
||||
const char *sentence;
|
||||
uint16_t gap_ms; /* wait before the next one */
|
||||
};
|
||||
|
||||
static const struct reapply_cmd reapply_casic[] = {
|
||||
{ pcas_sentences, GPS_CFG_SETTLE_MS },
|
||||
#if CONFIG_ZEPHCORE_GPS_NAV_MODE >= 0
|
||||
/* The driver's GNSS_LUATOS_AIR530Z_NAV_MODE mirrors this value, so
|
||||
* this matches what either path set at boot. */
|
||||
{ pcas_nav_mode, GPS_CFG_SETTLE_MS },
|
||||
#endif
|
||||
{ pcas_constellations, 0 },
|
||||
};
|
||||
static const struct reapply_cmd reapply_generic[] = {
|
||||
{ pmtk_constellations, GPS_CFG_RESTART_MS },
|
||||
{ pmtk_easy, GPS_CFG_SETTLE_MS },
|
||||
{ pmtk_aic, GPS_CFG_SETTLE_MS },
|
||||
{ pcas_sentences, GPS_CFG_SETTLE_MS },
|
||||
#if CONFIG_ZEPHCORE_GPS_NAV_MODE >= 0
|
||||
{ pcas_nav_mode, GPS_CFG_SETTLE_MS },
|
||||
#endif
|
||||
{ pcas_constellations, 0 },
|
||||
};
|
||||
|
||||
uint32_t gps_module_reapply_step(uint8_t step)
|
||||
{
|
||||
bool generic = (gps_cfg_diag.path == GPS_CFG_UART);
|
||||
const struct reapply_cmd *list = generic ? reapply_generic : reapply_casic;
|
||||
size_t n = generic ? ARRAY_SIZE(reapply_generic) : ARRAY_SIZE(reapply_casic);
|
||||
|
||||
if (step >= n) {
|
||||
return 0;
|
||||
}
|
||||
gps_uart_send((const uint8_t *)list[step].sentence, strlen(list[step].sentence));
|
||||
return (step + 1 < n) ? list[step].gap_ms : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ========== GPS UART Diagnostics ========== */
|
||||
|
||||
/**
|
||||
|
||||
@@ -532,8 +532,16 @@ static void gps_software_wake(void)
|
||||
|
||||
/* Module on or off with whatever this board has: the power GPIO or PMU rail,
|
||||
* else the UART sleep commands. keep_vrtc: T1000-E warm standby (off only). */
|
||||
uint32_t gps_power_on_count;
|
||||
uint32_t gps_power_off_count;
|
||||
|
||||
void gps_module_power(bool on, bool keep_vrtc)
|
||||
{
|
||||
if (on) {
|
||||
gps_power_on_count++;
|
||||
} else {
|
||||
gps_power_off_count++;
|
||||
}
|
||||
#if HAS_GPS_POWER_CONTROL || HAS_GPS_POWER_REGULATOR
|
||||
gps_power_control(on, keep_vrtc);
|
||||
#elif HAS_GPS_UART
|
||||
|
||||
@@ -1453,6 +1453,20 @@ void CompanionMesh::onContactResponse(const ContactInfo &contact, const uint8_t
|
||||
};
|
||||
ui_notify_joystick_event(UI_JOYSTICK_REQ_RESPONSE, contact.id.pub_key, &rr);
|
||||
}
|
||||
|
||||
/* Arduino b204f9a1: let the app know about unknown/unhandled responses
|
||||
* (eg. push telemetry from a sensor subscription): tag + payload as-is. */
|
||||
{
|
||||
uint8_t rsp[MAX_FRAME_SIZE];
|
||||
int i = 0;
|
||||
rsp[i++] = PUSH_CODE_BINARY_RESPONSE;
|
||||
rsp[i++] = 0; // reserved
|
||||
int data_len = len;
|
||||
if (data_len > (int)sizeof(rsp) - i) data_len = sizeof(rsp) - i;
|
||||
memcpy(&rsp[i], data, data_len);
|
||||
i += data_len;
|
||||
sendPush(rsp[0], &rsp[1], i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Raw packet logging - sends all RX packets to app for "heard X repeats" etc */
|
||||
|
||||
@@ -550,6 +550,19 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||
snprintf(reply, CLI_REPLY_SIZE, "%s (Build: %s)", _callbacks->getFirmwareVer(), _callbacks->getBuildDate());
|
||||
} else if (memcmp(command, "board", 5) == 0) {
|
||||
snprintf(reply, CLI_REPLY_SIZE, "%s", _board->getManufacturerName());
|
||||
} else if (strcmp(command, "power") == 0) {
|
||||
const char* usb_state = _board->hasUsbPowerDetect()
|
||||
? (_board->isUsbPowered() ? "yes" : "no")
|
||||
: "n/a";
|
||||
const char* solar_state = _board->hasSolarChargerDetect()
|
||||
? (_board->isSolarChargerActive() ? "yes" : "no")
|
||||
: "n/a";
|
||||
snprintf(reply, 160, "batt:%u mV usb:%s solar_chg:%s ext:%s charger:%s",
|
||||
(unsigned)_board->getBattMilliVolts(),
|
||||
usb_state,
|
||||
solar_state,
|
||||
_board->isExternalPowered() ? "yes" : "no",
|
||||
_board->isChargerActive() ? "yes" : "no");
|
||||
} else if (memcmp(command, "sensor get ", 11) == 0) {
|
||||
const char* key = command + 11;
|
||||
const char* val = _sensors->getSettingByKey(key);
|
||||
@@ -621,6 +634,21 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||
gps_request_fresh_fix();
|
||||
strcpy(reply, "ok");
|
||||
}
|
||||
} else if (strcmp(command, "gps diag") == 0) {
|
||||
/* ZEPHCORE: upstream asks the LocationProvider; here the GPS
|
||||
* manager formats the fields it has (see gps_format_diagnostics). */
|
||||
if (_sensors->isGPSDetected()) {
|
||||
const char* setting = _sensors->getSettingByKey("gps");
|
||||
bool requested = setting != NULL && strcmp(setting, "1") == 0;
|
||||
int prefix_len = snprintf(reply, 160, "req:%u ", requested ? 1U : 0U);
|
||||
if (prefix_len < 0 || prefix_len >= 160) {
|
||||
reply[159] = 0;
|
||||
} else {
|
||||
gps_format_diagnostics(reply + prefix_len, 160 - prefix_len);
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "gps provider not found");
|
||||
}
|
||||
} else if (memcmp(command, "gps setloc", 10) == 0) {
|
||||
_prefs->node_lat = _sensors->node_lat;
|
||||
_prefs->node_lon = _sensors->node_lon;
|
||||
|
||||
@@ -81,6 +81,16 @@ public:
|
||||
// ZEPHCORE: no isPwrMgtInitialised() / getWakeLpcompSupported() -- upstream's
|
||||
// nRF52 Arduino power manager; Zephyr PM covers this.
|
||||
virtual bool isExternalPowered() { return false; }
|
||||
// True while a board can identify an active battery-charging source.
|
||||
virtual bool isChargerActive() { return false; }
|
||||
|
||||
// Optional, source-specific power detection. Boards that can distinguish a USB
|
||||
// supply from a solar charger override these; defaults keep every other board
|
||||
// unaffected (the generic CLI prints "n/a" when a capability is absent).
|
||||
virtual bool hasUsbPowerDetect() const { return false; }
|
||||
virtual bool isUsbPowered() { return false; }
|
||||
virtual bool hasSolarChargerDetect() const { return false; }
|
||||
virtual bool isSolarChargerActive() { return false; }
|
||||
virtual uint16_t getBootVoltage() { return 0; }
|
||||
virtual uint32_t getResetReason() const { return 0; }
|
||||
virtual const char* getResetReasonString(uint32_t reason) { return "Not available"; }
|
||||
|
||||
Reference in new issue
Block a user