// firmware/fieldtest_beacon/src/main.cpp // 20260212 ChatGPT // $Id$ // $HeadURL$ #include #include #include #include "Boards.h" // Include microReticulum headers from your external tree #include "Identity.h" #include "Reticulum.h" #include "Destination.h" #include "Transport.h" // ---------- User-tunable ---------- static const uint32_t BEACON_INTERVAL_MS = 15000; static const char* PATH_IDENTITY_BIN = "/provisioning/identity.bin"; static const char* PATH_LABEL_TXT = "/provisioning/label.txt"; static const char* LOG_PATH = "/logs/fieldtest.log"; // ---------- Globals ---------- static uint32_t g_iter = 0; static uint32_t g_next_tx = 0; static File g_log; // Source board pin mapping from microReticulum_Firmware board definitions. static const int SD_CS_PIN = SD_CS; // Simple line logger (append-only) static void log_line(const String& line) { if (!g_log) return; g_log.println(line); g_log.flush(); } // Read whole file into a buffer static bool read_file(const char* path, std::vector& out) { File f = SD.open(path, FILE_READ); if (!f) return false; size_t n = f.size(); out.resize(n); if (n > 0) f.read(out.data(), n); f.close(); return true; } static String read_text_file(const char* path) { File f = SD.open(path, FILE_READ); if (!f) return String(""); String s = f.readString(); f.close(); s.trim(); return s; } void setup() { Serial.begin(115200); delay(250); // ---- SD init ---- if (!SD.begin(SD_CS_PIN)) { Serial.println("SD init failed"); return; } g_log = SD.open(LOG_PATH, FILE_APPEND); if (!g_log) { Serial.println("Failed to open log file"); return; } const String label = read_text_file(PATH_LABEL_TXT); log_line("BOOT\tlabel=" + label); std::vector id_bytes; if (!read_file(PATH_IDENTITY_BIN, id_bytes)) { log_line(String("ERROR\tmissing_identity\tpath=") + PATH_IDENTITY_BIN); return; } log_line(String("IDENTITY_OK\tbytes=") + id_bytes.size()); // ---- Load Identity into microReticulum ---- // TODO: adjust to the actual API in your microReticulum version // Example intent: // Identity ident = Identity::fromBytes(id_bytes.data(), id_bytes.size()); // Reticulum rns; // rns.setIdentity(ident); // rns.begin(...); // // Also: initialize your LoRa Interface and attach it to Reticulum here. log_line("RNS_INIT_OK"); g_next_tx = millis() + 3000; // wait a moment before first TX } void loop() { // TODO: run microReticulum polling / tick function, and radio interface polling const uint32_t now = millis(); if ((int32_t)(now - g_next_tx) >= 0) { g_next_tx = now + BEACON_INTERVAL_MS; // Build payload: timestamp + iterator (GPS later) const uint32_t epoch_guess = (uint32_t) (time(nullptr)); // placeholder; GPS later const String payload = String("t=") + epoch_guess + " i=" + g_iter++; // TODO: send to peer(s) (Destination derived from peers list) // bool ok = destination.send(payload_bytes, len); log_line(String("TX\t") + payload); } delay(5); }