시리얼 수정
This commit is contained in:
@@ -1736,16 +1736,26 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "sendSerial") == 0) {
|
||||
const char* data = doc["data"];
|
||||
if (data && strlen(data) > 0) {
|
||||
SerialComm.println(data);
|
||||
SerialMessage msg;
|
||||
const char* hexStr = doc["data"];
|
||||
if (hexStr && strlen(hexStr) > 0) {
|
||||
uint8_t rawBuf[MAX_SERIAL_LINE_LEN]; int rawLen = 0;
|
||||
for (int i = 0; hexStr[i] && hexStr[i+1] && rawLen < MAX_SERIAL_LINE_LEN; i += 2) {
|
||||
while (hexStr[i] == ' ') i++;
|
||||
if (!hexStr[i] || !hexStr[i+1]) break;
|
||||
char h[3] = {hexStr[i], hexStr[i+1], 0};
|
||||
rawBuf[rawLen++] = (uint8_t)strtoul(h, NULL, 16);
|
||||
}
|
||||
SerialComm.write(rawBuf, rawLen);
|
||||
totalSerialTxCount++;
|
||||
// ★ TX echo: s1 패킷으로 즉시 전송 → JS handlePacket(true, hex, ts)
|
||||
char txHex[MAX_SERIAL_LINE_LEN*2+1];
|
||||
for (int i=0; i<rawLen; i++) snprintf(&txHex[i*2], 3, "%02X", rawBuf[i]);
|
||||
txHex[rawLen*2] = '\0';
|
||||
struct timeval tv; gettimeofday(&tv, NULL);
|
||||
msg.timestamp_us = (uint64_t)tv.tv_sec * 1000000ULL + tv.tv_usec;
|
||||
msg.length = min((int)(strlen(data)+2), MAX_SERIAL_LINE_LEN-1);
|
||||
snprintf((char*)msg.data, MAX_SERIAL_LINE_LEN, "%s\r\n", data);
|
||||
msg.isTx = true;
|
||||
if (ring_serial_push(&serialRing, &msg)) totalSerialTxCount++;
|
||||
uint32_t tsMs = (uint32_t)(tv.tv_sec*1000ULL + tv.tv_usec/1000ULL);
|
||||
char s1pkt[MAX_SERIAL_LINE_LEN*2+80];
|
||||
snprintf(s1pkt, sizeof(s1pkt), "{\"type\":\"s1\",\"tx\":true,\"ts\":%u,\"d\":\"%s\"}", tsMs, txHex);
|
||||
webSocket.sendTXT(num, s1pkt);
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "setSerialConfig") == 0) {
|
||||
@@ -1798,16 +1808,25 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "sendSerial2") == 0) {
|
||||
const char* data = doc["data"];
|
||||
if (data && strlen(data) > 0) {
|
||||
Serial2Comm.println(data);
|
||||
SerialMessage msg;
|
||||
const char* hexStr = doc["data"];
|
||||
if (hexStr && strlen(hexStr) > 0) {
|
||||
uint8_t rawBuf[MAX_SERIAL_LINE_LEN]; int rawLen = 0;
|
||||
for (int i = 0; hexStr[i] && hexStr[i+1] && rawLen < MAX_SERIAL_LINE_LEN; i += 2) {
|
||||
while (hexStr[i] == ' ') i++;
|
||||
if (!hexStr[i] || !hexStr[i+1]) break;
|
||||
char h[3] = {hexStr[i], hexStr[i+1], 0};
|
||||
rawBuf[rawLen++] = (uint8_t)strtoul(h, NULL, 16);
|
||||
}
|
||||
Serial2Comm.write(rawBuf, rawLen);
|
||||
totalSerial2TxCount++;
|
||||
char txHex[MAX_SERIAL_LINE_LEN*2+1];
|
||||
for (int i=0; i<rawLen; i++) snprintf(&txHex[i*2], 3, "%02X", rawBuf[i]);
|
||||
txHex[rawLen*2] = '\0';
|
||||
struct timeval tv; gettimeofday(&tv, NULL);
|
||||
msg.timestamp_us = (uint64_t)tv.tv_sec * 1000000ULL + tv.tv_usec;
|
||||
msg.length = min((int)(strlen(data)+2), MAX_SERIAL_LINE_LEN-1);
|
||||
snprintf((char*)msg.data, MAX_SERIAL_LINE_LEN, "%s\r\n", data);
|
||||
msg.isTx = true;
|
||||
if (ring_serial_push(&serial2Ring, &msg)) totalSerial2TxCount++;
|
||||
uint32_t tsMs = (uint32_t)(tv.tv_sec*1000ULL + tv.tv_usec/1000ULL);
|
||||
char s2pkt[MAX_SERIAL_LINE_LEN*2+80];
|
||||
snprintf(s2pkt, sizeof(s2pkt), "{\"type\":\"s2\",\"tx\":true,\"ts\":%u,\"d\":\"%s\"}", tsMs, txHex);
|
||||
webSocket.sendTXT(num, s2pkt);
|
||||
}
|
||||
}
|
||||
else if (strcmp(cmd, "setSerial2Config") == 0) {
|
||||
@@ -1824,6 +1843,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length)
|
||||
r["stopBits"]=serial2Settings.stopBits;
|
||||
String j; serializeJson(r,j); webSocket.sendTXT(num,j);
|
||||
}
|
||||
else if (strcmp(cmd, "ping") == 0) {
|
||||
webSocket.sendTXT(num, "{\"type\":\"pong\"}");
|
||||
}
|
||||
else if (strcmp(cmd, "setSpeed") == 0) {
|
||||
int si = doc["speed"];
|
||||
if (si >= 0 && si < 4) {
|
||||
@@ -2244,39 +2266,40 @@ void webUpdateTask(void *parameter) {
|
||||
}
|
||||
}
|
||||
|
||||
// ★ Serial RingBuffer pop (최대 10개)
|
||||
SerialMessage serialMsg;
|
||||
JsonArray serialMessages = doc.createNestedArray("serialMessages");
|
||||
int serialCnt = 0;
|
||||
while (serialCnt < 10 && ring_serial_pop(&serialRing, &serialMsg)) {
|
||||
JsonObject so = serialMessages.createNestedObject();
|
||||
so["timestamp"] = serialMsg.timestamp_us;
|
||||
so["isTx"] = serialMsg.isTx;
|
||||
char ds[MAX_SERIAL_LINE_LEN+1];
|
||||
memcpy(ds, serialMsg.data, serialMsg.length);
|
||||
ds[serialMsg.length] = '\0';
|
||||
so["data"] = ds;
|
||||
serialCnt++;
|
||||
|
||||
// Serial SD 로깅
|
||||
// ★★★ Serial1/2 데이터: update 패킷 분리 → 별도 소형 s1/s2 패킷으로 즉시 전송
|
||||
// 이유: update 패킷 JSON 크기 초과 시 전체 드롭됨 (8192 또는 12000 limit)
|
||||
{
|
||||
SerialMessage sMsg;
|
||||
while (ring_serial_pop(&serialRing, &sMsg)) {
|
||||
// raw bytes → hex string (0x80+ UTF-8 안전)
|
||||
char hexBuf[MAX_SERIAL_LINE_LEN*2+1];
|
||||
for (int hi=0; hi<sMsg.length; hi++)
|
||||
snprintf(&hexBuf[hi*2], 3, "%02X", (uint8_t)sMsg.data[hi]);
|
||||
hexBuf[sMsg.length*2] = '\0';
|
||||
// s1 패킷 직접 포맷 (StaticJsonDocument heap 절약)
|
||||
uint32_t tsMs = (uint32_t)(sMsg.timestamp_us / 1000ULL);
|
||||
char s1pkt[MAX_SERIAL_LINE_LEN*2+80];
|
||||
snprintf(s1pkt, sizeof(s1pkt),
|
||||
"{\"type\":\"s1\",\"tx\":%s,\"ts\":%u,\"d\":\"%s\"}",
|
||||
sMsg.isTx ? "true":"false", tsMs, hexBuf);
|
||||
webSocket.broadcastTXT(s1pkt);
|
||||
// SD 로깅
|
||||
if (serialLoggingEnabled && sdCardReady) {
|
||||
if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
if (serialLogFormatCSV) {
|
||||
uint64_t rt = serialMsg.timestamp_us - serialLogStartTime;
|
||||
char csvLine[256];
|
||||
int ll = snprintf(csvLine, sizeof(csvLine),
|
||||
"%llu,%s,\"%s\"\n", rt, serialMsg.isTx?"TX":"RX", ds);
|
||||
uint64_t rt = sMsg.timestamp_us - serialLogStartTime;
|
||||
char csv[256];
|
||||
int ll = snprintf(csv, sizeof(csv), "%llu,%s,\"%s\"\n",
|
||||
rt, sMsg.isTx?"TX":"RX", hexBuf);
|
||||
if (serialCsvIndex+ll <= SERIAL_CSV_BUFFER_SIZE) {
|
||||
memcpy(&serialCsvBuffer[serialCsvIndex], csvLine, ll);
|
||||
serialCsvIndex += ll;
|
||||
currentSerialFileSize += ll;
|
||||
}
|
||||
if (serialCsvIndex >= SERIAL_CSV_BUFFER_SIZE - 256) {
|
||||
if (serialLogFile) { serialLogFile.write((uint8_t*)serialCsvBuffer, serialCsvIndex); serialLogFile.flush(); serialCsvIndex=0; }
|
||||
memcpy(&serialCsvBuffer[serialCsvIndex], csv, ll);
|
||||
serialCsvIndex += ll; currentSerialFileSize += ll;
|
||||
}
|
||||
if (serialCsvIndex >= SERIAL_CSV_BUFFER_SIZE-256 && serialLogFile)
|
||||
{ serialLogFile.write((uint8_t*)serialCsvBuffer, serialCsvIndex); serialLogFile.flush(); serialCsvIndex=0; }
|
||||
} else {
|
||||
if (serialLogFile) {
|
||||
serialLogFile.write((uint8_t*)&serialMsg, sizeof(SerialMessage));
|
||||
serialLogFile.write((uint8_t*)&sMsg, sizeof(SerialMessage));
|
||||
currentSerialFileSize += sizeof(SerialMessage);
|
||||
static int bfc=0; if (++bfc>=50){serialLogFile.flush();bfc=0;}
|
||||
}
|
||||
@@ -2285,39 +2308,36 @@ void webUpdateTask(void *parameter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ★ Serial2 RingBuffer pop
|
||||
SerialMessage serial2Msg;
|
||||
JsonArray serial2Messages = doc.createNestedArray("serial2Messages");
|
||||
int s2Cnt = 0;
|
||||
while (s2Cnt < 10 && ring_serial_pop(&serial2Ring, &serial2Msg)) {
|
||||
JsonObject so = serial2Messages.createNestedObject();
|
||||
so["timestamp"] = serial2Msg.timestamp_us;
|
||||
so["isTx"] = serial2Msg.isTx;
|
||||
char ds[MAX_SERIAL_LINE_LEN+1];
|
||||
memcpy(ds, serial2Msg.data, serial2Msg.length);
|
||||
ds[serial2Msg.length] = '\0';
|
||||
so["data"] = ds;
|
||||
s2Cnt++;
|
||||
|
||||
}
|
||||
{
|
||||
SerialMessage sMsg2;
|
||||
while (ring_serial_pop(&serial2Ring, &sMsg2)) {
|
||||
char hexBuf2[MAX_SERIAL_LINE_LEN*2+1];
|
||||
for (int hi=0; hi<sMsg2.length; hi++)
|
||||
snprintf(&hexBuf2[hi*2], 3, "%02X", (uint8_t)sMsg2.data[hi]);
|
||||
hexBuf2[sMsg2.length*2] = '\0';
|
||||
uint32_t tsMs2 = (uint32_t)(sMsg2.timestamp_us / 1000ULL);
|
||||
char s2pkt[MAX_SERIAL_LINE_LEN*2+80];
|
||||
snprintf(s2pkt, sizeof(s2pkt),
|
||||
"{\"type\":\"s2\",\"tx\":%s,\"ts\":%u,\"d\":\"%s\"}",
|
||||
sMsg2.isTx ? "true":"false", tsMs2, hexBuf2);
|
||||
webSocket.broadcastTXT(s2pkt);
|
||||
if (serial2LoggingEnabled && sdCardReady) {
|
||||
if (xSemaphoreTake(sdMutex, pdMS_TO_TICKS(10)) == pdTRUE) {
|
||||
if (serial2LogFormatCSV) {
|
||||
uint64_t rt = serial2Msg.timestamp_us - serial2LogStartTime;
|
||||
char csvLine[256];
|
||||
int ll = snprintf(csvLine, sizeof(csvLine),
|
||||
"%llu,%s,\"%s\"\n", rt, serial2Msg.isTx?"TX":"RX", ds);
|
||||
uint64_t rt = sMsg2.timestamp_us - serial2LogStartTime;
|
||||
char csv[256];
|
||||
int ll = snprintf(csv, sizeof(csv), "%llu,%s,\"%s\"\n",
|
||||
rt, sMsg2.isTx?"TX":"RX", hexBuf2);
|
||||
if (serial2CsvIndex+ll <= SERIAL2_CSV_BUFFER_SIZE) {
|
||||
memcpy(&serial2CsvBuffer[serial2CsvIndex], csvLine, ll);
|
||||
serial2CsvIndex += ll;
|
||||
currentSerial2FileSize += ll;
|
||||
}
|
||||
if (serial2CsvIndex >= SERIAL2_CSV_BUFFER_SIZE - 256) {
|
||||
if (serial2LogFile) { serial2LogFile.write((uint8_t*)serial2CsvBuffer, serial2CsvIndex); serial2LogFile.flush(); serial2CsvIndex=0; }
|
||||
memcpy(&serial2CsvBuffer[serial2CsvIndex], csv, ll);
|
||||
serial2CsvIndex += ll; currentSerial2FileSize += ll;
|
||||
}
|
||||
if (serial2CsvIndex >= SERIAL2_CSV_BUFFER_SIZE-256 && serial2LogFile)
|
||||
{ serial2LogFile.write((uint8_t*)serial2CsvBuffer, serial2CsvIndex); serial2LogFile.flush(); serial2CsvIndex=0; }
|
||||
} else {
|
||||
if (serial2LogFile) {
|
||||
serial2LogFile.write((uint8_t*)&serial2Msg, sizeof(SerialMessage));
|
||||
serial2LogFile.write((uint8_t*)&sMsg2, sizeof(SerialMessage));
|
||||
currentSerial2FileSize += sizeof(SerialMessage);
|
||||
static int bfc2=0; if (++bfc2>=50){serial2LogFile.flush();bfc2=0;}
|
||||
}
|
||||
@@ -2326,7 +2346,7 @@ void webUpdateTask(void *parameter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
String json;
|
||||
size_t jsonSize = serializeJson(doc, json);
|
||||
if (jsonSize > 0 && jsonSize < 8192) webSocket.broadcastTXT(json);
|
||||
@@ -2655,8 +2675,8 @@ void setup() {
|
||||
xTaskCreatePinnedToCore(sdMonitorTask, "SD_MONITOR", 4096, NULL, 1, NULL, 1);
|
||||
xTaskCreatePinnedToCore(sdFlushTask, "SD_FLUSH", 4096, NULL, 9, &sdFlushTaskHandle, 0);
|
||||
xTaskCreatePinnedToCore(sdWriteTask, "SD_WRITE", 18576, NULL, 8, &sdWriteTaskHandle, 0);
|
||||
xTaskCreatePinnedToCore(serialRxTask, "SERIAL_RX", 6144, NULL, 6, &serialRxTaskHandle, 0);
|
||||
xTaskCreatePinnedToCore(serial2RxTask, "SERIAL2_RX", 6144, NULL, 6, &serial2RxTaskHandle, 0);
|
||||
xTaskCreatePinnedToCore(serialRxTask, "SERIAL_RX", 6144, NULL, 6, &serialRxTaskHandle, 1);
|
||||
xTaskCreatePinnedToCore(serial2RxTask, "SERIAL2_RX", 6144, NULL, 6, &serial2RxTaskHandle, 1);
|
||||
if (timeSyncStatus.rtcAvailable)
|
||||
xTaskCreatePinnedToCore(rtcSyncTask,"RTC_SYNC", 3072, NULL, 0, &rtcTaskHandle, 0);
|
||||
// ★ canRxTask 마지막 생성 (Core 1 Pri 24 → 이 시점엔 setup() 완료 직전)
|
||||
|
||||
Reference in New Issue
Block a user