Adding firmware which was tested using microReticulum as a sub modules only, **not** microReticulum_Firmware. Preserving the fieldtest_beacon for posterity even though it will be modified to utilize microReticulm_Firmware going forward."

This commit is contained in:
John Poole 2026-02-14 09:25:22 -08:00
commit 1be5b59c7a
2 changed files with 138 additions and 0 deletions

View file

@ -0,0 +1,116 @@
// firmware/fieldtest_beacon/src/main.cpp
// 20260212 ChatGPT
// $Id$
// $HeadURL$
#include <Arduino.h>
#include <SPI.h>
#include <SD.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;
// TODO: replace with your boards SD CS pin if not default
static const int SD_CS_PIN = 10;
// 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<uint8_t>& 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<uint8_t> 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);
}