Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions examples/simple_repeater/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,13 @@ uint8_t MyMesh::handleAnonClockReq(const mesh::Identity& sender, uint32_t sender
memcpy(&reply_data[4], &now, 4); // include our clock (for easy clock sync, and packet hash uniqueness)
reply_data[8] = 0; // features
#ifdef WITH_RS232_BRIDGE
reply_data[8] |= 0x01; // is bridge, type UART
reply_data[8] |= RS232_BRIDGE; // is bridge, type UART
#elif WITH_ESPNOW_BRIDGE
reply_data[8] |= 0x03; // is bridge, type ESP-NOW
reply_data[8] |= ESPNOW_BRIDGE; // is bridge, type ESP-NOW
#elif WITH_USB_SERIAL_BRIDGE
reply_data[8] |= USB_SERIAL_BRIDGE; // is bridge, type USB serial
#elif WITH_TCP_BRIDGE
reply_data[8] |= TCP_BRIDGE; // is bridge, type TCP
#endif
if (_prefs.disable_fwd) { // is this repeater currently disabled
reply_data[8] |= 0x80; // is disabled
Expand Down Expand Up @@ -344,7 +348,7 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
int results_offset = 0;
uint8_t results_buffer[130];
for(int index = 0; index < count && index + offset < neighbours_count; index++){

// stop if we can't fit another entry in results
int entry_size = pubkey_prefix_length + 4 + 1;
if(results_offset + entry_size > sizeof(results_buffer)){
Expand Down Expand Up @@ -857,6 +861,12 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
#if defined(WITH_ESPNOW_BRIDGE)
, bridge(&_prefs, _mgr, &rtc)
#endif
#if defined(WITH_USB_SERIAL_BRIDGE)
, bridge(&_prefs, USB_SERIAL_STREAM, _mgr, &rtc)
#endif
#if defined(WITH_TCP_BRIDGE)
, bridge(&_prefs, _mgr, &rtc, TCP_BRIDGE_PORT)
#endif
{
last_millis = 0;
uptime_millis = 0;
Expand Down Expand Up @@ -1148,7 +1158,7 @@ void MyMesh::formatRadioStatsReply(char *reply) {
}

void MyMesh::formatPacketStatsReply(char *reply) {
StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(),
StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(),
getNumRecvFlood(), getNumRecvDirect());
}

Expand Down
21 changes: 20 additions & 1 deletion examples/simple_repeater/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
#define WITH_BRIDGE
#endif

#ifdef WITH_USB_SERIAL_BRIDGE
#include "helpers/bridges/USBSerialBridge.h"
#define WITH_BRIDGE
#endif

#ifdef WITH_TCP_BRIDGE
#include "helpers/bridges/TCPBridge.h"
#define WITH_BRIDGE
#endif

#include <helpers/AdvertDataHelpers.h>
#include <helpers/ArduinoHelpers.h>
#include <helpers/ClientACL.h>
Expand All @@ -37,8 +47,13 @@

#ifdef WITH_BRIDGE
extern AbstractBridge* bridge;
#define RS232_BRIDGE 0x01
#define ESPNOW_BRIDGE 0x03
#define USB_SERIAL_BRIDGE 0x04
#define TCP_BRIDGE 0x05
#endif


struct RepeaterStats {
uint16_t batt_milli_volts;
uint16_t curr_tx_queue_len;
Expand Down Expand Up @@ -117,6 +132,10 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
RS232Bridge bridge;
#elif defined(WITH_ESPNOW_BRIDGE)
ESPNowBridge bridge;
#elif defined(WITH_USB_SERIAL_BRIDGE)
USBSerialBridge bridge;
#elif defined(WITH_TCP_BRIDGE)
TCPBridge bridge;
#endif

void putNeighbour(const mesh::Identity& id, uint32_t timestamp, float snr);
Expand Down Expand Up @@ -236,7 +255,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
{
bridge.begin();
}
else
else
{
bridge.end();
}
Expand Down
11 changes: 11 additions & 0 deletions examples/simple_repeater/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ static unsigned long userBtnDownAt = 0;
#define USER_BTN_HOLD_OFF_MILLIS 1500
#endif

#ifdef ESP32
#ifdef WIFI_SSID
#include <helpers/esp32/SerialWifiInterface.h>
#endif
#endif

void setup() {
Serial.begin(115200);
delay(1000);
Expand Down Expand Up @@ -94,6 +100,11 @@ void setup() {
store.save("_main", the_mesh.self_id);
}

#ifdef WIFI_SSID
board.setInhibitSleep(true); // prevent sleep when WiFi is active
WiFi.begin(WIFI_SSID, WIFI_PWD);
#endif

Serial.print("Repeater ID: ");
mesh::Utils::printHex(Serial, the_mesh.self_id.pub_key, PUB_KEY_SIZE); Serial.println();

Expand Down
8 changes: 6 additions & 2 deletions src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,10 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
"rs232"
#elif WITH_ESPNOW_BRIDGE
"espnow"
#elif WITH_USB_SERIAL_BRIDGE
"usbserial"
#elif WITH_TCP_BRIDGE
"tcp"
#else
"none"
#endif
Expand Down Expand Up @@ -1138,7 +1142,7 @@ void CommonCLI::handleRegionCmd(char* command, char* reply) {
} else if (n >= 3 && strcmp(parts[1], "list") == 0) {
uint8_t mask = 0;
bool invert = false;

if (strcmp(parts[2], "allowed") == 0) {
mask = REGION_DENY_FLOOD;
invert = false; // list regions that DON'T have DENY flag
Expand All @@ -1149,7 +1153,7 @@ void CommonCLI::handleRegionCmd(char* command, char* reply) {
strcpy(reply, "Err - use 'allowed' or 'denied'");
return;
}

int len = _region_map->exportNamesTo(reply, 160, mask, invert);
if (len == 0) {
strcpy(reply, "-none-");
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/CommonCLI.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <helpers/ClientACL.h>
#include <helpers/RegionMap.h>

#if defined(WITH_RS232_BRIDGE) || defined(WITH_ESPNOW_BRIDGE)
#if defined(WITH_RS232_BRIDGE) || defined(WITH_ESPNOW_BRIDGE) || defined(WITH_USB_SERIAL_BRIDGE) || defined(WITH_TCP_BRIDGE)
#define WITH_BRIDGE
#endif

Expand Down
129 changes: 129 additions & 0 deletions src/helpers/bridges/TCPBridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include "TCPBridge.h"

#ifdef WITH_TCP_BRIDGE

TCPBridge::TCPBridge(NodePrefs* prefs, mesh::PacketManager* mgr, mesh::RTCClock* rtc, uint16_t port)
: BridgeBase(prefs, mgr, rtc), _port(port), _server(port) {}

void TCPBridge::begin() {
_server.begin();
_initialized = true;
BRIDGE_DEBUG_PRINTLN("TCP bridge listening on port %d\n", _port);
}

void TCPBridge::end() {
if (_client_connected) {
_client.stop();
_client_connected = false;
}
_server.end();
_initialized = false;
BRIDGE_DEBUG_PRINTLN("TCP bridge stopped\n");
}

void TCPBridge::loop() {
if (!_initialized) return;

// Accept new connection, displacing any existing one
WiFiClient incoming = _server.available();
if (incoming) {
if (_client_connected) {
_client.stop();
}
_client = incoming;
_client_connected = true;
_rx_buffer_pos = 0;
BRIDGE_DEBUG_PRINTLN("TCP client connected\n");
}

if (_client_connected) {
if (!_client.connected()) {
_client.stop();
_client_connected = false;
BRIDGE_DEBUG_PRINTLN("TCP client disconnected\n");
return;
}

while (_client.available()) {
uint8_t b = _client.read();

if (_rx_buffer_pos < 2) {
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 {
_rx_buffer_pos = 0;
if (b == ((BRIDGE_PACKET_MAGIC >> 8) & 0xFF)) {
_rx_buffer[_rx_buffer_pos++] = b;
}
}
} else {
_rx_buffer[_rx_buffer_pos++] = b;

if (_rx_buffer_pos >= 4) {
uint16_t len = (_rx_buffer[2] << 8) | _rx_buffer[3];

if (len > (MAX_TRANS_UNIT + 1)) {
BRIDGE_DEBUG_PRINTLN("RX invalid length %d, resetting\n", len);
_rx_buffer_pos = 0;
continue;
}

if (_rx_buffer_pos == len + TCP_OVERHEAD) {
uint16_t received_checksum = (_rx_buffer[4 + len] << 8) | _rx_buffer[5 + len];

if (validateChecksum(_rx_buffer + 4, len, received_checksum)) {
BRIDGE_DEBUG_PRINTLN("RX, len=%d crc=0x%04x\n", len, received_checksum);
mesh::Packet* pkt = _mgr->allocNew();
if (pkt) {
if (pkt->readFrom(_rx_buffer + 4, len)) {
onPacketReceived(pkt);
} else {
BRIDGE_DEBUG_PRINTLN("RX failed to parse packet\n");
_mgr->free(pkt);
}
} else {
BRIDGE_DEBUG_PRINTLN("RX failed to allocate packet\n");
}
} else {
BRIDGE_DEBUG_PRINTLN("RX checksum mismatch, rcv=0x%04x\n", received_checksum);
}
_rx_buffer_pos = 0;
}
}
}
}
}
}

void TCPBridge::sendPacket(mesh::Packet* packet) {
if (!_initialized || !packet || !_client_connected) return;

if (!_seen_packets.hasSeen(packet)) {
uint8_t buffer[MAX_TCP_PACKET_SIZE];
uint16_t len = packet->writeTo(buffer + 4);

if (len > (MAX_TRANS_UNIT + 1)) {
BRIDGE_DEBUG_PRINTLN("TX packet too large (payload=%d, max=%d)\n", len, MAX_TRANS_UNIT + 1);
return;
}

buffer[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF;
buffer[1] = BRIDGE_PACKET_MAGIC & 0xFF;
buffer[2] = (len >> 8) & 0xFF;
buffer[3] = len & 0xFF;

uint16_t checksum = fletcher16(buffer + 4, len);
buffer[4 + len] = (checksum >> 8) & 0xFF;
buffer[5 + len] = checksum & 0xFF;

_client.write(buffer, len + TCP_OVERHEAD);
BRIDGE_DEBUG_PRINTLN("TX, len=%d crc=0x%04x\n", len, checksum);
}
}

void TCPBridge::onPacketReceived(mesh::Packet* packet) {
handleReceivedPacket(packet);
}

#endif
47 changes: 47 additions & 0 deletions src/helpers/bridges/TCPBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include "helpers/bridges/BridgeBase.h"

#ifdef WITH_TCP_BRIDGE

#include <WiFiServer.h>
#include <WiFiClient.h>

/**
* Bridge using the RS232Bridge framing protocol over a WiFi TCP socket.
*
* The server listens on the port set by WITH_TCP_BRIDGE. One client is
* accepted at a time; a new connection displaces the previous one.
* WiFi must be connected before calling begin().
*
* Frame format (identical to RS232Bridge / USBSerialBridge):
* [2 bytes] Magic header: 0xC03E
* [2 bytes] Payload length
* [N bytes] Raw mesh packet bytes
* [2 bytes] Fletcher-16 checksum (over payload only)
*
* Enable with: -DWITH_TCP_BRIDGE=<port> (e.g. -DWITH_TCP_BRIDGE=4403)
*/
class TCPBridge : public BridgeBase {
public:
TCPBridge(NodePrefs* prefs, mesh::PacketManager* mgr, mesh::RTCClock* rtc, uint16_t port);

void begin() override;
void end() override;
void loop() override;
void sendPacket(mesh::Packet* packet) override;
void onPacketReceived(mesh::Packet* packet) override;

private:
static constexpr uint16_t TCP_OVERHEAD = BRIDGE_MAGIC_SIZE + BRIDGE_LENGTH_SIZE + BRIDGE_CHECKSUM_SIZE;
static constexpr uint16_t MAX_TCP_PACKET_SIZE = (MAX_TRANS_UNIT + 1) + TCP_OVERHEAD;

uint16_t _port;
WiFiServer _server;
WiFiClient _client;
bool _client_connected = false;
uint8_t _rx_buffer[MAX_TCP_PACKET_SIZE];
uint16_t _rx_buffer_pos = 0;
};

#endif
Loading