ESP32/main/metrics_protocol.c
2026-06-23 20:38:23 +08:00

552 lines
18 KiB
C

#include "metrics_protocol.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int clamp_percent(int value)
{
if (value < 0) {
return 0;
}
if (value > 100) {
return 100;
}
return value;
}
static bool parse_int_token(char **cursor, int *out)
{
char *token = strsep(cursor, ",");
if (token == NULL || token[0] == '\0') {
return false;
}
char *end = NULL;
long value = strtol(token, &end, 10);
if (end == token || *end != '\0') {
return false;
}
*out = (int)value;
return true;
}
static void set_disk_text(ui_metrics_t *metrics, const char *disk_text)
{
if (disk_text == NULL || disk_text[0] == '\0') {
metrics->disk_text[0] = '\0';
return;
}
snprintf(metrics->disk_text, sizeof(metrics->disk_text), "%s", disk_text);
}
static void set_optional_defaults(ui_metrics_t *metrics)
{
metrics->codex_5h_percent = -1;
metrics->codex_week_percent = -1;
metrics->codex_5h_reset_mins = -1;
metrics->codex_week_reset_mins = -1;
metrics->codex_reset_credits = -1;
metrics->codex_today_tokens_m10 = -1;
metrics->codex_daily_count = 0;
for (int i = 0; i < UI_CODEX_DAILY_BAR_COUNT; i++) {
metrics->codex_daily_percent[i] = -1;
}
metrics->zhipu_status = 0;
metrics->zhipu_quota_percent = -1;
metrics->zhipu_latency_ms = -1;
metrics->zhipu_5h_percent = -1;
metrics->zhipu_week_percent = -1;
metrics->zhipu_5h_reset_mins = -1;
metrics->zhipu_week_reset_mins = -1;
}
static void parse_codex_daily_bars(ui_metrics_t *metrics, const char *daily_text)
{
metrics->codex_daily_count = 0;
for (int i = 0; i < UI_CODEX_DAILY_BAR_COUNT; i++) {
metrics->codex_daily_percent[i] = -1;
}
if (daily_text == NULL || daily_text[0] == '\0') {
return;
}
char buffer[96];
snprintf(buffer, sizeof(buffer), "%s", daily_text);
char *cursor = buffer;
char *token = NULL;
while ((token = strsep(&cursor, ":")) != NULL && metrics->codex_daily_count < UI_CODEX_DAILY_BAR_COUNT) {
if (token[0] == '\0') {
continue;
}
char *end = NULL;
long value = strtol(token, &end, 10);
if (end == token || *end != '\0') {
continue;
}
metrics->codex_daily_percent[metrics->codex_daily_count] = clamp_percent((int)value);
metrics->codex_daily_count++;
}
}
static bool parse_sys2_line(const char *line, ui_metrics_t *metrics)
{
char buffer[320];
snprintf(buffer, sizeof(buffer), "%s", line);
char *cursor = buffer;
char *tag = strsep(&cursor, ",");
if (tag == NULL || strcmp(tag, "SYS2") != 0) {
return false;
}
int cpu = 0;
int cpu_mhz = 0;
int mem = 0;
int mem_used = 0;
int mem_total = 0;
int disk_count = 0;
int disk_percent = 0;
int disk_read = 0;
int disk_write = 0;
int rx = 0;
int tx = 0;
if (!parse_int_token(&cursor, &cpu) ||
!parse_int_token(&cursor, &cpu_mhz) ||
!parse_int_token(&cursor, &mem) ||
!parse_int_token(&cursor, &mem_used) ||
!parse_int_token(&cursor, &mem_total) ||
!parse_int_token(&cursor, &disk_count) ||
!parse_int_token(&cursor, &disk_percent) ||
!parse_int_token(&cursor, &disk_read) ||
!parse_int_token(&cursor, &disk_write) ||
!parse_int_token(&cursor, &rx) ||
!parse_int_token(&cursor, &tx)) {
return false;
}
metrics->cpu_percent = clamp_percent(cpu);
metrics->cpu_mhz = cpu_mhz;
metrics->memory_percent = clamp_percent(mem);
metrics->memory_used_mb = mem_used;
metrics->memory_total_mb = mem_total;
metrics->disk_count = disk_count;
metrics->disk_percent = clamp_percent(disk_percent);
metrics->disk_read_kbps = disk_read;
metrics->disk_write_kbps = disk_write;
metrics->rx_kbps = rx;
metrics->tx_kbps = tx;
set_disk_text(metrics, cursor);
return true;
}
static bool parse_sys3_line(const char *line, ui_metrics_t *metrics)
{
char buffer[384];
snprintf(buffer, sizeof(buffer), "%s", line);
char *cursor = buffer;
char *tag = strsep(&cursor, ",");
if (tag == NULL || strcmp(tag, "SYS3") != 0) {
return false;
}
int cpu = 0;
int cpu_mhz = 0;
int mem = 0;
int mem_used = 0;
int mem_total = 0;
int disk_count = 0;
int disk_percent = 0;
int disk_read = 0;
int disk_write = 0;
int rx = 0;
int tx = 0;
int codex_5h = -1;
int codex_week = -1;
int codex_5h_reset = -1;
int codex_week_reset = -1;
int codex_credits = -1;
int zhipu_status = 0;
int zhipu_quota = -1;
int zhipu_latency = -1;
if (!parse_int_token(&cursor, &cpu) ||
!parse_int_token(&cursor, &cpu_mhz) ||
!parse_int_token(&cursor, &mem) ||
!parse_int_token(&cursor, &mem_used) ||
!parse_int_token(&cursor, &mem_total) ||
!parse_int_token(&cursor, &disk_count) ||
!parse_int_token(&cursor, &disk_percent) ||
!parse_int_token(&cursor, &disk_read) ||
!parse_int_token(&cursor, &disk_write) ||
!parse_int_token(&cursor, &rx) ||
!parse_int_token(&cursor, &tx) ||
!parse_int_token(&cursor, &codex_5h) ||
!parse_int_token(&cursor, &codex_week) ||
!parse_int_token(&cursor, &codex_5h_reset) ||
!parse_int_token(&cursor, &codex_week_reset) ||
!parse_int_token(&cursor, &codex_credits) ||
!parse_int_token(&cursor, &zhipu_status) ||
!parse_int_token(&cursor, &zhipu_quota) ||
!parse_int_token(&cursor, &zhipu_latency)) {
return false;
}
metrics->cpu_percent = clamp_percent(cpu);
metrics->cpu_mhz = cpu_mhz;
metrics->memory_percent = clamp_percent(mem);
metrics->memory_used_mb = mem_used;
metrics->memory_total_mb = mem_total;
metrics->disk_count = disk_count;
metrics->disk_percent = clamp_percent(disk_percent);
metrics->disk_read_kbps = disk_read;
metrics->disk_write_kbps = disk_write;
metrics->rx_kbps = rx;
metrics->tx_kbps = tx;
metrics->codex_5h_percent = (codex_5h >= 0) ? clamp_percent(codex_5h) : -1;
metrics->codex_week_percent = (codex_week >= 0) ? clamp_percent(codex_week) : -1;
metrics->codex_5h_reset_mins = codex_5h_reset;
metrics->codex_week_reset_mins = codex_week_reset;
metrics->codex_reset_credits = codex_credits;
metrics->zhipu_status = zhipu_status;
metrics->zhipu_quota_percent = (zhipu_quota >= 0) ? clamp_percent(zhipu_quota) : -1;
metrics->zhipu_latency_ms = zhipu_latency;
metrics->zhipu_5h_percent = metrics->zhipu_quota_percent;
metrics->zhipu_week_percent = -1;
metrics->zhipu_5h_reset_mins = -1;
metrics->zhipu_week_reset_mins = -1;
set_disk_text(metrics, cursor);
return true;
}
static bool parse_sys4_line(const char *line, ui_metrics_t *metrics)
{
char buffer[384];
snprintf(buffer, sizeof(buffer), "%s", line);
char *cursor = buffer;
char *tag = strsep(&cursor, ",");
if (tag == NULL || strcmp(tag, "SYS4") != 0) {
return false;
}
int cpu = 0;
int cpu_mhz = 0;
int mem = 0;
int mem_used = 0;
int mem_total = 0;
int disk_count = 0;
int disk_percent = 0;
int disk_read = 0;
int disk_write = 0;
int rx = 0;
int tx = 0;
int codex_5h = -1;
int codex_week = -1;
int codex_5h_reset = -1;
int codex_week_reset = -1;
int codex_credits = -1;
int zhipu_status = 0;
int zhipu_5h = -1;
int zhipu_week = -1;
int zhipu_5h_reset = -1;
int zhipu_week_reset = -1;
if (!parse_int_token(&cursor, &cpu) ||
!parse_int_token(&cursor, &cpu_mhz) ||
!parse_int_token(&cursor, &mem) ||
!parse_int_token(&cursor, &mem_used) ||
!parse_int_token(&cursor, &mem_total) ||
!parse_int_token(&cursor, &disk_count) ||
!parse_int_token(&cursor, &disk_percent) ||
!parse_int_token(&cursor, &disk_read) ||
!parse_int_token(&cursor, &disk_write) ||
!parse_int_token(&cursor, &rx) ||
!parse_int_token(&cursor, &tx) ||
!parse_int_token(&cursor, &codex_5h) ||
!parse_int_token(&cursor, &codex_week) ||
!parse_int_token(&cursor, &codex_5h_reset) ||
!parse_int_token(&cursor, &codex_week_reset) ||
!parse_int_token(&cursor, &codex_credits) ||
!parse_int_token(&cursor, &zhipu_status) ||
!parse_int_token(&cursor, &zhipu_5h) ||
!parse_int_token(&cursor, &zhipu_week) ||
!parse_int_token(&cursor, &zhipu_5h_reset) ||
!parse_int_token(&cursor, &zhipu_week_reset)) {
return false;
}
metrics->cpu_percent = clamp_percent(cpu);
metrics->cpu_mhz = cpu_mhz;
metrics->memory_percent = clamp_percent(mem);
metrics->memory_used_mb = mem_used;
metrics->memory_total_mb = mem_total;
metrics->disk_count = disk_count;
metrics->disk_percent = clamp_percent(disk_percent);
metrics->disk_read_kbps = disk_read;
metrics->disk_write_kbps = disk_write;
metrics->rx_kbps = rx;
metrics->tx_kbps = tx;
metrics->codex_5h_percent = (codex_5h >= 0) ? clamp_percent(codex_5h) : -1;
metrics->codex_week_percent = (codex_week >= 0) ? clamp_percent(codex_week) : -1;
metrics->codex_5h_reset_mins = codex_5h_reset;
metrics->codex_week_reset_mins = codex_week_reset;
metrics->codex_reset_credits = codex_credits;
metrics->zhipu_status = zhipu_status;
metrics->zhipu_5h_percent = (zhipu_5h >= 0) ? clamp_percent(zhipu_5h) : -1;
metrics->zhipu_week_percent = (zhipu_week >= 0) ? clamp_percent(zhipu_week) : -1;
metrics->zhipu_5h_reset_mins = zhipu_5h_reset;
metrics->zhipu_week_reset_mins = zhipu_week_reset;
metrics->zhipu_quota_percent = metrics->zhipu_5h_percent;
metrics->zhipu_latency_ms = -1;
set_disk_text(metrics, cursor);
return true;
}
static bool parse_sys5_line(const char *line, ui_metrics_t *metrics)
{
char buffer[384];
snprintf(buffer, sizeof(buffer), "%s", line);
char *cursor = buffer;
char *tag = strsep(&cursor, ",");
if (tag == NULL || strcmp(tag, "SYS5") != 0) {
return false;
}
int cpu = 0;
int cpu_mhz = 0;
int mem = 0;
int mem_used = 0;
int mem_total = 0;
int disk_count = 0;
int disk_percent = 0;
int disk_read = 0;
int disk_write = 0;
int rx = 0;
int tx = 0;
int codex_5h = -1;
int codex_week = -1;
int codex_5h_reset = -1;
int codex_week_reset = -1;
int codex_credits = -1;
int codex_today_tokens_m10 = -1;
int zhipu_status = 0;
int zhipu_5h = -1;
int zhipu_week = -1;
int zhipu_5h_reset = -1;
int zhipu_week_reset = -1;
if (!parse_int_token(&cursor, &cpu) ||
!parse_int_token(&cursor, &cpu_mhz) ||
!parse_int_token(&cursor, &mem) ||
!parse_int_token(&cursor, &mem_used) ||
!parse_int_token(&cursor, &mem_total) ||
!parse_int_token(&cursor, &disk_count) ||
!parse_int_token(&cursor, &disk_percent) ||
!parse_int_token(&cursor, &disk_read) ||
!parse_int_token(&cursor, &disk_write) ||
!parse_int_token(&cursor, &rx) ||
!parse_int_token(&cursor, &tx) ||
!parse_int_token(&cursor, &codex_5h) ||
!parse_int_token(&cursor, &codex_week) ||
!parse_int_token(&cursor, &codex_5h_reset) ||
!parse_int_token(&cursor, &codex_week_reset) ||
!parse_int_token(&cursor, &codex_credits) ||
!parse_int_token(&cursor, &codex_today_tokens_m10) ||
!parse_int_token(&cursor, &zhipu_status) ||
!parse_int_token(&cursor, &zhipu_5h) ||
!parse_int_token(&cursor, &zhipu_week) ||
!parse_int_token(&cursor, &zhipu_5h_reset) ||
!parse_int_token(&cursor, &zhipu_week_reset)) {
return false;
}
metrics->cpu_percent = clamp_percent(cpu);
metrics->cpu_mhz = cpu_mhz;
metrics->memory_percent = clamp_percent(mem);
metrics->memory_used_mb = mem_used;
metrics->memory_total_mb = mem_total;
metrics->disk_count = disk_count;
metrics->disk_percent = clamp_percent(disk_percent);
metrics->disk_read_kbps = disk_read;
metrics->disk_write_kbps = disk_write;
metrics->rx_kbps = rx;
metrics->tx_kbps = tx;
metrics->codex_5h_percent = (codex_5h >= 0) ? clamp_percent(codex_5h) : -1;
metrics->codex_week_percent = (codex_week >= 0) ? clamp_percent(codex_week) : -1;
metrics->codex_5h_reset_mins = codex_5h_reset;
metrics->codex_week_reset_mins = codex_week_reset;
metrics->codex_reset_credits = codex_credits;
metrics->codex_today_tokens_m10 = codex_today_tokens_m10;
metrics->zhipu_status = zhipu_status;
metrics->zhipu_5h_percent = (zhipu_5h >= 0) ? clamp_percent(zhipu_5h) : -1;
metrics->zhipu_week_percent = (zhipu_week >= 0) ? clamp_percent(zhipu_week) : -1;
metrics->zhipu_5h_reset_mins = zhipu_5h_reset;
metrics->zhipu_week_reset_mins = zhipu_week_reset;
metrics->zhipu_quota_percent = metrics->zhipu_5h_percent;
metrics->zhipu_latency_ms = -1;
set_disk_text(metrics, cursor);
return true;
}
static bool parse_sys6_line(const char *line, ui_metrics_t *metrics)
{
char buffer[512];
snprintf(buffer, sizeof(buffer), "%s", line);
char *cursor = buffer;
char *tag = strsep(&cursor, ",");
if (tag == NULL || strcmp(tag, "SYS6") != 0) {
return false;
}
int cpu = 0;
int cpu_mhz = 0;
int mem = 0;
int mem_used = 0;
int mem_total = 0;
int disk_count = 0;
int disk_percent = 0;
int disk_read = 0;
int disk_write = 0;
int rx = 0;
int tx = 0;
int codex_5h = -1;
int codex_week = -1;
int codex_5h_reset = -1;
int codex_week_reset = -1;
int codex_credits = -1;
int codex_today_tokens_m10 = -1;
int zhipu_status = 0;
int zhipu_5h = -1;
int zhipu_week = -1;
int zhipu_5h_reset = -1;
int zhipu_week_reset = -1;
if (!parse_int_token(&cursor, &cpu) ||
!parse_int_token(&cursor, &cpu_mhz) ||
!parse_int_token(&cursor, &mem) ||
!parse_int_token(&cursor, &mem_used) ||
!parse_int_token(&cursor, &mem_total) ||
!parse_int_token(&cursor, &disk_count) ||
!parse_int_token(&cursor, &disk_percent) ||
!parse_int_token(&cursor, &disk_read) ||
!parse_int_token(&cursor, &disk_write) ||
!parse_int_token(&cursor, &rx) ||
!parse_int_token(&cursor, &tx) ||
!parse_int_token(&cursor, &codex_5h) ||
!parse_int_token(&cursor, &codex_week) ||
!parse_int_token(&cursor, &codex_5h_reset) ||
!parse_int_token(&cursor, &codex_week_reset) ||
!parse_int_token(&cursor, &codex_credits) ||
!parse_int_token(&cursor, &codex_today_tokens_m10)) {
return false;
}
char *daily_text = strsep(&cursor, ",");
if (daily_text == NULL ||
!parse_int_token(&cursor, &zhipu_status) ||
!parse_int_token(&cursor, &zhipu_5h) ||
!parse_int_token(&cursor, &zhipu_week) ||
!parse_int_token(&cursor, &zhipu_5h_reset) ||
!parse_int_token(&cursor, &zhipu_week_reset)) {
return false;
}
metrics->cpu_percent = clamp_percent(cpu);
metrics->cpu_mhz = cpu_mhz;
metrics->memory_percent = clamp_percent(mem);
metrics->memory_used_mb = mem_used;
metrics->memory_total_mb = mem_total;
metrics->disk_count = disk_count;
metrics->disk_percent = clamp_percent(disk_percent);
metrics->disk_read_kbps = disk_read;
metrics->disk_write_kbps = disk_write;
metrics->rx_kbps = rx;
metrics->tx_kbps = tx;
metrics->codex_5h_percent = (codex_5h >= 0) ? clamp_percent(codex_5h) : -1;
metrics->codex_week_percent = (codex_week >= 0) ? clamp_percent(codex_week) : -1;
metrics->codex_5h_reset_mins = codex_5h_reset;
metrics->codex_week_reset_mins = codex_week_reset;
metrics->codex_reset_credits = codex_credits;
metrics->codex_today_tokens_m10 = codex_today_tokens_m10;
parse_codex_daily_bars(metrics, daily_text);
metrics->zhipu_status = zhipu_status;
metrics->zhipu_5h_percent = (zhipu_5h >= 0) ? clamp_percent(zhipu_5h) : -1;
metrics->zhipu_week_percent = (zhipu_week >= 0) ? clamp_percent(zhipu_week) : -1;
metrics->zhipu_5h_reset_mins = zhipu_5h_reset;
metrics->zhipu_week_reset_mins = zhipu_week_reset;
metrics->zhipu_quota_percent = metrics->zhipu_5h_percent;
metrics->zhipu_latency_ms = -1;
set_disk_text(metrics, cursor);
return true;
}
static bool parse_legacy_sys_line(const char *line, ui_metrics_t *metrics)
{
int cpu = 0;
int mem = 0;
int disk = 0;
int rx = 0;
int tx = 0;
int matched = sscanf(line, "SYS,%d,%d,%d,%d,%d", &cpu, &mem, &disk, &rx, &tx);
if (matched != 5) {
return false;
}
metrics->cpu_percent = clamp_percent(cpu);
metrics->cpu_mhz = 0;
metrics->memory_percent = clamp_percent(mem);
metrics->memory_used_mb = 0;
metrics->memory_total_mb = 0;
metrics->disk_percent = clamp_percent(disk);
metrics->disk_read_kbps = 0;
metrics->disk_write_kbps = 0;
metrics->rx_kbps = rx;
metrics->tx_kbps = tx;
metrics->disk_count = 1;
snprintf(metrics->disk_text, sizeof(metrics->disk_text), "C:%d:-1:-1", metrics->disk_percent);
return true;
}
bool metrics_parse_line(const char *line, ui_metrics_t *metrics)
{
if (line == NULL || metrics == NULL) {
return false;
}
memset(metrics, 0, sizeof(*metrics));
set_optional_defaults(metrics);
if (strncmp(line, "SYS6,", 5) == 0) {
return parse_sys6_line(line, metrics);
}
if (strncmp(line, "SYS5,", 5) == 0) {
return parse_sys5_line(line, metrics);
}
if (strncmp(line, "SYS4,", 5) == 0) {
return parse_sys4_line(line, metrics);
}
if (strncmp(line, "SYS3,", 5) == 0) {
return parse_sys3_line(line, metrics);
}
if (strncmp(line, "SYS2,", 5) == 0) {
return parse_sys2_line(line, metrics);
}
return parse_legacy_sys_line(line, metrics);
}