Skip to content
Open
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
12 changes: 12 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ test_framework = googletest
build_flags = -std=c++17
-I src
-I test/mocks
-I variants/linux
; MicroNMEA is reached only from a test file, and a lib_deps entry that nothing
; under build_src_filter includes gets neither its include dir onto the test
; compile line nor its archive onto the link line (verified: dropping either of
; the two lines below fails, the first to compile and the second to link). So
; name both explicitly; lib_deps still pins the version and fetches it.
-I .pio/libdeps/native/MicroNMEA/src
test_build_src = yes
test_ignore = test_kiss_modem
build_src_filter =
Expand All @@ -232,8 +239,13 @@ build_src_filter =
+<../src/Packet.cpp>
+<../src/helpers/ConfigSerializer.cpp>
+<../src/helpers/DynamicConfigSerializer.cpp>
+<../variants/linux/LinuxGpsStream.cpp>
+<../.pio/libdeps/native/MicroNMEA/src/MicroNMEA.cpp>
lib_deps =
google/googletest @ 1.17.0
; test_linux_gps_stream includes <MicroNMEA.h> to prove with the real parser
; that gpsd's JSON control lines cannot corrupt a fix.
stevemarple/MicroNMEA @ ^2.0.6

[env:native_kiss_modem]
platform = native
Expand Down
36 changes: 30 additions & 6 deletions src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ static uint32_t _atoi(const char* sp) {
return n;
}

// setCurrentTime() returns void, so this is the only signal available that a
// set was honoured. On Linux it can be silently refused (host clock owned by
// chrony, or the process lacks CAP_SYS_TIME) and getCurrentTime() then reads
// back the unchanged clock; on every other target the set always takes, so
// this is always true there. A couple of seconds of slack absorbs a hardware
// RTC's read-back latency, not a real failure.
static bool clockSetTookEffect(uint32_t target, uint32_t actual) {
int64_t diff = (int64_t)actual - (int64_t)target;
return diff >= -2 && diff <= 2;
}

static bool isValidName(const char *n) {
while (*n) {
if (*n == '[' || *n == ']' || *n == '\\' || *n == ':' || *n == ',' || *n == '?' || *n == '*') return false;
Expand Down Expand Up @@ -210,10 +221,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
} else if (memcmp(command, "clock sync", 10) == 0) {
uint32_t curr = getRTCClock()->getCurrentTime();
if (sender_timestamp > curr) {
getRTCClock()->setCurrentTime(sender_timestamp + 1);
uint32_t target = sender_timestamp + 1;
getRTCClock()->setCurrentTime(target);
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());
if (clockSetTookEffect(target, now)) {
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());
} else {
strcpy(reply, "ERR: clock set was refused");
}
} else {
strcpy(reply, "ERR: clock cannot go backwards");
}
Expand All @@ -231,8 +247,12 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
if (secs > curr) {
getRTCClock()->setCurrentTime(secs);
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());
if (clockSetTookEffect(secs, now)) {
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());
} else {
strcpy(reply, "(ERR: clock set was refused)");
}
} else {
strcpy(reply, "(ERR: clock cannot go backwards)");
}
Expand Down Expand Up @@ -396,7 +416,11 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
bool enabled = l->isEnabled(); // is EN pin on ?
bool fix = l->isValid(); // has fix ?
int sats = l->satellitesCount();
bool active = !strcmp(_sensors->getSettingByKey("gps"), "1");
// getSettingByKey() returns NULL when no "gps" setting is registered
// (e.g. no GPS detected -- the Linux default) -- treat that as
// "deactivated" rather than handing strcmp() a NULL, which segfaults.
const char* gps_setting = _sensors->getSettingByKey("gps");
bool active = gps_setting != NULL && strcmp(gps_setting, "1") == 0;
if (enabled) {
sprintf(reply, "on, %s, %s, %d sats",
active?"active":"deactivated",
Expand Down
18 changes: 18 additions & 0 deletions src/helpers/sensors/EnvironmentSensorManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -747,8 +747,25 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val
}

#if ENV_INCLUDE_GPS
#if defined(ARDULINUX_PLATFORM)
// Defined in variants/linux/target.cpp. The Linux build opens the serial GPS
// device itself (there is no hardware UART); this reports whether that device
// is open.
bool linux_gps_present();
#endif

void EnvironmentSensorManager::initBasicGPS() {

#if defined(ARDULINUX_PLATFORM)
// Linux: the serial device is opened by the variant (target.cpp) from the
// gps_device/gps_baud config. A configured+opened device is treated as
// detected (no byte-sniff, which raced against slow-to-fix devices);
// runtime loop()/isValid() reports actual fix state. If nothing was
// configured/opened, GPS is off.
_location->begin(); // no-op on Linux (pin_en/pin_reset == -1)
_location->reset();
gps_detected = linux_gps_present();
#else
Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX);

#ifdef GPS_BAUD_RATE
Expand All @@ -774,6 +791,7 @@ void EnvironmentSensorManager::initBasicGPS() {
#else
gps_detected = (Serial1.available() > 0);
#endif
#endif // ARDULINUX_PLATFORM

if (gps_detected) {
MESH_DEBUG_PRINTLN("GPS detected");
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/sensors/LocationProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class LocationProvider {
virtual long satellitesCount() = 0;
virtual bool isValid() = 0;
virtual long getTimestamp() = 0;
virtual void sendSentence(const char * sentence);
virtual void sendSentence(const char * sentence) {}
virtual void reset() = 0;
virtual void begin() = 0;
virtual void stop() = 0;
Expand Down
1 change: 1 addition & 0 deletions test/mocks/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstdint>
#include <cmath>
#include <cctype> // real Arduino.h pulls this in; MicroNMEA relies on it
#include "Stream.h"

inline uint32_t g_mock_millis = 0;
Expand Down
6 changes: 6 additions & 0 deletions test/mocks/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,9 @@ class MainBoard {
};

}

// LinuxGpsStream.cpp logs through this. The real definition lives in
// src/MeshCore.h, which the native test env does not build.
#ifndef MESH_DEBUG_PRINTLN
#define MESH_DEBUG_PRINTLN(...) {}
#endif
Loading
Loading