diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 3f0c0ebe..4862d7d0 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -78,28 +78,38 @@ /* ------------------------------ Code -------------------------------- */ -#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS -#define REQ_TYPE_KEEP_ALIVE 0x02 -#define REQ_TYPE_GET_TELEMETRY_DATA 0x03 +#ifdef WITH_RS232_BRIDGE +#include "helpers/bridges/RS232Bridge.h" +#define WITH_BRIDGE +#endif -#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ +#ifdef WITH_ESPNOW_BRIDGE +#include "helpers/bridges/ESPNowBridge.h" +#define WITH_BRIDGE +#endif -struct RepeaterStats { - uint16_t batt_milli_volts; - uint16_t curr_tx_queue_len; - int16_t noise_floor; - int16_t last_rssi; - uint32_t n_packets_recv; - uint32_t n_packets_sent; - uint32_t total_air_time_secs; - uint32_t total_up_time_secs; - uint32_t n_sent_flood, n_sent_direct; - uint32_t n_recv_flood, n_recv_direct; - uint16_t err_events; // was 'n_full_events' - int16_t last_snr; // x 4 - uint16_t n_direct_dups, n_flood_dups; - uint32_t total_rx_air_time_secs; -}; +#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS +#define REQ_TYPE_KEEP_ALIVE 0x02 +#define REQ_TYPE_GET_TELEMETRY_DATA 0x03 + +#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ + + struct RepeaterStats { + uint16_t batt_milli_volts; + uint16_t curr_tx_queue_len; + int16_t noise_floor; + int16_t last_rssi; + uint32_t n_packets_recv; + uint32_t n_packets_sent; + uint32_t total_air_time_secs; + uint32_t total_up_time_secs; + uint32_t n_sent_flood, n_sent_direct; + uint32_t n_recv_flood, n_recv_direct; + uint16_t err_events; // was 'n_full_events' + int16_t last_snr; // x 4 + uint16_t n_direct_dups, n_flood_dups; + uint32_t total_rx_air_time_secs; + }; struct ClientInfo { mesh::Identity id; @@ -114,6 +124,10 @@ struct ClientInfo { #define MAX_CLIENTS 32 #endif +#ifdef WITH_BRIDGE +AbstractBridge* bridge; +#endif + struct NeighbourInfo { mesh::Identity id; uint32_t advert_timestamp; @@ -300,6 +314,9 @@ protected: } } void logTx(mesh::Packet* pkt, int len) override { +#ifdef WITH_BRIDGE + bridge->onPacketTransmitted(pkt); +#endif if (_logging) { File f = openAppend(PACKET_LOG_FILE); if (f) { @@ -364,9 +381,9 @@ protected: } else if (strcmp((char *) &data[4], _prefs.guest_password) == 0) { // check guest password is_admin = false; } else { - #if MESH_DEBUG +#if MESH_DEBUG MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]); - #endif +#endif return; } @@ -384,15 +401,15 @@ protected: uint32_t now = getRTCClock()->getCurrentTimeUnique(); memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp - #if 0 +#if 0 memcpy(&reply_data[4], "OK", 2); // legacy response - #else +#else reply_data[4] = RESP_SERVER_LOGIN_OK; reply_data[5] = 0; // NEW: recommended keep-alive interval (secs / 16) reply_data[6] = is_admin ? 1 : 0; reply_data[7] = 0; // FUTURE: reserved getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness - #endif +#endif if (packet->isRouteFlood()) { // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response @@ -565,14 +582,23 @@ public: : mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables), _cli(board, rtc, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4) { +#ifdef WITH_BRIDGE +#if defined(WITH_RS232_BRIDGE) + bridge = new RS232Bridge(WITH_RS232_BRIDGE, _mgr, &rtc); +#elif defined(WITH_ESPNOW_BRIDGE) + bridge = new ESPNowBridge(_mgr, &rtc); +#else +#error "You must choose either RS232 or ESPNow bridge" +#endif +#endif memset(known_clients, 0, sizeof(known_clients)); next_local_advert = next_flood_advert = 0; set_radio_at = revert_radio_at = 0; _logging = false; - #if MAX_NEIGHBOURS +#if MAX_NEIGHBOURS memset(neighbours, 0, sizeof(neighbours)); - #endif +#endif // defaults memset(&_prefs, 0, sizeof(_prefs)); @@ -765,6 +791,10 @@ public: } void loop() { +#ifdef WITH_BRIDGE + bridge->loop(); +#endif + mesh::Mesh::loop(); if (next_flood_advert && millisHasNowPassed(next_flood_advert)) { @@ -813,6 +843,10 @@ void setup() { Serial.begin(115200); delay(1000); +#ifdef WITH_BRIDGE + bridge->begin(); +#endif + board.begin(); #ifdef DISPLAY_CLASS @@ -824,7 +858,9 @@ void setup() { } #endif - if (!radio_init()) { halt(); } + if (!radio_init()) { + halt(); + } fast_rng.begin(radio_get_rng_seed()); diff --git a/platformio.ini b/platformio.ini index 4702ba56..11814a22 100644 --- a/platformio.ini +++ b/platformio.ini @@ -47,6 +47,7 @@ build_src_filter = +<*.cpp> + + + + + ; ----------------- ESP32 --------------------- diff --git a/src/helpers/AbstractBridge.h b/src/helpers/AbstractBridge.h new file mode 100644 index 00000000..a348e933 --- /dev/null +++ b/src/helpers/AbstractBridge.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +class AbstractBridge { +public: + virtual ~AbstractBridge() {} + + /** + * @brief Initializes the bridge. + */ + virtual void begin() = 0; + + /** + * @brief A method to be called on every main loop iteration. + * Used for tasks like checking for incoming data. + */ + virtual void loop() = 0; + + /** + * @brief A callback that is triggered when the mesh transmits a packet. + * The bridge can use this to forward the packet. + * + * @param packet The packet that was transmitted. + */ + virtual void onPacketTransmitted(mesh::Packet* packet) = 0; + + /** + * @brief Processes a received packet from the bridge's medium. + * + * @param packet The packet that was received. + */ + virtual void onPacketReceived(mesh::Packet* packet) = 0; +}; diff --git a/src/helpers/bridges/BridgeBase.cpp b/src/helpers/bridges/BridgeBase.cpp new file mode 100644 index 00000000..03871418 --- /dev/null +++ b/src/helpers/bridges/BridgeBase.cpp @@ -0,0 +1,36 @@ +#include "BridgeBase.h" + +#include + +const char *BridgeBase::getLogDateTime() { + static char tmp[32]; + uint32_t now = _rtc->getCurrentTime(); + DateTime dt = DateTime(now); + sprintf(tmp, "%02d:%02d:%02d - %d/%d/%d U", dt.hour(), dt.minute(), dt.second(), dt.day(), dt.month(), + dt.year()); + return tmp; +} + +uint16_t BridgeBase::fletcher16(const uint8_t *data, size_t len) { + uint8_t sum1 = 0, sum2 = 0; + + for (size_t i = 0; i < len; i++) { + sum1 = (sum1 + data[i]) % 255; + sum2 = (sum2 + sum1) % 255; + } + + return (sum2 << 8) | sum1; +} + +bool BridgeBase::validateChecksum(const uint8_t *data, size_t len, uint16_t received_checksum) { + uint16_t calculated_checksum = fletcher16(data, len); + return received_checksum == calculated_checksum; +} + +void BridgeBase::handleReceivedPacket(mesh::Packet *packet) { + if (!_seen_packets.hasSeen(packet)) { + _mgr->queueInbound(packet, millis() + BRIDGE_DELAY); + } else { + _mgr->free(packet); + } +} diff --git a/src/helpers/bridges/BridgeBase.h b/src/helpers/bridges/BridgeBase.h new file mode 100644 index 00000000..ab62619f --- /dev/null +++ b/src/helpers/bridges/BridgeBase.h @@ -0,0 +1,112 @@ +#pragma once + +#include "helpers/AbstractBridge.h" +#include "helpers/SimpleMeshTables.h" + +#include + +/** + * @brief Base class implementing common bridge functionality + * + * This class provides common functionality used by different bridge implementations + * like packet tracking, checksum calculation, timestamping, and duplicate detection. + * + * Features: + * - Fletcher-16 checksum calculation for data integrity + * - Packet duplicate detection using SimpleMeshTables + * - Common timestamp formatting for debug logging + * - Shared packet management and queuing logic + */ +class BridgeBase : public AbstractBridge { +public: + virtual ~BridgeBase() = default; + + /** + * @brief Common magic number used by all bridge implementations for packet identification + * + * This magic number is placed at the beginning of bridge packets to identify + * them as mesh bridge packets and provide frame synchronization. + */ + static constexpr uint16_t BRIDGE_PACKET_MAGIC = 0xC03E; + + /** + * @brief Common field sizes used by bridge implementations + * + * These constants define the size of common packet fields used across bridges. + * BRIDGE_MAGIC_SIZE is used by all bridges for packet identification. + * BRIDGE_LENGTH_SIZE is used by bridges that need explicit length fields (like RS232). + * BRIDGE_CHECKSUM_SIZE is used by all bridges for Fletcher-16 checksums. + */ + static constexpr uint16_t BRIDGE_MAGIC_SIZE = sizeof(BRIDGE_PACKET_MAGIC); + static constexpr uint16_t BRIDGE_LENGTH_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: + /** Packet manager for allocating and queuing mesh packets */ + mesh::PacketManager *_mgr; + + /** RTC clock for timestamping debug messages */ + mesh::RTCClock *_rtc; + + /** Tracks seen packets to prevent loops in broadcast communications */ + SimpleMeshTables _seen_packets; + + /** + * @brief Constructs a BridgeBase instance + * + * @param mgr PacketManager for allocating and queuing packets + * @param rtc RTCClock for timestamping debug messages + */ + BridgeBase(mesh::PacketManager *mgr, mesh::RTCClock *rtc) : _mgr(mgr), _rtc(rtc) {} + + /** + * @brief Gets formatted date/time string for logging + * + * Format: "HH:MM:SS - DD/MM/YYYY U" + * + * @return Formatted date/time string + */ + const char *getLogDateTime(); + + /** + * @brief Calculate Fletcher-16 checksum + * + * Based on: https://en.wikipedia.org/wiki/Fletcher%27s_checksum + * Used to verify data integrity of received packets + * + * @param data Pointer to data to calculate checksum for + * @param len Length of data in bytes + * @return Calculated Fletcher-16 checksum + */ + static uint16_t fletcher16(const uint8_t *data, size_t len); + + /** + * @brief Validate received checksum against calculated checksum + * + * @param data Pointer to data to validate + * @param len Length of data in bytes + * @param received_checksum Checksum received with data + * @return true if checksum is valid, false otherwise + */ + bool validateChecksum(const uint8_t *data, size_t len, uint16_t received_checksum); + + /** + * @brief Common packet handling for received packets + * + * Implements the standard pattern used by all bridges: + * - Check if packet was seen before using _seen_packets.hasSeen() + * - Queue packet for mesh processing if not seen before + * - Free packet if already seen to prevent duplicates + * + * @param packet The received mesh packet + */ + void handleReceivedPacket(mesh::Packet *packet); +}; diff --git a/src/helpers/bridges/ESPNowBridge.cpp b/src/helpers/bridges/ESPNowBridge.cpp new file mode 100644 index 00000000..a02f804e --- /dev/null +++ b/src/helpers/bridges/ESPNowBridge.cpp @@ -0,0 +1,196 @@ +#include "ESPNowBridge.h" + +#include +#include + +#ifdef WITH_ESPNOW_BRIDGE + +// Static member to handle callbacks +ESPNowBridge *ESPNowBridge::_instance = nullptr; + +// Static callback wrappers +void ESPNowBridge::recv_cb(const uint8_t *mac, const uint8_t *data, int32_t len) { + if (_instance) { + _instance->onDataRecv(mac, data, len); + } +} + +void ESPNowBridge::send_cb(const uint8_t *mac, esp_now_send_status_t status) { + if (_instance) { + _instance->onDataSent(mac, status); + } +} + +ESPNowBridge::ESPNowBridge(mesh::PacketManager *mgr, mesh::RTCClock *rtc) + : BridgeBase(mgr, rtc), _rx_buffer_pos(0) { + _instance = this; +} + +void ESPNowBridge::begin() { + // Initialize WiFi in station mode + WiFi.mode(WIFI_STA); + + // Initialize ESP-NOW + if (esp_now_init() != ESP_OK) { + Serial.printf("%s: ESPNOW BRIDGE: Error initializing ESP-NOW\n", getLogDateTime()); + return; + } + + // Register callbacks + esp_now_register_recv_cb(recv_cb); + esp_now_register_send_cb(send_cb); + + // Add broadcast peer + esp_now_peer_info_t peerInfo = {}; + memset(&peerInfo, 0, sizeof(peerInfo)); + memset(peerInfo.peer_addr, 0xFF, ESP_NOW_ETH_ALEN); // Broadcast address + peerInfo.channel = 0; + peerInfo.encrypt = false; + + if (esp_now_add_peer(&peerInfo) != ESP_OK) { + Serial.printf("%s: ESPNOW BRIDGE: Failed to add broadcast peer\n", getLogDateTime()); + return; + } +} + +void ESPNowBridge::loop() { + // Nothing to do here - ESP-NOW is callback based +} + +void ESPNowBridge::xorCrypt(uint8_t *data, size_t len) { + size_t keyLen = strlen(_secret); + for (size_t i = 0; i < len; i++) { + data[i] ^= _secret[i % keyLen]; + } +} + +void ESPNowBridge::onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t len) { + // Ignore packets that are too small to contain header + checksum + if (len < (BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX packet too small, len=%d\n", getLogDateTime(), len); +#endif + return; + } + + // Validate total packet size + if (len > MAX_ESPNOW_PACKET_SIZE) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX packet too large, len=%d\n", getLogDateTime(), len); +#endif + return; + } + + // Check packet header magic + uint16_t received_magic = (data[0] << 8) | data[1]; + if (received_magic != BRIDGE_PACKET_MAGIC) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX invalid magic 0x%04X\n", getLogDateTime(), received_magic); +#endif + return; + } + + // Make a copy we can decrypt + uint8_t decrypted[MAX_ESPNOW_PACKET_SIZE]; + const size_t encryptedDataLen = len - BRIDGE_MAGIC_SIZE; + memcpy(decrypted, data + BRIDGE_MAGIC_SIZE, encryptedDataLen); + + // Try to decrypt (checksum + payload) + xorCrypt(decrypted, encryptedDataLen); + + // Validate checksum + uint16_t received_checksum = (decrypted[0] << 8) | decrypted[1]; + const size_t payloadLen = encryptedDataLen - BRIDGE_CHECKSUM_SIZE; + + if (!validateChecksum(decrypted + BRIDGE_CHECKSUM_SIZE, payloadLen, received_checksum)) { + // Failed to decrypt - likely from a different network +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX checksum mismatch, rcv=0x%04X\n", getLogDateTime(), + received_checksum); +#endif + return; + } + +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: RX, payload_len=%d\n", getLogDateTime(), payloadLen); +#endif + + // Create mesh packet + mesh::Packet *pkt = _instance->_mgr->allocNew(); + if (!pkt) return; + + if (pkt->readFrom(decrypted + BRIDGE_CHECKSUM_SIZE, payloadLen)) { + _instance->onPacketReceived(pkt); + } else { + _instance->_mgr->free(pkt); + } +} + +void ESPNowBridge::onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { + // Could add transmission error handling here if needed +} + +void ESPNowBridge::onPacketReceived(mesh::Packet *packet) { + handleReceivedPacket(packet); +} + +void ESPNowBridge::onPacketTransmitted(mesh::Packet *packet) { + // First validate the packet pointer + if (!packet) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: TX invalid packet pointer\n", getLogDateTime()); +#endif + return; + } + + if (!_seen_packets.hasSeen(packet)) { + + // Create a temporary buffer just for size calculation and reuse for actual writing + uint8_t sizingBuffer[MAX_PAYLOAD_SIZE]; + uint16_t meshPacketLen = packet->writeTo(sizingBuffer); + + // Check if packet fits within our maximum payload size + if (meshPacketLen > MAX_PAYLOAD_SIZE) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: ESPNOW BRIDGE: TX packet too large (payload=%d, max=%d)\n", getLogDateTime(), + meshPacketLen, MAX_PAYLOAD_SIZE); +#endif + return; + } + + uint8_t buffer[MAX_ESPNOW_PACKET_SIZE]; + + // Write magic header (2 bytes) + buffer[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF; + buffer[1] = BRIDGE_PACKET_MAGIC & 0xFF; + + // Write packet payload starting after magic header and checksum + const size_t packetOffset = BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE; + memcpy(buffer + packetOffset, sizingBuffer, meshPacketLen); + + // Calculate and add checksum (only of the payload) + uint16_t checksum = fletcher16(buffer + packetOffset, meshPacketLen); + buffer[2] = (checksum >> 8) & 0xFF; // High byte + buffer[3] = checksum & 0xFF; // Low byte + + // Encrypt payload and checksum (not including magic header) + xorCrypt(buffer + BRIDGE_MAGIC_SIZE, meshPacketLen + BRIDGE_CHECKSUM_SIZE); + + // Total packet size: magic header + checksum + payload + const size_t totalPacketSize = BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE + meshPacketLen; + + // Broadcast using ESP-NOW + uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + esp_err_t result = esp_now_send(broadcastAddress, buffer, totalPacketSize); + +#if MESH_PACKET_LOGGING + if (result == ESP_OK) { + Serial.printf("%s: ESPNOW BRIDGE: TX, len=%d\n", getLogDateTime(), meshPacketLen); + } else { + Serial.printf("%s: ESPNOW BRIDGE: TX FAILED!\n", getLogDateTime()); + } +#endif + } +} + +#endif diff --git a/src/helpers/bridges/ESPNowBridge.h b/src/helpers/bridges/ESPNowBridge.h new file mode 100644 index 00000000..b43f1744 --- /dev/null +++ b/src/helpers/bridges/ESPNowBridge.h @@ -0,0 +1,156 @@ +#pragma once + +#include "MeshCore.h" +#include "esp_now.h" +#include "helpers/bridges/BridgeBase.h" + +#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 + * + * This bridge enables mesh packet transport over ESP-NOW, a connectionless communication + * protocol provided by Espressif that allows ESP32 devices to communicate directly + * without WiFi router infrastructure. + * + * Features: + * - Broadcast-based communication (all bridges receive all packets) + * - Network isolation using XOR encryption with shared secret + * - Duplicate packet detection using SimpleMeshTables tracking + * - Maximum packet size of 250 bytes (ESP-NOW limitation) + * + * Packet Structure: + * [2 bytes] Magic Header - Used to identify ESPNowBridge packets + * [2 bytes] Fletcher-16 checksum of encrypted payload (calculated over payload only) + * [246 bytes max] Encrypted payload containing the mesh packet + * + * The Fletcher-16 checksum is used to validate packet integrity and detect + * corrupted or tampered packets. It's calculated over the encrypted payload + * and provides a simple but effective way to verify packets are both + * uncorrupted and from the same network (since the checksum is calculated + * after encryption). + * + * Configuration: + * - Define WITH_ESPNOW_BRIDGE to enable this bridge + * - Define WITH_ESPNOW_BRIDGE_SECRET with a string to set the network encryption key + * + * Network Isolation: + * Multiple independent mesh networks can coexist by using different + * WITH_ESPNOW_BRIDGE_SECRET values. Packets encrypted with a different key will + * fail the checksum validation and be discarded. + */ +class ESPNowBridge : public BridgeBase { +private: + static ESPNowBridge *_instance; + static void recv_cb(const uint8_t *mac, const uint8_t *data, int32_t len); + static void send_cb(const uint8_t *mac, esp_now_send_status_t status); + + /** + * ESP-NOW Protocol Structure: + * - ESP-NOW header: 20 bytes (handled by ESP-NOW protocol) + * - ESP-NOW payload: 250 bytes maximum + * Total ESP-NOW packet: 270 bytes + * + * Our Bridge Packet Structure (must fit in ESP-NOW payload): + * - Magic header: 2 bytes + * - Checksum: 2 bytes + * - Available payload: 246 bytes + */ + static const size_t MAX_ESPNOW_PACKET_SIZE = 250; + + /** + * Size constants for packet parsing + */ + static const size_t MAX_PAYLOAD_SIZE = MAX_ESPNOW_PACKET_SIZE - (BRIDGE_MAGIC_SIZE + BRIDGE_CHECKSUM_SIZE); + + /** Buffer for receiving ESP-NOW packets */ + uint8_t _rx_buffer[MAX_ESPNOW_PACKET_SIZE]; + + /** Current position in receive buffer */ + 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 + * + * Uses WITH_ESPNOW_BRIDGE_SECRET as the key in a simple XOR operation. + * The same operation is used for both encryption and decryption. + * While not cryptographically secure, it provides basic network isolation. + * + * @param data Pointer to data to encrypt/decrypt + * @param len Length of data in bytes + */ + void xorCrypt(uint8_t *data, size_t len); + + /** + * ESP-NOW receive callback + * Called by ESP-NOW when a packet is received + * + * @param mac Source MAC address + * @param data Received data + * @param len Length of received data + */ + void onDataRecv(const uint8_t *mac, const uint8_t *data, int32_t len); + + /** + * ESP-NOW send callback + * Called by ESP-NOW after a transmission attempt + * + * @param mac_addr Destination MAC address + * @param status Transmission status + */ + void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status); + +public: + /** + * Constructs an ESPNowBridge instance + * + * @param mgr PacketManager for allocating and queuing packets + * @param rtc RTCClock for timestamping debug messages + */ + ESPNowBridge(mesh::PacketManager *mgr, mesh::RTCClock *rtc); + + /** + * Initializes the ESP-NOW bridge + * + * - Configures WiFi in station mode + * - Initializes ESP-NOW protocol + * - Registers callbacks + * - Sets up broadcast peer + */ + void begin() override; + + /** + * Main loop handler + * ESP-NOW is callback-based, so this is currently empty + */ + void loop() override; + + /** + * Called when a packet is received via ESP-NOW + * Queues the packet for mesh processing if not seen before + * + * @param packet The received mesh packet + */ + void onPacketReceived(mesh::Packet *packet) override; + + /** + * Called when a packet needs to be transmitted via ESP-NOW + * Encrypts and broadcasts the packet if not seen before + * + * @param packet The mesh packet to transmit + */ + void onPacketTransmitted(mesh::Packet *packet) override; +}; + +#endif diff --git a/src/helpers/bridges/RS232Bridge.cpp b/src/helpers/bridges/RS232Bridge.cpp new file mode 100644 index 00000000..d182aea6 --- /dev/null +++ b/src/helpers/bridges/RS232Bridge.cpp @@ -0,0 +1,147 @@ +#include "RS232Bridge.h" + +#include + +#ifdef WITH_RS232_BRIDGE + +RS232Bridge::RS232Bridge(Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc) + : BridgeBase(mgr, rtc), _serial(&serial) {} + +void RS232Bridge::begin() { +#if !defined(WITH_RS232_BRIDGE_RX) || !defined(WITH_RS232_BRIDGE_TX) +#error "WITH_RS232_BRIDGE_RX and WITH_RS232_BRIDGE_TX must be defined" +#endif + +#if defined(ESP32) + ((HardwareSerial *)_serial)->setPins(WITH_RS232_BRIDGE_RX, WITH_RS232_BRIDGE_TX); +#elif defined(NRF52_PLATFORM) + ((HardwareSerial *)_serial)->setPins(WITH_RS232_BRIDGE_RX, WITH_RS232_BRIDGE_TX); +#elif defined(RP2040_PLATFORM) + ((SerialUART *)_serial)->setRX(WITH_RS232_BRIDGE_RX); + ((SerialUART *)_serial)->setTX(WITH_RS232_BRIDGE_TX); +#elif defined(STM32_PLATFORM) + ((HardwareSerial *)_serial)->setRx(WITH_RS232_BRIDGE_RX); + ((HardwareSerial *)_serial)->setTx(WITH_RS232_BRIDGE_TX); +#else +#error RS232Bridge was not tested on the current platform +#endif + ((HardwareSerial *)_serial)->begin(115200); +} + +void RS232Bridge::onPacketTransmitted(mesh::Packet *packet) { + // First validate the packet pointer + if (!packet) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: TX invalid packet pointer\n", getLogDateTime()); +#endif + 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)) { +#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() { + while (_serial->available()) { + uint8_t b = _serial->read(); + + if (_rx_buffer_pos < 2) { + // Waiting for magic word + if ((_rx_buffer_pos == 0 && b == ((BRIDGE_PACKET_MAGIC >> 8) & 0xFF)) || + (_rx_buffer_pos == 1 && b == (BRIDGE_PACKET_MAGIC & 0xFF))) { + _rx_buffer[_rx_buffer_pos++] = b; + } else { + // Invalid magic byte, reset and start over + _rx_buffer_pos = 0; + // Check if this byte could be the start of a new magic word + if (b == ((BRIDGE_PACKET_MAGIC >> 8) & 0xFF)) { + _rx_buffer[_rx_buffer_pos++] = b; + } + } + } else { + // Reading length, payload, and checksum + _rx_buffer[_rx_buffer_pos++] = b; + + if (_rx_buffer_pos >= 4) { + uint16_t len = (_rx_buffer[2] << 8) | _rx_buffer[3]; + + // Validate length field + if (len > (MAX_TRANS_UNIT + 1)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX invalid length %d, resetting\n", getLogDateTime(), len); +#endif + _rx_buffer_pos = 0; // Invalid length, reset + continue; + } + + if (_rx_buffer_pos == len + SERIAL_OVERHEAD) { // Full packet received + uint16_t received_checksum = (_rx_buffer[4 + len] << 8) | _rx_buffer[5 + len]; + + if (validateChecksum(_rx_buffer + 4, len, received_checksum)) { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX, len=%d crc=0x%04x\n", getLogDateTime(), len, + received_checksum); +#endif + mesh::Packet *pkt = _mgr->allocNew(); + if (pkt) { + if (pkt->readFrom(_rx_buffer + 4, len)) { + onPacketReceived(pkt); + } else { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX failed to parse packet\n", getLogDateTime()); +#endif + _mgr->free(pkt); + } + } else { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX failed to allocate packet\n", getLogDateTime()); +#endif + } + } else { +#if MESH_PACKET_LOGGING + Serial.printf("%s: RS232 BRIDGE: RX checksum mismatch, rcv=0x%04x\n", getLogDateTime(), + received_checksum); +#endif + } + _rx_buffer_pos = 0; // Reset for next packet + } + } + } + } +} + +void RS232Bridge::onPacketReceived(mesh::Packet *packet) { + handleReceivedPacket(packet); +} + +#endif diff --git a/src/helpers/bridges/RS232Bridge.h b/src/helpers/bridges/RS232Bridge.h new file mode 100644 index 00000000..3b09de75 --- /dev/null +++ b/src/helpers/bridges/RS232Bridge.h @@ -0,0 +1,141 @@ +#pragma once + +#include "helpers/bridges/BridgeBase.h" + +#include + +#ifdef WITH_RS232_BRIDGE + +/** + * @brief Bridge implementation using RS232/UART protocol for packet transport + * + * This bridge enables mesh packet transport over serial/UART connections, + * allowing nodes to communicate over wired serial links. It implements a simple + * packet framing protocol with checksums for reliable transfer. + * + * Features: + * - Point-to-point communication over hardware UART + * - Fletcher-16 checksum for data integrity verification + * - Magic header for packet synchronization and frame alignment + * - Duplicate packet detection using SimpleMeshTables tracking + * - Configurable RX/TX pins via build defines + * - Fixed baud rate at 115200 for consistent timing + * + * Packet Structure: + * [2 bytes] Magic Header (0xC03E) - Used to identify start of RS232Bridge packets + * [2 bytes] Payload Length - Length of the mesh packet payload + * [n bytes] Mesh Packet Payload - The actual mesh packet data + * [2 bytes] Fletcher-16 Checksum - Calculated over the payload for integrity verification + * + * The Fletcher-16 checksum is calculated over the mesh packet payload and provides + * error detection capabilities suitable for serial communication where electrical + * noise, timing issues, or hardware problems could corrupt data. The checksum + * validation ensures only valid packets are forwarded to the mesh. + * + * Configuration: + * - Define WITH_RS232_BRIDGE to enable this bridge + * - Define WITH_RS232_BRIDGE_RX with the RX pin number + * - Define WITH_RS232_BRIDGE_TX with the TX pin number + * + * Platform Support: + * Different platforms require different pin configuration methods: + * - ESP32: Uses HardwareSerial::setPins(rx, tx) + * - NRF52: Uses HardwareSerial::setPins(rx, tx) + * - RP2040: Uses SerialUART::setRX(rx) and SerialUART::setTX(tx) + * - STM32: Uses HardwareSerial::setRx(rx) and HardwareSerial::setTx(tx) + */ +class RS232Bridge : public BridgeBase { +public: + /** + * @brief Constructs an RS232Bridge instance + * + * @param serial The hardware serial port to use + * @param mgr PacketManager for allocating and queuing packets + * @param rtc RTCClock for timestamping debug messages + */ + RS232Bridge(Stream &serial, mesh::PacketManager *mgr, mesh::RTCClock *rtc); + + /** + * Initializes the RS232 bridge + * + * - Validates that RX/TX pins are defined + * - Configures UART pins based on target platform + * - Sets baud rate to 115200 for consistent communication + * - Platform-specific pin configuration methods are used + */ + void begin() override; + + /** + * @brief Main loop handler for processing incoming serial data + * + * Implements a state machine for packet reception: + * 1. Searches for magic header bytes for packet synchronization + * 2. Reads length field to determine expected packet size + * 3. Validates packet length against maximum allowed size + * 4. Receives complete packet payload and checksum + * 5. Validates Fletcher-16 checksum for data integrity + * 6. Creates mesh packet and forwards if valid + */ + void loop() override; + + /** + * @brief Called when a packet needs to be transmitted over serial + * + * Formats the mesh packet with RS232 framing protocol: + * - Adds magic header for synchronization + * - Includes payload length field + * - Calculates Fletcher-16 checksum over payload + * - Transmits complete framed packet + * - Uses duplicate detection to prevent retransmission + * + * @param packet The mesh packet to transmit + */ + void onPacketTransmitted(mesh::Packet *packet) override; + + /** + * @brief Called when a complete valid packet has been received from serial + * + * Forwards the received packet to the mesh for processing. + * The packet has already been validated for checksum integrity + * and parsed successfully at this point. + * + * @param packet The received mesh packet ready for processing + */ + void onPacketReceived(mesh::Packet *packet) override; + +private: + /** + * RS232 Protocol Structure: + * - Magic header: 2 bytes (packet identification) + * - Length field: 2 bytes (payload length) + * - Payload: variable bytes (mesh packet data) + * - Checksum: 2 bytes (Fletcher-16 over payload) + * Total overhead: 6 bytes + */ + + /** + * @brief The total overhead of the serial protocol in bytes. + * Includes: MAGIC_WORD (2) + LENGTH (2) + CHECKSUM (2) = 6 bytes + */ + static constexpr uint16_t SERIAL_OVERHEAD = BRIDGE_MAGIC_SIZE + BRIDGE_LENGTH_SIZE + BRIDGE_CHECKSUM_SIZE; + + /** + * @brief The maximum size of a complete packet on the serial line. + * + * This is calculated as the sum of: + * - MAX_TRANS_UNIT + 1 for the maximum mesh packet size + * - SERIAL_OVERHEAD for the framing (magic + length + checksum) + */ + static constexpr uint16_t MAX_SERIAL_PACKET_SIZE = (MAX_TRANS_UNIT + 1) + SERIAL_OVERHEAD; + + /** Hardware serial port interface */ + Stream *_serial; + + /** Buffer for building received packets */ + uint8_t _rx_buffer[MAX_SERIAL_PACKET_SIZE]; + + /** Current position in the receive buffer */ + uint16_t _rx_buffer_pos = 0; +}; + +#endif diff --git a/variants/generic-e22/platformio.ini b/variants/generic-e22/platformio.ini index 8b2c293b..c9a67220 100644 --- a/variants/generic-e22/platformio.ini +++ b/variants/generic-e22/platformio.ini @@ -47,6 +47,53 @@ lib_deps = ${Generic_E22.lib_deps} ${esp32_ota.lib_deps} +; [env:Generic_E22_sx1262_repeater_bridge_rs232] +; extends = Generic_E22 +; build_src_filter = ${Generic_E22.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Generic_E22.build_flags} +; -D RADIO_CLASS=CustomSX1262 +; -D WRAPPER_CLASS=CustomSX1262Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Generic_E22.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Generic_E22_sx1262_repeater_bridge_espnow] +extends = Generic_E22 +build_src_filter = ${Generic_E22.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Generic_E22.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Generic_E22.lib_deps} + ${esp32_ota.lib_deps} + [env:Generic_E22_sx1268_repeater] extends = Generic_E22 build_src_filter = ${Generic_E22.build_src_filter} @@ -66,3 +113,50 @@ build_flags = lib_deps = ${Generic_E22.lib_deps} ${esp32_ota.lib_deps} + +; [env:Generic_E22_sx1268_repeater_bridge_rs232] +; extends = Generic_E22 +; build_src_filter = ${Generic_E22.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Generic_E22.build_flags} +; -D RADIO_CLASS=CustomSX1268 +; -D WRAPPER_CLASS=CustomSX1268Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Generic_E22.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Generic_E22_sx1268_repeater_bridge_espnow] +extends = Generic_E22 +build_src_filter = ${Generic_E22.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Generic_E22.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Generic_E22.lib_deps} + ${esp32_ota.lib_deps} diff --git a/variants/heltec_ct62/platformio.ini b/variants/heltec_ct62/platformio.ini index 0dc512b9..1b83adbf 100644 --- a/variants/heltec_ct62/platformio.ini +++ b/variants/heltec_ct62/platformio.ini @@ -49,6 +49,47 @@ lib_deps = ${Heltec_ct62.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_ct62_repeater_bridge_rs232] +; extends = Heltec_ct62 +; build_flags = +; ${Heltec_ct62.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_ct62.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_ct62.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_ct62_repeater_bridge_espnow] +extends = Heltec_ct62 +build_flags = + ${Heltec_ct62.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_ct62.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_ct62.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_ct62_companion_radio_usb] extends = Heltec_ct62 build_flags = diff --git a/variants/heltec_e213/platformio.ini b/variants/heltec_e213/platformio.ini index c8efc819..a6fe2560 100644 --- a/variants/heltec_e213/platformio.ini +++ b/variants/heltec_e213/platformio.ini @@ -93,6 +93,51 @@ lib_deps = ${Heltec_E213_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_E213_repeater_bridge_rs232] +; extends = Heltec_E213_base +; build_flags = +; ${Heltec_E213_base.build_flags} +; -D DISPLAY_CLASS=E213Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_E213_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_E213_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_E213_repeater_bridge_espnow] +extends = Heltec_E213_base +build_flags = + ${Heltec_E213_base.build_flags} + -D DISPLAY_CLASS=E213Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_E213_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_E213_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_E213_room_server] extends = Heltec_E213_base build_flags = diff --git a/variants/heltec_e290/platformio.ini b/variants/heltec_e290/platformio.ini index 377162f4..0223b30c 100644 --- a/variants/heltec_e290/platformio.ini +++ b/variants/heltec_e290/platformio.ini @@ -89,6 +89,51 @@ lib_deps = ${Heltec_E290_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_E290_repeater_bridge_rs232] +; extends = Heltec_E290_base +; build_flags = +; ${Heltec_E290_base.build_flags} +; -D DISPLAY_CLASS=E290Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_E290_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_E290_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_E290_repeater_bridge_espnow] +extends = Heltec_E290_base +build_flags = + ${Heltec_E290_base.build_flags} + -D DISPLAY_CLASS=E290Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_E290_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_E290_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_E290_room_server] extends = Heltec_E290_base build_flags = diff --git a/variants/heltec_t190/platformio.ini b/variants/heltec_t190/platformio.ini index 7debe178..52bb79e0 100644 --- a/variants/heltec_t190/platformio.ini +++ b/variants/heltec_t190/platformio.ini @@ -94,6 +94,47 @@ lib_deps = ${Heltec_T190_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_T190_repeater_bridge_rs232] +; extends = Heltec_T190_base +; build_flags = +; ${Heltec_T190_base.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_T190_base.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_T190_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_T190_repeater_bridge_espnow] +extends = Heltec_T190_base +build_flags = + ${Heltec_T190_base.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_T190_base.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_T190_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_T190_room_server] extends = Heltec_T190_base build_flags = diff --git a/variants/heltec_tracker/platformio.ini b/variants/heltec_tracker/platformio.ini index f1477e9f..5c0df007 100644 --- a/variants/heltec_tracker/platformio.ini +++ b/variants/heltec_tracker/platformio.ini @@ -80,6 +80,53 @@ lib_deps = ${Heltec_tracker_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_Wireless_Tracker_repeater_bridge_rs232] +; extends = Heltec_tracker_base +; build_flags = +; ${Heltec_tracker_base.build_flags} +; -D DISPLAY_ROTATION=1 +; -D DISPLAY_CLASS=ST7735Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_tracker_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_tracker_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_Wireless_Tracker_repeater_bridge_espnow] +extends = Heltec_tracker_base +build_flags = + ${Heltec_tracker_base.build_flags} + -D DISPLAY_ROTATION=1 + -D DISPLAY_CLASS=ST7735Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_tracker_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_tracker_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_Wireless_Tracker_room_server] extends = Heltec_tracker_base build_flags = diff --git a/variants/heltec_v2/platformio.ini b/variants/heltec_v2/platformio.ini index 352ea34d..d2afe4db 100644 --- a/variants/heltec_v2/platformio.ini +++ b/variants/heltec_v2/platformio.ini @@ -40,6 +40,53 @@ lib_deps = ${Heltec_lora32_v2.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_v2_repeater_bridge_rs232] +; extends = Heltec_lora32_v2 +; build_flags = +; ${Heltec_lora32_v2.build_flags} +; -D DISPLAY_CLASS=SSD1306Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_lora32_v2.build_src_filter} +; + +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_lora32_v2.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_v2_repeater_bridge_espnow] +extends = Heltec_lora32_v2 +build_flags = + ${Heltec_lora32_v2.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v2.build_src_filter} + + + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v2.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_v2_room_server] extends = Heltec_lora32_v2 build_flags = diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 2e7ac80c..417f6edb 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -49,6 +49,51 @@ lib_deps = ${esp32_ota.lib_deps} bakercp/CRC32 @ ^2.0.0 +[env:Heltec_v3_repeater_bridge_rs232] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=5 + -D WITH_RS232_BRIDGE_TX=6 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + +[env:Heltec_v3_repeater_bridge_espnow] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_v3_room_server] extends = Heltec_lora32_v3 build_flags = @@ -186,6 +231,49 @@ lib_deps = ${esp32_ota.lib_deps} bakercp/CRC32 @ ^2.0.0 +[env:Heltec_WSL3_repeater_bridge_rs232] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=5 + -D WITH_RS232_BRIDGE_TX=6 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 + +[env:Heltec_WSL3_repeater_bridge_espnow] +extends = Heltec_lora32_v3 +build_flags = + ${Heltec_lora32_v3.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_lora32_v3.lib_deps} + ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 + [env:Heltec_WSL3_room_server] extends = Heltec_lora32_v3 build_src_filter = ${Heltec_lora32_v3.build_src_filter} diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 8de826e4..43ac2a82 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -68,6 +68,51 @@ lib_deps = ${Heltec_Wireless_Paper_base.lib_deps} ${esp32_ota.lib_deps} +; [env:Heltec_Wireless_Paper_repeater_bridge_rs232] +; extends = Heltec_Wireless_Paper_base +; build_flags = +; ${Heltec_Wireless_Paper_base.build_flags} +; -D DISPLAY_CLASS=E213Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Heltec_Wireless_Paper_base.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Heltec_Wireless_Paper_repeater_bridge_espnow] +extends = Heltec_Wireless_Paper_base +build_flags = + ${Heltec_Wireless_Paper_base.build_flags} + -D DISPLAY_CLASS=E213Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_Wireless_Paper_base.lib_deps} + ${esp32_ota.lib_deps} + [env:Heltec_Wireless_Paper_room_server] extends = Heltec_Wireless_Paper_base build_flags = diff --git a/variants/lilygo_t3s3/platformio.ini b/variants/lilygo_t3s3/platformio.ini index 637cc123..ca221108 100644 --- a/variants/lilygo_t3s3/platformio.ini +++ b/variants/lilygo_t3s3/platformio.ini @@ -52,6 +52,51 @@ lib_deps = ${LilyGo_T3S3_sx1262.lib_deps} ${esp32_ota.lib_deps} +; [env:LilyGo_T3S3_sx1262_Repeater_bridge_rs232] +; extends = LilyGo_T3S3_sx1262 +; build_flags = +; ${LilyGo_T3S3_sx1262.build_flags} +; -D DISPLAY_CLASS=SSD1306Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_T3S3_sx1262.lib_deps} +; ${esp32_ota.lib_deps} + +[env:LilyGo_T3S3_sx1262_Repeater_bridge_espnow] +extends = LilyGo_T3S3_sx1262 +build_flags = + ${LilyGo_T3S3_sx1262.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_T3S3_sx1262.lib_deps} + ${esp32_ota.lib_deps} + [env:LilyGo_T3S3_sx1262_terminal_chat] extends = LilyGo_T3S3_sx1262 build_flags = diff --git a/variants/lilygo_t3s3_sx1276/platformio.ini b/variants/lilygo_t3s3_sx1276/platformio.ini index 23c58fb8..1c0d5cf1 100644 --- a/variants/lilygo_t3s3_sx1276/platformio.ini +++ b/variants/lilygo_t3s3_sx1276/platformio.ini @@ -50,6 +50,51 @@ lib_deps = ${LilyGo_T3S3_sx1276.lib_deps} ${esp32_ota.lib_deps} +; [env:LilyGo_T3S3_sx1276_Repeater_bridge_rs232] +; extends = LilyGo_T3S3_sx1276 +; build_flags = +; ${LilyGo_T3S3_sx1276.build_flags} +; -D DISPLAY_CLASS=SSD1306Display +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} +; + +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_T3S3_sx1276.lib_deps} +; ${esp32_ota.lib_deps} + +[env:LilyGo_T3S3_sx1276_Repeater_bridge_espnow] +extends = LilyGo_T3S3_sx1276 +build_flags = + ${LilyGo_T3S3_sx1276.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_T3S3_sx1276.build_src_filter} + + + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_T3S3_sx1276.lib_deps} + ${esp32_ota.lib_deps} + [env:LilyGo_T3S3_sx1276_terminal_chat] extends = LilyGo_T3S3_sx1276 build_flags = diff --git a/variants/lilygo_tbeam_SX1262/platformio.ini b/variants/lilygo_tbeam_SX1262/platformio.ini index ea8872de..f7d1a764 100644 --- a/variants/lilygo_tbeam_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_SX1262/platformio.ini @@ -74,6 +74,47 @@ lib_deps = ${LilyGo_TBeam_SX1262.lib_deps} ${esp32_ota.lib_deps} +; [env:Tbeam_SX1262_repeater_bridge_rs232] +; extends = LilyGo_TBeam_SX1262 +; build_flags = +; ${LilyGo_TBeam_SX1262.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_TBeam_SX1262.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tbeam_SX1262_repeater_bridge_espnow] +extends = LilyGo_TBeam_SX1262 +build_flags = + ${LilyGo_TBeam_SX1262.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_TBeam_SX1262.lib_deps} + ${esp32_ota.lib_deps} + [env:Tbeam_SX1262_room_server] extends = LilyGo_TBeam_SX1262 build_flags = diff --git a/variants/lilygo_tbeam_SX1276/platformio.ini b/variants/lilygo_tbeam_SX1276/platformio.ini index 782b74c7..d7e119ef 100644 --- a/variants/lilygo_tbeam_SX1276/platformio.ini +++ b/variants/lilygo_tbeam_SX1276/platformio.ini @@ -72,6 +72,49 @@ lib_deps = ${LilyGo_TBeam_SX1276.lib_deps} ${esp32_ota.lib_deps} +; [env:Tbeam_SX1276_repeater_bridge_rs232] +; extends = LilyGo_TBeam_SX1276 +; build_flags = +; ${LilyGo_TBeam_SX1276.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D PERSISTANT_GPS=1 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${LilyGo_TBeam_SX1276.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tbeam_SX1276_repeater_bridge_espnow] +extends = LilyGo_TBeam_SX1276 +build_flags = + ${LilyGo_TBeam_SX1276.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D PERSISTANT_GPS=1 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${LilyGo_TBeam_SX1276.lib_deps} + ${esp32_ota.lib_deps} + [env:Tbeam_SX1276_room_server] extends = LilyGo_TBeam_SX1276 build_flags = diff --git a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini index e6135872..328ebf07 100644 --- a/variants/lilygo_tbeam_supreme_SX1262/platformio.ini +++ b/variants/lilygo_tbeam_supreme_SX1262/platformio.ini @@ -52,6 +52,47 @@ lib_deps = ${T_Beam_S3_Supreme_SX1262.lib_deps} ${esp32_ota.lib_deps} +; [env:T_Beam_S3_Supreme_SX1262_repeater_bridge_rs232] +; extends = T_Beam_S3_Supreme_SX1262 +; build_flags = +; ${T_Beam_S3_Supreme_SX1262.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0 +; -D ADVERT_LON=0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${T_Beam_S3_Supreme_SX1262.lib_deps} +; ${esp32_ota.lib_deps} + +[env:T_Beam_S3_Supreme_SX1262_repeater_bridge_espnow] +extends = T_Beam_S3_Supreme_SX1262 +build_flags = + ${T_Beam_S3_Supreme_SX1262.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0 + -D ADVERT_LON=0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${T_Beam_S3_Supreme_SX1262.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${T_Beam_S3_Supreme_SX1262.lib_deps} + ${esp32_ota.lib_deps} + [env:T_Beam_S3_Supreme_SX1262_room_server] extends = T_Beam_S3_Supreme_SX1262 build_flags = diff --git a/variants/lilygo_tlora_v2_1/platformio.ini b/variants/lilygo_tlora_v2_1/platformio.ini index 05a87d70..aa957fba 100644 --- a/variants/lilygo_tlora_v2_1/platformio.ini +++ b/variants/lilygo_tlora_v2_1/platformio.ini @@ -156,3 +156,51 @@ build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} lib_deps = ${LilyGo_TLora_V2_1_1_6.lib_deps} densaugeo/base64 @ ~1.4.0 + +; +; Repeater Bridges +; +[env:LilyGo_TLora_V2_1_1_6_bridge_rs232] +extends = LilyGo_TLora_V2_1_1_6 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + + + +<../examples/simple_repeater> +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=34 + -D WITH_RS232_BRIDGE_TX=25 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +; -D CORE_DEBUG_LEVEL=3 +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + ${esp32_ota.lib_deps} + +[env:LilyGo_TLora_V2_1_1_6_bridge_espnow] +extends = LilyGo_TLora_V2_1_1_6 +build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} + + + + + +<../examples/simple_repeater> +build_flags = + ${LilyGo_TLora_V2_1_1_6.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +; -D CORE_DEBUG_LEVEL=3 +lib_deps = + ${LilyGo_TLora_V2_1_1_6.lib_deps} + ${esp32_ota.lib_deps} \ No newline at end of file diff --git a/variants/meshadventurer/platformio.ini b/variants/meshadventurer/platformio.ini index 1b881c1a..be3b4943 100644 --- a/variants/meshadventurer/platformio.ini +++ b/variants/meshadventurer/platformio.ini @@ -54,6 +54,55 @@ lib_deps = ${Meshadventurer.lib_deps} ${esp32_ota.lib_deps} +; [env:Meshadventurer_sx1262_repeater_bridge_rs232] +; extends = Meshadventurer +; build_src_filter = ${Meshadventurer.build_src_filter} +; + +; +<../examples/simple_repeater> +; + +; build_flags = +; ${Meshadventurer.build_flags} +; -D RADIO_CLASS=CustomSX1262 +; -D WRAPPER_CLASS=CustomSX1262Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Meshadventurer.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Meshadventurer_sx1262_repeater_bridge_espnow] +extends = Meshadventurer +build_src_filter = ${Meshadventurer.build_src_filter} + + + +<../examples/simple_repeater> + + +build_flags = + ${Meshadventurer.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Meshadventurer.lib_deps} + ${esp32_ota.lib_deps} + [env:Meshadventurer_sx1268_repeater] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} @@ -75,6 +124,55 @@ lib_deps = ${Meshadventurer.lib_deps} ${esp32_ota.lib_deps} +; [env:Meshadventurer_sx1268_repeater_bridge_rs232] +; extends = Meshadventurer +; build_src_filter = ${Meshadventurer.build_src_filter} +; + +; +<../examples/simple_repeater> +; + +; build_flags = +; ${Meshadventurer.build_flags} +; -D RADIO_CLASS=CustomSX1268 +; -D WRAPPER_CLASS=CustomSX1268Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Meshadventurer.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Meshadventurer_sx1268_repeater_bridge_espnow] +extends = Meshadventurer +build_src_filter = ${Meshadventurer.build_src_filter} + + + +<../examples/simple_repeater> + + +build_flags = + ${Meshadventurer.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Meshadventurer.lib_deps} + ${esp32_ota.lib_deps} + [env:Meshadventurer_sx1262_companion_radio_usb] extends = Meshadventurer build_src_filter = ${Meshadventurer.build_src_filter} diff --git a/variants/station_g2/platformio.ini b/variants/station_g2/platformio.ini index 0e1631a8..908d6443 100644 --- a/variants/station_g2/platformio.ini +++ b/variants/station_g2/platformio.ini @@ -45,6 +45,47 @@ lib_deps = ${Station_G2.lib_deps} ${esp32_ota.lib_deps} +; [env:Station_G2_repeater_bridge_rs232] +; extends = Station_G2 +; build_flags = +; ${Station_G2.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Station_G2.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Station_G2.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Station_G2_repeater_bridge_espnow] +extends = Station_G2 +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Station_G2.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Station_G2.lib_deps} + ${esp32_ota.lib_deps} + [env:Station_G2_logging_repeater] extends = Station_G2 build_flags = @@ -64,6 +105,49 @@ lib_deps = ${Station_G2.lib_deps} ${esp32_ota.lib_deps} +; [env:Station_G2_logging_repeater_bridge_rs232] +; extends = Station_G2 +; build_flags = +; ${Station_G2.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D SX126X_RX_BOOSTED_GAIN=1 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_DEBUG=1 +; build_src_filter = ${Station_G2.build_src_filter} +; + +; +<../examples/simple_repeater> +; lib_deps = +; ${Station_G2.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Station_G2_logging_repeater_bridge_espnow] +extends = Station_G2 +build_flags = + ${Station_G2.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D MESH_PACKET_LOGGING=1 + -D SX126X_RX_BOOSTED_GAIN=1 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_DEBUG=1 +build_src_filter = ${Station_G2.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Station_G2.lib_deps} + ${esp32_ota.lib_deps} + [env:Station_G2_room_server] extends = Station_G2 build_src_filter = ${Station_G2.build_src_filter} diff --git a/variants/tenstar_c3/platformio.ini b/variants/tenstar_c3/platformio.ini index 4967ec55..c22b3771 100644 --- a/variants/tenstar_c3/platformio.ini +++ b/variants/tenstar_c3/platformio.ini @@ -44,6 +44,55 @@ lib_deps = ${Tenstar_esp32_C3.lib_deps} ${esp32_ota.lib_deps} +; [env:Tenstar_C3_Repeater_sx1262_bridge_rs232] +; extends = Tenstar_esp32_C3 +; build_src_filter = ${Tenstar_esp32_C3.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Tenstar_esp32_C3.build_flags} +; -D RADIO_CLASS=CustomSX1262 +; -D WRAPPER_CLASS=CustomSX1262Wrapper +; -D SX126X_RX_BOOSTED_GAIN=1 +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Tenstar_esp32_C3.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tenstar_C3_Repeater_sx1262_bridge_espnow] +extends = Tenstar_esp32_C3 +build_src_filter = ${Tenstar_esp32_C3.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Tenstar_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D SX126X_RX_BOOSTED_GAIN=1 + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Tenstar_esp32_C3.lib_deps} + ${esp32_ota.lib_deps} + [env:Tenstar_C3_Repeater_sx1268] extends = Tenstar_esp32_C3 build_src_filter = ${Tenstar_esp32_C3.build_src_filter} @@ -63,3 +112,50 @@ build_flags = lib_deps = ${Tenstar_esp32_C3.lib_deps} ${esp32_ota.lib_deps} + +; [env:Tenstar_C3_Repeater_sx1268_bridge_rs232] +; extends = Tenstar_esp32_C3 +; build_src_filter = ${Tenstar_esp32_C3.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Tenstar_esp32_C3.build_flags} +; -D RADIO_CLASS=CustomSX1268 +; -D WRAPPER_CLASS=CustomSX1268Wrapper +; -D LORA_TX_POWER=22 +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Tenstar_esp32_C3.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Tenstar_C3_Repeater_sx1268_bridge_espnow] +extends = Tenstar_esp32_C3 +build_src_filter = ${Tenstar_esp32_C3.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Tenstar_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 +lib_deps = + ${Tenstar_esp32_C3.lib_deps} + ${esp32_ota.lib_deps} diff --git a/variants/waveshare_rp2040_lora/platformio.ini b/variants/waveshare_rp2040_lora/platformio.ini index e3c812b6..f2f180aa 100644 --- a/variants/waveshare_rp2040_lora/platformio.ini +++ b/variants/waveshare_rp2040_lora/platformio.ini @@ -46,6 +46,23 @@ build_flags = ${waveshare_rp2040_lora.build_flags} build_src_filter = ${waveshare_rp2040_lora.build_src_filter} +<../examples/simple_repeater> +[env:waveshare_rp2040_lora_repeater_bridge_rs232] +extends = waveshare_rp2040_lora +build_flags = ${waveshare_rp2040_lora.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_RS232_BRIDGE=Serial2 + -D WITH_RS232_BRIDGE_RX=9 + -D WITH_RS232_BRIDGE_TX=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${waveshare_rp2040_lora.build_src_filter} + + + +<../examples/simple_repeater> + [env:waveshare_rp2040_lora_room_server] extends = waveshare_rp2040_lora build_flags = ${waveshare_rp2040_lora.build_flags} diff --git a/variants/xiao_s3_wio/platformio.ini b/variants/xiao_s3_wio/platformio.ini index b4f25e53..7408f85d 100644 --- a/variants/xiao_s3_wio/platformio.ini +++ b/variants/xiao_s3_wio/platformio.ini @@ -44,6 +44,47 @@ lib_deps = ${Xiao_S3_WIO.lib_deps} ${esp32_ota.lib_deps} +; [env:Xiao_S3_WIO_Repeater_bridge_rs232] +; extends = Xiao_S3_WIO +; build_src_filter = ${Xiao_S3_WIO.build_src_filter} +; + +; +<../examples/simple_repeater/main.cpp> +; build_flags = +; ${Xiao_S3_WIO.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${Xiao_S3_WIO.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Xiao_S3_WIO_Repeater_bridge_espnow] +extends = Xiao_S3_WIO +build_src_filter = ${Xiao_S3_WIO.build_src_filter} + + + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_S3_WIO.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Xiao_S3_WIO.lib_deps} + ${esp32_ota.lib_deps} + [env:Xiao_S3_WIO_room_server] extends = Xiao_S3_WIO build_src_filter = ${Xiao_S3_WIO.build_src_filter}