mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-15 07:09:50 +00:00
Split T-Deck firmware from microReticulum examples/lxmf_tdeck/ into its own repo. microReticulum is consumed as a git submodule dependency pinned to feat/t-deck. All include paths updated from relative symlinks to bare includes resolved via library build flags. Both tdeck (NimBLE) and tdeck-bluedroid environments compile successfully. Licensed under AGPLv3. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
125 lines
3.5 KiB
C++
125 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include "Interface.h"
|
|
#include "Bytes.h"
|
|
#include "Type.h"
|
|
|
|
#ifdef ARDUINO
|
|
#include <WiFi.h>
|
|
#include <WiFiClient.h>
|
|
#else
|
|
#include <netinet/in.h>
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
#include <string>
|
|
|
|
#define DEFAULT_TCP_PORT 4965
|
|
|
|
/**
|
|
* TCPClientInterface - TCP client interface for microReticulum.
|
|
*
|
|
* Connects to a Python RNS TCPServerInterface or another TCP server.
|
|
* Uses HDLC framing for wire protocol compatibility with Python RNS.
|
|
*
|
|
* Features:
|
|
* - Automatic reconnection with configurable retry interval
|
|
* - TCP keepalive for connection health monitoring
|
|
* - HDLC framing (0x7E flags with byte stuffing)
|
|
*
|
|
* Usage:
|
|
* TCPClientInterface* tcp = new TCPClientInterface("tcp0");
|
|
* tcp->set_target_host("192.168.1.100");
|
|
* tcp->set_target_port(4965);
|
|
* Interface interface(tcp);
|
|
* interface.start();
|
|
* Transport::register_interface(interface);
|
|
*/
|
|
class TCPClientInterface : public RNS::InterfaceImpl {
|
|
|
|
public:
|
|
// Match Python RNS constants
|
|
static const uint32_t BITRATE_GUESS = 10 * 1000 * 1000; // 10 Mbps
|
|
static const uint32_t HW_MTU = 1064; // Match UDPInterface
|
|
|
|
// Reconnection parameters (match Python RNS)
|
|
static const uint32_t RECONNECT_WAIT_MS = 5000; // 5 seconds between reconnect attempts
|
|
static const uint32_t CONNECT_TIMEOUT_MS = 5000; // 5 second connection timeout
|
|
|
|
// TCP keepalive parameters (match Python RNS)
|
|
static const int TCP_KEEPIDLE_SEC = 5;
|
|
static const int TCP_KEEPINTVL_SEC = 2;
|
|
static const int TCP_KEEPCNT_PROBES = 12;
|
|
|
|
public:
|
|
TCPClientInterface(const char* name = "TCPClient");
|
|
virtual ~TCPClientInterface();
|
|
|
|
// Configuration (call before start())
|
|
void set_target_host(const std::string& host) { _target_host = host; }
|
|
void set_target_port(int port) { _target_port = port; }
|
|
|
|
// InterfaceImpl overrides
|
|
virtual bool start();
|
|
virtual void stop();
|
|
virtual void loop();
|
|
|
|
virtual inline std::string toString() const {
|
|
return "TCPClientInterface[" + _name + "/" + _target_host + ":" + std::to_string(_target_port) + "]";
|
|
}
|
|
|
|
protected:
|
|
virtual void send_outgoing(const RNS::Bytes& data);
|
|
|
|
private:
|
|
// Connection management
|
|
bool connect();
|
|
void disconnect();
|
|
void configure_socket();
|
|
void handle_disconnect();
|
|
|
|
// HDLC frame processing
|
|
void process_incoming();
|
|
void extract_and_process_frames();
|
|
|
|
// Target server
|
|
std::string _target_host;
|
|
int _target_port = DEFAULT_TCP_PORT;
|
|
|
|
// Connection state
|
|
bool _initiator = true;
|
|
uint32_t _last_connect_attempt = 0;
|
|
bool _reconnected = false; // Set when connection re-established after being offline
|
|
uint32_t _last_data_received = 0; // Track last data receipt for stale connection detection
|
|
static const uint32_t STALE_CONNECTION_MS = 120000; // Consider connection stale after 2 min no data
|
|
|
|
public:
|
|
// Check and clear reconnection flag (for announcing after reconnect)
|
|
bool check_reconnected() {
|
|
if (_reconnected) {
|
|
_reconnected = false;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
|
|
// HDLC frame buffer for partial frame reassembly
|
|
RNS::Bytes _frame_buffer;
|
|
|
|
// Read buffer for incoming data
|
|
RNS::Bytes _read_buffer;
|
|
|
|
// Platform-specific socket
|
|
#ifdef ARDUINO
|
|
WiFiClient _client;
|
|
// WiFi credentials (for ESP32 WiFi connection)
|
|
std::string _wifi_ssid;
|
|
std::string _wifi_password;
|
|
#else
|
|
int _socket = -1;
|
|
in_addr_t _target_address = INADDR_NONE;
|
|
#endif
|
|
};
|