[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81778":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":16,"starSnapshotCount":16,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},81778,"SimAdmin","3899\u002FSimAdmin","3899","🎉面向 Debian 蜂窝 CPE、随身 WiFi、软路由类设备的 SIM\u002FeSIM、蜂窝网络、短信、DDNS和系统状态管理系统。","",null,"Rust",56,11,50,1,0,4,6,45.84,"GNU General Public License v3.0",false,"main",true,[],"2026-06-12 04:01:35","\u003Ca href=\"https:\u002F\u002Fgithub.com\u002F3899\u002FSimAdmin\">\n  \u003Cimg src=\"https:\u002F\u002Fsocialify.git.ci\u002F3899\u002FSimAdmin\u002Fimage?description=1&descriptionEditable=%E9%9D%A2%E5%90%91%20Debian%20%E5%B9%B3%E5%8F%B0%E6%94%AF%E6%8C%81%20SIM%2FeSIM%20%E8%9C%82%E7%AA%9D%E8%AE%BE%E5%A4%87%E7%9A%84%E5%BC%80%E6%BA%90%20Web%20%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F&font=Source%20Code%20Pro&logo=https%3A%2F%2Fgithub.com%2F3899%2FSimAdmin%2Fblob%2Fmain%2Ffrontend%2Fpublic%2Fsimadmin-logo.svg%3Fraw%3Dtrue&name=1&owner=1&pattern=Floating%20Cogs&theme=Auto\" alt=\"SimAdmin\" \u002F>\n\u003C\u002Fa>\n\n\u003Cdiv align=\"center\">\n  \u003Cbr\u002F>\n\n  \u003Cdiv>\n    \u003Ca href=\"https:\u002F\u002Fgithub.com\u002F3899\u002FSimAdmin\u002Freleases\">\n      \u003Cimg \n        alt=\"Debian\"\n        src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDebian-%23D70A53?logo=debian&logoColor=white&style=flat-square\" \n      \u002F>\n    \u003C\u002Fa >\n    \u003Ca href=\".\u002FLICENSE\">\n      \u003Cimg\n        src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002F3899\u002FSimAdmin?style=flat-square\"\n      \u002F>\n    \u003C\u002Fa >\n    \u003Ca href=\"https:\u002F\u002Fgithub.com\u002F3899\u002FSimAdmin\u002Freleases\">\n      \u003Cimg\n        src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002F3899\u002FSimAdmin?style=flat-square\"\n      \u002F>\n    \u003C\u002Fa >\n    \u003Ca href=\"https:\u002F\u002Fgithub.com\u002F3899\u002FSimAdmin\u002Freleases\">\n      \u003Cimg\n        src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fdownloads\u002F3899\u002FSimAdmin\u002Ftotal?style=flat-square\"\n      \u002F>  \n    \u003C\u002Fa >\n  \u003C\u002Fdiv>\n\n  \u003Cbr\u002F>\n\n  \u003Cpicture>\n    \u003Cimg src=\".\u002Fstatic\u002FDashboard.png\" width=\"100%\" alt=\"Dashboard\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FDevice_Information.png\" width=\"100%\" alt=\"Device_Information\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FeSIM.png\" width=\"100%\" alt=\"eSIM\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FCellular_Network.png\" width=\"100%\" alt=\"Cellular_Network\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FWLAN.png\" width=\"100%\" alt=\"WLAN\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FDDNS.png\" width=\"100%\" alt=\"DDNS\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FSMS.png\" width=\"100%\" alt=\"SMS\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FNotificationLogs.png\" width=\"100%\" alt=\"NotificationLogs\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FNotificationRules.png\" width=\"100%\" alt=\"NotificationRules\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FDeviceStatusRule.png\" width=\"100%\" alt=\"DeviceStatusRule\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FNotificationChannels.png\" width=\"100%\" alt=\"NotificationChannels\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FBasic_Configuration.png\" width=\"100%\" alt=\"Basic_Configuration\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FSecurity_Settings.png\" width=\"100%\" alt=\"Security_Settings\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FOTA.png\" width=\"100%\" alt=\"OTA\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n\t\u003Cimg src=\".\u002Fstatic\u002FDashboard_Dark.png\" width=\"100%\" alt=\"Dashboard_Dark\" \u002F>\n\t\u003Cbr\u002F>\u003Cbr\u002F>\n  \u003C\u002Fpicture>\n  \n\u003C\u002Fdiv>\n\n# SimAdmin - SIM\u002FeSIM 中枢\n\nSimAdmin 是一套面向 Debian 蜂窝 CPE、随身 WiFi、软路由类设备的 SIM\u002FeSIM、蜂窝网络、短信和系统状态管理系统。\n\n当前项目由 Rust 后端和 React 前端组成：\n\n- 后端：Rust + Axum + zbus，主要通过 ModemManager D-Bus 接口管理 modem，并在部分场景使用 `mmcli`、`qmicli` 或 AT 直连兜底。\n- 前端：React + Vite + Material UI，提供仪表盘、设备信息、蜂窝网络、设备网络、短信、通知配置和 OTA 更新页面。\n- 部署形态：后端二进制同进程托管前端 SPA，默认安装到 `\u002Fopt\u002Fsimadmin`，通过 systemd 运行。\n\n健康检查整体按支持 ModemManager 的 Linux 蜂窝设备组织，不同 modem 固件、内核、ModemManager 版本暴露的能力不同，具体功能以实际设备为准。\n\n## 免责声明\n\n本项目会直接操作蜂窝 modem、SIM 注册、数据拨号、APN、频段、飞行模式、NetworkManager、systemd 服务、系统重启和 OTA 文件替换；iptables\u002Fip6tables 仅用于只读诊断，不会自动清空宿主机防火墙规则。\n\n请仅在你拥有控制权的设备上使用。错误配置可能导致断网、无法注册网络、SIM 漫游计费、设备需要手动恢复，甚至 OTA 后服务无法启动。任何使用本项目造成的后果由使用者自行承担。\n\n部分接口受硬件和 ModemManager 能力限制：\n\n- 频段锁定依赖 ModemManager 暴露的 `SupportedBands` \u002F `CurrentBands` \u002F `SetCurrentBands`。\n- 小区锁定当前为后端内存态展示，不会下发真实硬件锁小区命令。\n\n## 开源协议声明\n\n本项目采用 GNU General Public License v3.0 (GPLv3) 开源协议。\n\n你可以：\n\n- 自由使用、研究、修改本软件。\n- 分发本软件副本。\n- 分发修改后的版本。\n\n但你必须：\n\n1. 保留版权声明和许可证声明。\n2. 分发本软件或修改版本时，以 GPLv3 协议公开完整源代码。\n3. 基于本项目的衍生作品继续使用 GPLv3 协议。\n4. 明确标注修改内容和修改日期。\n5. 分发时附带完整 GPLv3 许可证文本。\n\n严禁将本项目或其衍生版本闭源后作为专有软件分发。\n\n## 社区交流\n\n⚠️ 温馨提示：群聊仅限日常讨论和经验分享，如需反馈问题或提交新需求。\n\n\u003Ctable>\n  \u003Cthead>\n    \u003Ctr>\n      \u003Cth width=\"50%\">QQ 群\u003C\u002Fth>\n    \u003C\u002Ftr>\n  \u003C\u002Fthead>\n  \u003Ctbody>\n    \u003Ctr>\n      \u003Ctd>\n        \u003Cpicture>\n          \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\".\u002Fstatic\u002FCommunity\u002FCommunity_QQ_Dark.png\" \u002F>\n          \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\".\u002Fstatic\u002FCommunity\u002FCommunity_QQ_Light.png\" \u002F>\n          \u003Cimg src=\".\u002Fstatic\u002FCommunity\u002FCommunity_QQ_Light.png\" \u002F>\n        \u003C\u002Fpicture>\n      \u003C\u002Ftd>\n    \u003C\u002Ftr>\n  \u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n## 快速开始\n\n### 项目结构\n\n```text\n.\n├── backend\u002F          # Rust + Axum 后端，ModemManager、SQLite、OTA、通知、系统接口\n├── frontend\u002F         # React + Vite + MUI 前端\n├── bruno-api\u002F        # Bruno API 调试集合\n├── scripts\u002F          # 构建、部署、systemd、modem 恢复脚本\n├── install_latest.sh # 设备侧一键安装 \u002F 升级脚本\n├── uninstall.sh      # 设备侧一键卸载脚本\n├── VERSION           # 项目版本号\n└── LICENSE           # GPLv3 许可证\n```\n\n### 前端开发\n\n```bash\ncd frontend\npnpm install\npnpm dev\n```\n\n构建前端：\n\n```bash\ncd frontend\npnpm run build\n```\n\n前端构建产物输出到 `frontend\u002Fdist\u002F`，部署后会复制为 `\u002Fopt\u002Fsimadmin\u002Fwww\u002F`。\n\n### 后端开发\n\n```bash\ncd backend\ncargo check\ncargo run -- --host :: --port 3000\n```\n\n参数和环境变量：\n\n| 参数 | 环境变量 | 默认值 | 说明 |\n|------|----------|--------|------|\n| `--host` \u002F `-H` | `HOST` | `::` | 监听地址，默认双栈 IPv4\u002FIPv6 |\n| `--port` \u002F `-p` | `PORT` | `3000` | HTTP 监听端口 |\n\n在普通开发机上运行后端时，如果没有 system D-Bus、ModemManager 或 modem，硬件相关接口会返回错误，这是预期行为。\n\n### 登录与管理员密码\n\nSimAdmin 采用后台式单管理员密码登录，不包含用户名和多账号权限系统。首次打开 Web 后台时会进入 `\u002Flogin` 的“设置管理员密码”页面；设置成功后会自动建立会话并进入管理后台。\n\n密码规则：\n\n- 8-64 个字符。\n- 只能使用英文字母、数字和符号，不允许空格或中文。\n- 至少包含两类字符，例如字母 + 数字、字母 + 符号或数字 + 符号。\n\n登录与接口保护：\n\n- 管理后台页面和 `\u002Fapi\u002F*` 业务接口默认需要登录；`\u002Fapi\u002Fhealth`、`\u002Fapi\u002Fauth\u002Fstatus`、`\u002Fapi\u002Fauth\u002Fsetup`、`\u002Fapi\u002Fauth\u002Flogin` 为公开接口。\n- 未登录访问受保护页面会跳转到 `\u002Flogin`；前端 API 请求遇到 `401` 会自动进入登录页，直接调用 API 时返回标准 JSON 错误。\n- 会话使用 `simadmin_session` HttpOnly Cookie，默认有效期 7 天。重置或清除管理员密码会清空所有 Web 会话。\n- 当前不提供手动登出入口，适合单管理员设备后台场景。\n\n忘记密码时，可通过 SSH 登录目标设备后执行交互式重置：\n\n```bash\n\u002Fopt\u002Fsimadmin\u002Fsimadmin auth reset-password\n```\n\n如需清除管理员密码并让 Web UI 下次重新进入首次设置：\n\n```bash\n\u002Fopt\u002Fsimadmin\u002Fsimadmin auth clear\n```\n\n如果使用了自定义安装目录，请将 `\u002Fopt\u002Fsimadmin\u002Fsimadmin` 替换为实际后端二进制路径。\n\n### 构建完整 OTA 包\n\n```bash\n.\u002Fscripts\u002Fbuild.sh\n```\n\n常用选项：\n\n```bash\n.\u002Fscripts\u002Fbuild.sh --backend-only\n.\u002Fscripts\u002Fbuild.sh --frontend-only\n.\u002Fscripts\u002Fbuild.sh --no-upx\n.\u002Fscripts\u002Fbuild.sh --no-ota\n```\n\nWindows 下建议在 WSL2 Ubuntu 中执行完整 OTA 构建。原生 PowerShell 不能直接运行 Bash 脚本；Git Bash 容易受 Node\u002Fnpm\u002Fpnpm PATH 影响，完整 OTA 仍需要 `aarch64-unknown-linux-musl-gcc` 等 Linux 交叉编译工具链：\n\n```bash\n.\u002Fscripts\u002Fbuild.sh --no-upx\n```\n\n构建脚本会：\n\n- 同步 `VERSION` 到 `backend\u002FCargo.toml` 和 `frontend\u002Fpackage.json`。\n- 使用 `pnpm-lock.yaml` 时通过 `pnpm install --frozen-lockfile`、`pnpm run lint` 和 `pnpm exec vite build` 构建前端到 `frontend\u002Fdist\u002F`。\n- 交叉编译后端到 `backend\u002Ftarget\u002Faarch64-unknown-linux-musl\u002Frelease\u002Fsimadmin`。\n- 可选使用 UPX 压缩后端二进制；未安装 UPX 时会自动跳过压缩。\n- 生成 `release\u002Fsimadmin_\u003Cversion>.tar.gz` OTA 包。\n\n### 通过 ADB 部署\n\n```bash\n.\u002Fscripts\u002Fdeploy.sh\n```\n\n常用选项：\n\n```bash\n.\u002Fscripts\u002Fdeploy.sh --backend-only\n.\u002Fscripts\u002Fdeploy.sh --frontend-only\n.\u002Fscripts\u002Fdeploy.sh --no-restart\n.\u002Fscripts\u002Fdeploy.sh --target=\u002Fopt\u002Fsimadmin\n```\n\n### 设备侧一键安装 \u002F 升级\n\n在目标设备上以 root 执行：\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Finstall_latest.sh | sh\n```\n\n国内网络环境：\n\n```bash\ncurl -fsSL https:\u002F\u002Fgh-proxy.com\u002Fhttps:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Finstall_latest.sh | sh\n```\n\n可选环境变量：\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Finstall_latest.sh \\\n  | REPO=3899\u002FSimAdmin INSTALL_DIR=\u002Fopt\u002Fsimadmin SERVICE_NAME=simadmin sh\n```\n\n脚本会：\n\n- 从 GitHub Release 下载 `simadmin.tar.gz`。\n- 安装后端二进制到 `\u002Fopt\u002Fsimadmin\u002Fsimadmin`。\n- 安装前端到 `\u002Fopt\u002Fsimadmin\u002Fwww`。\n- 安装并启用 `simadmin.service`。\n- 安装并启用 `simadmin-modem-recovery.service`。\n- 配置 NetworkManager 忽略 `wwan*` 接口，避免与 SimAdmin 抢占蜂窝连接管理。\n\n### 设备侧一键卸载\n\n默认彻底卸载，删除服务、程序文件、前端文件、OTA 临时目录、NetworkManager 配置以及用户数据：\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Funinstall.sh | sh\n```\n\n国内网络环境：\n\n```bash\ncurl -fsSL https:\u002F\u002Fgh-proxy.com\u002Fhttps:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Funinstall.sh | sh\n```\n\n如需保留短信数据库和配置文件：\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Funinstall.sh \\\n  | sh -s -- --keep-user-data\n```\n\n自定义安装路径或服务名时，需要和安装时保持一致：\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002F3899\u002FSimAdmin\u002Fmain\u002Funinstall.sh \\\n  | INSTALL_DIR=\u002Fopt\u002Fsimadmin SERVICE_NAME=simadmin sh -s -- --keep-user-data\n```\n\n可选参数：\n\n| 参数 | 说明 |\n|------|------|\n| `--purge` | 删除全部 SimAdmin 文件和用户数据，默认行为 |\n| `--keep-user-data` | 保留 `\u002Fopt\u002Fsimadmin\u002Fdata.db`、SQLite sidecar 文件和配置文件 |\n| `--install-dir PATH` | 指定安装目录，默认 `\u002Fopt\u002Fsimadmin` |\n| `--service-name NAME` | 指定主服务名，默认 `simadmin` |\n\n脚本会：\n\n- 停止并禁用 `simadmin.service`。\n- 停止并禁用 `simadmin-modem-recovery.service`。\n- 删除 systemd 单元文件并执行 `daemon-reload` \u002F `reset-failed`。\n- 删除 `\u002Fusr\u002Flocal\u002Fbin\u002Fsimadmin-modem-recovery.sh`。\n- 删除 `\u002Fetc\u002FNetworkManager\u002Fconf.d\u002F99-simadmin-unmanaged-modem.conf`，并在 NetworkManager 运行时重启它。\n- 删除 `\u002Ftmp\u002Fota_staging`。\n- 默认删除 `\u002Fopt\u002Fsimadmin` 和 `\u002Fdata\u002Fconfig.json`；使用 `--keep-user-data` 时保留用户数据。\n\n## 运行环境\n\n### 目标设备要求\n\n- Linux \u002F Debian 系统。\n- systemd。\n- root 权限。\n- system D-Bus。\n- ModemManager 和 `mmcli`。\n- 建议安装 `qmicli`，用于基站信息兜底读取。\n- `iptables` \u002F `ip6tables`，用于只读网络诊断；SimAdmin 不会自动清空宿主机防火墙规则。\n- `tar`，OTA 安装必需。\n- `unzip`、`busybox unzip` 或 `python3`，用于安装脚本解压自动下载的 `lpac`；`unzip` 也用于上传 zip 格式 OTA 包。\n- eSIM 管理依赖 `lpac`。使用 `install_latest.sh` 安装时会先校验设备上的 `lpac`，缺失、不可用或版本较旧时才按设备架构下载最新匹配版本；普通 SIM 模式下不会调用。\n\n### 安装路径\n\n| 路径 | 说明 |\n|------|------|\n| `\u002Fopt\u002Fsimadmin\u002Fsimadmin` | 后端二进制 |\n| `\u002Fopt\u002Fsimadmin\u002Fwww\u002F` | 前端静态文件 |\n| `\u002Fopt\u002Fsimadmin\u002Flpac\u002F` | 安装脚本按设备架构下载的私有 `lpac` 运行文件，后端优先使用 |\n| `\u002Fopt\u002Fsimadmin\u002Fdata.db` | SQLite 数据库，保存短信、登录认证配置和 Web 会话等数据 |\n| `\u002Fopt\u002Fsimadmin\u002Fmeta.json` | 当前安装包元数据 |\n| `\u002Fdata\u002Fconfig.json` | 优先使用的持久化配置文件 |\n| `\u002Fopt\u002Fsimadmin\u002Fconfig.json` | `\u002Fdata` 不存在时的配置文件回退路径 |\n| `\u002Ftmp\u002Fota_staging` | OTA 上传后的临时验证目录 |\n| `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fsimadmin.service` | 主服务 |\n| `\u002Fetc\u002Fsystemd\u002Fsystem\u002Fsimadmin-modem-recovery.service` | 开机 modem 自检恢复服务 |\n| `\u002Fusr\u002Flocal\u002Fbin\u002Fsimadmin-modem-recovery.sh` | 开机 modem 自检恢复脚本 |\n| `\u002Fetc\u002FNetworkManager\u002Fconf.d\u002F99-simadmin-unmanaged-modem.conf` | NetworkManager 忽略 `wwan*` 的配置 |\n\n### eSIM 管理\n\n本项目中的 eSIM 指写入了 Profiles 的实体 eUICC SIM 卡，插入设备 SIM 卡槽后仍按普通 SIM 使用。SimAdmin 的“eSIM 模式”只控制 eSIM 管理页面和接口是否开放，不切换设备板载硬件。\n\n普通 SIM 模式下，侧边栏隐藏 eSIM 管理入口，`\u002Fapi\u002Fesim\u002F*` 返回 `403`，前端不会下载 eSIM 页面 chunk，后端也不会主动调用 `lpac`。切换到 eSIM 模式后，只有打开 eSIM 管理页面或执行 Profile 操作时才会按需调用 `lpac chip info`、`lpac profile list`、`lpac profile enable`、`lpac profile nickname` 和 `lpac profile delete`。\n\nOTA 包不内置固定架构的 `lpac`。`install_latest.sh` 会在目标设备上根据 `uname -m` 和 glibc 版本优先选择兼容资产，已安装最新版本时跳过，否则安装到 `\u002Fopt\u002Fsimadmin\u002Flpac\u002Flpac`；兼容资产按 SimAdmin 的 `lpac` release manifest 比对版本，官方资产按 `estkme-group\u002Flpac` latest release 比对版本。后端优先使用该私有路径，找不到时再回退到 PATH 中的 `lpac`。如需跳过自动安装，可设置 `SIMADMIN_INSTALL_LPAC=0`；如需固定版本或使用镜像，可设置 `LPAC_TARGET_VERSION`、`LPAC_ASSET_URL`、`LPAC_ASSET_NAME`、`LPAC_RELEASE_BASE_URL` 或 `LPAC_COMPAT_RELEASE_BASE_URL`。仅手动上传 OTA 包不会自动安装或更新 `lpac`，首次部署建议先执行安装脚本一次。\n\n如果设备已经通过 OTA 更新到支持 eSIM 的版本，但还没有安装 `lpac`，eSIM 管理页面会显示状态提示并提供“安装\u002F修复 lpac”入口。修复过程只在 eSIM 模式下由用户手动触发，会根据设备 `uname -m` 和 glibc 版本优先下载兼容资产，失败后再尝试官方资产，并支持选择 GitHub 代理前缀；页面内修复由后端内置 ZIP 解压完成。\n\n### systemd 服务\n\n主服务单元位于 `scripts\u002Fsimadmin.service`，默认：\n\n- `WorkingDirectory=\u002Fopt\u002Fsimadmin`\n- `ExecStart=\u002Fopt\u002Fsimadmin\u002Fsimadmin`\n- `Restart=always`\n- `DBUS_SYSTEM_BUS_ADDRESS=unix:path=\u002Fvar\u002Frun\u002Fdbus\u002Fsystem_bus_socket`\n\n查看状态：\n\n```bash\nsystemctl status simadmin --no-pager\njournalctl -u simadmin -f\n```\n\n## 核心功能\n\n### Web 管理页面\n\n| 页面 | 路由 | 说明 |\n|------|------|------|\n| 登录认证 | `\u002Flogin` | 首次设置管理员密码、登录后台 |\n| 仪表盘 | `\u002F` | 在线状态、运营商、信号、网络延迟、数据\u002F漫游\u002F飞行模式快捷开关、系统资源、温度、流量 |\n| 设备信息 | `\u002Fdevice` | IMEI、厂商、型号、固件、SIM、系统信息 |\n| eSIM 管理 | `\u002Fesim` | eSIM 模式下显示，管理插入设备的实体 eUICC SIM 卡 Profiles |\n| 蜂窝网络 | `\u002Fnetwork` | 网络注册、服务小区和邻区、运营商扫描、APN、射频模式、频段锁定、小区锁定状态 |\n| 设备网络 | `\u002Fdevice-network` | WLAN 客户端联网、无线网络扫描和连接、DDNS 动态解析配置和同步日志 |\n| 短信管理 | `\u002Fsms` | 接收短信、发送短信、短信列表、会话、统计、删除对话、删除短信 |\n| 通知中心 | `\u002Fnotifications` | 转发日志、转发规则、转发通道、多通道测试发送 |\n| 系统配置 | `\u002Fconfig` | 设备操作、数据连接、漫游、飞行模式、基带重启、服务重启、系统重启等 |\n| OTA 更新 | `\u002Fota` | 上传 OTA 包、在线获取 Release、验证、应用或取消更新 |\n\n### 后端能力\n\n- 单管理员密码登录，支持首次设置、会话 Cookie、受保护 API 拦截和 SSH 本机恢复。\n- 设备信息、SIM 信息、网络注册信息读取。\n- 数据连接开关和漫游策略持久化。\n- 飞行模式控制。\n- 基带重启流程和进度查询。\n- 数据连接 watchdog，每 15 秒检查连接状态、iptables 规则数量和 modem 可用性；检测到宿主机防火墙规则时仅记录诊断日志，不自动清空规则。\n- ModemManager 丢失时触发 `mmcli --scan-modems`，连续失败后重启 ModemManager。\n- NetworkManager `wwan*` unmanaged 配置。\n- 设备侧 WLAN 客户端连接管理，通过 NetworkManager\u002Fnmcli 扫描和连接无线局域网，WLAN 在线时优先作为设备默认出口。\n- 原生 DDNS 同步，支持腾讯云 DNSPod、阿里云 AliDNS 和 Cloudflare，支持 IPv4\u002FIPv6 独立配置、API\u002F网卡取 IP 和变更\u002F失败事件通知；默认通过网卡取 IP，可切换为内置多接口 API fallback。\n- 短信发送、接收监听、SQLite 持久化和多渠道通知转发。\n- APN 列表读取和 APN 修改。\n- 运营商列表、扫描、手动注册、自动注册。\n- eSIM 模式下按需调用 `lpac` 管理实体 eUICC SIM 卡 Profiles；普通 SIM 模式下不调用 eSIM 能力。\n- 安装脚本按设备架构自动准备私有 `lpac`；OTA 包本身不绑定 `lpac` 架构或版本。\n- OTA 上传、在线下载、校验、替换二进制和前端资源。\n\n## 🚀 版本更新记录\n\n### 📌 v1.0.9\n\n#### ✨ 新增功能\n\n- 短信通知模板新增 `{{验证码}}` 变量，可按需嵌入转发规则使用，原有默认模板保持不变。\n- 后端新增专属验证码识别提取器，结合数字位数、位置权重、关键词关联、格式特征及干扰词剔除等规则进行加权识别智能解析验证码。\n- 适配中英文主流验证码短信格式，可识别带短横线分隔的验证码，并自动规整为纯数字格式。\n- 通知中心新增设备状态定时报表，支持定点或间隔周期推送，兼容现有通知规则、推送通道、转发日志及免打扰机制。\n- 报表支持各项状态指标单独启停监控，涵盖网络连接、蜂窝状态、系统运行、流量使用、短信转发统计、OTA 更新等设备核心信息。\n- 短信转发统计支持今日、最近 24 小时、最近 7 天和累计统计周期，优先展示接收、成功、失败关键数据，自动隐藏无数据空值项。\n- 新增消息队列与保护机制，转发通道支持独立频率配置并预置默认规则。\n\n#### 💫 体验优化\n\n- 设备状态数据采用懒加载采集策略，仅读取已开启指标数据，减少无效系统调用，节约系统资源。\n- 后端统一处理温度传感器名称映射，报表与仪表盘统一展示中文友好名称。\n- 设备状态报表模板支持分类段落排版，规整内容层级结构，条理更清晰，方便查阅各类设备指标信息。\n\n### 📌 v1.0.8\n\n#### ✨ 新增功能\n\n- 短信管理加入常驻搜索框，支持按号码、短信内容检索会话；匹配项可自动高亮检索关键词。\n- 短信统计新增推送数据统计，直观展示推送成功、尝试推送条数。\n- 新增系统配置「安全性」页面，支持启用密码保护、修改管理员密码、密码策略、会话有效期和空闲超时设置。\n- 重构通知中心架构，解耦为转发日志、转发规则、转发通道三大模块，明确分工：通道负责发送、规则负责筛选分配、日志负责监控排错。\n- 升级转发通道，支持多实例配置，可创建多个同类型通道，支持独立命名、启停、配置及测试发送。\n- 升级转发规则为事件路由层，支持多类型事件匹配、多目标通道分发、纯文本模板配置，新增星期 + 时间段免打扰。\n- 转发日志新增分页、多维度筛选及清空功能，细化状态分类，提升转发链路问题排查效率。\n- 转发日志增强时间范围筛选、高级清理和自动清理配置，支持按类型、状态、时间段及保留策略管理日志。\n- DDNS 转发规则新增连续失败推送阈值，支持达到指定失败次数后再推送，减少短时网络波动造成的通知干扰。\n- 通知中心新增系统事件通知，覆盖基带、蜂窝网络、设备网络、系统\u002F服务、安全审计、SIM\u002FeSIM 和资源告警，支持按事件独立启停、阈值\u002F恢复推送及系统事件模板。\n\n#### 💫 体验优化\n\n- 精简短信统计面板，隐藏总计数据，保留收发统计，新增独立推送统计卡片，支持悬停查看数据说明。\n- 持久化存储短信转发状态，过滤无效异常数据，保证推送统计结果准确可靠。\n- 优化登录页和首次设置密码页视觉效果，补充忘记密码提示。\n- 支持按已保存的密码策略校验新密码，并提供密码强度提示。\n- 统一通知模板为纯文本格式，前端支持中文变量名，简化模板配置。\n- 优化短信监听转发策略，区分历史短信补录与新短信转发，避免批量转发与消息漏推。\n\n### 📌 v1.0.7\n\n#### ✨ 新增功能\n\n- 新增管理员密码登录能力，支持初始配置、会话校验，防护页面与接口访问访问保护。\n- 支持 SSH 本地命令交互式重置密码、清空认证配置后重新设置。\n- 增加密码复杂度校验，过滤非法格式字符。\n\n#### 💫 体验优化\n\n- 优化本机号码变量展示，国内号码精简为 11 位格式，境外号码保留或补全国际前缀。\n- 版本检测改为北京时间每天 09:00 和 18:00 执行，并新增超时限制、多节点降级重试，提升更新通知获取成功率。\n\n### 📌 v1.0.6\n\n#### ✨ 新增功能\n\n- 数据连接管控从 ModemManager D-Bus 迁移至 NetworkManager，通过nmcli实现联网启停。\n- 交由 NetworkManager 自动完成接口启用、IP、DNS、IPv6 及路由全流程配置。\n- 新增双轨流量统计机制，精准获取蜂窝网口真实上下行流量。\n- 新增统一网络地址选择能力，仪表盘与 DDNS 共用同一套 IPv4 \u002F IPv6 网口判断逻辑。\n- 在未自动识别到 SIM 卡的本机号码或短信中心（SMSC）时，允许用户在界面手动输入并持久化缓存。\n- 手动输入的本机号码立即生效，自动支持并映射通知中心的短信转发变量。\n\n#### 💫 体验优化\n\n- 职责拆分，ModemManager 仅负责信号、注册状态等只读查询。\n- 程序启动自动清理旧 `unmanaged` 配置，自动生成蜂窝网络配置。\n- 移除 `wwan0` 等网口名称硬编码，由 `NetworkManager` 自动适配识别。\n- APN 配置界面默认选中并展示当前已连接的 APN 槽位。\n- 优化 DDNS 公网 IP 获取逻辑，非蜂窝网卡跳过冗余 D-Bus 请求，减少资源开销。\n- 完善蜂窝接口流量展示，支持展示真实上下行流量字节与数据包数量。\n- 优化仪表盘与 DDNS 的 IP 展示和获取优先级，有无线网络时优先使用无线网口，无无线网络时自动回落到蜂窝数据网口。\n- 自动识别无线网口、蜂窝网口和默认路由，不再依赖 `wlan0`、`wwan0` 等固定网口名称。\n- 在仪表盘和设备信息页增加 SIM 号码空值识别，无缝集成在线编辑组件及输入格式校验。\n\n#### 🐞 bug 修复\n\n- 彻底修复数据连接假开关问题，解决前台显示已联网、实际接口未启用无 IP 无法上网的故障。\n- 修复正常网口因内核限制被误判为 `UNKNOWN` 的问题，优化状态自动纠正逻辑。\n- 彻底解决高通平台蜂窝网口流量统计恒为 0 问题，同时兼容联发科、展锐等多类模组设备。\n- 解决内核网口统计数据不准，造成前端无法展示真实蜂窝流量的问题。\n- 修复仪表盘和 DDNS 在部分场景下误选本地回环、管理桥或链路本地地址，导致显示或解析 IP 不符合实际上网出口的问题。\n\n### 📌 v1.0.5\n\n#### ✨ 新增功能\n\n- 新增短信中心号码、本机号码多源读取 + 缓存能力，多通道静默提取、命中即止。\n- 新增缓存表，接收短信时自动学习并持久化存储短信中心号码、本机号码。\n- 新增 SIM \u002F eSIM 工作模式功能开关，默认保持普通 SIM 模式。\n- 依托 `lpac` 实现实体 eUICC 卡轻量 eSIM 管理，配套管理页面支持卡信息查看、配置文件切换、重命名与删除。\n- 通知模板新增本机号码变量，适配短信转发场景。\n\n#### 💫 体验优化\n\n- 短信中心号码、本机号码读取失败均静默处理，不影响功能使用与页面展示。\n- 优化短信接收可靠性，服务启动、Profile 切换和基带恢复后会主动检查未同步短信。\n- 优化短信去重策略，减少设备重启或短信编号复用导致的误判漏收。\n- 采用命中即停策略，减少冗余调制解调器指令调用，降低日志干扰。\n- 优化系统配置页面 UI，调整布局并新增工作模式卡片。\n- 侧边栏随工作模式动态隐藏 eSIM 相关入口，普通 SIM 模式不加载对应页面资源。\n- 优化 eSIM 调用逻辑，仅使用对应功能时调用 `lpac`，无需常驻后台进程。\n- 优化设备开机及 SIM 搜网注册阶段前端界面频繁报错的问题，同时将用户操作触发的错误提示改为常显，解决此前错误信息自动消失过快导致用户无法阅读的问题。\n\n#### 🐞 bug 修复\n\n- 修复 PushPlus 部分配置场景报错问题，提升通知渠道兼容性。\n- 修复短信中心号码读取时，ModemManager 非调试模式的未授权告警问题。\n- 修复实体 eSIM 卡在 Profile 切换或基带恢复后，短信已到设备但 Web 页面未显示的问题。\n\n#### 📚 接口与文档更新\n\n- 数据库新增号码缓存表，持久化存储 SMSC 与本机号码。\n- 新增工作模式、eSIM 管理全套 API 接口。\n- eSIM 接口适配 `lpac` 标准 JSON 输出，适配各类 eSIM 管理操作。\n- 完善文档，补充相关使用说明。\n\n### 📌 v1.0.4\n\n#### ✨ 新增功能\n\n- 通知中心新增 PushPlus 通知渠道，支持配置 Token、标题模板、群组编码、消息模板、发送渠道、渠道参数和回调地址，并接入短信、DDNS 事件转发及测试发送。\n- 通知中心新增版本更新提醒：后台每天北京时间 09:00 和 18:00 检测，发现新版本时按渠道首次提醒一次，不对检测失败或无更新场景推送通知。\n\n#### 💫 体验优化\n\n- 抽象封装前端通用 IPv6 公网地址筛选工具，仪表盘连接展示、设备网络 DDNS 接口统一复用同一套判定规则。\n- 数据连接看门狗保留蜂窝状态巡检与 Modem 自愈能力，不再自动清空宿主机 iptables\u002Fip6tables 规则，避免影响 Docker、VPN 及容器端口映射等业务。\n- 切换蜂窝数据连接时取消全局防火墙规则刷新，减少对宿主机网络栈、容器转发链路的副作用。\n- 通知中心统一在模板渲染层将短信、DDNS 的时间变量格式化为北京时间，避免各渠道收到 UTC 原始时间。\n\n#### 🐞 bug 修复\n\n- 修正 DDNS 模块 IPv6 公网地址判断逻辑，前后端统一以公网域 IPv6 作为 AAAA 记录候选地址，避免误选链路本地地址、内网 ULA 地址。\n- IPv6 地址候选按 `\u002F128` 优先排序，提升多 IPv6 地址场景下 DDNS 自动选择地址的准确性。\n- 修复宿主机 `FORWARD` 默认策略为 `DROP` 时，清空 filter 表规则引发 Docker 网桥转发失效、外部无法访问容器映射端口的问题。\n- 修复企业微信应用消息可能报错的问题。\n\n#### 📚 接口与文档更新\n\n- 明确 NetworkManager `wwan*` 非托管配置仅用于防止蜂窝接口被双重管理，不会直接修改 iptables 规则。\n- 同步更新 README 及 Bruno 接口示例，标注 `iptables\u002Fip6tables` 仅作只读诊断使用，程序不会自动清空宿主机防火墙规则。\n\n### 📌 v1.0.3\n\n#### ✨ 新增功能\n\n- 新增“设备网络”模块，用于配置设备侧 WLAN 客户端联网、 DDNS 动态解析，以及后期其他高级功能的扩充。\n- 新增设备侧 WLAN 管理能力：\n  - 开启 \u002F 关闭 WLAN。\n  - 扫描附近无线网络。\n  - 连接、断开和忘记已保存 WLAN。\n  - 保存自动加入和 IPv4 地址配置。\n- 新增原生 DDNS 同步能力：\n  - 支持腾讯云 DNSPod、阿里云 AliDNS 和 Cloudflare。\n  - 支持 IPv4 \u002F IPv6 独立解析配置。\n  - 支持通过网卡或多接口 API 获取公网 IP。\n  - 支持立即同步、后台周期同步、同步状态和最近 50 条运行日志。\n- DDNS 变更和失败事件接入通知中心，可按通知渠道独立开启“DDNS 变更”转发。\n\n#### 💫 体验优化\n\n- 侧边栏和页面分为“蜂窝网络”和“设备网络”，职责更清晰。\n- OTA 更新页面优化待安装更新和验证结果展示，在线更新支持 GitHub Release 检查、下载加速节点和下载进度。\n- 仪表盘温度展示改为冷到热连续热力色，并同时标识最低和最高温度探头。\n\n#### 🐞 bug 修复\n\n- 运营商扫描和手动 \u002F 自动注册增加超时处理，避免 ModemManager D-Bus 调用长时间阻塞。\n- 数据连接 watchdog 增强长时间 `searching` 状态恢复逻辑，可自动尝试重新注册或循环射频状态。\n- 注册遇到 QMI network selection internal 类错误时统一走射频恢复流程，减少注册异常后的卡死概率。\n\n#### 📚 接口与文档更新\n\n- 新增设备网络 API 文档和 Bruno 示例，覆盖 DDNS 配置、状态、同步、日志以及 WLAN 状态、扫描、连接、断开、忘记和配置保存。\n- API 契约新增 DDNS、WLAN 和 DDNS 同步日志相关类型。\n- 配置持久化新增 `device_network.ddns`，通知渠道配置新增 `forward_ddns`。\n\n### 📌 v1.0.2\n\n#### ✨ 新增功能\n\n- 频段锁定状态新增后端报告的真实支持频段：\n  - `supported_lte_fdd_bands`\n  - `supported_lte_tdd_bands`\n  - `supported_nr_fdd_bands`\n  - `supported_nr_tdd_bands`\n- 小区与信号数据增加 `qmicli` 兜底解析，提升 ModemManager `GetCellInfo` 不可用场景下的可观测性。\n\n#### 💫 体验优化\n\n- 优化移动网络注册问题的诊断路径，重点区分 SIM 归属运营商、当前注册网络、漫游状态、射频模式、频段限制和小区数据。\n- 前端自定义频段选项改为基于后端 `SupportedBands` 动态显示，不再依赖固定写死的 LTE\u002FNR 频段列表。\n- 从“未锁定”切换到“自定义”时，默认勾选当前设备真实支持的全部频段，更符合使用预期。\n- 移除网络页面中不必要的“验证说明”文案，简化频段锁定 UI。\n\n#### 🐞 bug 修复\n\n- SIM 信息优先从 IMSI 推导 MCC\u002FMNC，避免注册到漫游网络时把当前网络运营商误当成 SIM 归属运营商。\n- 后端设置自定义频段时会校验用户选择是否被当前 modem 支持；发现不支持的频段会返回明确错误，不再静默忽略。\n- 自动注册遇到 QMI Internal 类错误时增强恢复处理，降低调制解调器处于异常注册状态时的卡死概率。\n\n#### 📚 接口与文档更新\n\n- 修正 README、Bruno API 示例和前端开发代理中的默认访问地址为 `http:\u002F\u002F192.168.68.1:3000\u002F`。\n\n### 📌 v1.0.1\n\n#### ✨ 新增功能\n\n- 新增“通知中心”多渠道通知配置能力。\n  - 通知配置从单一 Webhook 扩展为多渠道：\n    - Webhook\n    - Bark\n    - 企业微信应用消息\n    - 企业微信群机器人\n    - 钉钉群自定义机器人\n    - 钉钉企业内机器人\n    - 飞书机器人\n    - Telegram 机器人\n  - 新增通知中心后端接口：\n    - `GET \u002Fapi\u002Fnotifications\u002Fconfig`\n    - `POST \u002Fapi\u002Fnotifications\u002Fconfig`\n    - `POST \u002Fapi\u002Fnotifications\u002Ftest\u002F{channel}`\n  - 新增各通知渠道的测试发送能力，可按渠道发送模拟短信测试。\n- 新增短信批量管理能力。\n  - 删除短信：\n    - 删除单条短信\n    - 删除整个短信对话\n    - 批量删除短信或多个对话\n  - 新增短信删除相关后端接口：\n    - `DELETE \u002Fapi\u002Fsms\u002Fmessage\u002F{id}`\n    - `DELETE \u002Fapi\u002Fsms\u002Fconversation\u002F{phone_number}`\n    - `POST \u002Fapi\u002Fsms\u002Fbatch-delete`\n- 新增设备侧一键卸载脚本 `uninstall.sh`，支持彻底卸载和保留用户数据卸载。\n\n#### 💫 体验优化\n\n- Dashboard 仪表盘加载性能优化。\n- 通知中心页面重构为左右分栏布局：\n  - 左侧展示通知渠道列表和启用统计\n  - 右侧展示当前渠道配置表单\n- 通知中心支持按渠道独立配置启用状态、短信转发、模板和渠道专属参数。\n- 通知模板编辑支持中文变量标签，前端显示中文变量，保存时映射为后端变量。\n- 通知渠道测试按钮会先保存当前配置，再执行测试，减少“配置未保存导致测试不生效”的误操作。\n- 短信页面优化为更完整的对话管理体验：\n  - 对话列表支持删除按钮\n  - 聊天消息支持单条删除\n  - 支持批量管理，有清晰的选择数量提示\n  - 删除这种不可逆的危险操作增加二次确认\n- 短信列表加载数量提升，减少历史短信遗漏。\n\n#### 📚 接口与文档更新\n\n- README 中 Webhook 章节改为“通知中心”，补充多渠道通知能力说明。\n- Bruno 文档同步更新通知中心接口说明。\n- README 新增卸载脚本使用说明、参数说明和清理范围说明。\n- API 类型定义新增完整通知中心配置类型，包括各渠道配置结构。\n\n## ModemManager D-Bus 接口\n\n当前实现以 ModemManager 为主。\n\n### 核心接口\n\n| 接口 | 说明 |\n|------|------|\n| `org.freedesktop.ModemManager1` | ModemManager 根服务 |\n| `org.freedesktop.ModemManager1.Modem` | Modem 状态、开关、模式、频段 |\n| `org.freedesktop.ModemManager1.Modem.Modem3gpp` | 运营商、注册、扫描 |\n| `org.freedesktop.ModemManager1.Modem.Simple` | 简化连接和断开 |\n| `org.freedesktop.ModemManager1.Modem.Messaging` | 短信发送和接收 |\n| `org.freedesktop.ModemManager1.Sim` | SIM 属性 |\n| `org.freedesktop.ModemManager1.Bearer` | 数据连接 bearer |\n\n### 常用调试命令\n\n```bash\n# 查看 modem 列表\nmmcli -L\n\n# 查看 modem 详情\nmmcli -m any\n\n# 查看注册和连接简要状态\nmmcli -m any --simple-status\n\n# 查看 3GPP 定位信息\nmmcli -m any --location-get\n\n# 查看信号指标\nmmcli -m any --signal-get\n\n# 发送 AT 指令\nmmcli -m any --command='AT+CGSN'\n```\n\n### D-Bus 监控\n\n```bash\n# 监听 ModemManager 信号\ndbus-monitor --system \"sender='org.freedesktop.ModemManager1'\"\n\n# 查看 modem 0 暴露的接口\nbusctl introspect org.freedesktop.ModemManager1 \u002Forg\u002Ffreedesktop\u002FModemManager1\u002FModem\u002F0\n```\n\n## 频段与小区控制\n\n### 射频模式\n\n`\u002Fapi\u002Fradio-mode` 支持：\n\n| 值 | 说明 |\n|----|------|\n| `auto` | LTE\u002FNR 自动 |\n| `lte` | LTE only |\n| `nr` | NR only |\n\n实际是否可切换取决于 modem 的 `SupportedModes`。\n\n### 频段锁定\n\n频段锁定通过 ModemManager 的 `SetCurrentBands` 实现。API 使用用户熟悉的物理频段号，后端内部转换为 ModemManager band id：\n\n- LTE：`30 + Bn`\n- NR：`300 + Nn`\n\n示例，锁定 LTE B1 + B3：\n\n```json\n{\n  \"lte_fdd_bands\": [1, 3],\n  \"lte_tdd_bands\": [],\n  \"nr_fdd_bands\": [],\n  \"nr_tdd_bands\": []\n}\n```\n\n示例，锁定 NR N78：\n\n```json\n{\n  \"lte_fdd_bands\": [],\n  \"lte_tdd_bands\": [],\n  \"nr_fdd_bands\": [],\n  \"nr_tdd_bands\": [78]\n}\n```\n\n示例，混合锁定 LTE 和 NR：\n\n```json\n{\n  \"lte_fdd_bands\": [1, 3],\n  \"lte_tdd_bands\": [38, 40, 41],\n  \"nr_fdd_bands\": [],\n  \"nr_tdd_bands\": [78, 79]\n}\n```\n\n解锁所有频段时传空数组：\n\n```json\n{\n  \"lte_fdd_bands\": [],\n  \"lte_tdd_bands\": [],\n  \"nr_fdd_bands\": [],\n  \"nr_tdd_bands\": []\n}\n```\n\n后端会与 modem 的 `SupportedBands` 取交集。如果所选频段不被当前 modem 支持，会返回错误。\n\n### 小区锁定\n\n当前 `\u002Fapi\u002Fcell-lock` 只维护内存状态，支持记录 LTE 和 NR 的 ARFCN\u002FPCI：\n\n```json\n{\n  \"rat\": 16,\n  \"enable\": true,\n  \"pci\": 123,\n  \"arfcn\": 627264\n}\n```\n\n`rat=12` 表示 LTE，`rat=16` 表示 NR。这个接口当前不会下发真实 AT 或 QMI 小区锁定命令。\n\n## API 接口文档\n\n所有主要业务接口返回统一 JSON 包装：\n\n```json\n{\n  \"status\": \"ok\",\n  \"message\": \"Success\",\n  \"data\": {}\n}\n```\n\n错误响应：\n\n```json\n{\n  \"status\": \"error\",\n  \"message\": \"错误信息\"\n}\n```\n\n除 `\u002Fapi\u002Fhealth` 和认证初始化接口外，业务接口需要携带登录后由后端设置的 `simadmin_session` Cookie。\n\n### 登录认证\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fauth\u002Fstatus` | GET | 查询是否已设置管理员密码以及当前会话是否已登录 |\n| `\u002Fapi\u002Fauth\u002Fsetup` | POST | 首次设置管理员密码，仅在尚未配置密码时可用 |\n| `\u002Fapi\u002Fauth\u002Flogin` | POST | 使用管理员密码登录，成功后写入 `simadmin_session` Cookie |\n| `\u002Fapi\u002Fauth\u002Fpassword` | POST | 已登录后修改管理员密码，并清空旧 Web 会话 |\n\n`\u002Fapi\u002Fauth\u002Fsetup` 和 `\u002Fapi\u002Fauth\u002Flogin` 请求体：\n\n```json\n{\n  \"password\": \"AdminPassword123!\"\n}\n```\n\n`\u002Fapi\u002Fauth\u002Fpassword` 请求体：\n\n```json\n{\n  \"new_password\": \"NewPassword123!\"\n}\n```\n\n### 基础信息\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fhealth` | GET | 健康检查，返回平台和版本 |\n| `\u002Fapi\u002Fdevice` | GET | 设备信息 |\n| `\u002Fapi\u002Fsim` | GET | SIM 卡信息 |\n\n### 网络状态\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fnetwork` | GET | 网络注册信息、运营商、信号百分比 |\n| `\u002Fapi\u002Fcells` | GET | 服务小区和邻区信息 |\n| `\u002Fapi\u002Fcell-monitor\u002Fstart` | POST | 启动小区监控 |\n| `\u002Fapi\u002Fcell-monitor\u002Fstop` | POST | 停止小区监控 |\n| `\u002Fapi\u002Fnetwork\u002Finterfaces` | GET | 网络接口、IP、流量统计 |\n| `\u002Fapi\u002Fdevice-network\u002Fddns\u002Fconfig` | GET\u002FPOST | DDNS 配置读取和保存 |\n| `\u002Fapi\u002Fdevice-network\u002Fddns\u002Fstatus` | GET | DDNS 当前状态和最近同步结果 |\n| `\u002Fapi\u002Fdevice-network\u002Fddns\u002Fsync` | POST | 立即执行 DDNS 同步 |\n| `\u002Fapi\u002Fdevice-network\u002Fddns\u002Flogs` | GET | 最近 50 条 DDNS 同步日志 |\n| `\u002Fapi\u002Fdevice-network\u002Fddns\u002Flogs\u002Fclear` | POST | 清空 DDNS 同步日志 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fstatus` | GET | WLAN 设备、开关、连接和 IP 状态 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fenabled` | POST | 开启或关闭设备 WLAN |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fscan` | POST | 扫描附近 WLAN 热点 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fprofiles` | GET | 获取已保存 WLAN 网络 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fforget` | POST | 忘记已保存 WLAN 网络 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fconnect` | POST | 连接指定 WLAN 热点 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fdisconnect` | POST | 断开当前 WLAN 连接 |\n| `\u002Fapi\u002Fdevice-network\u002Fwlan\u002Fprofile` | POST | 保存 WLAN 自动加入和 IPv4 配置 |\n| `\u002Fapi\u002Fnetwork\u002Fsignal-strength` | GET | 信号强度 |\n| `\u002Fapi\u002Flocation\u002Fcell-info` | GET | 基站定位参数 |\n| `\u002Fapi\u002Fnetwork\u002Foperators` | GET | 当前和已知运营商 |\n| `\u002Fapi\u002Fnetwork\u002Foperators\u002Fscan` | GET | 扫描可用运营商，可能耗时较长 |\n| `\u002Fapi\u002Fnetwork\u002Fregister-manual` | POST | 手动注册运营商 |\n| `\u002Fapi\u002Fnetwork\u002Fregister-auto` | POST | 自动注册运营商 |\n| `\u002Fapi\u002Fconnectivity` | GET | IPv4 \u002F IPv6 连通性检测 |\n\n### 模块控制\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fdata` | GET\u002FPOST | 数据连接状态和开关 |\n| `\u002Fapi\u002Froaming` | GET\u002FPOST | 漫游策略和当前漫游状态 |\n| `\u002Fapi\u002Fairplane-mode` | GET\u002FPOST | 飞行模式 |\n| `\u002Fapi\u002Fradio-mode` | GET\u002FPOST | 射频模式 |\n| `\u002Fapi\u002Fband-lock` | GET\u002FPOST | 频段锁定 |\n| `\u002Fapi\u002Fcell-lock` | GET\u002FPOST | 小区锁定内存状态 |\n| `\u002Fapi\u002Fcell-lock\u002Funlock-all` | POST | 清空小区锁定状态 |\n| `\u002Fapi\u002Fapn` | GET\u002FPOST | APN 列表和配置 |\n| `\u002Fapi\u002Fbaseband\u002Frestart` | POST | 重启基带并尝试恢复网络 |\n| `\u002Fapi\u002Fbaseband\u002Frestart\u002Fstatus` | GET | 基带重启进度 |\n| `\u002Fapi\u002Fwork-mode` | GET\u002FPOST | 读取或切换普通 SIM \u002F eSIM 工作模式 |\n\n### eSIM 管理\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fesim\u002Flpac\u002Fstatus` | GET | 检测 `lpac` 安装路径、架构匹配和可用状态 |\n| `\u002Fapi\u002Fesim\u002Flpac\u002Frepair` | POST | 按设备架构下载并安装\u002F修复私有 `lpac`，支持 `proxy_prefix` |\n| `\u002Fapi\u002Fesim\u002Feuicc` | GET | 读取 eUICC 芯片信息 |\n| `\u002Fapi\u002Fesim\u002Fprofiles` | GET | 读取 Profiles 列表 |\n| `\u002Fapi\u002Fesim\u002Fprofiles\u002F{iccid}\u002Fenable` | POST | 启用指定 Profile |\n| `\u002Fapi\u002Fesim\u002Fprofiles\u002F{iccid}\u002Frename` | POST | 重命名指定 Profile |\n| `\u002Fapi\u002Fesim\u002Fprofiles\u002F{iccid}` | DELETE | 删除指定 Profile |\n\n### 短信功能\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fsms\u002Fsend` | POST | 发送短信 |\n| `\u002Fapi\u002Fsms\u002Flist` | GET | 短信列表，支持 `limit` \u002F `offset` |\n| `\u002Fapi\u002Fsms\u002Fconversation` | GET | 指定号码会话，参数 `phone_number` |\n| `\u002Fapi\u002Fsms\u002Fstats` | GET | 短信统计 |\n| `\u002Fapi\u002Fsms\u002Fclear` | POST | 清空短信记录 |\n| `\u002Fapi\u002Fsms\u002Fmessage\u002F{id}` | DELETE | 删除单条短信 |\n| `\u002Fapi\u002Fsms\u002Fconversation\u002F{phone_number}` | DELETE | 删除指定号码会话 |\n| `\u002Fapi\u002Fsms\u002Fbatch-delete` | POST | 批量删除短信或多个会话 |\n\n### 系统信息\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fstats` | GET | 网速、内存、磁盘、CPU、运行时间、系统信息、温度 |\n| `\u002Fapi\u002Fstats\u002Fcpu` | GET | CPU 详细信息 |\n| `\u002Fapi\u002Fsystem\u002Freboot` | POST | 系统重启 |\n| `\u002Fapi\u002Fservice\u002Frestart` | POST | 重启 SimAdmin 服务 |\n\n### 通知中心\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fnotifications\u002Fconfig` | GET\u002FPOST | 转发通道和转发规则配置 |\n| `\u002Fapi\u002Fnotifications\u002Ftest\u002F{channel}` | POST | 测试指定通知通道实例 |\n| `\u002Fapi\u002Fnotifications\u002Flogs` | GET | 查询转发日志，支持类型、状态和关键词筛选 |\n| `\u002Fapi\u002Fnotifications\u002Flogs\u002Fclear` | POST | 清空转发日志 |\n\n通知配置支持：\n\n- Webhook。\n- Bark。\n- 企业微信应用消息。\n- 企业微信群机器人。\n- 钉钉群自定义机器人。\n- 钉钉企业内机器人。\n- 飞书机器人。\n- Telegram 机器人。\n- 转发通道可创建多个同类型实例，并支持独立启用\u002F停用。\n- 转发规则按短信、DDNS、版本更新和系统事件路由；短信\u002FDDNS\u002F版本更新支持内容匹配，系统事件按具体事件码独立启用\u002F停用。\n- 转发日志按单个通道发送结果记录，状态包括成功、失败、免打扰、未匹配规则和无可用通道。\n\n系统事件覆盖基带、蜂窝网络、设备网络、系统\u002F服务、安全审计、SIM\u002FeSIM 和资源告警。默认开启高价值低噪音事件，例如 Modem 丢失\u002F恢复、蜂窝连接失败\u002F恢复、系统重启请求、安全策略变更、eSIM 失败事件、CPU\u002F内存\u002F磁盘\u002F温度\u002FIPv4 连通性阈值和恢复；默认关闭 WLAN 连接\u002F断开、服务启动完成、成功登录、lpac\u002FProfile 成功类提示、IPv6 连通性和接口错误包增长等容易产生噪音的事件。\n\n模板变量包括本机号码、短信号码、短信内容、运营商、短信方向、短信状态和时间等字段。系统事件模板支持 `{{分类}}`、`{{事件}}`、`{{等级}}`、`{{状态}}`、`{{对象}}`、`{{消息}}`、`{{时间}}`；版本更新模板支持固件包名、版本号、Commit、构建时间和 OTA 包 MD5；构建时间会按北京时间展示。\n\n### OTA 更新\n\n| 接口 | 方法 | 说明 |\n|------|------|------|\n| `\u002Fapi\u002Fota\u002Fstatus` | GET | 当前版本和待安装更新 |\n| `\u002Fapi\u002Fota\u002Fupload` | POST | 上传 OTA 包，最大 50 MB |\n| `\u002Fapi\u002Fota\u002Flatest-release` | POST | 查询 GitHub latest release |\n| `\u002Fapi\u002Fota\u002Fonline-prepare` | POST | 在线下载 latest release 中的 OTA 包并验证 |\n| `\u002Fapi\u002Fota\u002Fapply` | POST | 应用待安装更新 |\n| `\u002Fapi\u002Fota\u002Fcancel` | POST | 取消待安装更新 |\n\nOTA 包结构：\n\n```text\nmeta.json\nsimadmin\nwww\u002F\n```\n\n`meta.json` 示例：\n\n```json\n{\n  \"version\": \"1.0.9\",\n  \"commit\": \"abcdef0\",\n  \"build_time\": \"2026-05-06T00:00:00Z\",\n  \"binary_md5\": \"md5-of-binary\",\n  \"frontend_md5\": \"md5-of-www\",\n  \"arch\": \"aarch64-unknown-linux-musl\"\n}\n```\n\n当前验证逻辑会检查：\n\n- OTA 包中存在 `simadmin`。\n- OTA 包中存在 `www\u002F`。\n- 二进制 MD5 匹配。\n- 架构为 `aarch64-unknown-linux-musl`。\n- 版本号是否高于当前版本会作为提示字段返回，不是唯一安装条件。\n\n## 开发指南\n\n### D-Bus 操作序列化\n\n会改变 modem 状态的操作应通过 `with_serial` 串行执行，避免 ModemManager 或底层设备出现并发冲突：\n\n```rust\nuse crate::serial::with_serial;\n\npub async fn set_some_modem_state(conn: &Connection) -> zbus::Result\u003C()> {\n    with_serial(async {\n        \u002F\u002F D-Bus \u002F modem operation\n        Ok(())\n    }).await\n}\n```\n\n### 前后端契约\n\n- 后端模型位于 `backend\u002Fsrc\u002Fmodels.rs`。\n- 前端类型位于 `frontend\u002Fsrc\u002Fapi\u002Fcontracts.ts`。\n- 前端 API 封装位于 `frontend\u002Fsrc\u002Fapi\u002Fcurrent.ts`。\n- 路由集中在 `backend\u002Fsrc\u002Fmain.rs` 和 `frontend\u002Fsrc\u002FApp.tsx`。\n\n新增接口时建议同步修改：\n\n1. `backend\u002Fsrc\u002Fmodels.rs`\n2. `backend\u002Fsrc\u002Fhandlers.rs`\n3. `backend\u002Fsrc\u002Fmain.rs`\n4. `frontend\u002Fsrc\u002Fapi\u002Fcontracts.ts`\n5. `frontend\u002Fsrc\u002Fapi\u002Fcurrent.ts`\n6. 对应页面或 hook\n7. `bruno-api\u002F` 调试请求\n\n### 数据持久化\n\nSQLite 数据库保存：\n\n- `sms_messages`：短信收发记录。\n- `auth_config`：管理员密码哈希等登录认证配置。\n- `auth_sessions`：Web 会话哈希和过期时间。\n\n管理员密码和会话 token 不以明文存储。修改或清除管理员密码会同步清空旧会话。\n\n配置文件保存：\n\n- 通知中心配置。\n- 是否允许漫游。\n- 数据连接是否由用户启用。\n- 设备网络 DDNS 配置。\n\n### 版本注入\n\n`backend\u002Fbuild.rs` 会在编译期注入：\n\n- `APP_VERSION`\n- `GIT_BRANCH`\n- `GIT_COMMIT`\n\n其中版本号来自根目录 `VERSION`。\n\n### Bruno API 集合\n\n`bruno-api\u002F` 是 Bruno 调试集合，默认按 `http:\u002F\u002FIP:3000` 组织请求。导入 Bruno 后可批量验证后端接口。\n\n## 依赖\n\n### 后端\n\n- `axum 0.8`：HTTP 服务。\n- `tokio 1.48`：异步运行时。\n- `zbus 5`：D-Bus 客户端。\n- `rusqlite 0.32`：SQLite。\n- `tower-http 0.6`：CORS 和静态文件相关能力。\n- `reqwest 0.12`：在线 OTA Release 查询和下载。\n- `clap 4.5`：命令行参数。\n- `tracing`：日志。\n\n### 前端\n\n- `react 19`\n- `vite 7`\n- `@mui\u002Fmaterial 7`\n- `@mui\u002Ficons-material`\n- `@mui\u002Fx-charts`\n- `@mui\u002Fx-data-grid`\n- `@tanstack\u002Freact-query`\n- `swr`\n- `react-router-dom 7`\n\n### 目标设备命令\n\n- `ModemManager`\n- `mmcli`\n- `NetworkManager` \u002F `nmcli`\n- `qmicli`\n- `iptables` \u002F `ip6tables`（只读诊断）\n- `systemctl`\n- `tar`\n- `unzip`\n- `curl`\n\n##  license 许可证\n\n> GNU General Public License v3.0\n\n## 🎖️ 鸣谢\n\n### 📦 参考项目\n\n- [project-cpe](https:\u002F\u002Fgithub.com\u002F1orz\u002Fproject-cpe)\n- [SmsForwarder](https:\u002F\u002Fgithub.com\u002Fpppscn\u002FSmsForwarder)\n- [ddns-go](https:\u002F\u002Fgithub.com\u002Fjeessy2\u002Fddns-go)\n","SimAdmin 是一个面向 Debian 平台的 SIM\u002FeSIM、蜂窝网络、短信和系统状态管理的开源 Web 管理系统。项目采用 Rust 语言开发后端，利用 Axum 和 zbus 框架通过 ModemManager D-Bus 接口来管理和控制 modem 设备，并在某些场景下使用 `mmcli`、`qmicli` 或 AT 命令进行补充。前端基于 React 构建，结合 Vite 和 Material UI 提供了丰富的用户界面，包括仪表盘、设备信息、蜂窝网络配置、WLAN 管理、短信收发等功能。此外，还支持 DDNS 配置、通知规则设置以及 OTA 更新等高级特性。SimAdmin 适用于需要对蜂窝 CPE、随身 WiFi 或软路由类设备进行全面远程管理的场合，如家庭或小型企业网络环境中的移动宽带接入管理。",2,"2026-06-11 04:06:40","CREATED_QUERY"]