.
├── backend/ # Rust + Axum 后端,ModemManager、SQLite、OTA、通知、系统接口
├── frontend/ # React + Vite + MUI 前端
├── bruno-api/ # Bruno API 调试集合
├── scripts/ # 构建(build)、系统服务(system)、测试(tests)、评测工具(tool)
├── install_latest.sh # 设备侧一键安装 / 升级脚本
├── uninstall.sh # 设备侧一键卸载脚本
├── VERSION # 项目版本号
└── LICENSE # GPLv3 许可证
cd frontend
pnpm install
pnpm devcd frontend
pnpm run build前端构建产物输出到 frontend/dist/,部署后会复制为 /opt/simadmin/www/。
cd backend
cargo check
cargo run -- --host :: --port 3000| 参数 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
--host / -H |
HOST |
:: |
监听地址,默认双栈 IPv4/IPv6 |
--port / -p |
PORT |
3000 |
HTTP 监听端口 |
在普通开发机上运行后端时,如果没有 system D-Bus、ModemManager 或 modem,硬件相关接口会返回错误,这是预期行为。
./scripts/build/build.sh./scripts/build/build.sh --backend-only
./scripts/build/build.sh --frontend-only
./scripts/build/build.sh --no-upx
./scripts/build/build.sh --no-ota
./scripts/build/build.sh --target=x86_64
./scripts/build/build.sh --target=armv7 --no-upxWindows 下建议在 WSL2 Ubuntu 中执行完整 OTA 构建。原生 PowerShell 不能直接运行 Bash 脚本;Git Bash 容易受 Node/npm/pnpm PATH 影响,完整 OTA 仍需要目标架构对应的 Linux musl 工具链:
./scripts/build/build.sh --no-upxARMv7 本地后端交叉编译需要 armv7-unknown-linux-musleabihf Rust target 和
arm-linux-musleabihf-gcc linker。没有本机 ARMv7 musl 工具链时,可在安装 Docker
后使用 cross-rs(CI 使用同一目标镜像):
rustup target add armv7-unknown-linux-musleabihf
cargo install cross --locked
cross build --locked --release --target armv7-unknown-linux-musleabihf -p simadmin在没有 ARMv7 工具链的主机上,可以先运行与工具链无关的边界检查:
bash ./scripts/tests/test-armv7.sh该检查覆盖架构别名、ARMv7 OTA 产物命名、Shell 语法,以及 ARMv7 强制跳过
lpac(包括显式 ARM64 覆盖变量)。它不能替代 CI 交叉编译、QEMU 启动或 UFI210
真机验收。
生成 OTA 包前仍需先构建前端,然后执行
./scripts/build/pack-ota.sh --target=armv7;打包脚本会拒绝非 ARM ELF32 后端。
- 同步
VERSION到backend/Cargo.toml和frontend/package.json。 - 使用
pnpm-lock.yaml时通过pnpm install --frozen-lockfile、pnpm run lint和pnpm exec vite build构建前端到frontend/dist/。 - 默认交叉编译后端到
target/aarch64-unknown-linux-musl/release/simadmin;传入--target=armv7时生成target/armv7-unknown-linux-musleabihf/release/simadmin,传入--target=x86_64时生成target/x86_64-unknown-linux-musl/release/simadmin。 - 可选使用 UPX 压缩后端二进制;未安装 UPX 时会自动跳过压缩。ARMv7 默认跳过 UPX,待 UFI210 真机验收后可通过
SIMADMIN_ALLOW_UPX_ARMV7=1显式启用。 - 生成
release/simadmin_<version>_<target>.tar.gzOTA 包,并在meta.json中写入相同 target triple。
GitHub Actions 会构建 ARM64、ARMv7 hard-float 和 x86_64 三种产物,发布 simadmin-aarch64.tar.gz、simadmin-armv7.tar.gz 与 simadmin-x86_64.tar.gz。ARMv7 使用 cross-rs 交叉工具链;simadmin.tar.gz 继续作为 ARM64 兼容别名。
build/build-simadmin.ps1 使用 Windows 上的 Zig C 工具链和 Rust target 构建完整 OTA 包,默认目标仍为 AArch64。构建 ARMv7 hard-float 包:
pwsh -File .\build\build-simadmin.ps1 -Target armv7脚本也接受 armv7l、armhf 和完整 target triple 作为 -Target 值,会自动安装缺失的 Rust target,并在打包前校验 ARM ELF32 hard-float 头。ARMv7 默认输出 release/simadmin_<version>_armv7.tar.gz,同时生成供安装脚本使用的 release/simadmin-armv7.tar.gz;使用 -NoLatestAlias 可关闭别名。若依赖已安装,可加 -NoInstall 跳过 pnpm install。
./scripts/build/deploy.sh./scripts/build/deploy.sh --backend-only
./scripts/build/deploy.sh --frontend-only
./scripts/build/deploy.sh --no-restart
./scripts/build/deploy.sh --target=/opt/simadmin
./scripts/build/deploy.sh --build-target=x86_64
./scripts/build/deploy.sh --build-target=armv7- 管理后台页面和
/api/*业务接口默认需要登录;/api/health、/api/auth/status、/api/auth/setup、/api/auth/login为公开接口。 - 未登录访问受保护页面会跳转到
/login;前端 API 请求遇到401会自动进入登录页,直接调用 API 时返回标准 JSON 错误。 - 会话使用
simadmin_sessionHttpOnly Cookie,默认有效期 7 天。重置或清除管理员密码会清空所有 Web 会话。 - 当前不提供手动登出入口,适合单管理员设备后台场景。
- 后端模型位于
backend/src/models.rs。 - 前端类型位于
frontend/src/api/contracts.ts。 - 前端 API 封装位于
frontend/src/api/current.ts。 - 路由集中在
backend/src/main.rs和frontend/src/App.tsx。
新增接口时建议同步修改:
backend/src/models.rsbackend/src/handlers.rsbackend/src/main.rsfrontend/src/api/contracts.tsfrontend/src/api/current.ts- 对应页面或 hook
bruno-api/调试请求 (详情请参阅 Bruno 接口文档)
会改变 modem 状态的操作应通过 with_serial 串行执行,避免 ModemManager 或底层设备出现并发冲突:
use crate::serial::with_serial;
pub async fn set_some_modem_state(conn: &Connection) -> zbus::Result<()> {
with_serial(async {
// D-Bus / modem operation
Ok(())
}).await
}backend/build.rs 会在编译期注入:
APP_VERSIONGIT_BRANCHGIT_COMMITAPP_TARGET_TRIPLE
其中版本号来自根目录 VERSION。
当前底层实现以 ModemManager 接口交互为主。
| 接口 | 说明 |
|---|---|
org.freedesktop.ModemManager1 |
ModemManager 根服务 |
org.freedesktop.ModemManager1.Modem |
Modem 状态、开关、模式、频段 |
org.freedesktop.ModemManager1.Modem.Modem3gpp |
运营商、注册、扫描 |
org.freedesktop.ModemManager1.Modem.Simple |
简化连接和断开 |
org.freedesktop.ModemManager1.Modem.Messaging |
短信发送和接收 |
org.freedesktop.ModemManager1.Sim |
SIM 属性 |
org.freedesktop.ModemManager1.Bearer |
数据连接 bearer |
# 查看 modem 列表
mmcli -L
# 查看 modem 详情
mmcli -m any
# 查看注册和连接简要状态
mmcli -m any --simple-status
# 查看 3GPP 定位信息
mmcli -m any --location-get
# 查看信号指标
mmcli -m any --signal-get
# 发送 AT 指令
mmcli -m any --command='AT+CGSN'# 监听 ModemManager 信号
dbus-monitor --system "sender='org.freedesktop.ModemManager1'"
# 查看 modem 0 暴露的接口
busctl introspect org.freedesktop.ModemManager1 /org/freedesktop/ModemManager1/Modem/0