mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
Bridge: enhance CLI configuration options
This commit is contained in:
parent
aa946bbe36
commit
8edcb46a28
11 changed files with 162 additions and 118 deletions
|
|
@ -231,6 +231,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) {
|
||||||
|
|
@ -252,8 +258,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) {
|
||||||
|
|
@ -481,9 +490,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;
|
||||||
|
|
@ -513,8 +523,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
|
||||||
_prefs.bridge_enabled = 1; // enabled
|
|
||||||
_prefs.bridge_channel = 0; // auto
|
// 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) {
|
||||||
|
|
@ -525,9 +541,6 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
||||||
|
|
||||||
acl.load(_fs);
|
acl.load(_fs);
|
||||||
|
|
||||||
#if defined(WITH_ESPNOW_BRIDGE)
|
|
||||||
bridge.setChannel(_prefs.bridge_channel);
|
|
||||||
#endif
|
|
||||||
#if defined(WITH_BRIDGE)
|
#if defined(WITH_BRIDGE)
|
||||||
if (_prefs.bridge_enabled) {
|
if (_prefs.bridge_enabled) {
|
||||||
bridge.begin();
|
bridge.begin();
|
||||||
|
|
|
||||||
|
|
@ -165,23 +165,6 @@ public:
|
||||||
void updateAdvertTimer() override;
|
void updateAdvertTimer() override;
|
||||||
void updateFloodAdvertTimer() override;
|
void updateFloodAdvertTimer() override;
|
||||||
|
|
||||||
#if defined(WITH_BRIDGE)
|
|
||||||
void setBridgeState(bool enable) {
|
|
||||||
if (enable == bridge.getState()) return;
|
|
||||||
enable ? bridge.begin() : bridge.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(WITH_ESPNOW_BRIDGE)
|
|
||||||
void updateBridgeChannel(int ch) override {
|
|
||||||
bridge.setChannel(ch);
|
|
||||||
if (bridge.getState()) {
|
|
||||||
bridge.end();
|
|
||||||
bridge.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setLoggingOn(bool enable) override { _logging = enable; }
|
void setLoggingOn(bool enable) override { _logging = enable; }
|
||||||
|
|
||||||
void eraseLogFile() override {
|
void eraseLogFile() override {
|
||||||
|
|
@ -199,4 +182,17 @@ 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.getState()) return;
|
||||||
|
enable ? bridge.begin() : bridge.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void restartBridge() override {
|
||||||
|
if (!bridge.getState()) return;
|
||||||
|
bridge.end();
|
||||||
|
bridge.begin();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public:
|
||||||
*
|
*
|
||||||
* @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.
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,11 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||||
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_enabled, sizeof(_prefs->bridge_enabled)); // 127
|
||||||
file.read((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 128
|
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);
|
||||||
|
|
@ -72,7 +76,12 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||||
_prefs->cr = constrain(_prefs->cr, 5, 8);
|
_prefs->cr = constrain(_prefs->cr, 5, 8);
|
||||||
_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_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);
|
_prefs->bridge_channel = constrain(_prefs->bridge_channel, 0, 14);
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
@ -119,7 +128,11 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
||||||
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_enabled, sizeof(_prefs->bridge_enabled)); // 127
|
||||||
file.write((uint8_t *)&_prefs->bridge_channel, sizeof(_prefs->bridge_channel)); // 128
|
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();
|
||||||
}
|
}
|
||||||
|
|
@ -205,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) {
|
||||||
|
|
@ -261,38 +277,29 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
||||||
#ifdef WITH_BRIDGE
|
#ifdef WITH_BRIDGE
|
||||||
} else if (memcmp(config, "bridge.enabled", 14) == 0) {
|
} else if (memcmp(config, "bridge.enabled", 14) == 0) {
|
||||||
sprintf(reply, "> %s", _prefs->bridge_enabled ? "on" : "off");
|
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
|
#ifdef WITH_ESPNOW_BRIDGE
|
||||||
} else if (memcmp(config, "bridge.channel", 14) == 0) {
|
} else if (memcmp(config, "bridge.channel", 14) == 0) {
|
||||||
sprintf(reply, "> %d", (uint32_t)_prefs->bridge_channel);
|
sprintf(reply, "> %d", (uint32_t)_prefs->bridge_channel);
|
||||||
#endif
|
} else if (memcmp(config, "bridge.secret", 13) == 0) {
|
||||||
|
sprintf(reply, "> %s", _prefs->bridge_secret);
|
||||||
#endif
|
#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];
|
||||||
#ifdef WITH_BRIDGE
|
|
||||||
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
|
|
||||||
#ifdef WITH_ESPNOW_BRIDGE
|
|
||||||
if (memcmp(config, "bridge.channel ", 15) == 0) {
|
|
||||||
int ch = atoi(&config[15]);
|
|
||||||
if (ch > 0 && ch < 15) {
|
|
||||||
_prefs->bridge_channel = (uint8_t)ch;
|
|
||||||
_callbacks->updateBridgeChannel(ch);
|
|
||||||
savePrefs();
|
|
||||||
strcpy(reply, "OK");
|
|
||||||
} else {
|
|
||||||
strcpy(reply, "Error: channel must be 0 (AUTO) or 1-14");
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
if (memcmp(config, "af ", 3) == 0) {
|
if (memcmp(config, "af ", 3) == 0) {
|
||||||
_prefs->airtime_factor = atof(&config[3]);
|
_prefs->airtime_factor = atof(&config[3]);
|
||||||
savePrefs();
|
savePrefs();
|
||||||
|
|
@ -428,6 +435,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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,13 @@ struct NodePrefs { // persisted to file
|
||||||
uint8_t flood_max;
|
uint8_t flood_max;
|
||||||
uint8_t interference_threshold;
|
uint8_t interference_threshold;
|
||||||
uint8_t agc_reset_interval; // secs / 4
|
uint8_t agc_reset_interval; // secs / 4
|
||||||
uint8_t bridge_enabled; // boolean
|
// Bridge settings
|
||||||
uint8_t bridge_channel; // 1-14
|
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 {
|
||||||
|
|
@ -57,12 +62,13 @@ public:
|
||||||
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;
|
||||||
|
|
||||||
#ifdef WITH_BRIDGE
|
virtual void setBridgeState(bool enable) {
|
||||||
virtual void setBridgeState(bool enable) = 0;
|
// no op by default
|
||||||
#ifdef WITH_ESPNOW_BRIDGE
|
};
|
||||||
virtual void updateBridgeChannel(int ch) = 0;
|
|
||||||
#endif
|
virtual void restartBridge() {
|
||||||
#endif
|
// no op by default
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommonCLI {
|
class CommonCLI {
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ void BridgeBase::handleReceivedPacket(mesh::Packet *packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -48,34 +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 */
|
/** Tracks bridge state */
|
||||||
bool _initialized = false;
|
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
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,8 +33,8 @@ void ESPNowBridge::begin() {
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
|
||||||
// Set wifi channel
|
// Set wifi channel
|
||||||
if (esp_wifi_set_channel(_channel, WIFI_SECOND_CHAN_NONE) != ESP_OK) {
|
if (esp_wifi_set_channel(_prefs->bridge_channel, WIFI_SECOND_CHAN_NONE) != ESP_OK) {
|
||||||
Serial.printf("%s: ESPNOW BRIDGE: Error setting WIFI channel to %d\n", getLogDateTime(), _channel);
|
Serial.printf("%s: ESPNOW BRIDGE: Error setting WIFI channel to %d\n", getLogDateTime(), _prefs->bridge_channel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ 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 = _channel;
|
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) {
|
||||||
|
|
@ -94,9 +94,9 @@ 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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,10 +166,9 @@ 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::onPacketTransmitted(mesh::Packet *packet) {
|
void ESPNowBridge::sendPacket(mesh::Packet *packet) {
|
||||||
// Guard against uninitialized state
|
// Guard against uninitialized state
|
||||||
if (_initialized == false) {
|
if (_initialized == false) {
|
||||||
Serial.printf("%s: ESPNOW BRIDGE: TX packet attempted before initialization\n", getLogDateTime());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,22 +73,10 @@ 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Channel for ESP-NOW communication
|
|
||||||
* Valid 2.4GHz channels: 1-14
|
|
||||||
*/
|
|
||||||
int _channel = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 WITH_ESPNOW_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.
|
||||||
|
|
@ -121,10 +109,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
|
||||||
|
|
@ -166,21 +155,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;
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current channel
|
|
||||||
*
|
|
||||||
* @return The current channel (0 = AUTO, 1-14 = valid channel)
|
|
||||||
*/
|
|
||||||
int getChannel() const { return _channel; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the channel for ESP-NOW communication
|
|
||||||
*
|
|
||||||
* @param ch The channel to set (0 = AUTO, 1-14 = valid channel)
|
|
||||||
*/
|
|
||||||
void setChannel(int ch) { _channel = ch; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -4,11 +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() {
|
||||||
Serial.printf("%s: RS232 BRIDGE: Initializing...\n", getLogDateTime());
|
Serial.printf("%s: RS232 BRIDGE: Initializing at %d baud...\n", getLogDateTime(), _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
|
||||||
|
|
@ -26,7 +26,7 @@ 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
|
// Update bridge state
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
@ -114,10 +114,9 @@ void RS232Bridge::loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RS232Bridge::onPacketTransmitted(mesh::Packet *packet) {
|
void RS232Bridge::sendPacket(mesh::Packet *packet) {
|
||||||
// Guard against uninitialized state
|
// Guard against uninitialized state
|
||||||
if (_initialized == false) {
|
if (_initialized == false) {
|
||||||
Serial.printf("%s: ESPNOW BRIDGE: TX packet attempted before initialization\n", getLogDateTime());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -96,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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue