Codex added unified library, all work
This commit is contained in:
parent
18a1d1558c
commit
8370e546ff
25 changed files with 2935 additions and 0 deletions
91
tests/01_storage_logger/platformio.ini
Normal file
91
tests/01_storage_logger/platformio.ini
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
; Repository-level hardware test for tbeam_storage and tbeam_logger.
|
||||
|
||||
[platformio]
|
||||
default_envs = cy
|
||||
extra_configs = ../../shared/platformio/tbeam_supreme_units.ini
|
||||
|
||||
[storage_logger_base]
|
||||
extends = tbeam_supreme_common
|
||||
lib_deps =
|
||||
${tbeam_supreme_common.lib_deps}
|
||||
build_flags =
|
||||
${tbeam_supreme_common.build_flags}
|
||||
-D STORAGE_LOGGER_TEST=1
|
||||
|
||||
[env:amy]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"AMY\"
|
||||
-D NODE_LABEL=\"Amy\"
|
||||
-D NODE_SHORT=\"A\"
|
||||
-D NODE_SLOT_INDEX=0
|
||||
-D LOG_AP_IP_OCTET=23
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:bob]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"BOB\"
|
||||
-D NODE_LABEL=\"Bob\"
|
||||
-D NODE_SHORT=\"B\"
|
||||
-D NODE_SLOT_INDEX=1
|
||||
-D LOG_AP_IP_OCTET=24
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:cy]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"CY\"
|
||||
-D NODE_LABEL=\"Cy\"
|
||||
-D NODE_SHORT=\"C\"
|
||||
-D NODE_SLOT_INDEX=2
|
||||
-D LOG_AP_IP_OCTET=25
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:dan]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"DAN\"
|
||||
-D NODE_LABEL=\"Dan\"
|
||||
-D NODE_SHORT=\"D\"
|
||||
-D NODE_SLOT_INDEX=3
|
||||
-D LOG_AP_IP_OCTET=26
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:ed]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"ED\"
|
||||
-D NODE_LABEL=\"Ed\"
|
||||
-D NODE_SHORT=\"E\"
|
||||
-D NODE_SLOT_INDEX=4
|
||||
-D LOG_AP_IP_OCTET=27
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:flo]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"FLO\"
|
||||
-D NODE_LABEL=\"Flo\"
|
||||
-D NODE_SHORT=\"F\"
|
||||
-D NODE_SLOT_INDEX=5
|
||||
-D LOG_AP_IP_OCTET=28
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:guy]
|
||||
extends = storage_logger_base
|
||||
build_flags =
|
||||
${storage_logger_base.build_flags}
|
||||
-D BOARD_ID=\"GUY\"
|
||||
-D NODE_LABEL=\"Guy\"
|
||||
-D NODE_SHORT=\"G\"
|
||||
-D NODE_SLOT_INDEX=6
|
||||
-D LOG_AP_IP_OCTET=29
|
||||
-D GNSS_CHIP_NAME=\"MAX-M10S\"
|
||||
-D GPS_UBLOX
|
||||
87
tests/01_storage_logger/src/main.cpp
Normal file
87
tests/01_storage_logger/src/main.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#include <Arduino.h>
|
||||
#include <TBeamLogger.h>
|
||||
#include <TBeamStorage.h>
|
||||
|
||||
#ifndef BOARD_ID
|
||||
#define BOARD_ID "UNKNOWN"
|
||||
#endif
|
||||
|
||||
#ifndef NODE_LABEL
|
||||
#define NODE_LABEL "Unknown"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
tbeam::TBeamStorage storage(Serial);
|
||||
tbeam::TBeamLogger Log;
|
||||
|
||||
uint32_t sampleSeq = 0;
|
||||
uint32_t lastSampleMs = 0;
|
||||
|
||||
void onStorageEvent(tbeam::SdEvent event, const char* message) {
|
||||
const char* label = "unknown";
|
||||
if (event == tbeam::SdEvent::NO_CARD) label = "no_card";
|
||||
if (event == tbeam::SdEvent::CARD_MOUNTED) label = "mounted";
|
||||
if (event == tbeam::SdEvent::CARD_REMOVED) label = "removed";
|
||||
Serial.printf("[storage-event] %s: %s\r\n", label, message ? message : "");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1500);
|
||||
Serial.println();
|
||||
Serial.printf("storage_logger test boot board=%s label=%s\r\n", BOARD_ID, NODE_LABEL);
|
||||
|
||||
tbeam::StorageConfig storageConfig;
|
||||
storageConfig.logDir = "/logs/storage_logger";
|
||||
storageConfig.enablePinDumps = false;
|
||||
|
||||
const bool mounted = storage.begin(storageConfig, onStorageEvent);
|
||||
Log.begin(Serial, &storage);
|
||||
|
||||
if (mounted && Log.openUniqueLog(BOARD_ID, ".csv")) {
|
||||
Log.printf("# test: storage_logger\r\n");
|
||||
Log.printf("# board_id: %s\r\n", BOARD_ID);
|
||||
Log.printf("# node_label: %s\r\n", NODE_LABEL);
|
||||
Log.printf("# log_path: %s\r\n", Log.currentLogPath());
|
||||
Log.println("seq,millis,sd_ready,free_heap");
|
||||
Log.flush();
|
||||
Serial.printf("Log opened: %s\r\n", Log.currentLogPath());
|
||||
} else {
|
||||
Serial.printf("Log open skipped: mounted=%s error=%s\r\n",
|
||||
mounted ? "yes" : "no",
|
||||
storage.lastError());
|
||||
}
|
||||
|
||||
Serial.println("Initial SD listing:");
|
||||
storage.listFiles(Serial, "/logs", 3);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
storage.update();
|
||||
Log.update();
|
||||
|
||||
if (storage.consumeMountedEvent() && !Log.storageReady()) {
|
||||
if (Log.openUniqueLog(BOARD_ID, ".csv")) {
|
||||
Log.println("seq,millis,sd_ready,free_heap");
|
||||
Log.flush();
|
||||
Serial.printf("Log reopened: %s\r\n", Log.currentLogPath());
|
||||
}
|
||||
}
|
||||
|
||||
if (storage.consumeRemovedEvent()) {
|
||||
Serial.println("SD removed; continuing Serial-only logging");
|
||||
}
|
||||
|
||||
const uint32_t now = millis();
|
||||
if ((uint32_t)(now - lastSampleMs) >= 1000) {
|
||||
lastSampleMs = now;
|
||||
Log.printf("%lu,%lu,%s,%lu\r\n",
|
||||
(unsigned long)sampleSeq++,
|
||||
(unsigned long)now,
|
||||
storage.ready() ? "yes" : "no",
|
||||
(unsigned long)ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
92
tests/02_clock/platformio.ini
Normal file
92
tests/02_clock/platformio.ini
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
; Repository-level hardware test for tbeam_clock.
|
||||
|
||||
[platformio]
|
||||
default_envs = cy
|
||||
extra_configs = ../../shared/platformio/tbeam_supreme_units.ini
|
||||
|
||||
[clock_test_base]
|
||||
extends = tbeam_supreme_common
|
||||
lib_deps =
|
||||
${tbeam_supreme_common.lib_deps}
|
||||
build_flags =
|
||||
${tbeam_supreme_common.build_flags}
|
||||
-D CLOCK_TEST=1
|
||||
;-D CLOCK_TEST_ALLOW_SET=1
|
||||
|
||||
[env:amy]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"AMY\"
|
||||
-D NODE_LABEL=\"Amy\"
|
||||
-D NODE_SHORT=\"A\"
|
||||
-D NODE_SLOT_INDEX=0
|
||||
-D LOG_AP_IP_OCTET=23
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:bob]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"BOB\"
|
||||
-D NODE_LABEL=\"Bob\"
|
||||
-D NODE_SHORT=\"B\"
|
||||
-D NODE_SLOT_INDEX=1
|
||||
-D LOG_AP_IP_OCTET=24
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:cy]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"CY\"
|
||||
-D NODE_LABEL=\"Cy\"
|
||||
-D NODE_SHORT=\"C\"
|
||||
-D NODE_SLOT_INDEX=2
|
||||
-D LOG_AP_IP_OCTET=25
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:dan]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"DAN\"
|
||||
-D NODE_LABEL=\"Dan\"
|
||||
-D NODE_SHORT=\"D\"
|
||||
-D NODE_SLOT_INDEX=3
|
||||
-D LOG_AP_IP_OCTET=26
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:ed]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"ED\"
|
||||
-D NODE_LABEL=\"Ed\"
|
||||
-D NODE_SHORT=\"E\"
|
||||
-D NODE_SLOT_INDEX=4
|
||||
-D LOG_AP_IP_OCTET=27
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:flo]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"FLO\"
|
||||
-D NODE_LABEL=\"Flo\"
|
||||
-D NODE_SHORT=\"F\"
|
||||
-D NODE_SLOT_INDEX=5
|
||||
-D LOG_AP_IP_OCTET=28
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:guy]
|
||||
extends = clock_test_base
|
||||
build_flags =
|
||||
${clock_test_base.build_flags}
|
||||
-D BOARD_ID=\"GUY\"
|
||||
-D NODE_LABEL=\"Guy\"
|
||||
-D NODE_SHORT=\"G\"
|
||||
-D NODE_SLOT_INDEX=6
|
||||
-D LOG_AP_IP_OCTET=29
|
||||
-D GNSS_CHIP_NAME=\"MAX-M10S\"
|
||||
-D GPS_UBLOX
|
||||
201
tests/02_clock/src/main.cpp
Normal file
201
tests/02_clock/src/main.cpp
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
#include <Arduino.h>
|
||||
#include <TBeamClock.h>
|
||||
#include <TBeamLogger.h>
|
||||
#include <TBeamStorage.h>
|
||||
#include "tbeam_supreme_adapter.h"
|
||||
|
||||
#ifndef BOARD_ID
|
||||
#define BOARD_ID "UNKNOWN"
|
||||
#endif
|
||||
|
||||
#ifndef NODE_LABEL
|
||||
#define NODE_LABEL "Unknown"
|
||||
#endif
|
||||
|
||||
#ifndef CLOCK_TEST_ALLOW_SET
|
||||
#define CLOCK_TEST_ALLOW_SET 0
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
tbeam::TBeamClock clockService(Wire1);
|
||||
tbeam::TBeamStorage storage(Serial);
|
||||
tbeam::TBeamLogger Log;
|
||||
|
||||
XPowersLibInterface* pmu = nullptr;
|
||||
String commandBuffer;
|
||||
bool lastWasCr = false;
|
||||
uint32_t sampleSeq = 0;
|
||||
uint32_t lastSampleMs = 0;
|
||||
|
||||
void printDateTime(Print& out, const tbeam::DateTime& dt) {
|
||||
char iso[32];
|
||||
tbeam::TBeamClock::formatIsoUtc(dt, iso, sizeof(iso));
|
||||
out.print(iso);
|
||||
}
|
||||
|
||||
void printHelp() {
|
||||
Serial.println("Commands:");
|
||||
Serial.println(" help");
|
||||
Serial.println(" show");
|
||||
#if CLOCK_TEST_ALLOW_SET
|
||||
Serial.println(" set YYYY-MM-DD HH:MM:SS");
|
||||
#else
|
||||
Serial.println(" set disabled; build with CLOCK_TEST_ALLOW_SET=1 to enable writes");
|
||||
#endif
|
||||
}
|
||||
|
||||
void showClock() {
|
||||
clockService.update();
|
||||
Serial.printf("rtc_ready=%s valid=%s low_voltage=%s error=%s\r\n",
|
||||
clockService.ready() ? "yes" : "no",
|
||||
clockService.valid() ? "yes" : "no",
|
||||
clockService.lowVoltage() ? "yes" : "no",
|
||||
clockService.lastError());
|
||||
Serial.print("rtc_utc=");
|
||||
printDateTime(Serial, clockService.lastRtc());
|
||||
Serial.printf(" epoch=%lld\r\n", (long long)clockService.lastEpoch());
|
||||
}
|
||||
|
||||
void handleCommand(const String& raw) {
|
||||
String line = raw;
|
||||
line.trim();
|
||||
if (line.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (line == "help") {
|
||||
printHelp();
|
||||
return;
|
||||
}
|
||||
if (line == "show") {
|
||||
showClock();
|
||||
return;
|
||||
}
|
||||
if (line.startsWith("set ")) {
|
||||
#if CLOCK_TEST_ALLOW_SET
|
||||
tbeam::DateTime dt{};
|
||||
if (!tbeam::TBeamClock::parseDateTime(line.c_str() + 4, dt)) {
|
||||
Serial.println("set parse failed");
|
||||
return;
|
||||
}
|
||||
if (!clockService.writeRtc(dt)) {
|
||||
Serial.println("RTC write failed");
|
||||
return;
|
||||
}
|
||||
Serial.println("RTC write succeeded");
|
||||
showClock();
|
||||
#else
|
||||
Serial.println("RTC set disabled in this build");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("Unknown command: %s\r\n", line.c_str());
|
||||
}
|
||||
|
||||
void pollSerialCommands() {
|
||||
while (Serial.available() > 0) {
|
||||
const char c = (char)Serial.read();
|
||||
if (c == '\r' || c == '\n') {
|
||||
if ((c == '\n' && lastWasCr) || (c == '\r' && !lastWasCr && commandBuffer.length() == 0)) {
|
||||
lastWasCr = (c == '\r');
|
||||
continue;
|
||||
}
|
||||
handleCommand(commandBuffer);
|
||||
commandBuffer = "";
|
||||
lastWasCr = (c == '\r');
|
||||
} else {
|
||||
lastWasCr = false;
|
||||
commandBuffer += c;
|
||||
if (commandBuffer.length() > 120) {
|
||||
commandBuffer = "";
|
||||
Serial.println("Input line too long; buffer cleared");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void openClockLog() {
|
||||
if (!storage.ready()) {
|
||||
Serial.printf("Clock log skipped: storage error=%s\r\n", storage.lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
bool opened = false;
|
||||
if (clockService.valid()) {
|
||||
char runId[64];
|
||||
char path[112];
|
||||
tbeam::TBeamClock::makeRunId(clockService.lastRtc(), BOARD_ID, runId, sizeof(runId));
|
||||
snprintf(path, sizeof(path), "%s/%s.csv", storage.logDir(), runId);
|
||||
opened = Log.openLog(path);
|
||||
}
|
||||
if (!opened) {
|
||||
opened = Log.openUniqueLog(BOARD_ID, ".csv");
|
||||
}
|
||||
|
||||
if (!opened) {
|
||||
Serial.printf("Clock log open failed: %s\r\n", storage.lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
Log.printf("# test: clock\r\n");
|
||||
Log.printf("# board_id: %s\r\n", BOARD_ID);
|
||||
Log.printf("# node_label: %s\r\n", NODE_LABEL);
|
||||
Log.printf("# log_path: %s\r\n", Log.currentLogPath());
|
||||
Log.printf("# rtc_valid_at_boot: %s\r\n", clockService.valid() ? "yes" : "no");
|
||||
Log.println("seq,millis,rtc_ready,rtc_valid,low_voltage,epoch,iso_utc,free_heap");
|
||||
Log.flush();
|
||||
Serial.printf("Clock log opened: %s\r\n", Log.currentLogPath());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1500);
|
||||
Serial.println();
|
||||
Serial.printf("clock test boot board=%s label=%s\r\n", BOARD_ID, NODE_LABEL);
|
||||
|
||||
if (!tbeam_supreme::initPmuForPeripherals(pmu, &Serial)) {
|
||||
Serial.println("PMU init failed; RTC read may fail");
|
||||
}
|
||||
|
||||
tbeam::StorageConfig storageConfig;
|
||||
storageConfig.logDir = "/logs/clock";
|
||||
storageConfig.enablePinDumps = false;
|
||||
storage.begin(storageConfig);
|
||||
Log.begin(Serial, &storage);
|
||||
|
||||
clockService.begin();
|
||||
showClock();
|
||||
openClockLog();
|
||||
printHelp();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
pollSerialCommands();
|
||||
storage.update();
|
||||
Log.update();
|
||||
|
||||
const uint32_t now = millis();
|
||||
if ((uint32_t)(now - lastSampleMs) >= 1000) {
|
||||
lastSampleMs = now;
|
||||
clockService.update();
|
||||
|
||||
char iso[32] = "";
|
||||
if (clockService.ready()) {
|
||||
tbeam::TBeamClock::formatIsoUtc(clockService.lastRtc(), iso, sizeof(iso));
|
||||
}
|
||||
|
||||
Log.printf("%lu,%lu,%s,%s,%s,%lld,%s,%lu\r\n",
|
||||
(unsigned long)sampleSeq++,
|
||||
(unsigned long)now,
|
||||
clockService.ready() ? "yes" : "no",
|
||||
clockService.valid() ? "yes" : "no",
|
||||
clockService.lowVoltage() ? "yes" : "no",
|
||||
(long long)clockService.lastEpoch(),
|
||||
iso,
|
||||
(unsigned long)ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
92
tests/03_display/platformio.ini
Normal file
92
tests/03_display/platformio.ini
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
; Repository-level hardware test for tbeam_display.
|
||||
|
||||
[platformio]
|
||||
default_envs = cy
|
||||
extra_configs = ../../shared/platformio/tbeam_supreme_units.ini
|
||||
|
||||
[display_test_base]
|
||||
extends = tbeam_supreme_common
|
||||
lib_deps =
|
||||
${tbeam_supreme_common.lib_deps}
|
||||
olikraus/U8g2@^2.36.4
|
||||
build_flags =
|
||||
${tbeam_supreme_common.build_flags}
|
||||
-D DISPLAY_TEST=1
|
||||
|
||||
[env:amy]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"AMY\"
|
||||
-D NODE_LABEL=\"Amy\"
|
||||
-D NODE_SHORT=\"A\"
|
||||
-D NODE_SLOT_INDEX=0
|
||||
-D LOG_AP_IP_OCTET=23
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:bob]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"BOB\"
|
||||
-D NODE_LABEL=\"Bob\"
|
||||
-D NODE_SHORT=\"B\"
|
||||
-D NODE_SLOT_INDEX=1
|
||||
-D LOG_AP_IP_OCTET=24
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:cy]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"CY\"
|
||||
-D NODE_LABEL=\"Cy\"
|
||||
-D NODE_SHORT=\"C\"
|
||||
-D NODE_SLOT_INDEX=2
|
||||
-D LOG_AP_IP_OCTET=25
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:dan]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"DAN\"
|
||||
-D NODE_LABEL=\"Dan\"
|
||||
-D NODE_SHORT=\"D\"
|
||||
-D NODE_SLOT_INDEX=3
|
||||
-D LOG_AP_IP_OCTET=26
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:ed]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"ED\"
|
||||
-D NODE_LABEL=\"Ed\"
|
||||
-D NODE_SHORT=\"E\"
|
||||
-D NODE_SLOT_INDEX=4
|
||||
-D LOG_AP_IP_OCTET=27
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:flo]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"FLO\"
|
||||
-D NODE_LABEL=\"Flo\"
|
||||
-D NODE_SHORT=\"F\"
|
||||
-D NODE_SLOT_INDEX=5
|
||||
-D LOG_AP_IP_OCTET=28
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:guy]
|
||||
extends = display_test_base
|
||||
build_flags =
|
||||
${display_test_base.build_flags}
|
||||
-D BOARD_ID=\"GUY\"
|
||||
-D NODE_LABEL=\"Guy\"
|
||||
-D NODE_SHORT=\"G\"
|
||||
-D NODE_SLOT_INDEX=6
|
||||
-D LOG_AP_IP_OCTET=29
|
||||
-D GNSS_CHIP_NAME=\"MAX-M10S\"
|
||||
-D GPS_UBLOX
|
||||
154
tests/03_display/src/main.cpp
Normal file
154
tests/03_display/src/main.cpp
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#include <Arduino.h>
|
||||
#include <TBeamClock.h>
|
||||
#include <TBeamDisplay.h>
|
||||
#include <TBeamLogger.h>
|
||||
#include <TBeamStorage.h>
|
||||
|
||||
#ifndef BOARD_ID
|
||||
#define BOARD_ID "UNKNOWN"
|
||||
#endif
|
||||
|
||||
#ifndef NODE_LABEL
|
||||
#define NODE_LABEL "Unknown"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
tbeam::TBeamDisplay display;
|
||||
tbeam::TBeamClock clockService(Wire1);
|
||||
tbeam::TBeamStorage storage(Serial);
|
||||
tbeam::TBeamLogger Log;
|
||||
|
||||
uint32_t sampleSeq = 0;
|
||||
uint32_t lastSampleMs = 0;
|
||||
uint32_t lastPageMs = 0;
|
||||
uint8_t page = 0;
|
||||
|
||||
void formatRtc(char* out, size_t outSize) {
|
||||
if (!clockService.ready()) {
|
||||
strlcpy(out, "RTC read fail", outSize);
|
||||
return;
|
||||
}
|
||||
if (!clockService.valid()) {
|
||||
strlcpy(out, clockService.lowVoltage() ? "RTC low voltage" : "RTC invalid", outSize);
|
||||
return;
|
||||
}
|
||||
tbeam::TBeamClock::formatIsoUtc(clockService.lastRtc(), out, outSize);
|
||||
}
|
||||
|
||||
void openDisplayLog() {
|
||||
if (!storage.ready()) {
|
||||
Serial.printf("Display log skipped: storage error=%s\r\n", storage.lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
bool opened = false;
|
||||
if (clockService.valid()) {
|
||||
char runId[64];
|
||||
char path[112];
|
||||
tbeam::TBeamClock::makeRunId(clockService.lastRtc(), BOARD_ID, runId, sizeof(runId));
|
||||
snprintf(path, sizeof(path), "%s/%s.csv", storage.logDir(), runId);
|
||||
opened = Log.openLog(path);
|
||||
}
|
||||
if (!opened) {
|
||||
opened = Log.openUniqueLog(BOARD_ID, ".csv");
|
||||
}
|
||||
if (!opened) {
|
||||
Serial.printf("Display log open failed: %s\r\n", storage.lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
Log.printf("# test: display\r\n");
|
||||
Log.printf("# board_id: %s\r\n", BOARD_ID);
|
||||
Log.printf("# node_label: %s\r\n", NODE_LABEL);
|
||||
Log.printf("# log_path: %s\r\n", Log.currentLogPath());
|
||||
Log.println("seq,millis,page,display_ready,rtc_valid,sd_ready,free_heap");
|
||||
Log.flush();
|
||||
Serial.printf("Display log opened: %s\r\n", Log.currentLogPath());
|
||||
}
|
||||
|
||||
void drawCurrentPage() {
|
||||
char line1[32];
|
||||
char line2[32];
|
||||
char line3[32];
|
||||
char line4[32];
|
||||
char line5[32];
|
||||
char rtc[32];
|
||||
|
||||
formatRtc(rtc, sizeof(rtc));
|
||||
|
||||
if (page == 0) {
|
||||
snprintf(line1, sizeof(line1), "Display Test");
|
||||
snprintf(line2, sizeof(line2), "Board: %s", BOARD_ID);
|
||||
snprintf(line3, sizeof(line3), "Node: %s", NODE_LABEL);
|
||||
snprintf(line4, sizeof(line4), "OLED: %s", display.ready() ? "ready" : "fail");
|
||||
snprintf(line5, sizeof(line5), "Seq: %lu", (unsigned long)sampleSeq);
|
||||
display.showLines(line1, line2, line3, line4, line5);
|
||||
} else if (page == 1) {
|
||||
display.showStatus("Clock", rtc, clockService.valid() ? "OK" : "BAD", storage.ready() ? "SD mounted" : "SD missing");
|
||||
} else if (page == 2) {
|
||||
snprintf(line1, sizeof(line1), "Storage");
|
||||
snprintf(line2, sizeof(line2), "SD: %s", storage.ready() ? "mounted" : "missing");
|
||||
snprintf(line3, sizeof(line3), "Log: %s", Log.storageReady() ? "open" : "closed");
|
||||
snprintf(line4, sizeof(line4), "Heap: %lu", (unsigned long)ESP.getFreeHeap());
|
||||
snprintf(line5, sizeof(line5), "Millis: %lu", (unsigned long)millis());
|
||||
display.showLines(line1, line2, line3, line4, line5);
|
||||
} else {
|
||||
display.setFont(tbeam::DisplayFont::SMALL);
|
||||
snprintf(line1, sizeof(line1), "Services");
|
||||
snprintf(line2, sizeof(line2), "clock: %s", clockService.valid() ? "valid" : "bad");
|
||||
snprintf(line3, sizeof(line3), "storage: %s", storage.ready() ? "ready" : "bad");
|
||||
snprintf(line4, sizeof(line4), "logger: %s", Log.storageReady() ? "file" : "serial");
|
||||
snprintf(line5, sizeof(line5), "%s", rtc);
|
||||
display.showLines(line1, line2, line3, line4, line5, "page 4/4");
|
||||
display.setFont(tbeam::DisplayFont::NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1500);
|
||||
Serial.println();
|
||||
Serial.printf("display test boot board=%s label=%s\r\n", BOARD_ID, NODE_LABEL);
|
||||
|
||||
const bool displayReady = display.begin();
|
||||
Serial.printf("display_begin=%s error=%s\r\n", displayReady ? "ok" : "fail", display.lastError());
|
||||
display.showBoot("Display Test", BOARD_ID, "starting services");
|
||||
|
||||
tbeam::StorageConfig storageConfig;
|
||||
storageConfig.logDir = "/logs/display";
|
||||
storageConfig.enablePinDumps = false;
|
||||
storage.begin(storageConfig);
|
||||
Log.begin(Serial, &storage);
|
||||
|
||||
clockService.begin();
|
||||
openDisplayLog();
|
||||
drawCurrentPage();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
storage.update();
|
||||
clockService.update();
|
||||
Log.update();
|
||||
|
||||
const uint32_t now = millis();
|
||||
if ((uint32_t)(now - lastSampleMs) >= 1000) {
|
||||
lastSampleMs = now;
|
||||
Log.printf("%lu,%lu,%u,%s,%s,%s,%lu\r\n",
|
||||
(unsigned long)sampleSeq++,
|
||||
(unsigned long)now,
|
||||
(unsigned)page,
|
||||
display.ready() ? "yes" : "no",
|
||||
clockService.valid() ? "yes" : "no",
|
||||
storage.ready() ? "yes" : "no",
|
||||
(unsigned long)ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
if ((uint32_t)(now - lastPageMs) >= 2500) {
|
||||
lastPageMs = now;
|
||||
page = (uint8_t)((page + 1U) % 4U);
|
||||
drawCurrentPage();
|
||||
}
|
||||
}
|
||||
89
tests/04_web_files/platformio.ini
Normal file
89
tests/04_web_files/platformio.ini
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
; Repository-level hardware test for tbeam_web.
|
||||
|
||||
[platformio]
|
||||
default_envs = cy
|
||||
extra_configs = ../../shared/platformio/tbeam_supreme_units.ini
|
||||
|
||||
[web_files_base]
|
||||
extends = tbeam_supreme_common
|
||||
build_flags =
|
||||
${tbeam_supreme_common.build_flags}
|
||||
-D WEB_FILES_TEST=1
|
||||
|
||||
[env:amy]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"AMY\"
|
||||
-D NODE_LABEL=\"Amy\"
|
||||
-D NODE_SHORT=\"A\"
|
||||
-D NODE_SLOT_INDEX=0
|
||||
-D LOG_AP_IP_OCTET=23
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:bob]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"BOB\"
|
||||
-D NODE_LABEL=\"Bob\"
|
||||
-D NODE_SHORT=\"B\"
|
||||
-D NODE_SLOT_INDEX=1
|
||||
-D LOG_AP_IP_OCTET=24
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:cy]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"CY\"
|
||||
-D NODE_LABEL=\"Cy\"
|
||||
-D NODE_SHORT=\"C\"
|
||||
-D NODE_SLOT_INDEX=2
|
||||
-D LOG_AP_IP_OCTET=25
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:dan]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"DAN\"
|
||||
-D NODE_LABEL=\"Dan\"
|
||||
-D NODE_SHORT=\"D\"
|
||||
-D NODE_SLOT_INDEX=3
|
||||
-D LOG_AP_IP_OCTET=26
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:ed]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"ED\"
|
||||
-D NODE_LABEL=\"Ed\"
|
||||
-D NODE_SHORT=\"E\"
|
||||
-D NODE_SLOT_INDEX=4
|
||||
-D LOG_AP_IP_OCTET=27
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:flo]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"FLO\"
|
||||
-D NODE_LABEL=\"Flo\"
|
||||
-D NODE_SHORT=\"F\"
|
||||
-D NODE_SLOT_INDEX=5
|
||||
-D LOG_AP_IP_OCTET=28
|
||||
-D GNSS_CHIP_NAME=\"L76K\"
|
||||
|
||||
[env:guy]
|
||||
extends = web_files_base
|
||||
build_flags =
|
||||
${web_files_base.build_flags}
|
||||
-D BOARD_ID=\"GUY\"
|
||||
-D NODE_LABEL=\"Guy\"
|
||||
-D NODE_SHORT=\"G\"
|
||||
-D NODE_SLOT_INDEX=6
|
||||
-D LOG_AP_IP_OCTET=29
|
||||
-D GNSS_CHIP_NAME=\"MAX-M10S\"
|
||||
-D GPS_UBLOX
|
||||
132
tests/04_web_files/src/main.cpp
Normal file
132
tests/04_web_files/src/main.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#include <Arduino.h>
|
||||
#include <TBeamClock.h>
|
||||
#include <TBeamDisplay.h>
|
||||
#include <TBeamLogger.h>
|
||||
#include <TBeamStorage.h>
|
||||
#include <TBeamWeb.h>
|
||||
|
||||
#ifndef BOARD_ID
|
||||
#define BOARD_ID "UNKNOWN"
|
||||
#endif
|
||||
|
||||
#ifndef NODE_LABEL
|
||||
#define NODE_LABEL "Unknown"
|
||||
#endif
|
||||
|
||||
#ifndef LOG_AP_IP_OCTET
|
||||
#define LOG_AP_IP_OCTET 25
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
tbeam::TBeamClock clockService(Wire1);
|
||||
tbeam::TBeamDisplay display;
|
||||
tbeam::TBeamStorage storage(Serial);
|
||||
tbeam::TBeamLogger Log;
|
||||
tbeam::TBeamWeb web(Serial);
|
||||
|
||||
uint32_t sampleSeq = 0;
|
||||
uint32_t lastSampleMs = 0;
|
||||
uint32_t lastDisplayMs = 0;
|
||||
|
||||
void openWebLog() {
|
||||
if (!storage.ready()) {
|
||||
Serial.printf("Web log skipped: storage error=%s\r\n", storage.lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
bool opened = false;
|
||||
if (clockService.valid()) {
|
||||
char runId[64];
|
||||
char path[112];
|
||||
tbeam::TBeamClock::makeRunId(clockService.lastRtc(), BOARD_ID, runId, sizeof(runId));
|
||||
snprintf(path, sizeof(path), "%s/%s.csv", storage.logDir(), runId);
|
||||
opened = Log.openLog(path);
|
||||
}
|
||||
if (!opened) {
|
||||
opened = Log.openUniqueLog(BOARD_ID, ".csv");
|
||||
}
|
||||
if (!opened) {
|
||||
Serial.printf("Web log open failed: %s\r\n", storage.lastError());
|
||||
return;
|
||||
}
|
||||
|
||||
Log.printf("# test: web_files\r\n");
|
||||
Log.printf("# board_id: %s\r\n", BOARD_ID);
|
||||
Log.printf("# node_label: %s\r\n", NODE_LABEL);
|
||||
Log.printf("# log_path: %s\r\n", Log.currentLogPath());
|
||||
Log.println("seq,millis,web_ready,stations,sd_ready,rtc_valid,free_heap");
|
||||
Log.flush();
|
||||
Serial.printf("Web log opened: %s\r\n", Log.currentLogPath());
|
||||
}
|
||||
|
||||
void drawStatus() {
|
||||
char ipLine[32];
|
||||
char webLine[32];
|
||||
char sdLine[32];
|
||||
char logLine[32];
|
||||
|
||||
snprintf(ipLine, sizeof(ipLine), "%s", web.ip().toString().c_str());
|
||||
snprintf(webLine, sizeof(webLine), "AP: %s", web.ssid());
|
||||
snprintf(sdLine, sizeof(sdLine), "SD:%s STA:%u", storage.ready() ? "ok" : "bad", (unsigned)web.stationCount());
|
||||
snprintf(logLine, sizeof(logLine), "Log:%s", Log.storageReady() ? "open" : "serial");
|
||||
|
||||
display.showLines("Web Files", webLine, ipLine, sdLine, logLine, BOARD_ID);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1500);
|
||||
Serial.println();
|
||||
Serial.printf("web files test boot board=%s label=%s\r\n", BOARD_ID, NODE_LABEL);
|
||||
|
||||
display.begin();
|
||||
display.showBoot("Web Files", BOARD_ID, "starting services");
|
||||
|
||||
tbeam::StorageConfig storageConfig;
|
||||
storageConfig.logDir = "/logs/web";
|
||||
storageConfig.enablePinDumps = false;
|
||||
storage.begin(storageConfig);
|
||||
Log.begin(Serial, &storage);
|
||||
|
||||
clockService.begin();
|
||||
openWebLog();
|
||||
|
||||
tbeam::WebConfig webConfig;
|
||||
webConfig.ssidPrefix = "GPSQA";
|
||||
webConfig.boardId = BOARD_ID;
|
||||
webConfig.ipOctet = LOG_AP_IP_OCTET;
|
||||
webConfig.enableDelete = true;
|
||||
web.begin(storage, webConfig);
|
||||
|
||||
Serial.printf("Web UI: http://%s/\r\n", web.ip().toString().c_str());
|
||||
Serial.printf("SSID: %s\r\n", web.ssid());
|
||||
drawStatus();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
storage.update();
|
||||
clockService.update();
|
||||
web.update();
|
||||
Log.update();
|
||||
|
||||
const uint32_t now = millis();
|
||||
if ((uint32_t)(now - lastSampleMs) >= 1000) {
|
||||
lastSampleMs = now;
|
||||
Log.printf("%lu,%lu,%s,%u,%s,%s,%lu\r\n",
|
||||
(unsigned long)sampleSeq++,
|
||||
(unsigned long)now,
|
||||
web.ready() ? "yes" : "no",
|
||||
(unsigned)web.stationCount(),
|
||||
storage.ready() ? "yes" : "no",
|
||||
clockService.valid() ? "yes" : "no",
|
||||
(unsigned long)ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
if ((uint32_t)(now - lastDisplayMs) >= 2500) {
|
||||
lastDisplayMs = now;
|
||||
drawStatus();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue