- Introduced functions to capture and manage incoming print logs. - Added a download link for the incoming print log in the web interface. - Updated device name prefix for BLE and added device name building logic. - Enhanced SerialCommand class with line handler support. - Implemented WiFi reconnect logic and status tracking.
153 lines
3.2 KiB
C++
153 lines
3.2 KiB
C++
#include "EggDuino.h"
|
|
|
|
namespace {
|
|
constexpr size_t kLogCapacity = 80;
|
|
constexpr size_t kLogLineLength = 160;
|
|
constexpr size_t kIncomingLogCapacity = 128;
|
|
constexpr size_t kIncomingLogLineLength = SERIALCOMMAND_BUFFER + 24;
|
|
|
|
char g_logLines[kLogCapacity][kLogLineLength];
|
|
uint32_t g_logSeq[kLogCapacity];
|
|
size_t g_logWritePos = 0;
|
|
uint32_t g_nextLogSeq = 1;
|
|
|
|
char g_incomingLogLines[kIncomingLogCapacity][kIncomingLogLineLength];
|
|
uint32_t g_incomingLogSeq[kIncomingLogCapacity];
|
|
size_t g_incomingLogWritePos = 0;
|
|
uint32_t g_nextIncomingLogSeq = 1;
|
|
|
|
void appendJsonEscaped(String &out, const char *text) {
|
|
out += "\"";
|
|
for (size_t i = 0; text[i] != '\0'; ++i) {
|
|
const char c = text[i];
|
|
switch (c) {
|
|
case '\\':
|
|
out += "\\\\";
|
|
break;
|
|
case '"':
|
|
out += "\\\"";
|
|
break;
|
|
case '\n':
|
|
out += "\\n";
|
|
break;
|
|
case '\r':
|
|
out += "\\r";
|
|
break;
|
|
case '\t':
|
|
out += "\\t";
|
|
break;
|
|
default:
|
|
if (static_cast<unsigned char>(c) < 0x20) {
|
|
out += '?';
|
|
} else {
|
|
out += c;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
out += "\"";
|
|
}
|
|
|
|
const char *transportLabel(ProtocolTransport transport) {
|
|
switch (transport) {
|
|
case PROTOCOL_TRANSPORT_BLE:
|
|
return "BLE";
|
|
case PROTOCOL_TRANSPORT_WIFI:
|
|
return "WIFI";
|
|
case PROTOCOL_TRANSPORT_SERIAL:
|
|
default:
|
|
return "SERIAL";
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
void Log(const String &message) {
|
|
snprintf(
|
|
g_logLines[g_logWritePos],
|
|
kLogLineLength,
|
|
"[%010lu] %s",
|
|
static_cast<unsigned long>(millis()),
|
|
message.c_str()
|
|
);
|
|
g_logSeq[g_logWritePos] = g_nextLogSeq++;
|
|
g_logWritePos = (g_logWritePos + 1) % kLogCapacity;
|
|
}
|
|
|
|
void Log(const char *message) {
|
|
Log(String(message));
|
|
}
|
|
|
|
String buildLogsJson(uint32_t sinceSeq) {
|
|
String output;
|
|
output.reserve(2048);
|
|
output += "{\"logs\":[";
|
|
uint32_t lastSeq = sinceSeq;
|
|
bool first = true;
|
|
|
|
for (size_t i = 0; i < kLogCapacity; ++i) {
|
|
const size_t idx = (g_logWritePos + i) % kLogCapacity;
|
|
const uint32_t seq = g_logSeq[idx];
|
|
if (seq == 0 || seq <= sinceSeq) {
|
|
continue;
|
|
}
|
|
|
|
if (!first) {
|
|
output += ",";
|
|
}
|
|
first = false;
|
|
output += "{\"seq\":";
|
|
output += String(seq);
|
|
output += ",\"text\":";
|
|
appendJsonEscaped(output, g_logLines[idx]);
|
|
output += "}";
|
|
lastSeq = seq;
|
|
}
|
|
|
|
output += "],\"lastSeq\":";
|
|
output += String(lastSeq);
|
|
output += "}";
|
|
return output;
|
|
}
|
|
|
|
void captureIncomingPrintLine(const char *line, ProtocolTransport transport) {
|
|
if ((line == NULL) || (line[0] == '\0')) {
|
|
return;
|
|
}
|
|
|
|
snprintf(
|
|
g_incomingLogLines[g_incomingLogWritePos],
|
|
kIncomingLogLineLength,
|
|
"[%010lu] %s %s",
|
|
static_cast<unsigned long>(millis()),
|
|
transportLabel(transport),
|
|
line
|
|
);
|
|
g_incomingLogSeq[g_incomingLogWritePos] = g_nextIncomingLogSeq++;
|
|
g_incomingLogWritePos = (g_incomingLogWritePos + 1) % kIncomingLogCapacity;
|
|
}
|
|
|
|
String buildIncomingPrintLogText() {
|
|
String output;
|
|
output.reserve(4096);
|
|
|
|
for (size_t i = 0; i < kIncomingLogCapacity; ++i) {
|
|
const size_t idx = (g_incomingLogWritePos + i) % kIncomingLogCapacity;
|
|
if (g_incomingLogSeq[idx] == 0) {
|
|
continue;
|
|
}
|
|
output += g_incomingLogLines[idx];
|
|
output += "\n";
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
void clearIncomingPrintLog() {
|
|
for (size_t i = 0; i < kIncomingLogCapacity; ++i) {
|
|
g_incomingLogSeq[i] = 0;
|
|
g_incomingLogLines[i][0] = '\0';
|
|
}
|
|
g_incomingLogWritePos = 0;
|
|
g_nextIncomingLogSeq = 1;
|
|
}
|