Merge pull request #831 from Meshcore-Portugal/jbrazio/2025_87fe0ad8

Add bridge management CLI
This commit is contained in:
fdlamotte 2025-10-06 14:23:35 +02:00 committed by GitHub
commit 5f31979e1e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 508 additions and 248 deletions

View file

@ -331,6 +331,12 @@ void MyMesh::logRxRaw(float snr, float rssi, const uint8_t raw[], int len) {
} }
void MyMesh::logRx(mesh::Packet *pkt, int len, float score) { void MyMesh::logRx(mesh::Packet *pkt, int len, float score) {
#ifdef WITH_BRIDGE
if (_prefs.bridge_pkt_src == 1) {
bridge.sendPacket(pkt);
}
#endif
if (_logging) { if (_logging) {
File f = openAppend(PACKET_LOG_FILE); File f = openAppend(PACKET_LOG_FILE);
if (f) { if (f) {
@ -352,8 +358,11 @@ void MyMesh::logRx(mesh::Packet *pkt, int len, float score) {
void MyMesh::logTx(mesh::Packet *pkt, int len) { void MyMesh::logTx(mesh::Packet *pkt, int len) {
#ifdef WITH_BRIDGE #ifdef WITH_BRIDGE
bridge.onPacketTransmitted(pkt); if (_prefs.bridge_pkt_src == 0) {
bridge.sendPacket(pkt);
}
#endif #endif
if (_logging) { if (_logging) {
File f = openAppend(PACKET_LOG_FILE); File f = openAppend(PACKET_LOG_FILE);
if (f) { if (f) {
@ -582,9 +591,10 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
: mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables), : mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables),
_cli(board, rtc, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4) _cli(board, rtc, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4)
#if defined(WITH_RS232_BRIDGE) #if defined(WITH_RS232_BRIDGE)
, bridge(WITH_RS232_BRIDGE, _mgr, &rtc) , bridge(&_prefs, WITH_RS232_BRIDGE, _mgr, &rtc)
#elif defined(WITH_ESPNOW_BRIDGE) #endif
, bridge(_mgr, &rtc) #if defined(WITH_ESPNOW_BRIDGE)
, bridge(&_prefs, _mgr, &rtc)
#endif #endif
{ {
next_local_advert = next_flood_advert = 0; next_local_advert = next_flood_advert = 0;
@ -614,6 +624,14 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
_prefs.flood_advert_interval = 12; // 12 hours _prefs.flood_advert_interval = 12; // 12 hours
_prefs.flood_max = 64; _prefs.flood_max = 64;
_prefs.interference_threshold = 0; // disabled _prefs.interference_threshold = 0; // disabled
// bridge defaults
_prefs.bridge_enabled = 1; // enabled
_prefs.bridge_delay = 500; // milliseconds
_prefs.bridge_pkt_src = 0; // logTx
_prefs.bridge_baud = 115200; // baud rate
_prefs.bridge_channel = 1; // channel 1
StrHelper::strncpy(_prefs.bridge_secret, "LVSITANOS", sizeof(_prefs.bridge_secret));
} }
void MyMesh::begin(FILESYSTEM *fs) { void MyMesh::begin(FILESYSTEM *fs) {
@ -624,8 +642,10 @@ void MyMesh::begin(FILESYSTEM *fs) {
acl.load(_fs); acl.load(_fs);
#ifdef WITH_BRIDGE #if defined(WITH_BRIDGE)
bridge.begin(); if (_prefs.bridge_enabled) {
bridge.begin();
}
#endif #endif
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr); radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);

View file

@ -2,7 +2,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <Mesh.h> #include <Mesh.h>
#include <helpers/CommonCLI.h> #include <RTClib.h>
#include <target.h>
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
#include <InternalFileSystem.h> #include <InternalFileSystem.h>
@ -12,16 +13,6 @@
#include <SPIFFS.h> #include <SPIFFS.h>
#endif #endif
#include <helpers/ArduinoHelpers.h>
#include <helpers/StaticPoolPacketManager.h>
#include <helpers/SimpleMeshTables.h>
#include <helpers/IdentityStore.h>
#include <helpers/AdvertDataHelpers.h>
#include <helpers/TxtDataHelpers.h>
#include <helpers/ClientACL.h>
#include <RTClib.h>
#include <target.h>
#ifdef WITH_RS232_BRIDGE #ifdef WITH_RS232_BRIDGE
#include "helpers/bridges/RS232Bridge.h" #include "helpers/bridges/RS232Bridge.h"
#define WITH_BRIDGE #define WITH_BRIDGE
@ -32,6 +23,15 @@
#define WITH_BRIDGE #define WITH_BRIDGE
#endif #endif
#include <helpers/AdvertDataHelpers.h>
#include <helpers/ArduinoHelpers.h>
#include <helpers/ClientACL.h>
#include <helpers/CommonCLI.h>
#include <helpers/IdentityStore.h>
#include <helpers/SimpleMeshTables.h>
#include <helpers/StaticPoolPacketManager.h>
#include <helpers/TxtDataHelpers.h>
#ifdef WITH_BRIDGE #ifdef WITH_BRIDGE
extern AbstractBridge* bridge; extern AbstractBridge* bridge;
#endif #endif
@ -182,4 +182,24 @@ public:
void clearStats() override; void clearStats() override;
void handleCommand(uint32_t sender_timestamp, char* command, char* reply); void handleCommand(uint32_t sender_timestamp, char* command, char* reply);
void loop(); void loop();
#if defined(WITH_BRIDGE)
void setBridgeState(bool enable) override {
if (enable == bridge.isRunning()) return;
if (enable)
{
bridge.begin();
}
else
{
bridge.end();
}
}
void restartBridge() override {
if (!bridge.isRunning()) return;
bridge.end();
bridge.begin();
}
#endif
}; };

View file

@ -28,6 +28,12 @@
#define MESH_DEBUG_PRINTLN(...) {} #define MESH_DEBUG_PRINTLN(...) {}
#endif #endif
#if BRIDGE_DEBUG && ARDUINO
#define BRIDGE_DEBUG_PRINTLN(F, ...) Serial.printf("%s BRIDGE: " F, getLogDateTime(), ##__VA_ARGS__)
#else
#define BRIDGE_DEBUG_PRINTLN(...) {}
#endif
namespace mesh { namespace mesh {
#define BD_STARTUP_NORMAL 0 // getStartupReason() codes #define BD_STARTUP_NORMAL 0 // getStartupReason() codes

View file

@ -11,6 +11,18 @@ public:
*/ */
virtual void begin() = 0; virtual void begin() = 0;
/**
* @brief Stops the bridge.
*/
virtual void end() = 0;
/**
* @brief Gets the current state of the bridge.
*
* @return true if the bridge is initialized and running, false otherwise.
*/
virtual bool isRunning() const = 0;
/** /**
* @brief A method to be called on every main loop iteration. * @brief A method to be called on every main loop iteration.
* Used for tasks like checking for incoming data. * Used for tasks like checking for incoming data.
@ -20,14 +32,14 @@ public:
/** /**
* @brief A callback that is triggered when the mesh transmits a packet. * @brief A callback that is triggered when the mesh transmits a packet.
* The bridge can use this to forward the packet. * The bridge can use this to forward the packet.
* *
* @param packet The packet that was transmitted. * @param packet The packet that was transmitted.
*/ */
virtual void onPacketTransmitted(mesh::Packet* packet) = 0; virtual void sendPacket(mesh::Packet* packet) = 0;
/** /**
* @brief Processes a received packet from the bridge's medium. * @brief Processes a received packet from the bridge's medium.
* *
* @param packet The packet that was received. * @param packet The packet that was received.
*/ */
virtual void onPacketReceived(mesh::Packet* packet) = 0; virtual void onPacketReceived(mesh::Packet* packet) = 0;

View file

@ -32,32 +32,38 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
if (file) { if (file) {
uint8_t pad[8]; uint8_t pad[8];
file.read((uint8_t *) &_prefs->airtime_factor, sizeof(_prefs->airtime_factor)); // 0 file.read((uint8_t *)&_prefs->airtime_factor, sizeof(_prefs->airtime_factor)); // 0
file.read((uint8_t *) &_prefs->node_name, sizeof(_prefs->node_name)); // 4 file.read((uint8_t *)&_prefs->node_name, sizeof(_prefs->node_name)); // 4
file.read(pad, 4); // 36 file.read(pad, 4); // 36
file.read((uint8_t *) &_prefs->node_lat, sizeof(_prefs->node_lat)); // 40 file.read((uint8_t *)&_prefs->node_lat, sizeof(_prefs->node_lat)); // 40
file.read((uint8_t *) &_prefs->node_lon, sizeof(_prefs->node_lon)); // 48 file.read((uint8_t *)&_prefs->node_lon, sizeof(_prefs->node_lon)); // 48
file.read((uint8_t *) &_prefs->password[0], sizeof(_prefs->password)); // 56 file.read((uint8_t *)&_prefs->password[0], sizeof(_prefs->password)); // 56
file.read((uint8_t *) &_prefs->freq, sizeof(_prefs->freq)); // 72 file.read((uint8_t *)&_prefs->freq, sizeof(_prefs->freq)); // 72
file.read((uint8_t *) &_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76 file.read((uint8_t *)&_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76
file.read((uint8_t *) &_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77 file.read((uint8_t *)&_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77
file.read((uint8_t *) &_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78 file.read((uint8_t *)&_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78
file.read((uint8_t *) pad, 1); // 79 was 'unused' file.read((uint8_t *)pad, 1); // 79 was 'unused'
file.read((uint8_t *) &_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80 file.read((uint8_t *)&_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80
file.read((uint8_t *) &_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84 file.read((uint8_t *)&_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84
file.read((uint8_t *) &_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88 file.read((uint8_t *)&_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88
file.read((uint8_t *) &_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104 file.read((uint8_t *)&_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104
file.read(pad, 4); // 108 file.read(pad, 4); // 108
file.read((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112 file.read((uint8_t *)&_prefs->sf, sizeof(_prefs->sf)); // 112
file.read((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113 file.read((uint8_t *)&_prefs->cr, sizeof(_prefs->cr)); // 113
file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114 file.read((uint8_t *)&_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
file.read((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115 file.read((uint8_t *)&_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115
file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 file.read((uint8_t *)&_prefs->bw, sizeof(_prefs->bw)); // 116
file.read((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120 file.read((uint8_t *)&_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
file.read(pad, 3); // 121 file.read(pad, 3); // 121
file.read((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124 file.read((uint8_t *)&_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
file.read((uint8_t *) &_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125 file.read((uint8_t *)&_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
file.read((uint8_t *) &_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126 file.read((uint8_t *)&_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126
file.read((uint8_t *)&_prefs->bridge_enabled, sizeof(_prefs->bridge_enabled)); // 127
file.read((uint8_t *)&_prefs->bridge_delay, sizeof(_prefs->bridge_delay)); // 128
file.read((uint8_t *)&_prefs->bridge_pkt_src, sizeof(_prefs->bridge_pkt_src)); // 130
file.read((uint8_t *)&_prefs->bridge_baud, sizeof(_prefs->bridge_baud)); // 131
file.read((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 132
file.read((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret)); // 133
// sanitise bad pref values // sanitise bad pref values
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
@ -71,6 +77,13 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
_prefs->tx_power_dbm = constrain(_prefs->tx_power_dbm, 1, 30); _prefs->tx_power_dbm = constrain(_prefs->tx_power_dbm, 1, 30);
_prefs->multi_acks = constrain(_prefs->multi_acks, 0, 1); _prefs->multi_acks = constrain(_prefs->multi_acks, 0, 1);
// sanitise bad bridge pref values
_prefs->bridge_enabled = constrain(_prefs->bridge_enabled, 0, 1);
_prefs->bridge_delay = constrain(_prefs->bridge_delay, 0, 10000);
_prefs->bridge_pkt_src = constrain(_prefs->bridge_pkt_src, 0, 1);
_prefs->bridge_baud = constrain(_prefs->bridge_baud, 9600, 115200);
_prefs->bridge_channel = constrain(_prefs->bridge_channel, 0, 14);
file.close(); file.close();
} }
} }
@ -88,32 +101,38 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
uint8_t pad[8]; uint8_t pad[8];
memset(pad, 0, sizeof(pad)); memset(pad, 0, sizeof(pad));
file.write((uint8_t *) &_prefs->airtime_factor, sizeof(_prefs->airtime_factor)); // 0 file.write((uint8_t *)&_prefs->airtime_factor, sizeof(_prefs->airtime_factor)); // 0
file.write((uint8_t *) &_prefs->node_name, sizeof(_prefs->node_name)); // 4 file.write((uint8_t *)&_prefs->node_name, sizeof(_prefs->node_name)); // 4
file.write(pad, 4); // 36 file.write(pad, 4); // 36
file.write((uint8_t *) &_prefs->node_lat, sizeof(_prefs->node_lat)); // 40 file.write((uint8_t *)&_prefs->node_lat, sizeof(_prefs->node_lat)); // 40
file.write((uint8_t *) &_prefs->node_lon, sizeof(_prefs->node_lon)); // 48 file.write((uint8_t *)&_prefs->node_lon, sizeof(_prefs->node_lon)); // 48
file.write((uint8_t *) &_prefs->password[0], sizeof(_prefs->password)); // 56 file.write((uint8_t *)&_prefs->password[0], sizeof(_prefs->password)); // 56
file.write((uint8_t *) &_prefs->freq, sizeof(_prefs->freq)); // 72 file.write((uint8_t *)&_prefs->freq, sizeof(_prefs->freq)); // 72
file.write((uint8_t *) &_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76 file.write((uint8_t *)&_prefs->tx_power_dbm, sizeof(_prefs->tx_power_dbm)); // 76
file.write((uint8_t *) &_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77 file.write((uint8_t *)&_prefs->disable_fwd, sizeof(_prefs->disable_fwd)); // 77
file.write((uint8_t *) &_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78 file.write((uint8_t *)&_prefs->advert_interval, sizeof(_prefs->advert_interval)); // 78
file.write((uint8_t *) pad, 1); // 79 was 'unused' file.write((uint8_t *)pad, 1); // 79 was 'unused'
file.write((uint8_t *) &_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80 file.write((uint8_t *)&_prefs->rx_delay_base, sizeof(_prefs->rx_delay_base)); // 80
file.write((uint8_t *) &_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84 file.write((uint8_t *)&_prefs->tx_delay_factor, sizeof(_prefs->tx_delay_factor)); // 84
file.write((uint8_t *) &_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88 file.write((uint8_t *)&_prefs->guest_password[0], sizeof(_prefs->guest_password)); // 88
file.write((uint8_t *) &_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104 file.write((uint8_t *)&_prefs->direct_tx_delay_factor, sizeof(_prefs->direct_tx_delay_factor)); // 104
file.write(pad, 4); // 108 file.write(pad, 4); // 108
file.write((uint8_t *) &_prefs->sf, sizeof(_prefs->sf)); // 112 file.write((uint8_t *)&_prefs->sf, sizeof(_prefs->sf)); // 112
file.write((uint8_t *) &_prefs->cr, sizeof(_prefs->cr)); // 113 file.write((uint8_t *)&_prefs->cr, sizeof(_prefs->cr)); // 113
file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114 file.write((uint8_t *)&_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114
file.write((uint8_t *) &_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115 file.write((uint8_t *)&_prefs->multi_acks, sizeof(_prefs->multi_acks)); // 115
file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 file.write((uint8_t *)&_prefs->bw, sizeof(_prefs->bw)); // 116
file.write((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120 file.write((uint8_t *)&_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
file.write(pad, 3); // 121 file.write(pad, 3); // 121
file.write((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124 file.write((uint8_t *)&_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
file.write((uint8_t *) &_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125 file.write((uint8_t *)&_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
file.write((uint8_t *) &_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126 file.write((uint8_t *)&_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126
file.write((uint8_t *)&_prefs->bridge_enabled, sizeof(_prefs->bridge_enabled)); // 127
file.write((uint8_t *)&_prefs->bridge_delay, sizeof(_prefs->bridge_delay)); // 128
file.write((uint8_t *)&_prefs->bridge_pkt_src, sizeof(_prefs->bridge_pkt_src)); // 130
file.write((uint8_t *)&_prefs->bridge_baud, sizeof(_prefs->bridge_baud)); // 131
file.write((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 132
file.write((uint8_t *)&_prefs->bridge_secret, sizeof(_prefs->bridge_secret)); // 133
file.close(); file.close();
} }
@ -199,6 +218,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
} else if (memcmp(command, "clear stats", 11) == 0) { } else if (memcmp(command, "clear stats", 11) == 0) {
_callbacks->clearStats(); _callbacks->clearStats();
strcpy(reply, "(OK - stats reset)"); strcpy(reply, "(OK - stats reset)");
/*
* GET commands
*/
} else if (memcmp(command, "get ", 4) == 0) { } else if (memcmp(command, "get ", 4) == 0) {
const char* config = &command[4]; const char* config = &command[4];
if (memcmp(config, "af", 2) == 0) { if (memcmp(config, "af", 2) == 0) {
@ -252,9 +274,40 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
mesh::Utils::toHex(&reply[2], _callbacks->getSelfId().pub_key, PUB_KEY_SIZE); mesh::Utils::toHex(&reply[2], _callbacks->getSelfId().pub_key, PUB_KEY_SIZE);
} else if (memcmp(config, "role", 4) == 0) { } else if (memcmp(config, "role", 4) == 0) {
sprintf(reply, "> %s", _callbacks->getRole()); sprintf(reply, "> %s", _callbacks->getRole());
} else if (memcmp(config, "bridge.type", 11) == 0) {
sprintf(reply, "> %s",
#ifdef WITH_RS232_BRIDGE
"rs232"
#elif WITH_ESPNOW_BRIDGE
"espnow"
#else
"none"
#endif
);
#ifdef WITH_BRIDGE
} else if (memcmp(config, "bridge.enabled", 14) == 0) {
sprintf(reply, "> %s", _prefs->bridge_enabled ? "on" : "off");
} else if (memcmp(config, "bridge.delay", 12) == 0) {
sprintf(reply, "> %d", (uint32_t)_prefs->bridge_delay);
} else if (memcmp(config, "bridge.source", 13) == 0) {
sprintf(reply, "> %s", _prefs->bridge_pkt_src ? "logRx" : "logTx");
#endif
#ifdef WITH_RS232_BRIDGE
} else if (memcmp(config, "bridge.baud", 11) == 0) {
sprintf(reply, "> %d", (uint32_t)_prefs->bridge_baud);
#endif
#ifdef WITH_ESPNOW_BRIDGE
} else if (memcmp(config, "bridge.channel", 14) == 0) {
sprintf(reply, "> %d", (uint32_t)_prefs->bridge_channel);
} else if (memcmp(config, "bridge.secret", 13) == 0) {
sprintf(reply, "> %s", _prefs->bridge_secret);
#endif
} else { } else {
sprintf(reply, "??: %s", config); sprintf(reply, "??: %s", config);
} }
/*
* SET commands
*/
} else if (memcmp(command, "set ", 4) == 0) { } else if (memcmp(command, "set ", 4) == 0) {
const char* config = &command[4]; const char* config = &command[4];
if (memcmp(config, "af ", 3) == 0) { if (memcmp(config, "af ", 3) == 0) {
@ -301,7 +354,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
StrHelper::strncpy(_prefs->guest_password, &config[15], sizeof(_prefs->guest_password)); StrHelper::strncpy(_prefs->guest_password, &config[15], sizeof(_prefs->guest_password));
savePrefs(); savePrefs();
strcpy(reply, "OK"); strcpy(reply, "OK");
} else if (sender_timestamp == 0 && memcmp(config, "prv.key ", 8) == 0) { // from serial command line only } else if (sender_timestamp == 0 &&
memcmp(config, "prv.key ", 8) == 0) { // from serial command line only
uint8_t prv_key[PRV_KEY_SIZE]; uint8_t prv_key[PRV_KEY_SIZE];
bool success = mesh::Utils::fromHex(prv_key, PRV_KEY_SIZE, &config[8]); bool success = mesh::Utils::fromHex(prv_key, PRV_KEY_SIZE, &config[8]);
if (success) { if (success) {
@ -391,6 +445,55 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
_prefs->freq = atof(&config[5]); _prefs->freq = atof(&config[5]);
savePrefs(); savePrefs();
strcpy(reply, "OK - reboot to apply"); strcpy(reply, "OK - reboot to apply");
#ifdef WITH_BRIDGE
} else if (memcmp(config, "bridge.enabled ", 15) == 0) {
_prefs->bridge_enabled = memcmp(&config[15], "on", 2) == 0;
_callbacks->setBridgeState(_prefs->bridge_enabled);
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "bridge.delay ", 13) == 0) {
int delay = _atoi(&config[13]);
if (delay >= 0 && delay <= 10000) {
_prefs->bridge_delay = (uint16_t)delay;
savePrefs();
strcpy(reply, "OK");
} else {
strcpy(reply, "Error: delay must be between 0-10000 ms");
}
} else if (memcmp(config, "bridge.source ", 14) == 0) {
_prefs->bridge_pkt_src = memcmp(&config[14], "rx", 2) == 0;
savePrefs();
strcpy(reply, "OK");
#endif
#ifdef WITH_RS232_BRIDGE
} else if (memcmp(config, "bridge.baud ", 12) == 0) {
uint32_t baud = atoi(&config[12]);
if (baud >= 9600 && baud <= 115200) {
_prefs->bridge_baud = (uint32_t)baud;
_callbacks->restartBridge();
savePrefs();
strcpy(reply, "OK");
} else {
strcpy(reply, "Error: baud rate must be between 9600-115200");
}
#endif
#ifdef WITH_ESPNOW_BRIDGE
} else if (memcmp(config, "bridge.channel ", 15) == 0) {
int ch = atoi(&config[15]);
if (ch > 0 && ch < 15) {
_prefs->bridge_channel = (uint8_t)ch;
_callbacks->restartBridge();
savePrefs();
strcpy(reply, "OK");
} else {
strcpy(reply, "Error: channel must be between 1-14");
}
} else if (memcmp(config, "bridge.secret ", 14) == 0) {
StrHelper::strncpy(_prefs->bridge_secret, &config[14], sizeof(_prefs->bridge_secret));
_callbacks->restartBridge();
savePrefs();
strcpy(reply, "OK");
#endif
} else { } else {
sprintf(reply, "unknown config: %s", config); sprintf(reply, "unknown config: %s", config);
} }

View file

@ -3,29 +3,40 @@
#include "Mesh.h" #include "Mesh.h"
#include <helpers/IdentityStore.h> #include <helpers/IdentityStore.h>
struct NodePrefs { // persisted to file #if defined(WITH_RS232_BRIDGE) || defined(WITH_ESPNOW_BRIDGE)
float airtime_factor; #define WITH_BRIDGE
char node_name[32]; #endif
double node_lat, node_lon;
char password[16]; struct NodePrefs { // persisted to file
float freq; float airtime_factor;
uint8_t tx_power_dbm; char node_name[32];
uint8_t disable_fwd; double node_lat, node_lon;
uint8_t advert_interval; // minutes / 2 char password[16];
uint8_t flood_advert_interval; // hours float freq;
float rx_delay_base; uint8_t tx_power_dbm;
float tx_delay_factor; uint8_t disable_fwd;
char guest_password[16]; uint8_t advert_interval; // minutes / 2
float direct_tx_delay_factor; uint8_t flood_advert_interval; // hours
uint32_t guard; float rx_delay_base;
uint8_t sf; float tx_delay_factor;
uint8_t cr; char guest_password[16];
uint8_t allow_read_only; float direct_tx_delay_factor;
uint8_t multi_acks; uint32_t guard;
float bw; uint8_t sf;
uint8_t flood_max; uint8_t cr;
uint8_t interference_threshold; uint8_t allow_read_only;
uint8_t agc_reset_interval; // secs / 4 uint8_t multi_acks;
float bw;
uint8_t flood_max;
uint8_t interference_threshold;
uint8_t agc_reset_interval; // secs / 4
// Bridge settings
uint8_t bridge_enabled; // boolean
uint16_t bridge_delay; // milliseconds (default 500 ms)
uint8_t bridge_pkt_src; // 0 = logTx, 1 = logRx (default logTx)
uint32_t bridge_baud; // 9600, 19200, 38400, 57600, 115200 (default 115200)
uint8_t bridge_channel; // 1-14 (ESP-NOW only)
char bridge_secret[16]; // for XOR encryption of bridge packets (ESP-NOW only)
}; };
class CommonCLICallbacks { class CommonCLICallbacks {
@ -50,6 +61,14 @@ public:
virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0; virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0;
virtual void clearStats() = 0; virtual void clearStats() = 0;
virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0; virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0;
virtual void setBridgeState(bool enable) {
// no op by default
};
virtual void restartBridge() {
// no op by default
};
}; };
class CommonCLI { class CommonCLI {

View file

@ -2,6 +2,10 @@
#include <Arduino.h> #include <Arduino.h>
bool BridgeBase::isRunning() const {
return _initialized;
}
const char *BridgeBase::getLogDateTime() { const char *BridgeBase::getLogDateTime() {
static char tmp[32]; static char tmp[32];
uint32_t now = _rtc->getCurrentTime(); uint32_t now = _rtc->getCurrentTime();
@ -28,8 +32,16 @@ bool BridgeBase::validateChecksum(const uint8_t *data, size_t len, uint16_t rece
} }
void BridgeBase::handleReceivedPacket(mesh::Packet *packet) { void BridgeBase::handleReceivedPacket(mesh::Packet *packet) {
// Guard against uninitialized state
if (_initialized == false) {
BRIDGE_DEBUG_PRINTLN("RX packet received before initialization\n");
_mgr->free(packet);
return;
}
if (!_seen_packets.hasSeen(packet)) { if (!_seen_packets.hasSeen(packet)) {
_mgr->queueInbound(packet, millis() + BRIDGE_DELAY); // bridge_delay provides a buffer to prevent immediate processing conflicts in the mesh network.
_mgr->queueInbound(packet, millis() + _prefs->bridge_delay);
} else { } else {
_mgr->free(packet); _mgr->free(packet);
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "helpers/AbstractBridge.h" #include "helpers/AbstractBridge.h"
#include "helpers/CommonCLI.h"
#include "helpers/SimpleMeshTables.h" #include "helpers/SimpleMeshTables.h"
#include <RTClib.h> #include <RTClib.h>
@ -21,6 +22,13 @@ class BridgeBase : public AbstractBridge {
public: public:
virtual ~BridgeBase() = default; virtual ~BridgeBase() = default;
/**
* @brief Gets the current state of the bridge.
*
* @return true if the bridge is initialized and running, false otherwise.
*/
bool isRunning() const override;
/** /**
* @brief Common magic number used by all bridge implementations for packet identification * @brief Common magic number used by all bridge implementations for packet identification
* *
@ -41,31 +49,31 @@ public:
static constexpr uint16_t BRIDGE_LENGTH_SIZE = sizeof(uint16_t); static constexpr uint16_t BRIDGE_LENGTH_SIZE = sizeof(uint16_t);
static constexpr uint16_t BRIDGE_CHECKSUM_SIZE = sizeof(uint16_t); static constexpr uint16_t BRIDGE_CHECKSUM_SIZE = sizeof(uint16_t);
/**
* @brief Default delay in milliseconds for scheduling inbound packet processing
*
* It provides a buffer to prevent immediate processing conflicts in the mesh network.
* Used in handleReceivedPacket() as: millis() + BRIDGE_DELAY
*/
static constexpr uint16_t BRIDGE_DELAY = 500; // TODO: maybe too high ?
protected: protected:
/** Tracks bridge state */
bool _initialized = false;
/** Packet manager for allocating and queuing mesh packets */ /** Packet manager for allocating and queuing mesh packets */
mesh::PacketManager *_mgr; mesh::PacketManager *_mgr;
/** RTC clock for timestamping debug messages */ /** RTC clock for timestamping debug messages */
mesh::RTCClock *_rtc; mesh::RTCClock *_rtc;
/** Node preferences for configuration settings */
NodePrefs *_prefs;
/** Tracks seen packets to prevent loops in broadcast communications */ /** Tracks seen packets to prevent loops in broadcast communications */
SimpleMeshTables _seen_packets; SimpleMeshTables _seen_packets;
/** /**
* @brief Constructs a BridgeBase instance * @brief Constructs a BridgeBase instance
* *
* @param prefs Node preferences for configuration settings
* @param mgr PacketManager for allocating and queuing packets * @param mgr PacketManager for allocating and queuing packets
* @param rtc RTCClock for timestamping debug messages * @param rtc RTCClock for timestamping debug messages
*/ */
BridgeBase(mesh::PacketManager *mgr, mesh::RTCClock *rtc) : _mgr(mgr), _rtc(rtc) {} BridgeBase(NodePrefs *prefs, mesh::PacketManager *mgr, mesh::RTCClock *rtc)
: _prefs(prefs), _mgr(mgr), _rtc(rtc) {}
/** /**
* @brief Gets formatted date/time string for logging * @brief Gets formatted date/time string for logging

View file

@ -21,18 +21,26 @@ void ESPNowBridge::send_cb(const uint8_t *mac, esp_now_send_status_t status) {
} }
} }
ESPNowBridge::ESPNowBridge(mesh::PacketManager *mgr, mesh::RTCClock *rtc) ESPNowBridge::ESPNowBridge(NodePrefs *prefs, mesh::PacketManager *mgr, mesh::RTCClock *rtc)
: BridgeBase(mgr, rtc), _rx_buffer_pos(0) { : BridgeBase(prefs, mgr, rtc), _rx_buffer_pos(0) {
_instance = this; _instance = this;
} }
void ESPNowBridge::begin() { void ESPNowBridge::begin() {
BRIDGE_DEBUG_PRINTLN("Initializing...\n");
// Initialize WiFi in station mode // Initialize WiFi in station mode
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
// Set wifi channel
if (esp_wifi_set_channel(_prefs->bridge_channel, WIFI_SECOND_CHAN_NONE) != ESP_OK) {
BRIDGE_DEBUG_PRINTLN("Error setting WIFI channel to %d\n", _prefs->bridge_channel);
return;
}
// Initialize ESP-NOW // Initialize ESP-NOW
if (esp_now_init() != ESP_OK) { if (esp_now_init() != ESP_OK) {
Serial.printf("%s: ESPNOW BRIDGE: Error initializing ESP-NOW\n", getLogDateTime()); BRIDGE_DEBUG_PRINTLN("Error initializing ESP-NOW\n");
return; return;
} }
@ -44,13 +52,41 @@ void ESPNowBridge::begin() {
esp_now_peer_info_t peerInfo = {}; esp_now_peer_info_t peerInfo = {};
memset(&peerInfo, 0, sizeof(peerInfo)); memset(&peerInfo, 0, sizeof(peerInfo));
memset(peerInfo.peer_addr, 0xFF, ESP_NOW_ETH_ALEN); // Broadcast address memset(peerInfo.peer_addr, 0xFF, ESP_NOW_ETH_ALEN); // Broadcast address
peerInfo.channel = 0; peerInfo.channel = _prefs->bridge_channel;
peerInfo.encrypt = false; peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) { if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.printf("%s: ESPNOW BRIDGE: Failed to add broadcast peer\n", getLogDateTime()); BRIDGE_DEBUG_PRINTLN("Failed to add broadcast peer\n");
return; return;
} }
// Update bridge state
_initialized = true;
}
void ESPNowBridge::end() {
BRIDGE_DEBUG_PRINTLN("Stopping...\n");
// Remove broadcast peer
uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
if (esp_now_del_peer(broadcastAddress) != ESP_OK) {
BRIDGE_DEBUG_PRINTLN("Error removing broadcast peer\n");
}
// Unregister callbacks
esp_now_register_recv_cb(nullptr);
esp_now_register_send_cb(nullptr);
// Deinitialize ESP-NOW
if (esp_now_deinit() != ESP_OK) {
BRIDGE_DEBUG_PRINTLN("Error deinitializing ESP-NOW\n");
}
// Turn off WiFi
WiFi.mode(WIFI_OFF);
// Update bridge state
_initialized = false;
} }
void ESPNowBridge::loop() { void ESPNowBridge::loop() {
@ -58,35 +94,29 @@ void ESPNowBridge::loop() {
} }
void ESPNowBridge::xorCrypt(uint8_t *data, size_t len) { void ESPNowBridge::xorCrypt(uint8_t *data, size_t len) {
size_t keyLen = strlen(_secret); size_t keyLen = strlen(_prefs->bridge_secret);
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
data[i] ^= _secret[i % keyLen]; data[i] ^= _prefs->bridge_secret[i % keyLen];
} }
} }
void ESPNowBridge::onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t len) { void ESPNowBridge::onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t len) {
// Ignore packets that are too small to contain header + checksum // Ignore packets that are too small to contain header + checksum
if (len < (BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE)) { if (len < (BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE)) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX packet too small, len=%d\n", len);
Serial.printf("%s: ESPNOW BRIDGE: RX packet too small, len=%d\n", getLogDateTime(), len);
#endif
return; return;
} }
// Validate total packet size // Validate total packet size
if (len > MAX_ESPNOW_PACKET_SIZE) { if (len > MAX_ESPNOW_PACKET_SIZE) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX packet too large, len=%d\n", len);
Serial.printf("%s: ESPNOW BRIDGE: RX packet too large, len=%d\n", getLogDateTime(), len);
#endif
return; return;
} }
// Check packet header magic // Check packet header magic
uint16_t received_magic = (data[0] << 8) | data[1]; uint16_t received_magic = (data[0] << 8) | data[1];
if (received_magic != BRIDGE_PACKET_MAGIC) { if (received_magic != BRIDGE_PACKET_MAGIC) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX invalid magic 0x%04X\n", received_magic);
Serial.printf("%s: ESPNOW BRIDGE: RX invalid magic 0x%04X\n", getLogDateTime(), received_magic);
#endif
return; return;
} }
@ -104,16 +134,11 @@ void ESPNowBridge::onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t l
if (!validateChecksum(decrypted + BRIDGE_CHECKSUM_SIZE, payloadLen, received_checksum)) { if (!validateChecksum(decrypted + BRIDGE_CHECKSUM_SIZE, payloadLen, received_checksum)) {
// Failed to decrypt - likely from a different network // Failed to decrypt - likely from a different network
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX checksum mismatch, rcv=0x%04X\n", received_checksum);
Serial.printf("%s: ESPNOW BRIDGE: RX checksum mismatch, rcv=0x%04X\n", getLogDateTime(),
received_checksum);
#endif
return; return;
} }
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX, payload_len=%d\n", payloadLen);
Serial.printf("%s: ESPNOW BRIDGE: RX, payload_len=%d\n", getLogDateTime(), payloadLen);
#endif
// Create mesh packet // Create mesh packet
mesh::Packet *pkt = _instance->_mgr->allocNew(); mesh::Packet *pkt = _instance->_mgr->allocNew();
@ -130,31 +155,27 @@ void ESPNowBridge::onDataSent(const uint8_t *mac_addr, esp_now_send_status_t sta
// Could add transmission error handling here if needed // Could add transmission error handling here if needed
} }
void ESPNowBridge::onPacketReceived(mesh::Packet *packet) { void ESPNowBridge::sendPacket(mesh::Packet *packet) {
handleReceivedPacket(packet); // Guard against uninitialized state
} if (_initialized == false) {
return;
}
void ESPNowBridge::onPacketTransmitted(mesh::Packet *packet) {
// First validate the packet pointer // First validate the packet pointer
if (!packet) { if (!packet) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("TX invalid packet pointer\n");
Serial.printf("%s: ESPNOW BRIDGE: TX invalid packet pointer\n", getLogDateTime());
#endif
return; return;
} }
if (!_seen_packets.hasSeen(packet)) { if (!_seen_packets.hasSeen(packet)) {
// Create a temporary buffer just for size calculation and reuse for actual writing // Create a temporary buffer just for size calculation and reuse for actual writing
uint8_t sizingBuffer[MAX_PAYLOAD_SIZE]; uint8_t sizingBuffer[MAX_PAYLOAD_SIZE];
uint16_t meshPacketLen = packet->writeTo(sizingBuffer); uint16_t meshPacketLen = packet->writeTo(sizingBuffer);
// Check if packet fits within our maximum payload size // Check if packet fits within our maximum payload size
if (meshPacketLen > MAX_PAYLOAD_SIZE) { if (meshPacketLen > MAX_PAYLOAD_SIZE) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("TX packet too large (payload=%d, max=%d)\n", meshPacketLen,
Serial.printf("%s: ESPNOW BRIDGE: TX packet too large (payload=%d, max=%d)\n", getLogDateTime(), MAX_PAYLOAD_SIZE);
meshPacketLen, MAX_PAYLOAD_SIZE);
#endif
return; return;
} }
@ -183,14 +204,16 @@ void ESPNowBridge::onPacketTransmitted(mesh::Packet *packet) {
uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
esp_err_t result = esp_now_send(broadcastAddress, buffer, totalPacketSize); esp_err_t result = esp_now_send(broadcastAddress, buffer, totalPacketSize);
#if MESH_PACKET_LOGGING
if (result == ESP_OK) { if (result == ESP_OK) {
Serial.printf("%s: ESPNOW BRIDGE: TX, len=%d\n", getLogDateTime(), meshPacketLen); BRIDGE_DEBUG_PRINTLN("TX, len=%d\n", meshPacketLen);
} else { } else {
Serial.printf("%s: ESPNOW BRIDGE: TX FAILED!\n", getLogDateTime()); BRIDGE_DEBUG_PRINTLN("TX FAILED!\n");
} }
#endif
} }
} }
void ESPNowBridge::onPacketReceived(mesh::Packet *packet) {
handleReceivedPacket(packet);
}
#endif #endif

View file

@ -6,10 +6,6 @@
#ifdef WITH_ESPNOW_BRIDGE #ifdef WITH_ESPNOW_BRIDGE
#ifndef WITH_ESPNOW_BRIDGE_SECRET
#error WITH_ESPNOW_BRIDGE_SECRET must be defined to use ESPNowBridge
#endif
/** /**
* @brief Bridge implementation using ESP-NOW protocol for packet transport * @brief Bridge implementation using ESP-NOW protocol for packet transport
* *
@ -36,11 +32,11 @@
* *
* Configuration: * Configuration:
* - Define WITH_ESPNOW_BRIDGE to enable this bridge * - Define WITH_ESPNOW_BRIDGE to enable this bridge
* - Define WITH_ESPNOW_BRIDGE_SECRET with a string to set the network encryption key * - Define _prefs->bridge_secret with a string to set the network encryption key
* *
* Network Isolation: * Network Isolation:
* Multiple independent mesh networks can coexist by using different * Multiple independent mesh networks can coexist by using different
* WITH_ESPNOW_BRIDGE_SECRET values. Packets encrypted with a different key will * _prefs->bridge_secret values. Packets encrypted with a different key will
* fail the checksum validation and be discarded. * fail the checksum validation and be discarded.
*/ */
class ESPNowBridge : public BridgeBase { class ESPNowBridge : public BridgeBase {
@ -73,17 +69,11 @@ private:
/** Current position in receive buffer */ /** Current position in receive buffer */
size_t _rx_buffer_pos; size_t _rx_buffer_pos;
/**
* Network encryption key from build define
* Must be defined with WITH_ESPNOW_BRIDGE_SECRET
* Used for XOR encryption to isolate different mesh networks
*/
const char *_secret = WITH_ESPNOW_BRIDGE_SECRET;
/** /**
* Performs XOR encryption/decryption of data * Performs XOR encryption/decryption of data
* Used to isolate different mesh networks
* *
* Uses WITH_ESPNOW_BRIDGE_SECRET as the key in a simple XOR operation. * Uses _prefs->bridge_secret as the key in a simple XOR operation.
* The same operation is used for both encryption and decryption. * The same operation is used for both encryption and decryption.
* While not cryptographically secure, it provides basic network isolation. * While not cryptographically secure, it provides basic network isolation.
* *
@ -115,10 +105,11 @@ public:
/** /**
* Constructs an ESPNowBridge instance * Constructs an ESPNowBridge instance
* *
* @param prefs Node preferences for configuration settings
* @param mgr PacketManager for allocating and queuing packets * @param mgr PacketManager for allocating and queuing packets
* @param rtc RTCClock for timestamping debug messages * @param rtc RTCClock for timestamping debug messages
*/ */
ESPNowBridge(mesh::PacketManager *mgr, mesh::RTCClock *rtc); ESPNowBridge(NodePrefs *prefs, mesh::PacketManager *mgr, mesh::RTCClock *rtc);
/** /**
* Initializes the ESP-NOW bridge * Initializes the ESP-NOW bridge
@ -130,6 +121,16 @@ public:
*/ */
void begin() override; void begin() override;
/**
* Stops the ESP-NOW bridge
*
* - Removes broadcast peer
* - Unregisters callbacks
* - Deinitializes ESP-NOW protocol
* - Turns off WiFi to release radio resources
*/
void end() override;
/** /**
* Main loop handler * Main loop handler
* ESP-NOW is callback-based, so this is currently empty * ESP-NOW is callback-based, so this is currently empty
@ -150,7 +151,7 @@ public:
* *
* @param packet The mesh packet to transmit * @param packet The mesh packet to transmit
*/ */
void onPacketTransmitted(mesh::Packet *packet) override; void sendPacket(mesh::Packet *packet) override;
}; };
#endif #endif

View file

@ -4,10 +4,11 @@
#ifdef WITH_RS232_BRIDGE #ifdef WITH_RS232_BRIDGE
RS232Bridge::RS232Bridge(Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc) RS232Bridge::RS232Bridge(NodePrefs *prefs, Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc)
: BridgeBase(mgr, rtc), _serial(&serial) {} : BridgeBase(prefs, mgr, rtc), _serial(&serial) {}
void RS232Bridge::begin() { void RS232Bridge::begin() {
BRIDGE_DEBUG_PRINTLN("Initializing at %d baud...\n", _prefs->bridge_baud);
#if !defined(WITH_RS232_BRIDGE_RX) || !defined(WITH_RS232_BRIDGE_TX) #if !defined(WITH_RS232_BRIDGE_RX) || !defined(WITH_RS232_BRIDGE_TX)
#error "WITH_RS232_BRIDGE_RX and WITH_RS232_BRIDGE_TX must be defined" #error "WITH_RS232_BRIDGE_RX and WITH_RS232_BRIDGE_TX must be defined"
#endif #endif
@ -25,53 +26,26 @@ void RS232Bridge::begin() {
#else #else
#error RS232Bridge was not tested on the current platform #error RS232Bridge was not tested on the current platform
#endif #endif
((HardwareSerial *)_serial)->begin(115200); ((HardwareSerial *)_serial)->begin(_prefs->bridge_baud);
// Update bridge state
_initialized = true;
} }
void RS232Bridge::onPacketTransmitted(mesh::Packet *packet) { void RS232Bridge::end() {
// First validate the packet pointer BRIDGE_DEBUG_PRINTLN("Stopping...\n");
if (!packet) { ((HardwareSerial *)_serial)->end();
#if MESH_PACKET_LOGGING
Serial.printf("%s: RS232 BRIDGE: TX invalid packet pointer\n", getLogDateTime());
#endif
return;
}
if (!_seen_packets.hasSeen(packet)) { // Update bridge state
_initialized = false;
uint8_t buffer[MAX_SERIAL_PACKET_SIZE];
uint16_t len = packet->writeTo(buffer + 4);
// Check if packet fits within our maximum payload size
if (len > (MAX_TRANS_UNIT + 1)) {
#if MESH_PACKET_LOGGING
Serial.printf("%s: RS232 BRIDGE: TX packet too large (payload=%d, max=%d)\n", getLogDateTime(), len,
MAX_TRANS_UNIT + 1);
#endif
return;
}
// Build packet header
buffer[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF; // Magic high byte
buffer[1] = BRIDGE_PACKET_MAGIC & 0xFF; // Magic low byte
buffer[2] = (len >> 8) & 0xFF; // Length high byte
buffer[3] = len & 0xFF; // Length low byte
// Calculate checksum over the payload
uint16_t checksum = fletcher16(buffer + 4, len);
buffer[4 + len] = (checksum >> 8) & 0xFF; // Checksum high byte
buffer[5 + len] = checksum & 0xFF; // Checksum low byte
// Send complete packet
_serial->write(buffer, len + SERIAL_OVERHEAD);
#if MESH_PACKET_LOGGING
Serial.printf("%s: RS232 BRIDGE: TX, len=%d crc=0x%04x\n", getLogDateTime(), len, checksum);
#endif
}
} }
void RS232Bridge::loop() { void RS232Bridge::loop() {
// Guard against uninitialized state
if (_initialized == false) {
return;
}
while (_serial->available()) { while (_serial->available()) {
uint8_t b = _serial->read(); uint8_t b = _serial->read();
@ -97,9 +71,7 @@ void RS232Bridge::loop() {
// Validate length field // Validate length field
if (len > (MAX_TRANS_UNIT + 1)) { if (len > (MAX_TRANS_UNIT + 1)) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX invalid length %d, resetting\n", len);
Serial.printf("%s: RS232 BRIDGE: RX invalid length %d, resetting\n", getLogDateTime(), len);
#endif
_rx_buffer_pos = 0; // Invalid length, reset _rx_buffer_pos = 0; // Invalid length, reset
continue; continue;
} }
@ -108,30 +80,20 @@ void RS232Bridge::loop() {
uint16_t received_checksum = (_rx_buffer[4 + len] << 8) | _rx_buffer[5 + len]; uint16_t received_checksum = (_rx_buffer[4 + len] << 8) | _rx_buffer[5 + len];
if (validateChecksum(_rx_buffer + 4, len, received_checksum)) { if (validateChecksum(_rx_buffer + 4, len, received_checksum)) {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX, len=%d crc=0x%04x\n", len, received_checksum);
Serial.printf("%s: RS232 BRIDGE: RX, len=%d crc=0x%04x\n", getLogDateTime(), len,
received_checksum);
#endif
mesh::Packet *pkt = _mgr->allocNew(); mesh::Packet *pkt = _mgr->allocNew();
if (pkt) { if (pkt) {
if (pkt->readFrom(_rx_buffer + 4, len)) { if (pkt->readFrom(_rx_buffer + 4, len)) {
onPacketReceived(pkt); onPacketReceived(pkt);
} else { } else {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX failed to parse packet\n");
Serial.printf("%s: RS232 BRIDGE: RX failed to parse packet\n", getLogDateTime());
#endif
_mgr->free(pkt); _mgr->free(pkt);
} }
} else { } else {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX failed to allocate packet\n");
Serial.printf("%s: RS232 BRIDGE: RX failed to allocate packet\n", getLogDateTime());
#endif
} }
} else { } else {
#if MESH_PACKET_LOGGING BRIDGE_DEBUG_PRINTLN("RX checksum mismatch, rcv=0x%04x\n", received_checksum);
Serial.printf("%s: RS232 BRIDGE: RX checksum mismatch, rcv=0x%04x\n", getLogDateTime(),
received_checksum);
#endif
} }
_rx_buffer_pos = 0; // Reset for next packet _rx_buffer_pos = 0; // Reset for next packet
} }
@ -140,6 +102,48 @@ void RS232Bridge::loop() {
} }
} }
void RS232Bridge::sendPacket(mesh::Packet *packet) {
// Guard against uninitialized state
if (_initialized == false) {
return;
}
// First validate the packet pointer
if (!packet) {
BRIDGE_DEBUG_PRINTLN("TX invalid packet pointer\n");
return;
}
if (!_seen_packets.hasSeen(packet)) {
uint8_t buffer[MAX_SERIAL_PACKET_SIZE];
uint16_t len = packet->writeTo(buffer + 4);
// Check if packet fits within our maximum payload size
if (len > (MAX_TRANS_UNIT + 1)) {
BRIDGE_DEBUG_PRINTLN("TX packet too large (payload=%d, max=%d)\n", len,
MAX_TRANS_UNIT + 1);
return;
}
// Build packet header
buffer[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF; // Magic high byte
buffer[1] = BRIDGE_PACKET_MAGIC & 0xFF; // Magic low byte
buffer[2] = (len >> 8) & 0xFF; // Length high byte
buffer[3] = len & 0xFF; // Length low byte
// Calculate checksum over the payload
uint16_t checksum = fletcher16(buffer + 4, len);
buffer[4 + len] = (checksum >> 8) & 0xFF; // Checksum high byte
buffer[5 + len] = checksum & 0xFF; // Checksum low byte
// Send complete packet
_serial->write(buffer, len + SERIAL_OVERHEAD);
BRIDGE_DEBUG_PRINTLN("TX, len=%d crc=0x%04x\n", len, checksum);
}
}
void RS232Bridge::onPacketReceived(mesh::Packet *packet) { void RS232Bridge::onPacketReceived(mesh::Packet *packet) {
handleReceivedPacket(packet); handleReceivedPacket(packet);
} }

View file

@ -49,11 +49,12 @@ public:
/** /**
* @brief Constructs an RS232Bridge instance * @brief Constructs an RS232Bridge instance
* *
* @param prefs Node preferences for configuration settings
* @param serial The hardware serial port to use * @param serial The hardware serial port to use
* @param mgr PacketManager for allocating and queuing packets * @param mgr PacketManager for allocating and queuing packets
* @param rtc RTCClock for timestamping debug messages * @param rtc RTCClock for timestamping debug messages
*/ */
RS232Bridge(Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc); RS232Bridge(NodePrefs *prefs, Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc);
/** /**
* Initializes the RS232 bridge * Initializes the RS232 bridge
@ -65,6 +66,12 @@ public:
*/ */
void begin() override; void begin() override;
/**
* Stops the RS232 bridge
*
*/
void end() override;
/** /**
* @brief Main loop handler for processing incoming serial data * @brief Main loop handler for processing incoming serial data
* *
@ -90,7 +97,7 @@ public:
* *
* @param packet The mesh packet to transmit * @param packet The mesh packet to transmit
*/ */
void onPacketTransmitted(mesh::Packet *packet) override; void sendPacket(mesh::Packet *packet) override;
/** /**
* @brief Called when a complete valid packet has been received from serial * @brief Called when a complete valid packet has been received from serial

View file

@ -65,6 +65,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -87,7 +88,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =
@ -132,6 +133,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -154,7 +156,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =

View file

@ -61,6 +61,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_ct62.build_src_filter} ; build_src_filter = ${Heltec_ct62.build_src_filter}
@ -80,7 +81,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_ct62.build_src_filter} build_src_filter = ${Heltec_ct62.build_src_filter}

View file

@ -108,6 +108,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_E213_base.build_src_filter} ; build_src_filter = ${Heltec_E213_base.build_src_filter}
@ -129,7 +130,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_E213_base.build_src_filter} build_src_filter = ${Heltec_E213_base.build_src_filter}

View file

@ -104,6 +104,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_E290_base.build_src_filter} ; build_src_filter = ${Heltec_E290_base.build_src_filter}
@ -125,7 +126,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_E290_base.build_src_filter} build_src_filter = ${Heltec_E290_base.build_src_filter}

View file

@ -108,6 +108,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_T190_base.build_src_filter} ; build_src_filter = ${Heltec_T190_base.build_src_filter}
@ -127,7 +128,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_T190_base.build_src_filter} build_src_filter = ${Heltec_T190_base.build_src_filter}

View file

@ -94,6 +94,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_tracker_base.build_src_filter} ; build_src_filter = ${Heltec_tracker_base.build_src_filter}
@ -116,7 +117,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_tracker_base.build_src_filter} build_src_filter = ${Heltec_tracker_base.build_src_filter}

View file

@ -53,6 +53,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_lora32_v2.build_src_filter} ; build_src_filter = ${Heltec_lora32_v2.build_src_filter}
@ -75,7 +76,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v2.build_src_filter} build_src_filter = ${Heltec_lora32_v2.build_src_filter}

View file

@ -62,6 +62,7 @@ build_flags =
-D WITH_RS232_BRIDGE=Serial2 -D WITH_RS232_BRIDGE=Serial2
-D WITH_RS232_BRIDGE_RX=5 -D WITH_RS232_BRIDGE_RX=5
-D WITH_RS232_BRIDGE_TX=6 -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter} build_src_filter = ${Heltec_lora32_v3.build_src_filter}
@ -83,7 +84,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter} build_src_filter = ${Heltec_lora32_v3.build_src_filter}
@ -243,6 +244,7 @@ build_flags =
-D WITH_RS232_BRIDGE=Serial2 -D WITH_RS232_BRIDGE=Serial2
-D WITH_RS232_BRIDGE_RX=5 -D WITH_RS232_BRIDGE_RX=5
-D WITH_RS232_BRIDGE_TX=6 -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter} build_src_filter = ${Heltec_lora32_v3.build_src_filter}
@ -263,7 +265,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter} build_src_filter = ${Heltec_lora32_v3.build_src_filter}

View file

@ -77,7 +77,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v4.build_src_filter} build_src_filter = ${Heltec_lora32_v4.build_src_filter}

View file

@ -83,6 +83,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} ; build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter}
@ -104,7 +105,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter}

View file

@ -65,6 +65,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} ; build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter}
@ -86,7 +87,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter}

View file

@ -63,6 +63,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} ; build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter}
@ -84,7 +85,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter}

View file

@ -86,6 +86,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} ; build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter}
@ -105,7 +106,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter}

View file

@ -85,6 +85,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} ; build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter}
@ -105,7 +106,7 @@ build_flags =
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D PERSISTANT_GPS=1 -D PERSISTANT_GPS=1
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter}

View file

@ -64,6 +64,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} ; build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter}
@ -83,7 +84,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter}

View file

@ -176,6 +176,7 @@ build_flags =
-D WITH_RS232_BRIDGE=Serial2 -D WITH_RS232_BRIDGE=Serial2
-D WITH_RS232_BRIDGE_RX=34 -D WITH_RS232_BRIDGE_RX=34
-D WITH_RS232_BRIDGE_TX=25 -D WITH_RS232_BRIDGE_TX=25
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
; -D CORE_DEBUG_LEVEL=3 ; -D CORE_DEBUG_LEVEL=3
@ -197,7 +198,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
; -D CORE_DEBUG_LEVEL=3 ; -D CORE_DEBUG_LEVEL=3

View file

@ -74,6 +74,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -97,7 +98,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =
@ -144,6 +145,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -167,7 +169,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =

View file

@ -57,6 +57,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Station_G2.build_src_filter} ; build_src_filter = ${Station_G2.build_src_filter}
@ -76,7 +77,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Station_G2.build_src_filter} build_src_filter = ${Station_G2.build_src_filter}
@ -119,6 +120,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; build_src_filter = ${Station_G2.build_src_filter} ; build_src_filter = ${Station_G2.build_src_filter}
; +<helpers/bridges/RS232Bridge.cpp> ; +<helpers/bridges/RS232Bridge.cpp>
@ -139,7 +141,7 @@ build_flags =
-D MESH_PACKET_LOGGING=1 -D MESH_PACKET_LOGGING=1
-D SX126X_RX_BOOSTED_GAIN=1 -D SX126X_RX_BOOSTED_GAIN=1
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${Station_G2.build_src_filter} build_src_filter = ${Station_G2.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp> +<helpers/bridges/ESPNowBridge.cpp>

View file

@ -63,6 +63,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -86,7 +87,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =
@ -131,6 +132,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -153,7 +155,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =

View file

@ -57,6 +57,7 @@ build_flags = ${waveshare_rp2040_lora.build_flags}
-D WITH_RS232_BRIDGE=Serial2 -D WITH_RS232_BRIDGE=Serial2
-D WITH_RS232_BRIDGE_RX=9 -D WITH_RS232_BRIDGE_RX=9
-D WITH_RS232_BRIDGE_TX=8 -D WITH_RS232_BRIDGE_TX=8
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
build_src_filter = ${waveshare_rp2040_lora.build_src_filter} build_src_filter = ${waveshare_rp2040_lora.build_src_filter}

View file

@ -59,6 +59,7 @@ lib_deps =
; -D WITH_RS232_BRIDGE=Serial2 ; -D WITH_RS232_BRIDGE=Serial2
; -D WITH_RS232_BRIDGE_RX=5 ; -D WITH_RS232_BRIDGE_RX=5
; -D WITH_RS232_BRIDGE_TX=6 ; -D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; ; -D MESH_PACKET_LOGGING=1 ; ; -D MESH_PACKET_LOGGING=1
; ; -D MESH_DEBUG=1 ; ; -D MESH_DEBUG=1
; lib_deps = ; lib_deps =
@ -78,7 +79,7 @@ build_flags =
-D ADMIN_PASSWORD='"password"' -D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50 -D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1 -D WITH_ESPNOW_BRIDGE=1
-D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' ; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1 ; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1 ; -D MESH_DEBUG=1
lib_deps = lib_deps =