Второй экран показывает загрузку ОЗУ крупной цифрой и её график со шкалой 0-100 - у памяти она естественная, подбирать нечего. В углу свой значок, планка памяти вместо микросхемы: он же и говорит, какой экран открыт. Тревога в приоритете: при перегреве плата принудительно возвращается на экран процессора и кнопка не работает, пока температура не упадёт. Смысл тревоги в том, что её нельзя прощёлкать. Экран памяти выпадает из листания, если агент не шлёт ключ M - со старым агентом кнопка просто ничего не делает. То же решение подойдёт машинам без дискретной видеокарты. Выбранный экран не запоминается при перезагрузке: хранить негде. Тревоги по памяти нет намеренно - загрузка ОЗУ под 100% здесь обычное рабочее состояние. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
1.7 KiB
C++
67 lines
1.7 KiB
C++
#include "link.h"
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include "config.h"
|
|
|
|
static const size_t BUF_SIZE = 64;
|
|
static char buf[BUF_SIZE];
|
|
static size_t len = 0;
|
|
|
|
void linkBegin() {
|
|
Serial.begin(SERIAL_BAUD);
|
|
len = 0;
|
|
}
|
|
|
|
static bool parseLine(char *line, CpuStats &out) {
|
|
bool haveTemp = false;
|
|
bool haveLoad = false;
|
|
CpuStats parsed = {0.0f, 0, -1};
|
|
|
|
char *save = nullptr;
|
|
for (char *tok = strtok_r(line, ";", &save); tok; tok = strtok_r(nullptr, ";", &save)) {
|
|
char *eq = strchr(tok, '=');
|
|
if (!eq) continue;
|
|
*eq = '\0';
|
|
const char *key = tok;
|
|
const char *val = eq + 1;
|
|
|
|
if (strcmp(key, "T") == 0) {
|
|
parsed.tempC = atof(val);
|
|
haveTemp = true;
|
|
} else if (strcmp(key, "L") == 0) {
|
|
parsed.loadPct = atoi(val);
|
|
haveLoad = true;
|
|
} else if (strcmp(key, "M") == 0) {
|
|
// Память необязательна: старый агент её не шлёт, и это не повод
|
|
// отбрасывать строку целиком.
|
|
parsed.memPct = atoi(val);
|
|
}
|
|
// прочие ключи игнорируются намеренно: протокол расширяемый
|
|
}
|
|
|
|
if (!haveTemp || !haveLoad) return false;
|
|
out = parsed;
|
|
return true;
|
|
}
|
|
|
|
bool linkPoll(CpuStats &out) {
|
|
bool got = false;
|
|
while (Serial.available()) {
|
|
const char c = (char)Serial.read();
|
|
if (c == '\r') continue;
|
|
if (c == '\n') {
|
|
buf[len] = '\0';
|
|
if (len > 0 && parseLine(buf, out)) got = true;
|
|
len = 0;
|
|
continue;
|
|
}
|
|
if (len < BUF_SIZE - 1) {
|
|
buf[len++] = c;
|
|
} else {
|
|
len = 0; // строка длиннее буфера — мусор, начинаем заново
|
|
}
|
|
}
|
|
return got;
|
|
}
|