diff --git a/main/metrics_protocol.c b/main/metrics_protocol.c index 137088c..b9280dc 100644 --- a/main/metrics_protocol.c +++ b/main/metrics_protocol.c @@ -42,8 +42,19 @@ static void set_disk_text(ui_metrics_t *metrics, const char *disk_text) snprintf(metrics->disk_text, sizeof(metrics->disk_text), "%s", disk_text); } +static void set_cpu_core_text(ui_metrics_t *metrics, const char *core_text) +{ + if (core_text == NULL || core_text[0] == '\0') { + metrics->cpu_core_text[0] = '\0'; + return; + } + + snprintf(metrics->cpu_core_text, sizeof(metrics->cpu_core_text), "%s", core_text); +} + static void set_optional_defaults(ui_metrics_t *metrics) { + metrics->cpu_core_text[0] = '\0'; metrics->codex_5h_percent = -1; metrics->codex_week_percent = -1; metrics->codex_5h_reset_mins = -1; @@ -491,6 +502,105 @@ static bool parse_sys6_line(const char *line, ui_metrics_t *metrics) return true; } +static bool parse_sys7_line(const char *line, ui_metrics_t *metrics) +{ + char buffer[640]; + snprintf(buffer, sizeof(buffer), "%s", line); + + char *cursor = buffer; + char *tag = strsep(&cursor, ","); + if (tag == NULL || strcmp(tag, "SYS7") != 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; + } + + char *core_text = strsep(&cursor, ","); + if (core_text == NULL) { + 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_cpu_core_text(metrics, core_text); + set_disk_text(metrics, cursor); + return true; +} + static bool parse_legacy_sys_line(const char *line, ui_metrics_t *metrics) { int cpu = 0; @@ -527,6 +637,10 @@ bool metrics_parse_line(const char *line, ui_metrics_t *metrics) memset(metrics, 0, sizeof(*metrics)); set_optional_defaults(metrics); + if (strncmp(line, "SYS7,", 5) == 0) { + return parse_sys7_line(line, metrics); + } + if (strncmp(line, "SYS6,", 5) == 0) { return parse_sys6_line(line, metrics); } diff --git a/main/ui_screen.c b/main/ui_screen.c index 7d68dfc..96cdea9 100644 --- a/main/ui_screen.c +++ b/main/ui_screen.c @@ -10,12 +10,13 @@ #define CPU_HISTORY_POINTS 64 #define CPU_CHART_W 184 #define CPU_CHART_H 78 +#define CPU_TOP_CORE_COUNT 4 #define HALO_LABEL_COUNT 8 #define DISK_ROW_COUNT 4 #define CODEX_DAILY_BAR_W 8 #define CODEX_DAILY_BAR_GAP 5 #define CODEX_DAILY_BAR_BASE_Y 292 -#define CODEX_DAILY_BAR_MAX_H 26 +#define CODEX_DAILY_BAR_MAX_H 46 typedef enum { CONN_USB = 0, @@ -29,6 +30,7 @@ static lv_obj_t *s_conn_label; static lv_obj_t *s_env_label; static lv_obj_t *s_cpu_value_label; static lv_obj_t *s_cpu_freq_label; +static lv_obj_t *s_cpu_core_labels[CPU_TOP_CORE_COUNT]; static lv_obj_t *s_cpu_value_halo[HALO_LABEL_COUNT]; static lv_obj_t *s_cpu_freq_halo[HALO_LABEL_COUNT]; static lv_obj_t *s_cpu_line; @@ -49,6 +51,7 @@ static lv_obj_t *s_codex_5h_value_label; static lv_obj_t *s_codex_week_value_label; static lv_obj_t *s_codex_5h_reset_label; static lv_obj_t *s_codex_week_reset_label; +static lv_obj_t *s_codex_today_label; static lv_obj_t *s_codex_5h_bar; static lv_obj_t *s_codex_week_bar; static lv_obj_t *s_codex_daily_bars[UI_CODEX_DAILY_BAR_COUNT]; @@ -276,11 +279,24 @@ static void format_percent_compact(int percent, char *out, size_t out_size) } } +static void format_tokens_m10(int tokens_m10, char *out, size_t out_size) +{ + if (tokens_m10 < 0) { + snprintf(out, out_size, "--"); + } else if (tokens_m10 >= 10000) { + snprintf(out, out_size, "%d.%dB", tokens_m10 / 10000, (tokens_m10 % 10000) / 1000); + } else if (tokens_m10 >= 1000) { + snprintf(out, out_size, "%dM", (tokens_m10 + 5) / 10); + } else { + snprintf(out, out_size, "%d.%dM", tokens_m10 / 10, tokens_m10 % 10); + } +} + static const char *zhipu_status_text(int status) { switch (status) { case 1: - return "KEY"; + return "KEY OK"; case 2: return "ERR"; default: @@ -448,6 +464,9 @@ static void update_codex_panel(const ui_metrics_t *metrics) lv_label_set_text(s_codex_5h_reset_label, reset_5h); lv_label_set_text(s_codex_week_reset_label, reset_week); + format_tokens_m10(metrics->codex_today_tokens_m10, value, sizeof(value)); + lv_label_set_text(s_codex_today_label, value); + for (int i = 0; i < UI_CODEX_DAILY_BAR_COUNT; i++) { lv_obj_t *bar = s_codex_daily_bars[i]; if (bar == NULL) { @@ -475,7 +494,7 @@ static void update_zhipu_panel(const ui_metrics_t *metrics) char reset[12]; char text[24]; - snprintf(text, sizeof(text), "STAT %s", zhipu_status_text(metrics->zhipu_status)); + snprintf(text, sizeof(text), "%s", zhipu_status_text(metrics->zhipu_status)); lv_label_set_text(s_zhipu_status_label, text); format_percent_compact(metrics->zhipu_5h_percent, value, sizeof(value)); @@ -491,6 +510,31 @@ static void update_zhipu_panel(const ui_metrics_t *metrics) lv_label_set_text(s_zhipu_week_reset_label, reset); } +static void update_cpu_core_labels(const char *core_text) +{ + char buffer[UI_MAX_CPU_CORE_TEXT]; + int row = 0; + + snprintf(buffer, sizeof(buffer), "%s", core_text != NULL ? core_text : ""); + char *cursor = buffer; + char *token = strtok(cursor, " "); + while (token != NULL && row < CPU_TOP_CORE_COUNT) { + for (char *p = token; *p != '\0'; p++) { + if (*p == ':') { + *p = ' '; + } + } + lv_label_set_text(s_cpu_core_labels[row], token); + lv_obj_clear_flag(s_cpu_core_labels[row], LV_OBJ_FLAG_HIDDEN); + row++; + token = strtok(NULL, " "); + } + + for (int i = row; i < CPU_TOP_CORE_COUNT; i++) { + lv_obj_add_flag(s_cpu_core_labels[i], LV_OBJ_FLAG_HIDDEN); + } +} + static void update_net_line(const ui_metrics_t *metrics) { char rx[12]; @@ -557,6 +601,15 @@ void ui_screen_create(void) lv_obj_set_width(s_cpu_freq_label, 128); lv_obj_align(s_cpu_freq_label, LV_ALIGN_TOP_LEFT, 8, 72); + for (int i = 0; i < CPU_TOP_CORE_COUNT; i++) { + s_cpu_core_labels[i] = make_label(screen, "--", &lv_font_montserrat_14); + lv_label_set_long_mode(s_cpu_core_labels[i], LV_LABEL_LONG_CLIP); + lv_obj_set_width(s_cpu_core_labels[i], 58); + lv_obj_set_style_text_align(s_cpu_core_labels[i], LV_TEXT_ALIGN_RIGHT, 0); + lv_obj_align(s_cpu_core_labels[i], LV_ALIGN_TOP_LEFT, 138, 28 + i * 16); + lv_obj_add_flag(s_cpu_core_labels[i], LV_OBJ_FLAG_HIDDEN); + } + lv_obj_t *memory_title = make_label(screen, "MEM", &lv_font_montserrat_14); lv_obj_align(memory_title, LV_ALIGN_TOP_LEFT, 208, 8); make_label_halo(screen, s_memory_value_halo, "--%", &lv_font_montserrat_20, 50, @@ -607,32 +660,37 @@ void ui_screen_create(void) lv_obj_t *codex_title = make_label(screen, "CODEX", &lv_font_montserrat_14); lv_obj_align(codex_title, LV_ALIGN_TOP_LEFT, 8, 184); + s_codex_today_label = make_label(screen, "--", &lv_font_montserrat_14); + lv_label_set_long_mode(s_codex_today_label, LV_LABEL_LONG_CLIP); + lv_obj_set_width(s_codex_today_label, 70); + lv_obj_set_style_text_align(s_codex_today_label, LV_TEXT_ALIGN_RIGHT, 0); + lv_obj_align(s_codex_today_label, LV_ALIGN_TOP_LEFT, 126, 184); s_codex_5h_label = make_label(screen, "5H", &lv_font_montserrat_14); lv_obj_set_width(s_codex_5h_label, 28); - lv_obj_align(s_codex_5h_label, LV_ALIGN_TOP_LEFT, 8, 198); + lv_obj_align(s_codex_5h_label, LV_ALIGN_TOP_LEFT, 8, 204); s_codex_5h_bar = make_bar(screen, 78, 8); - lv_obj_align(s_codex_5h_bar, LV_ALIGN_TOP_LEFT, 36, 202); + lv_obj_align(s_codex_5h_bar, LV_ALIGN_TOP_LEFT, 36, 208); s_codex_5h_value_label = make_label(screen, "--", &lv_font_montserrat_14); lv_obj_set_width(s_codex_5h_value_label, 38); - lv_obj_align(s_codex_5h_value_label, LV_ALIGN_TOP_LEFT, 118, 198); + lv_obj_align(s_codex_5h_value_label, LV_ALIGN_TOP_LEFT, 118, 204); s_codex_5h_reset_label = make_label(screen, "--", &lv_font_montserrat_14); lv_label_set_long_mode(s_codex_5h_reset_label, LV_LABEL_LONG_CLIP); lv_obj_set_width(s_codex_5h_reset_label, 38); - lv_obj_align(s_codex_5h_reset_label, LV_ALIGN_TOP_LEFT, 158, 198); + lv_obj_align(s_codex_5h_reset_label, LV_ALIGN_TOP_LEFT, 158, 204); s_codex_week_label = make_label(screen, "WK", &lv_font_montserrat_14); lv_obj_set_width(s_codex_week_label, 28); - lv_obj_align(s_codex_week_label, LV_ALIGN_TOP_LEFT, 8, 216); + lv_obj_align(s_codex_week_label, LV_ALIGN_TOP_LEFT, 8, 224); s_codex_week_bar = make_bar(screen, 78, 8); - lv_obj_align(s_codex_week_bar, LV_ALIGN_TOP_LEFT, 36, 220); + lv_obj_align(s_codex_week_bar, LV_ALIGN_TOP_LEFT, 36, 228); s_codex_week_value_label = make_label(screen, "--", &lv_font_montserrat_14); lv_obj_set_width(s_codex_week_value_label, 38); - lv_obj_align(s_codex_week_value_label, LV_ALIGN_TOP_LEFT, 118, 216); + lv_obj_align(s_codex_week_value_label, LV_ALIGN_TOP_LEFT, 118, 224); s_codex_week_reset_label = make_label(screen, "--", &lv_font_montserrat_14); lv_label_set_long_mode(s_codex_week_reset_label, LV_LABEL_LONG_CLIP); lv_obj_set_width(s_codex_week_reset_label, 38); - lv_obj_align(s_codex_week_reset_label, LV_ALIGN_TOP_LEFT, 158, 216); + lv_obj_align(s_codex_week_reset_label, LV_ALIGN_TOP_LEFT, 158, 224); make_rule(screen, 8, CODEX_DAILY_BAR_BASE_Y, 188, 1); for (int i = 0; i < UI_CODEX_DAILY_BAR_COUNT; i++) { @@ -652,36 +710,36 @@ void ui_screen_create(void) lv_obj_t *zhipu_title = make_label(screen, "ZHIPU", &lv_font_montserrat_14); lv_obj_align(zhipu_title, LV_ALIGN_TOP_LEFT, 208, 184); - s_zhipu_status_label = make_label(screen, "STAT WAIT", &lv_font_montserrat_14); - lv_obj_set_width(s_zhipu_status_label, 96); + s_zhipu_status_label = make_label(screen, "WAIT", &lv_font_montserrat_14); + lv_obj_set_width(s_zhipu_status_label, 78); lv_obj_set_style_text_align(s_zhipu_status_label, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_align(s_zhipu_status_label, LV_ALIGN_TOP_RIGHT, -8, 184); s_zhipu_5h_label = make_label(screen, "5H", &lv_font_montserrat_14); lv_obj_set_width(s_zhipu_5h_label, 28); - lv_obj_align(s_zhipu_5h_label, LV_ALIGN_TOP_LEFT, 208, 198); + lv_obj_align(s_zhipu_5h_label, LV_ALIGN_TOP_LEFT, 208, 204); s_zhipu_5h_bar = make_bar(screen, 78, 8); - lv_obj_align(s_zhipu_5h_bar, LV_ALIGN_TOP_LEFT, 236, 202); + lv_obj_align(s_zhipu_5h_bar, LV_ALIGN_TOP_LEFT, 236, 208); s_zhipu_5h_value_label = make_label(screen, "--", &lv_font_montserrat_14); lv_obj_set_width(s_zhipu_5h_value_label, 38); - lv_obj_align(s_zhipu_5h_value_label, LV_ALIGN_TOP_LEFT, 318, 198); + lv_obj_align(s_zhipu_5h_value_label, LV_ALIGN_TOP_LEFT, 318, 204); s_zhipu_5h_reset_label = make_label(screen, "--", &lv_font_montserrat_14); lv_label_set_long_mode(s_zhipu_5h_reset_label, LV_LABEL_LONG_CLIP); lv_obj_set_width(s_zhipu_5h_reset_label, 38); - lv_obj_align(s_zhipu_5h_reset_label, LV_ALIGN_TOP_LEFT, 358, 198); + lv_obj_align(s_zhipu_5h_reset_label, LV_ALIGN_TOP_LEFT, 358, 204); s_zhipu_week_label = make_label(screen, "WK", &lv_font_montserrat_14); lv_obj_set_width(s_zhipu_week_label, 28); - lv_obj_align(s_zhipu_week_label, LV_ALIGN_TOP_LEFT, 208, 216); + lv_obj_align(s_zhipu_week_label, LV_ALIGN_TOP_LEFT, 208, 224); s_zhipu_week_bar = make_bar(screen, 78, 8); - lv_obj_align(s_zhipu_week_bar, LV_ALIGN_TOP_LEFT, 236, 220); + lv_obj_align(s_zhipu_week_bar, LV_ALIGN_TOP_LEFT, 236, 228); s_zhipu_week_value_label = make_label(screen, "--", &lv_font_montserrat_14); lv_obj_set_width(s_zhipu_week_value_label, 38); - lv_obj_align(s_zhipu_week_value_label, LV_ALIGN_TOP_LEFT, 318, 216); + lv_obj_align(s_zhipu_week_value_label, LV_ALIGN_TOP_LEFT, 318, 224); s_zhipu_week_reset_label = make_label(screen, "--", &lv_font_montserrat_14); lv_label_set_long_mode(s_zhipu_week_reset_label, LV_LABEL_LONG_CLIP); lv_obj_set_width(s_zhipu_week_reset_label, 38); - lv_obj_align(s_zhipu_week_reset_label, LV_ALIGN_TOP_LEFT, 358, 216); + lv_obj_align(s_zhipu_week_reset_label, LV_ALIGN_TOP_LEFT, 358, 224); } void ui_screen_tick(void) @@ -781,6 +839,7 @@ void ui_screen_update_metrics_from_source(const ui_metrics_t *metrics, const cha snprintf(text, sizeof(text), "--GHz"); } set_label_with_halo(s_cpu_freq_label, s_cpu_freq_halo, text); + update_cpu_core_labels(metrics->cpu_core_text); set_cpu_curve(metrics->cpu_percent); snprintf(text, sizeof(text), "%d%%", clamp_percent(metrics->memory_percent)); diff --git a/main/ui_screen.h b/main/ui_screen.h index ee69526..f9c97bd 100644 --- a/main/ui_screen.h +++ b/main/ui_screen.h @@ -5,6 +5,7 @@ extern "C" { #endif #define UI_MAX_DISK_TEXT 128 +#define UI_MAX_CPU_CORE_TEXT 48 #define UI_CODEX_DAILY_BAR_COUNT 14 typedef struct { @@ -34,6 +35,7 @@ typedef struct { int zhipu_week_percent; int zhipu_5h_reset_mins; int zhipu_week_reset_mins; + char cpu_core_text[UI_MAX_CPU_CORE_TEXT]; char disk_text[UI_MAX_DISK_TEXT]; } ui_metrics_t; diff --git a/tools/pc-metrics/push-metrics-ble.py b/tools/pc-metrics/push-metrics-ble.py index 50b9adb..7c33999 100644 --- a/tools/pc-metrics/push-metrics-ble.py +++ b/tools/pc-metrics/push-metrics-ble.py @@ -122,7 +122,9 @@ class CpuFrequencyReader: def __init__(self) -> None: self.pdh = None self.query = ctypes.c_void_p() - self.counter = ctypes.c_void_p() + self.total_counter = ctypes.c_void_p() + self.core_counters: list[tuple[int, ctypes.c_void_p]] = [] + self.base_mhz = self._base_mhz() self.available = False if sys.platform != "win32": @@ -159,10 +161,20 @@ class CpuFrequencyReader: return if add_counter( self.query, - r"\Processor Information(_Total)\Actual Frequency", + r"\Processor Information(_Total)\% Processor Performance", None, - ctypes.byref(self.counter), + ctypes.byref(self.total_counter), ) != 0: + self.total_counter = ctypes.c_void_p() + + logical_count = psutil.cpu_count(logical=True) or 0 + for index in range(logical_count): + counter = ctypes.c_void_p() + path = rf"\Processor Information(0,{index})\% Processor Performance" + if add_counter(self.query, path, None, ctypes.byref(counter)) == 0: + self.core_counters.append((index, counter)) + + if not self.total_counter and not self.core_counters: return self.pdh.PdhCollectQueryData(self.query) @@ -170,22 +182,66 @@ class CpuFrequencyReader: except OSError: self.available = False - def read_mhz(self) -> int: - if self.available and self.pdh is not None: - value = _PdhCounterValue() - counter_type = wintypes.DWORD() + @staticmethod + def _base_mhz() -> int: + freq = psutil.cpu_freq() + if freq and freq.max: + return int(round(freq.max)) + if freq and freq.current: + return int(round(freq.current)) + return 0 + + @staticmethod + def _format_core_mhz(index: int, mhz: int) -> str: + ghz10 = max(0, int(round(mhz / 100))) + return f"{index:02d}:{ghz10 // 10}.{ghz10 % 10}" + + def _read_counter(self, counter: ctypes.c_void_p) -> float: + if self.pdh is None or not counter: + return -1.0 + + value = _PdhCounterValue() + counter_type = wintypes.DWORD() + rc = self.pdh.PdhGetFormattedCounterValue( + counter, + 0x00000200, + ctypes.byref(counter_type), + ctypes.byref(value), + ) + if rc != 0 or value.status != 0 or value.double_value < 0: + return -1.0 + return value.double_value + + def _perf_to_mhz(self, performance_percent: float) -> int: + if self.base_mhz <= 0 or performance_percent < 0: + return 0 + return int(round(self.base_mhz * performance_percent / 100)) + + def read(self) -> tuple[int, str]: + if self.available and self.pdh is not None and self.base_mhz > 0: if self.pdh.PdhCollectQueryData(self.query) == 0: - rc = self.pdh.PdhGetFormattedCounterValue( - self.counter, - 0x00000200, - ctypes.byref(counter_type), - ctypes.byref(value), + total_mhz = self._perf_to_mhz(self._read_counter(self.total_counter)) + core_values: list[tuple[int, int]] = [] + for index, counter in self.core_counters: + mhz = self._perf_to_mhz(self._read_counter(counter)) + if mhz > 0: + core_values.append((index, mhz)) + + core_values.sort(key=lambda item: (-item[1], item[0])) + top_text = " ".join( + self._format_core_mhz(index, mhz) + for index, mhz in core_values[:4] ) - if rc == 0 and value.status == 0 and value.double_value > 0: - return int(round(value.double_value)) + if total_mhz <= 0 and core_values: + total_mhz = core_values[0][1] + if total_mhz > 0: + return total_mhz, top_text freq = psutil.cpu_freq() - return int(round(freq.current)) if freq and freq.current else 0 + return (int(round(freq.current)) if freq and freq.current else 0), "" + + def read_mhz(self) -> int: + return self.read()[0] class LogicalDiskRateReader: @@ -695,7 +751,7 @@ class MetricsSampler: disk_rates = self.disk_rates.read_rates() cpu = self.cpu_percent.read_percent() - cpu_mhz = self.cpu_frequency.read_mhz() + cpu_mhz, cpu_core_text = self.cpu_frequency.read() mem_info = psutil.virtual_memory() mem_percent = clamp_percent(mem_info.percent) @@ -708,12 +764,12 @@ class MetricsSampler: zhipu_status, zhipu_5h, zhipu_week, zhipu_5h_reset, zhipu_week_reset = self.zhipu.read() return ( - f"SYS6,{cpu},{cpu_mhz},{mem_percent},{mem_used_mb},{mem_total_mb}," + f"SYS7,{cpu},{cpu_mhz},{mem_percent},{mem_used_mb},{mem_total_mb}," f"{disk_count},{disk_percent},{disk_read_kbps},{disk_write_kbps}," f"{rx_kbps},{tx_kbps}," f"{codex_5h},{codex_week},{codex_5h_reset},{codex_week_reset},{codex_credits},{codex_today_tokens_m10}," f"{codex_daily_bars}," - f"{zhipu_status},{zhipu_5h},{zhipu_week},{zhipu_5h_reset},{zhipu_week_reset},{disk_text}" + f"{zhipu_status},{zhipu_5h},{zhipu_week},{zhipu_5h_reset},{zhipu_week_reset},{cpu_core_text},{disk_text}" )