mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-27 12:46:34 +00:00
Reduce telnet stack usage fixing ESP8266 exceptions
This commit is contained in:
parent
b47a1bc1e2
commit
caac9f1257
@ -47,11 +47,8 @@ extern "C" int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t
|
|||||||
uint32_t runTimeCcys, int8_t alignPhase, uint32_t phaseOffsetCcys, bool autoPwm);
|
uint32_t runTimeCcys, int8_t alignPhase, uint32_t phaseOffsetCcys, bool autoPwm);
|
||||||
extern "C" void setTimer1Callback(uint32_t (*fn)());
|
extern "C" void setTimer1Callback(uint32_t (*fn)());
|
||||||
#ifdef USE_SERIAL_BRIDGE
|
#ifdef USE_SERIAL_BRIDGE
|
||||||
void SerialBridgePrint(char *data);
|
void SerialBridgePrintf(PGM_P formatP, ...);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TELNET
|
|
||||||
void TelnetPrint(char *data);
|
|
||||||
#endif // USE_TELNET
|
|
||||||
#ifdef USE_INFLUXDB
|
#ifdef USE_INFLUXDB
|
||||||
void InfluxDbProcess(bool use_copy = false);
|
void InfluxDbProcess(bool use_copy = false);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2655,17 +2655,10 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
|||||||
|
|
||||||
if ((loglevel <= TasmotaGlobal.seriallog_level) &&
|
if ((loglevel <= TasmotaGlobal.seriallog_level) &&
|
||||||
(TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) {
|
(TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) {
|
||||||
char* data = ext_snprintf_malloc_P("%s%s%s%s\r\n", mxtime, log_data, log_data_payload, log_data_retained);
|
TasConsole.printf("%s%s%s%s\r\n", mxtime, log_data, log_data_payload, log_data_retained);
|
||||||
if (data) {
|
|
||||||
TasConsole.print(data);
|
|
||||||
#ifdef USE_SERIAL_BRIDGE
|
#ifdef USE_SERIAL_BRIDGE
|
||||||
SerialBridgePrint(data);
|
SerialBridgePrintf("%s%s%s%s\r\n", mxtime, log_data, log_data_payload, log_data_retained);
|
||||||
#endif // USE_SERIAL_BRIDGE
|
#endif // USE_SERIAL_BRIDGE
|
||||||
#ifdef USE_TELNET
|
|
||||||
TelnetPrint(data);
|
|
||||||
#endif // USE_TELNET
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TasmotaGlobal.log_buffer) { return; } // Leave now if there is no buffer available
|
if (!TasmotaGlobal.log_buffer) { return; } // Leave now if there is no buffer available
|
||||||
|
@ -99,11 +99,18 @@ void SetSSerialConfig(uint32_t serial_config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialBridgePrint(char *data) {
|
void SerialBridgePrintf(PGM_P formatP, ...) {
|
||||||
#ifdef USE_SERIAL_BRIDGE_TEE
|
#ifdef USE_SERIAL_BRIDGE_TEE
|
||||||
if ((SB_TEE == Settings->sserial_mode) && serial_bridge_buffer) {
|
if ((SB_TEE == Settings->sserial_mode) && serial_bridge_buffer) {
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, formatP);
|
||||||
|
char* data = ext_vsnprintf_malloc_P(formatP, arg);
|
||||||
|
va_end(arg);
|
||||||
|
if (data == nullptr) { return; }
|
||||||
|
|
||||||
// SerialBridgeSerial->printf(data); // This resolves "MqttClientMask":"DVES_%06X" into "DVES_000002"
|
// SerialBridgeSerial->printf(data); // This resolves "MqttClientMask":"DVES_%06X" into "DVES_000002"
|
||||||
SerialBridgeSerial->print(data); // This does not resolve "DVES_%06X"
|
SerialBridgeSerial->print(data); // This does not resolve "DVES_%06X"
|
||||||
|
free(data);
|
||||||
}
|
}
|
||||||
#endif // USE_SERIAL_BRIDGE_TEE
|
#endif // USE_SERIAL_BRIDGE_TEE
|
||||||
}
|
}
|
||||||
@ -267,8 +274,7 @@ void SerialBridgeInit(void) {
|
|||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SBR: Serial UART%d"), SerialBridgeSerial->getUart());
|
AddLog(LOG_LEVEL_DEBUG, PSTR("SBR: Serial UART%d"), SerialBridgeSerial->getUart());
|
||||||
#endif
|
#endif
|
||||||
SerialBridgeSerial->flush();
|
SerialBridgeSerial->flush();
|
||||||
char data[] = "\r\n";
|
SerialBridgePrintf("\r\n");
|
||||||
SerialBridgePrint(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1089,11 +1089,8 @@ extern "C" {
|
|||||||
if (len+3 > LOGSZ) { strcat(log_data, "..."); } // Actual data is more
|
if (len+3 > LOGSZ) { strcat(log_data, "..."); } // Actual data is more
|
||||||
TasConsole.printf(log_data);
|
TasConsole.printf(log_data);
|
||||||
#ifdef USE_SERIAL_BRIDGE
|
#ifdef USE_SERIAL_BRIDGE
|
||||||
SerialBridgePrint(log_data);
|
SerialBridgePrintf(log_data);
|
||||||
#endif // USE_SERIAL_BRIDGE
|
#endif // USE_SERIAL_BRIDGE
|
||||||
#ifdef USE_TELNET
|
|
||||||
TelnetPrint(log_data);
|
|
||||||
#endif // USE_TELNET
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void berry_log_C(const char * berry_buf, ...) {
|
void berry_log_C(const char * berry_buf, ...) {
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
* TelnetBuffer - Show current input buffer size (default 256)
|
* TelnetBuffer - Show current input buffer size (default 256)
|
||||||
* TelnetBuffer 300 - Change input buffer size to 300 characters
|
* TelnetBuffer 300 - Change input buffer size to 300 characters
|
||||||
* TelnetColor - Show prompt, response and log colors
|
* TelnetColor - Show prompt, response and log colors
|
||||||
|
* TelnetColor 0 - Set all colors to default
|
||||||
|
* TelnetColor 1 - Set colors to defined colors
|
||||||
* TelnetColor 33,36,32 - Set prompt (yellow), response (cyan) and log (green) colors
|
* TelnetColor 33,36,32 - Set prompt (yellow), response (cyan) and log (green) colors
|
||||||
*
|
*
|
||||||
* To start telnet at restart add a rule like
|
* To start telnet at restart add a rule like
|
||||||
@ -60,35 +62,14 @@ struct {
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint16_t buffer_size;
|
uint16_t buffer_size;
|
||||||
uint16_t in_byte_counter;
|
uint16_t in_byte_counter;
|
||||||
|
uint8_t index;
|
||||||
uint8_t prompt;
|
uint8_t prompt;
|
||||||
uint8_t color[3];
|
uint8_t color[3];
|
||||||
bool overrun;
|
|
||||||
bool ip_filter_enabled;
|
bool ip_filter_enabled;
|
||||||
} Telnet;
|
} Telnet;
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
void TelnetPrint(char *data) {
|
|
||||||
if (Telnet.server) {
|
|
||||||
WiFiClient &client = Telnet.client;
|
|
||||||
if (client) {
|
|
||||||
if (1 == Telnet.prompt) {
|
|
||||||
client.write("\r\n");
|
|
||||||
Telnet.prompt = 3; // Do not print linefeed for any data
|
|
||||||
}
|
|
||||||
if (Telnet.prompt > 1) {
|
|
||||||
client.printf("\x1b[%dm", Telnet.color[Telnet.prompt -1]);
|
|
||||||
}
|
|
||||||
client.print(data); // This does not resolve "DVES_%06X"
|
|
||||||
if (Telnet.prompt > 1) {
|
|
||||||
client.printf("\x1b[0m");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
|
||||||
|
|
||||||
void TelnetLoop(void) {
|
void TelnetLoop(void) {
|
||||||
// check for a new client connection
|
// check for a new client connection
|
||||||
if ((Telnet.server) && (Telnet.server->hasClient())) {
|
if ((Telnet.server) && (Telnet.server->hasClient())) {
|
||||||
@ -100,81 +81,87 @@ void TelnetLoop(void) {
|
|||||||
if (Telnet.ip_filter != new_client.remoteIP()) {
|
if (Telnet.ip_filter != new_client.remoteIP()) {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("TLN: Rejected due to filtering"));
|
AddLog(LOG_LEVEL_INFO, PSTR("TLN: Rejected due to filtering"));
|
||||||
new_client.stop();
|
new_client.stop();
|
||||||
// } else {
|
|
||||||
// AddLog(LOG_LEVEL_INFO, PSTR("TLN: Allowed through filter"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClient &client = Telnet.client;
|
if (Telnet.client) {
|
||||||
if (client) {
|
Telnet.client.stop();
|
||||||
client.stop();
|
|
||||||
}
|
}
|
||||||
client = new_client;
|
Telnet.client = new_client;
|
||||||
if (client) {
|
if (Telnet.client) {
|
||||||
client.printf("Tasmota %s %s (%s) %s\r\n\n", TasmotaGlobal.hostname, TasmotaGlobal.version, GetBuildDateAndTime().c_str(), GetDeviceHardware().c_str());
|
Telnet.client.printf("Tasmota %s %s (%s) %s\r\n", TasmotaGlobal.hostname, TasmotaGlobal.version, GetBuildDateAndTime().c_str(), GetDeviceHardware().c_str());
|
||||||
client.printf("\x1b[%dm", Telnet.color[2]);
|
Telnet.index = 0; // Dump start of log buffer for restart messages
|
||||||
uint32_t index = 1; // Dump start of log buffer for restart messages
|
Telnet.prompt = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Telnet.client) {
|
||||||
|
// output latest log buffer data
|
||||||
|
uint32_t index = Telnet.index; // Dump log buffer
|
||||||
char* line;
|
char* line;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
bool first = true;
|
||||||
while (GetLog(TasmotaGlobal.seriallog_level, &index, &line, &len)) {
|
while (GetLog(TasmotaGlobal.seriallog_level, &index, &line, &len)) {
|
||||||
// [14:49:36.123 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
// [14:49:36.123 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
||||||
client.write(line, len -1);
|
if (first) {
|
||||||
client.write("\r\n");
|
first = false;
|
||||||
|
if (3 == Telnet.prompt) {
|
||||||
|
Telnet.client.write("\r\n");
|
||||||
|
Telnet.prompt = 2; // Do not print linefeed for any data and use log color
|
||||||
}
|
}
|
||||||
client.printf("\x1b[0m");
|
Telnet.client.printf("\x1b[%dm", Telnet.color[Telnet.prompt]);
|
||||||
Telnet.prompt = 0;
|
|
||||||
}
|
}
|
||||||
|
Telnet.client.write(line, len -1);
|
||||||
|
Telnet.client.write("\r\n");
|
||||||
}
|
}
|
||||||
|
if (!first) {
|
||||||
WiFiClient &client = Telnet.client;
|
Telnet.client.write("\x1b[0m"); // Restore colors
|
||||||
if (client) {
|
if ((0 == Telnet.index) || (Telnet.prompt != 2)) {
|
||||||
if (0 == Telnet.prompt) {
|
Telnet.client.printf("\x1b[%dm%s:#\x1b[0m ", Telnet.color[0], TasmotaGlobal.hostname); // \x1b[33m = Yellow, \x1b[0m = end color
|
||||||
client.printf("\x1b[%dm%s:#\x1b[0m ", Telnet.color[0], TasmotaGlobal.hostname); // \x1b[33m = Yellow, \x1b[0m = end color
|
Telnet.prompt = 3; // Print linefeed for non-requested data
|
||||||
Telnet.prompt = 1; // Print single linefeed for non-requested data
|
while (Telnet.client.available()) { Telnet.client.read(); } // Flush input
|
||||||
while (client.available()) { client.read(); } // Flush input
|
}
|
||||||
|
Telnet.index = index;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Input keyboard data
|
||||||
while (client.available()) {
|
while (Telnet.client.available()) {
|
||||||
yield();
|
yield();
|
||||||
uint8_t in_byte = client.read();
|
uint8_t in_byte = Telnet.client.read();
|
||||||
if (isprint(in_byte)) { // Any char between 32 and 127
|
if (isprint(in_byte)) { // Any char between 32 and 127
|
||||||
if (Telnet.in_byte_counter < Telnet.buffer_size -1) { // Add char to string if it still fits
|
if (Telnet.in_byte_counter < Telnet.buffer_size -1) { // Add char to string if it still fits
|
||||||
Telnet.buffer[Telnet.in_byte_counter++] = in_byte;
|
Telnet.buffer[Telnet.in_byte_counter++] = in_byte;
|
||||||
} else {
|
|
||||||
Telnet.overrun = true; // Signal overrun but continue reading input to flush until '\n' (EOL)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (in_byte == '\n') {
|
else if (in_byte == '\n') {
|
||||||
Telnet.buffer[Telnet.in_byte_counter] = 0; // Telnet data completed
|
Telnet.buffer[Telnet.in_byte_counter] = 0; // Telnet data completed
|
||||||
TasmotaGlobal.seriallog_level = (Settings->seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings->seriallog_level;
|
TasmotaGlobal.seriallog_level = (Settings->seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings->seriallog_level;
|
||||||
client.printf("\r"); // Move cursor to begin of line (needed for non-buffered input)
|
Telnet.client.write("\r"); // Move cursor to begin of line (needed for non-buffered input)
|
||||||
Telnet.prompt = 2; // Do not print linefeed for requested data
|
Telnet.prompt = 1; // Do not print linefeed for requested data and use response color
|
||||||
if (Telnet.overrun) {
|
if (Telnet.in_byte_counter >= Telnet.buffer_size) {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("TLN: buffer overrun"));
|
AddLog(LOG_LEVEL_INFO, PSTR("TLN: buffer overrun"));
|
||||||
} else {
|
} else {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("TLN: %s"), Telnet.buffer);
|
AddLog(LOG_LEVEL_INFO, PSTR("TLN: %s"), Telnet.buffer);
|
||||||
ExecuteCommand(Telnet.buffer, SRC_TELNET);
|
ExecuteCommand(Telnet.buffer, SRC_TELNET);
|
||||||
}
|
}
|
||||||
Telnet.in_byte_counter = 0;
|
Telnet.in_byte_counter = 0;
|
||||||
Telnet.overrun = false;
|
|
||||||
Telnet.prompt = 0; // Print prompt
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
void TelnetStop(void) {
|
void TelnetStop(void) {
|
||||||
|
if (Telnet.client) {
|
||||||
|
Telnet.client.stop();
|
||||||
|
}
|
||||||
if (Telnet.server) {
|
if (Telnet.server) {
|
||||||
Telnet.server->stop();
|
Telnet.server->stop();
|
||||||
delete Telnet.server;
|
delete Telnet.server;
|
||||||
Telnet.server = nullptr;
|
Telnet.server = nullptr;
|
||||||
}
|
}
|
||||||
WiFiClient &client = Telnet.client;
|
|
||||||
if (client) {
|
|
||||||
client.stop();
|
|
||||||
}
|
|
||||||
free(Telnet.buffer);
|
free(Telnet.buffer);
|
||||||
Telnet.buffer = nullptr;
|
Telnet.buffer = nullptr;
|
||||||
}
|
}
|
||||||
@ -264,14 +251,30 @@ void CmndTelnetBuffer(void) {
|
|||||||
|
|
||||||
void CmndTelnetColor(void) {
|
void CmndTelnetColor(void) {
|
||||||
// TelnetColor - Show prompt, response and log colors
|
// TelnetColor - Show prompt, response and log colors
|
||||||
|
// TelnetColor 0 - Set all colors to default
|
||||||
|
// TelnetColor 1 - Set colors to defined colors
|
||||||
// TelnetColor 33,37,32 - Set prompt (yellow), response (white) and log (green) colors
|
// TelnetColor 33,37,32 - Set prompt (yellow), response (white) and log (green) colors
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
uint32_t colors[] = { TELNET_COL_PROMPT, TELNET_COL_RESPONSE, TELNET_COL_LOGGING };
|
uint32_t colors[sizeof(Telnet.color)];
|
||||||
uint32_t count = ParseParameters(3, colors);
|
uint32_t count = ParseParameters(sizeof(Telnet.color), colors);
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
if (1 == count) {
|
||||||
|
if (0 == colors[0]) { // TelnetColor 0
|
||||||
|
Telnet.color[0] = 39;
|
||||||
|
Telnet.color[1] = 39;
|
||||||
|
Telnet.color[2] = 39;
|
||||||
|
}
|
||||||
|
else if (1 == colors[0]) { // TelnetColor 1
|
||||||
|
Telnet.color[0] = TELNET_COL_PROMPT;
|
||||||
|
Telnet.color[1] = TELNET_COL_RESPONSE;
|
||||||
|
Telnet.color[2] = TELNET_COL_LOGGING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sizeof(Telnet.color) == count) {
|
||||||
|
for (uint32_t i = 0; i < sizeof(Telnet.color); i++) {
|
||||||
Telnet.color[i] = colors[i];
|
Telnet.color[i] = colors[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Response_P(PSTR("{\"%s\":[%d,%d,%d]}"),
|
Response_P(PSTR("{\"%s\":[%d,%d,%d]}"),
|
||||||
XdrvMailbox.command, Telnet.color[0], Telnet.color[1], Telnet.color[2]);
|
XdrvMailbox.command, Telnet.color[0], Telnet.color[1], Telnet.color[2]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user