Tasmota/tasmota/tasmota_xdrv_driver/xdrv_41_tcp_bridge.ino

299 lines
9.0 KiB
Arduino
Raw Normal View History

/*
xdrv_41_tcp_bridge.ino - TCP to serial bridge
2021-01-01 12:44:04 +00:00
Copyright (C) 2021 Theo Arends and Stephan Hadinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_TCP_BRIDGE
#define XDRV_41 41
#ifndef TCP_BRIDGE_CONNECTIONS
#define TCP_BRIDGE_CONNECTIONS 2 // number of maximum parallel connections
#endif
#ifndef TCP_BRIDGE_BUF_SIZE
#define TCP_BRIDGE_BUF_SIZE 255 // size of the buffer, above 132 required for efficient XMODEM
#endif
//const uint16_t tcp_port = 8880;
WiFiServer *server_tcp = nullptr;
//WiFiClient client_tcp1, client_tcp2;
WiFiClient client_tcp[TCP_BRIDGE_CONNECTIONS];
uint8_t client_next = 0;
uint8_t *tcp_buf = nullptr; // data transfer buffer
2021-08-03 10:51:11 +01:00
IPAddress ip_filter;
#include <TasmotaSerial.h>
TasmotaSerial *TCPSerial = nullptr;
const char kTCPCommands[] PROGMEM = "TCP" "|" // prefix
2022-02-16 10:32:58 +00:00
"Start" "|" "Baudrate" "|" "Config" "|" "Connect"
;
void (* const TCPCommand[])(void) PROGMEM = {
2022-02-16 10:32:58 +00:00
&CmndTCPStart, &CmndTCPBaudrate, &CmndTCPConfig, &CmndTCPConnect
};
//
// Called at event loop, checks for incoming data from the CC2530
//
void TCPLoop(void)
{
uint8_t c;
bool busy; // did we transfer some data?
int32_t buf_len;
if (!TCPSerial) return;
// check for a new client connection
if ((server_tcp) && (server_tcp->hasClient())) {
WiFiClient new_client = server_tcp->available();
2021-08-03 10:51:11 +01:00
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Got connection from %s"), new_client.remoteIP().toString().c_str());
// Check for IP filtering if it's enabled.
if (ip_filter) {
if (ip_filter != new_client.remoteIP()) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Rejected due to filtering"));
new_client.stop();
} else {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Allowed through filter"));
}
}
// find an empty slot
uint32_t i;
2021-02-28 11:50:02 +00:00
for (i=0; i<nitems(client_tcp); i++) {
WiFiClient &client = client_tcp[i];
if (!client) {
client = new_client;
break;
}
}
2021-02-28 11:50:02 +00:00
if (i >= nitems(client_tcp)) {
i = client_next++ % nitems(client_tcp);
WiFiClient &client = client_tcp[i];
client.stop();
client = new_client;
}
}
do {
busy = false; // exit loop if no data was transferred
// start reading the UART, this buffer can quickly overflow
buf_len = 0;
while ((buf_len < TCP_BRIDGE_BUF_SIZE) && (TCPSerial->available())) {
c = TCPSerial->read();
if (c >= 0) {
tcp_buf[buf_len++] = c;
busy = true;
}
}
if (buf_len > 0) {
2022-02-26 17:02:16 +00:00
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_TCP "from MCU: %*_H"), buf_len, tcp_buf);
2021-02-28 11:50:02 +00:00
for (uint32_t i=0; i<nitems(client_tcp); i++) {
WiFiClient &client = client_tcp[i];
if (client) { client.write(tcp_buf, buf_len); }
}
}
// handle data received from TCP
2021-02-28 11:50:02 +00:00
for (uint32_t i=0; i<nitems(client_tcp); i++) {
WiFiClient &client = client_tcp[i];
buf_len = 0;
while (client && (buf_len < TCP_BRIDGE_BUF_SIZE) && (client.available())) {
c = client.read();
if (c >= 0) {
tcp_buf[buf_len++] = c;