2020-06-15 18:22:56 +01:00
|
|
|
/*
|
|
|
|
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
|
2020-06-15 18:22:56 +01:00
|
|
|
|
|
|
|
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;
|
2020-06-15 18:22:56 +01:00
|
|
|
|
|
|
|
#include <TasmotaSerial.h>
|
|
|
|
TasmotaSerial *TCPSerial = nullptr;
|
|
|
|
|
|
|
|
const char kTCPCommands[] PROGMEM = "TCP" "|" // prefix
|
2022-02-16 10:32:58 +00:00
|
|
|
"Start" "|" "Baudrate" "|" "Config" "|" "Connect"
|
2020-06-15 18:22:56 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
void (* const TCPCommand[])(void) PROGMEM = {
|
2022-02-16 10:32:58 +00:00
|
|
|
&CmndTCPStart, &CmndTCPBaudrate, &CmndTCPConfig, &CmndTCPConnect
|
2020-06-15 18:22:56 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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())) {
|
2021-08-01 12:26:42 +01:00
|
|
|
WiFiClient new_client = server_tcp->available();
|
2021-08-03 10:51:11 +01:00
|
|
|
|
2021-08-01 12:26:42 +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"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-15 18:22:56 +01:00
|
|
|
// find an empty slot
|
|
|
|
uint32_t i;
|
2021-02-28 11:50:02 +00:00
|
|
|
for (i=0; i<nitems(client_tcp); i++) {
|
2020-06-15 18:22:56 +01:00
|
|
|
WiFiClient &client = client_tcp[i];
|
|
|
|
if (!client) {
|
2021-08-01 12:26:42 +01:00
|
|
|
client = new_client;
|
2020-06-15 18:22:56 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-02-28 11:50:02 +00:00
|
|
|
if (i >= nitems(client_tcp)) {
|
|
|
|
i = client_next++ % nitems(client_tcp);
|
2020-06-15 18:22:56 +01:00
|
|
|
WiFiClient &client = client_tcp[i];
|
|
|
|
client.stop();
|
2021-08-01 12:26:42 +01:00
|
|
|
client = new_client;
|
2020-06-15 18:22:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2020-06-15 18:22:56 +01:00
|
|
|
|
2021-02-28 11:50:02 +00:00
|
|
|
for (uint32_t i=0; i<nitems(client_tcp); i++) {
|
2020-06-15 18:22:56 +01:00
|
|
|
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++) {
|
2020-06-15 18:22:56 +01:00
|
|
|
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;
|
|