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