Fix serial resource checks

Fix serial resource checks (#20053)
This commit is contained in:
Theo Arends 2023-11-20 12:35:06 +01:00
parent 7d30ab5929
commit 433d69d4bc
2 changed files with 70 additions and 90 deletions

View File

@ -37,6 +37,7 @@ uint8_t client_next = 0;
uint8_t *tcp_buf = nullptr; // data transfer buffer uint8_t *tcp_buf = nullptr; // data transfer buffer
bool ip_filter_enabled = false; bool ip_filter_enabled = false;
IPAddress ip_filter; IPAddress ip_filter;
bool tcp_serial = false;
#include <TasmotaSerial.h> #include <TasmotaSerial.h>
TasmotaSerial *TCPSerial = nullptr; TasmotaSerial *TCPSerial = nullptr;
@ -58,8 +59,6 @@ void TCPLoop(void)
bool busy; // did we transfer some data? bool busy; // did we transfer some data?
int32_t buf_len; int32_t buf_len;
if (!TCPSerial) return;
// check for a new client connection // check for a new client connection
if ((server_tcp) && (server_tcp->hasClient())) { if ((server_tcp) && (server_tcp->hasClient())) {
WiFiClient new_client = server_tcp->available(); WiFiClient new_client = server_tcp->available();
@ -138,14 +137,21 @@ void TCPLoop(void)
void TCPInit(void) { void TCPInit(void) {
if (PinUsed(GPIO_TCP_RX) && PinUsed(GPIO_TCP_TX)) { if (PinUsed(GPIO_TCP_RX) && PinUsed(GPIO_TCP_TX)) {
if (0 == (0x80 & Settings->tcp_config)) // !0x80 means unitialized if (0 == (0x80 & Settings->tcp_config)) { // !0x80 means unitialized
Settings->tcp_config = 0x80 | ParseSerialConfig("8N1"); // default as 8N1 for backward compatibility Settings->tcp_config = 0x80 | ParseSerialConfig("8N1"); // default as 8N1 for backward compatibility
}
tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE); tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE);
if (!tcp_buf) { AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer")); return; } if (!tcp_buf) {
AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer"));
return;
}
if (!Settings->tcp_baudrate) { Settings->tcp_baudrate = 115200 / 1200; } if (!Settings->tcp_baudrate) {
Settings->tcp_baudrate = 115200 / 1200;
}
TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), TasmotaGlobal.seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), TasmotaGlobal.seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes
if (TCPSerial->begin(Settings->tcp_baudrate * 1200, ConvertSerialConfig(0x7F & Settings->tcp_config))) { tcp_serial = TCPSerial->begin(Settings->tcp_baudrate * 1200, ConvertSerialConfig(0x7F & Settings->tcp_config));
if (tcp_serial) {
if (TCPSerial->hardwareSerial()) { if (TCPSerial->hardwareSerial()) {
ClaimSerial(); ClaimSerial();
} }
@ -167,9 +173,6 @@ void TCPInit(void) {
// Params: port,<IPv4 allow> // Params: port,<IPv4 allow>
// //
void CmndTCPStart(void) { void CmndTCPStart(void) {
if (!TCPSerial) { return; }
int32_t tcp_port = XdrvMailbox.payload; int32_t tcp_port = XdrvMailbox.payload;
if (ArgC() == 2) { if (ArgC() == 2) {
char sub_string[XdrvMailbox.data_len]; char sub_string[XdrvMailbox.data_len];
@ -205,8 +208,6 @@ void CmndTCPStart(void) {
} }
void CmndTCPBaudrate(void) { void CmndTCPBaudrate(void) {
if (!TCPSerial) { return; }
if ((XdrvMailbox.payload >= 1200) && (XdrvMailbox.payload <= 115200)) { if ((XdrvMailbox.payload >= 1200) && (XdrvMailbox.payload <= 115200)) {
XdrvMailbox.payload /= 1200; // Make it a valid baudrate XdrvMailbox.payload /= 1200; // Make it a valid baudrate
if (Settings->tcp_baudrate != XdrvMailbox.payload) { if (Settings->tcp_baudrate != XdrvMailbox.payload) {
@ -220,8 +221,6 @@ void CmndTCPBaudrate(void) {
} }
void CmndTCPConfig(void) { void CmndTCPConfig(void) {
if (!TCPSerial) { return; }
if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.data_len > 0) {
uint8_t serial_config = ParseSerialConfig(XdrvMailbox.data); uint8_t serial_config = ParseSerialConfig(XdrvMailbox.data);
if ((serial_config >= 0) && (Settings->tcp_config != (0x80 | serial_config))) { if ((serial_config >= 0) && (Settings->tcp_config != (0x80 | serial_config))) {
@ -241,8 +240,6 @@ void CmndTCPConfig(void) {
void CmndTCPConnect(void) { void CmndTCPConnect(void) {
int32_t tcp_port = XdrvMailbox.payload; int32_t tcp_port = XdrvMailbox.payload;
if (!TCPSerial) { return; }
if (ArgC() == 2) { if (ArgC() == 2) {
char sub_string[XdrvMailbox.data_len]; char sub_string[XdrvMailbox.data_len];
WiFiClient new_client; WiFiClient new_client;
@ -283,16 +280,17 @@ bool Xdrv41(uint32_t function)
{ {
bool result = false; bool result = false;
switch (function) { if (FUNC_PRE_INIT == function) {
case FUNC_LOOP: TCPInit();
TCPLoop(); } else if (tcp_serial) {
break; switch (function) {
case FUNC_PRE_INIT: case FUNC_LOOP:
TCPInit(); TCPLoop();
break; break;
case FUNC_COMMAND: case FUNC_COMMAND:
result = DecodeCommand(kTCPCommands, TCPCommand); result = DecodeCommand(kTCPCommands, TCPCommand);
break; break;
}
} }
return result; return result;
} }

View File

@ -102,7 +102,7 @@ struct ModbusBridgeTCP
}; };
ModbusBridgeTCP modbusBridgeTCP; ModbusBridgeTCP modbusBridgeTCP;
#endif #endif // USE_MODBUS_BRIDGE_TCP
#include <TasmotaModbus.h> #include <TasmotaModbus.h>
TasmotaModbus *modbusBridgeModbus = nullptr; TasmotaModbus *modbusBridgeModbus = nullptr;
@ -171,6 +171,7 @@ struct ModbusBridge
uint8_t count = 0; // Number of values to read / write uint8_t count = 0; // Number of values to read / write
bool raw = false; bool raw = false;
uint8_t *buffer = nullptr; // Buffer for storing read / write data uint8_t *buffer = nullptr; // Buffer for storing read / write data
bool enabled = false;
}; };
ModbusBridge modbusBridge; ModbusBridge modbusBridge;
@ -193,28 +194,28 @@ void ModbusBridgeAllocError(const char* s)
// //
// Applies serial configuration to modbus serial port // Applies serial configuration to modbus serial port
// //
bool ModbusBridgeBegin(void) bool ModbusBridgeBegin(void) {
{ if ((Settings->modbus_sbaudrate < 1) || (Settings->modbus_sbaudrate > (115200 / 300))) {
if ((Settings->modbus_sbaudrate < 1) || (Settings->modbus_sbaudrate > (115200 / 300)))
Settings->modbus_sbaudrate = (uint8_t)((uint32_t)MBR_BAUDRATE / 300); Settings->modbus_sbaudrate = (uint8_t)((uint32_t)MBR_BAUDRATE / 300);
if (Settings->modbus_sconfig > TS_SERIAL_8O2) }
if (Settings->modbus_sconfig > TS_SERIAL_8O2) {
Settings->modbus_sconfig = TS_SERIAL_8N1; Settings->modbus_sconfig = TS_SERIAL_8N1;
}
int result = modbusBridgeModbus->Begin(Settings->modbus_sbaudrate * 300, ConvertSerialConfig(Settings->modbus_sconfig)); // Reinitialize modbus port with new baud rate int result = modbusBridgeModbus->Begin(Settings->modbus_sbaudrate * 300, ConvertSerialConfig(Settings->modbus_sconfig)); // Reinitialize modbus port with new baud rate
if (result) if (result) {
{ if (2 == result) {
if (2 == result)
{
ClaimSerial(); ClaimSerial();
} }
AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR %s ser init at %d baud"), (2 == result ? "HW" : "SW"), Settings->modbus_sbaudrate * 300); AddLog(LOG_LEVEL_DEBUG, PSTR("MBS: MBR %s ser init at %d baud"), (2 == result ? "HW" : "SW"), Settings->modbus_sbaudrate * 300);
if (nullptr == modbusBridge.buffer) modbusBridge.buffer = (uint8_t *)malloc(MBR_RECEIVE_BUFFER_SIZE); if (nullptr == modbusBridge.buffer) {
if (nullptr == modbusBridge.buffer) modbusBridge.buffer = (uint8_t *)malloc(MBR_RECEIVE_BUFFER_SIZE);
{ }
ModbusBridgeAllocError(PSTR("BUFFER")); if (nullptr == modbusBridge.buffer) {
result = false; ModbusBridgeAllocError(PSTR("BUFFER"));
} result = false;
}
} }
return result; return result;
@ -569,31 +570,29 @@ void ModbusBridgeHandle(void)
// //
// Inits the tasmota modbus driver, sets serialport and if TCP enabled allocates a TCP buffer // Inits the tasmota modbus driver, sets serialport and if TCP enabled allocates a TCP buffer
// //
void ModbusBridgeInit(void) void ModbusBridgeInit(void) {
{ if (PinUsed(GPIO_MBR_RX) && PinUsed(GPIO_MBR_TX)) {
if (PinUsed(GPIO_MBR_RX) && PinUsed(GPIO_MBR_TX)) modbusBridgeModbus = new TasmotaModbus(Pin(GPIO_MBR_RX), Pin(GPIO_MBR_TX), Pin(GPIO_MBR_TX_ENA));
{ if (ModbusBridgeBegin()) {
if (nullptr == modbusBridgeModbus) modbusBridgeModbus = new TasmotaModbus(Pin(GPIO_MBR_RX), Pin(GPIO_MBR_TX), Pin(GPIO_MBR_TX_ENA)); modbusBridge.enabled = true;
ModbusBridgeBegin();
#ifdef USE_MODBUS_BRIDGE_TCP #ifdef USE_MODBUS_BRIDGE_TCP
// If TCP bridge is enabled allocate a TCP receive buffer // If TCP bridge is enabled allocate a TCP receive buffer
if (nullptr == modbusBridgeTCP.tcp_buf) modbusBridgeTCP.tcp_buf = (uint8_t *)malloc(MODBUS_BRIDGE_TCP_BUF_SIZE); if (nullptr == modbusBridgeTCP.tcp_buf) modbusBridgeTCP.tcp_buf = (uint8_t *)malloc(MODBUS_BRIDGE_TCP_BUF_SIZE);
if (nullptr == modbusBridgeTCP.tcp_buf) if (nullptr == modbusBridgeTCP.tcp_buf) {
{ ModbusBridgeAllocError(PSTR("TCP"));
ModbusBridgeAllocError(PSTR("TCP")); return;
return; }
}
#ifdef MODBUS_BRIDGE_TCP_DEFAULT_PORT #ifdef MODBUS_BRIDGE_TCP_DEFAULT_PORT
else else {
{ AddLog(LOG_LEVEL_INFO, PSTR("MBS: MBRTCP Starting server on port %d"), MODBUS_BRIDGE_TCP_DEFAULT_PORT);
AddLog(LOG_LEVEL_INFO, PSTR("MBS: MBRTCP Starting server on port %d"), MODBUS_BRIDGE_TCP_DEFAULT_PORT);
modbusBridgeTCP.server_tcp = new WiFiServer(MODBUS_BRIDGE_TCP_DEFAULT_PORT); modbusBridgeTCP.server_tcp = new WiFiServer(MODBUS_BRIDGE_TCP_DEFAULT_PORT);
modbusBridgeTCP.server_tcp->begin(); // start TCP server modbusBridgeTCP.server_tcp->begin(); // start TCP server
modbusBridgeTCP.server_tcp->setNoDelay(true); modbusBridgeTCP.server_tcp->setNoDelay(true);
}
#endif // MODBUS_BRIDGE_TCP_DEFAULT_PORT
#endif // USE_MODBUS_BRIDGE_TCP
} }
#endif
#endif
} }
} }
@ -608,9 +607,6 @@ void ModbusTCPHandle(void)
bool busy; // did we transfer some data? bool busy; // did we transfer some data?
int32_t buf_len; int32_t buf_len;
if (!modbusBridgeModbus)
return;
// check for a new client connection // check for a new client connection
if ((modbusBridgeTCP.server_tcp) && (modbusBridgeTCP.server_tcp->hasClient())) if ((modbusBridgeTCP.server_tcp) && (modbusBridgeTCP.server_tcp->hasClient()))
{ {
@ -1055,13 +1051,8 @@ void CmndModbusBridgeSetConfig(void)
// //
void CmndModbusTCPStart(void) void CmndModbusTCPStart(void)
{ {
if (!modbusBridgeModbus)
{
return;
}
int32_t tcp_port = XdrvMailbox.payload; int32_t tcp_port = XdrvMailbox.payload;
if (ArgC() == 2) if (ArgC() == 2)
{ {
char sub_string[XdrvMailbox.data_len]; char sub_string[XdrvMailbox.data_len];
@ -1109,11 +1100,6 @@ void CmndModbusTCPConnect(void)
{ {
int32_t tcp_port = XdrvMailbox.payload; int32_t tcp_port = XdrvMailbox.payload;
if (!modbusBridgeModbus)
{
return;
}
if (ArgC() == 2) if (ArgC() == 2)
{ {
char sub_string[XdrvMailbox.data_len]; char sub_string[XdrvMailbox.data_len];
@ -1170,23 +1156,19 @@ bool Xdrv63(uint32_t function)
{ {
bool result = false; bool result = false;
if (FUNC_PRE_INIT == function) if (FUNC_PRE_INIT == function) {
{
ModbusBridgeInit(); ModbusBridgeInit();
} } else if (modbusBridge.enabled) {
else if (modbusBridgeModbus) switch (function) {
{ case FUNC_LOOP:
switch (function) ModbusBridgeHandle();
{
case FUNC_COMMAND:
result = DecodeCommand(kModbusBridgeCommands, ModbusBridgeCommand);
break;
case FUNC_LOOP:
ModbusBridgeHandle();
#ifdef USE_MODBUS_BRIDGE_TCP #ifdef USE_MODBUS_BRIDGE_TCP
ModbusTCPHandle(); ModbusTCPHandle();
#endif #endif
break; break;
case FUNC_COMMAND:
result = DecodeCommand(kModbusBridgeCommands, ModbusBridgeCommand);
break;
} }
} }
return result; return result;