refactor(panel): 前后端按模块拆分+屏幕/控制合并页 — 后端meowpanel.c 6372行拆src/*.c+mp.h(235函数原型,20端点output byte-identical,0warning)+前端拆mp_shared/mp_pages/meowpanel三层;屏幕·遥控合并(左屏实时画面+右MD3 SVG矢量按钮无emoji);重编后热更TF卡
This commit is contained in:
1 parent
f3ae06d7cd
commit
2dc4cad454
26 files changed
+9317
-2755
No files matched your search
@@ -0,0 +1,192 @@
|
||||
/* mp_perf.c — 性能/系统域:/api/perf,/api/system,action,pin-unlock(经 meow_svc_perf IPC 聚合)。 */
|
||||
#include "mp.h"
|
||||
|
||||
|
||||
int api_perf(int sock, const char *path)
|
||||
{
|
||||
char json[4096];
|
||||
int rc = ipc_perf_query(perf_subset_for_path(path), json, sizeof json);
|
||||
if (rc != MEOW_OK || !utf8_valid_n(json, strlen(json))) /* 上游坏字节 → 不返回,降级 */
|
||||
return send_err(sock, 500, "INTERNAL", "性能服务不可用(IPC 连接/应答失败)");
|
||||
return send_json(sock, 200, json);
|
||||
}
|
||||
|
||||
int perf_extract_network(const char *json, char *out, int cap)
|
||||
{
|
||||
const char *p = json;
|
||||
for (;;) {
|
||||
p = strstr(p, "\"network\"");
|
||||
if (!p) return -1;
|
||||
const char *q = p + 9; /* strlen("\"network\"") */
|
||||
while (*q == ' ' || *q == '\t') q++;
|
||||
if (*q == ':') { p = q + 1; break; } /* 顶层 network 键 */
|
||||
p += 9; /* 嵌套同名键跳过 */
|
||||
}
|
||||
while (*p == ' ' || *p == '\t') p++;
|
||||
if (*p != '{') return -1;
|
||||
int depth = 0, in_str = 0, esc = 0;
|
||||
const char *q;
|
||||
for (q = p; *q; q++) {
|
||||
char ch = *q;
|
||||
if (in_str) {
|
||||
if (esc) esc = 0;
|
||||
else if (ch == '\\') esc = 1;
|
||||
else if (ch == '"') in_str = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '"') { in_str = 1; continue; }
|
||||
if (ch == '{') depth++;
|
||||
else if (ch == '}') { depth--; if (depth == 0) { q++; break; } }
|
||||
}
|
||||
if (depth != 0) return -1;
|
||||
size_t len = (size_t)(q - p);
|
||||
if (len == 0) return -1;
|
||||
if (len >= (size_t)cap) len = (size_t)cap - 1;
|
||||
memcpy(out, p, len); out[len] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int api_system(int sock)
|
||||
{
|
||||
char json[4096];
|
||||
int rc = ipc_perf_query(0, json, sizeof json);
|
||||
if (rc != MEOW_OK) return send_err(sock, 500, "INTERNAL", "性能服务不可用(IPC 连接/应答失败)");
|
||||
jv_t *root = jv_parse(json, (int)strlen(json));
|
||||
if (!root) return send_err(sock, 500, "INTERNAL", "性能服务 JSON 解析失败");
|
||||
jv_t *jsys = jv_obj_get(root, "system");
|
||||
jv_t *jupt = jv_obj_get(root, "uptime_sec");
|
||||
jv_t *jst = jv_obj_get(root, "storage");
|
||||
jv_t *jtf = jv_obj_get(root, "tfcard");
|
||||
const char *ver = "-", *host = "-", *ker = "-", *arch = "-";
|
||||
if (jsys && jsys->type == J_OBJ) {
|
||||
jv_t *v = jv_obj_get(jsys, "version"); if (v && v->type == J_STR) ver = v->str;
|
||||
v = jv_obj_get(jsys, "hostname"); if (v && v->type == J_STR) host = v->str;
|
||||
v = jv_obj_get(jsys, "kernel"); if (v && v->type == J_STR) ker = v->str;
|
||||
v = jv_obj_get(jsys, "arch"); if (v && v->type == J_STR) arch = v->str;
|
||||
}
|
||||
long long upt = jupt ? (long long)jupt->dnum : 0;
|
||||
/* boot default:读权威 /data/meow_boot_default(0=meow 默认, 1=hiby),失败回退 meow */
|
||||
int bdf = -1;
|
||||
{
|
||||
char b[16];
|
||||
FILE *f = fopen(BOOT_DEFAULT_FILE, "r");
|
||||
if (f) { if (fgets(b, sizeof b, f)) bdf = atoi(b); fclose(f); }
|
||||
}
|
||||
const char *bootname = bdf < 0 ? "meow" : (bdf ? "hiby" : "meow");
|
||||
/* 当前运行模式:读 /tmp/meow_boot_mode(meow/hiby),缺失回退 default(PANEL_ENHANCE_PLAN 批1 前端读 boot.mode) */
|
||||
char modebuf[16] = {0};
|
||||
{
|
||||
FILE *f = fopen("/tmp/meow_boot_mode", "r");
|
||||
if (f) {
|
||||
if (fgets(modebuf, sizeof modebuf, f)) {
|
||||
char *p = modebuf;
|
||||
while (*p) { if (*p == '\n' || *p == '\r' || *p == ' ') { *p = 0; break; } p++; }
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
const char *bootmode = (modebuf[0] == 'm' || modebuf[0] == 'h') ? modebuf : bootname;
|
||||
char host_local[80];
|
||||
snprintf(host_local, sizeof host_local, "%s.local", host);
|
||||
sbuf_t s = {0};
|
||||
sA(&s, "{\"version\":");
|
||||
sA_str(&s, ver);
|
||||
sA(&s, ",\"hostname\":");
|
||||
sA_str(&s, host);
|
||||
sA(&s, ",\"kernel\":");
|
||||
sA_str(&s, ker);
|
||||
sA(&s, ",\"arch\":");
|
||||
sA_str(&s, arch);
|
||||
sA(&s, ",\"uptime_sec\":%lld,\"boot\":{\"default\":", upt);
|
||||
sA_str(&s, bootname);
|
||||
sA(&s, ",\"mode\":");
|
||||
sA_str(&s, bootmode);
|
||||
sA(&s, "},\"network\":");
|
||||
char netbuf[1024];
|
||||
/* 透传 perf 权威 network 段(wifi/bluetooth/hostname_local);含非法 UTF-8(如坏 ssid)→ 回退,不嵌坏字节 */
|
||||
if (perf_extract_network(json, netbuf, sizeof netbuf) == 0 && utf8_valid_n(netbuf, strlen(netbuf))) {
|
||||
sA(&s, "%s", netbuf);
|
||||
} else {
|
||||
/* 回退:perf 未含 network 段 → 仅 hostname_local(保持原语义,不崩) */
|
||||
sA(&s, "{\"hostname_local\":");
|
||||
sA_str(&s, host_local);
|
||||
sA(&s, "}");
|
||||
}
|
||||
sA(&s, ",\"storage\":{");
|
||||
if (jst && jst->type == J_OBJ) {
|
||||
jv_t *t = jv_obj_get(jst, "total"); long long tot = t ? (long long)t->dnum : 0;
|
||||
jv_t *u = jv_obj_get(jst, "used"); long long usd = u ? (long long)u->dnum : 0;
|
||||
jv_t *a = jv_obj_get(jst, "avail"); long long ava = a ? (long long)a->dnum : 0;
|
||||
sA(&s, "\"root\":{\"total\":%lld,\"used\":%lld,\"avail\":%lld}", tot, usd, ava);
|
||||
} else {
|
||||
sA(&s, "\"root\":{\"total\":0,\"used\":0,\"avail\":0}");
|
||||
}
|
||||
sA(&s, ",\"tfcard\":{");
|
||||
if (jtf && jtf->type == J_OBJ) {
|
||||
jv_t *pr = jv_obj_get(jtf, "present"); int present = pr && pr->bval;
|
||||
long long tot = 0, usd = 0, ava = 0;
|
||||
jv_t *t = jv_obj_get(jtf, "total"); if (t) tot = (long long)t->dnum;
|
||||
jv_t *u = jv_obj_get(jtf, "used"); if (u) usd = (long long)u->dnum;
|
||||
jv_t *a = jv_obj_get(jtf, "avail"); if (a) ava = (long long)a->dnum;
|
||||
sA(&s, "\"present\":%s,\"total\":%lld,\"used\":%lld,\"avail\":%lld}", present ? "true" : "false", tot, usd, ava);
|
||||
} else {
|
||||
sA(&s, "\"present\":false,\"total\":0,\"used\":0,\"avail\":0}");
|
||||
}
|
||||
sA(&s, "},\"ota\":{\"current\":");
|
||||
sA_str(&s, ver);
|
||||
sA(&s, ",\"latest\":");
|
||||
sA_str(&s, ver);
|
||||
sA(&s, ",\"available\":false,\"url\":null}");
|
||||
/* 重启原因 / 升级状态:svc_power 读级查询(POWER_REBOOT_REASON(8)/POWER_UPGRADE_STATUS(9),只读、
|
||||
* 任意调用者)。st.msg 分别为 "coldboot=reboot|shutdown|unknown" 与 "upgrade=yes|no"。
|
||||
* 前端批1-B 已留位(读 d.reboot_reason / d.upgrade_status),此处点亮。查询失败保持空串(不谎报)。 */
|
||||
char rreason[48] = "", ustatus[32] = "";
|
||||
{
|
||||
m_power_status_t st;
|
||||
memset(&st, 0, sizeof st);
|
||||
if (ipc_power_action(POWER_REBOOT_REASON, 0, NULL, &st) == MEOW_OK)
|
||||
svc_msg_kv(st.msg, "coldboot", rreason, sizeof rreason);
|
||||
memset(&st, 0, sizeof st);
|
||||
if (ipc_power_action(POWER_UPGRADE_STATUS, 0, NULL, &st) == MEOW_OK)
|
||||
svc_msg_kv(st.msg, "upgrade", ustatus, sizeof ustatus);
|
||||
}
|
||||
sA(&s, ",\"reboot_reason\":");
|
||||
sA_str(&s, rreason);
|
||||
sA(&s, ",\"upgrade_status\":");
|
||||
sA_str(&s, ustatus);
|
||||
sA(&s, "}");
|
||||
jv_free(root);
|
||||
int ret = send_json(sock, 200, s.b ? s.b : "");
|
||||
sbuf_free(&s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int api_pin_unlock_once(int sock)
|
||||
{
|
||||
const char *path = "/tmp/meow_pin_unlock_once";
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) return send_err(sock, 500, "INTERNAL", "无法写入一次性解锁标志");
|
||||
fputs("1\n", f);
|
||||
fclose(f);
|
||||
return send_json(sock, 200, "{\"unlock_once\":true}");
|
||||
}
|
||||
|
||||
int api_system_action(int sock, const char *which, const req_t *r)
|
||||
{
|
||||
(void)r;
|
||||
uint32_t cmd;
|
||||
if (!strcmp(which, "reboot")) cmd = POWER_REBOOT;
|
||||
else if (!strcmp(which, "shutdown")) cmd = POWER_SHUTDOWN;
|
||||
else if (!strcmp(which, "ota")) cmd = POWER_UPGRADE;
|
||||
else return send_err(sock, 404, "NOT_FOUND", "未知系统动作");
|
||||
m_power_status_t st;
|
||||
memset(&st, 0, sizeof st);
|
||||
int rc = ipc_power_action(cmd, 0, NULL, &st);
|
||||
if (rc == MEOW_OK) return send_json(sock, 200, "{\"accepted\":true}");
|
||||
/* 系统动作类服务端通常「先应答受理再执行」;此处若返回非 OK 则说明服务未受理 */
|
||||
const char *why = st.msg[0] ? st.msg : power_code_str(rc);
|
||||
if (rc == MEOW_ERR_PERM) return send_err(sock, 403, "FORBIDDEN", "电源服务拒绝(非 root 调用)");
|
||||
if (rc == MEOW_ERR_NODEV) return send_err(sock, 503, "NO_CARD", "升级文件缺失或服务不可达");
|
||||
if (rc == MEOW_ERR_NOENT || rc == MEOW_ERR_IO) return send_err(sock, 503, "NO_CARD", why);
|
||||
return send_err(sock, 500, "INTERNAL", why);
|
||||
}
|
||||
Reference in new issue
Block a user