Files

160 lines
4.2 KiB
C++
Raw Permalink Normal View History

2025-01-12 18:08:57 +01:00
#include "comms/UARTClient.h"
2024-04-17 20:22:49 +02:00
#include "Arduino.h"
2025-01-12 18:08:57 +01:00
#include "util/ILog.h"
2024-04-17 20:22:49 +02:00
#ifndef SERIAL_BAUD
#define SERIAL_BAUD 38400
#endif
#define CONNECTION_TIMEOUT 60 // seconds
2024-04-17 20:22:49 +02:00
#define RX_BUFFER 1024
#define TIMEOUT 250 // ms
#define MAX_PACKET_SIZE 284
2024-04-17 20:22:49 +02:00
extern const uint8_t MT_MAGIC_0;
UARTClient::UARTClient(const char *name) : SerialClient(name), isActive(false), _serial(nullptr) {}
2024-04-17 20:22:49 +02:00
/**
* @brief init serial interface
* Defaults:
* ESP32: RX0=3, TX0=1, RX1=9, TX1=10, RX2=16, TX2=17
* ESP32S2: RX0=44, TX0=43, RX1=18, TX1=17
* ESP32C3: RX0=20, TX0=21, RX1=18, TX1=19
* ESP32S3: RX0=44, TX0=43, RX1=15, TX1=16, RX2=19, TX2=20
*/
void UARTClient::init(void)
{
#if SOC_UART_NUM > 2 && defined(USE_SERIAL2)
2024-10-17 09:06:42 +02:00
ILOG_INFO("UARTClient::init SERIAL2 baud=%d", SERIAL_BAUD);
2024-04-17 20:22:49 +02:00
_serial = &Serial2;
#elif SOC_UART_NUM > 1 && defined(USE_SERIAL1)
2024-10-17 09:06:42 +02:00
ILOG_INFO("UARTClient::init SERIAL1 baud=%d", SERIAL_BAUD);
2024-04-17 20:22:49 +02:00
_serial = &Serial1;
#elif defined(ARDUINO_USB_CDC_ON_BOOT) && ARDUINO_USB_CDC_ON_BOOT
_serial = &Serial0;
2024-05-16 08:38:13 +02:00
#elif !defined(ARCH_PORTDUINO)
2024-10-17 09:06:42 +02:00
ILOG_INFO("UARTClient::init SERIAL1 baud=%d", SERIAL_BAUD);
2024-04-17 20:22:49 +02:00
_serial = &Serial;
#else
_serial = nullptr;
#endif
#if defined(ARCH_ESP32)
_serial->setTimeout(TIMEOUT);
_serial->setRxBufferSize(RX_BUFFER);
_serial->begin(SERIAL_BAUD);
#else
// not supported
#endif
#ifdef SERIAL_RX
_serial->setPins(SERIAL_RX, SERIAL_TX);
2024-10-17 09:06:42 +02:00
ILOG_INFO("UARTClient::setPins rx=%d, tx=%d with %d baud", SERIAL_RX, SERIAL_TX, SERIAL_BAUD);
2024-04-17 20:22:49 +02:00
#endif
time(&lastReceived);
2024-04-17 20:22:49 +02:00
SerialClient::init();
}
bool UARTClient::connect(void)
{
if (clientStatus != eConnected) {
ILOG_DEBUG("serial client connecting...");
setConnectionStatus(eConnecting, "Connecting...");
2024-04-17 20:22:49 +02:00
time_t timeout = millis();
while (!*_serial) {
if ((millis() - timeout) > 5) {
setConnectionStatus(eError, "Connection failed!");
ILOG_WARN("serial client connection failed!");
2024-04-17 20:22:49 +02:00
return false;
}
}
// skip some available bytes until we see magic header
int skipped = 0;
while (_serial->available()) {
if (_serial->peek() != MT_MAGIC_0) {
_serial->read();
skipped++;
delay(1);
}
isActive = true;
2024-04-17 20:22:49 +02:00
}
if (isActive) {
setConnectionStatus(eConnected, "Connected!");
ILOG_INFO("serial client connected! (skipped %d bytes)", skipped);
} else {
// pretend to be connected and start sending data
clientStatus = eConnected;
}
2024-04-17 20:22:49 +02:00
}
return clientStatus == eConnected;
2024-04-17 20:22:49 +02:00
}
bool UARTClient::disconnect(void)
{
ILOG_DEBUG("serial client disconnecting...");
isActive = false;
setConnectionStatus(eDisconnected, "Disconnected");
2024-04-17 20:22:49 +02:00
return SerialClient::disconnect();
}
bool UARTClient::isConnected(void)
{
time_t now;
time(&now);
if (now - lastReceived > CONNECTION_TIMEOUT && isActive) {
isActive = false;
setConnectionStatus(eDisconnected, "Disconnected");
}
return *_serial && (clientStatus == eConnected || isActive);
2024-04-17 20:22:49 +02:00
}
meshtastic_FromRadio UARTClient::receive(void)
{
return SerialClient::receive();
}
UARTClient::~UARTClient()
{
if (_serial) {
_serial->end();
}
2024-04-17 20:22:49 +02:00
};
// --- protected part ---
// raw write to serial UART interface
bool UARTClient::send(const uint8_t *buf, size_t len)
{
2024-10-17 09:06:42 +02:00
ILOG_TRACE("sending %d bytes to radio", len);
2024-04-17 20:22:49 +02:00
size_t wrote = _serial->write(buf, len);
if (wrote != len) {
2024-10-17 09:06:42 +02:00
ILOG_ERROR("only %d bytes were sent this time", wrote);
2024-04-17 20:22:49 +02:00
}
return wrote == len;
}
// raw read from serial UART interface
size_t UARTClient::receive(uint8_t *buf, size_t space_left)
{
size_t bytes_read = 0;
while (_serial->available() && bytes_read < MAX_PACKET_SIZE) {
2024-04-17 20:22:49 +02:00
uint8_t byte = _serial->read();
*buf++ = byte;
if (++bytes_read >= space_left) {
// no error, but serial thread is too slow (-> reduce sleep_time)
ILOG_WARN("Serial overflow!");
2024-04-17 20:22:49 +02:00
break;
}
}
if (bytes_read > 0) {
2024-10-17 09:06:42 +02:00
ILOG_TRACE("received %d bytes from serial", bytes_read);
time(&lastReceived);
isActive = true;
2024-04-17 20:22:49 +02:00
}
return bytes_read;
}