chaithubk/medtech-device-os
GitHub: chaithubk/medtech-device-os
基于 Yocto Project 构建的医疗物联网设备嵌入式 Linux 操作系统,集成 MQTT 数据流、TensorFlow Lite 边缘推理、SBOM 合规工具和完整的 CI/CD 流水线。
Stars: 0 | Forks: 0
# MedTech Device OS
使用 Yocto Project (kirkstone) 为医疗 IoT 设备构建的嵌入式 Linux 操作系统。
## 目录
- [从这里开始](#start-here)
- [部署](#deployment)
- [阶段 1: QEMU 仿真](#stage-1-qemu-emulation)
- [功能](#features)
- [架构](#architecture)
- [快速开始](#quick-start)
- [QEMU 内部的健全性检查](#sanity-checks-inside-qemu)
- [生成 SBOM](#generate-sbom)
- [启动后的 SSH 访问(两种方式)](#ssh-access-after-boot-both-paths)
- [CI/CD](#cicd)
- [哪些文件会影响 CI 与本地构建?](#which-files-affect-ci-vs-local-builds)
- [本地可复现构建说明](#local-reproducible-build-notes)
- [磁盘空间优化](#disk-space-optimization)
- [层结构](#layer-structure)
- [文档索引](#documentation-index)
## 从这里开始
如果您是第一次使用此仓库,请按以下顺序操作:
1. 执行 [快速开始](#quick-start) 中的构建步骤。
2. 使用 [QEMU 内部的健全性检查](#sanity-checks-inside-qemu) 启动并验证行为。
3. 在 [CI/CD](#cicd) 中查看 CI 行为。
4. 使用 [文档索引](#documentation-index) 中的故障排除文档。
## 部署
本项目支持两种用于 QEMU 镜像的部署/测试路径。
### 打包和验证 GHCR 工件
构建镜像后,您可以使用提供的脚本打包 QEMU 工件以进行分发,并验证其完整性:
#### 1. 打包工件
```
bash scripts/package-ghcr-artifacts.sh --image-name core-image-medtech
```
预期输出:
```
=== GHCR bundle created ===
Output directory : /workspace/artifacts
Archive : /workspace/artifacts/core-image-medtech-qemuarm64-bundle.tar.gz
Manifest : /workspace/artifacts/core-image-medtech-qemuarm64-manifest.json
Checksums : /workspace/artifacts/SHA256SUMS
```
生成的工件:
- core-image-medtech-qemuarm64-bundle.tar.gz
- core-image-medtech-qemuarm64-manifest.json
- SHA256SUMS
#### 2. 验证工件
```
bash scripts/verify-ghcr-package.sh --image-name core-image-medtech
```
预期输出:
```
core-image-medtech-qemuarm64-bundle.tar.gz: OK
core-image-medtech-qemuarm64-manifest.json: OK
=== GHCR bundle verification passed ===
Archive: /workspace/artifacts/core-image-medtech-qemuarm64-bundle.tar.gz
Contents summary:
payload/image/
payload/image/core-image-medtech-qemuarm64-.rootfs.ext4
payload/image/Image-qemuarm64.bin
payload/metadata/
payload/metadata/core-image-medtech-qemuarm64-.rootfs.manifest
payload/metadata/core-image-medtech-qemuarm64.testdata.json
payload/metadata/core-image-medtech-qemuarm64.qemuboot.conf
payload/metadata/manifest.json
```
这可确保归档文件和 manifest 有效,并且 payload 包含预期的文件。
### 路径 A:运行本地构建的镜像(在 dev container 内部)
1. 构建镜像:`bitbake core-image-medtech`
2. 启动镜像:`bash scripts/run-qemu.sh`
3. 验证服务:使用 [QEMU 内部的健全性检查](#sanity-checks-inside-qemu)
启动命令详情(终端模式):
```
bash scripts/run-qemu.sh
```
### 路径 B:在 Ubuntu 主机上运行 GHCR 镜像(在容器外部)
1. 准备主机(一次性操作):
```
bash scripts/setup-host-qemu-prereqs.sh
```
2. 运行 GHCR 镜像(从 `/artifacts/` 自动检测 kernel + rootfs):
```
bash scripts/run-ghcr-qemu.sh --image ghcr.io///qemu-image:latest
```
3. 使用 [启动后的 SSH 访问(两种方式)](#ssh-access-after-boot-both-paths) 进行 SSH 连接。
### GHCR 未授权错误(快速修复)
如果拉取失败并显示 `unauthorized`,请将 Docker 认证到 GHCR:
```
export GHCR_PAT=
echo "$GHCR_PAT" | docker login ghcr.io -u --password-stdin
```
如果包属于某个组织,请确保该 token 已获得该组织的 SSO 授权。
### 较旧的 GHCR 镜像中缺少 Kernel
如果您有一个仅包含 `.ext4`(没有 kernel)的较旧 GHCR 镜像,请显式提供 kernel 路径:
```
bash scripts/run-ghcr-qemu.sh \
--image ghcr.io///qemu-image:old-tag \
--kernel /path/to/Image-qemuarm64.bin
```
新的构建(在此 CI 修复之后)在 `/artifacts/` 中包含 kernel + rootfs + dtb,因此您不再需要 `--kernel`。
### 启动后的 SSH 访问(两种方式)
```
ssh -p 2222 root@localhost
```
## 阶段 1: QEMU 仿真
### 功能
- ✅ Yocto/Poky kirkstone 构建系统
- ✅ `core-image-medtech` 自定义镜像
- ✅ **MQTT Broker** (Mosquitto) – 开机自动启动
- ✅ **生命体征发布器** – 每 10 秒发布模拟的病人生命体征
- ✅ **边缘分析** – TensorFlow Lite 败血症检测
- ✅ **临床医生 UI** – Qt6 仪表板(QEMU 下的无头/离屏模式)
- ✅ 具有正确依赖链的 Systemd 服务管理
- ✅ CycloneDX SBOM 生成
- ✅ QEMU ARM64 仿真器
- ✅ SSH 服务器
- ✅ 通过 GitHub Actions 实现 CI/CD → GHCR
### 架构
```
MQTT Data Flow
──────────────
Vitals Publisher ──→ mosquitto (1883) ──→ Edge Analytics ──→ Clinician UI
(Python) (MQTT) (TFLite) (Qt6)
Topic: medtech/vitals/latest medtech/predictions/sepsis
Systemd Dependency Chain
────────────────────────
mosquitto.service
└── medtech-vitals-publisher.service
└── medtech-edge-analytics.service
└── medtech-clinician-ui.service
```
### 快速开始
#### 在 Dev Container 中构建
```
# 在容器中重新打开文件夹
# Cmd+Shift+P → Dev Containers: Reopen in Container
# dev container 的创建后步骤会自动运行 quick-setup。
# 容器准备就绪后,直接构建:
bitbake core-image-medtech
```
#### 在本地构建单个 Recipe
```
# 示例:仅构建 clinician UI recipe
bitbake medtech-clinician-ui
# 可选:强制清理并重新构建该 recipe
bitbake -c cleansstate medtech-clinician-ui
bitbake medtech-clinician-ui
```
#### 构建完整镜像(手动路径)
```
bash scripts/setup-devenv.sh
bash scripts/clone-with-retry.sh
su - builder -c 'cd /workspace && source yocto/poky/oe-init-build-env yocto/build >/dev/null && cp -n ../conf/local.conf.sample conf/local.conf && cp -n ../conf/bblayers.conf.sample conf/bblayers.conf && bitbake core-image-medtech'
```
#### 在 QEMU 中启动
请使用 [部署](#deployment) 中的规范部署说明。
### QEMU 内部的健全性检查
启动后,以 `root` 用户登录并运行以下检查:
#### 1. 检查所有服务是否正在运行
```
systemctl status mosquitto
systemctl status medtech-vitals-publisher
systemctl status medtech-edge-analytics
systemctl status medtech-clinician-ui
```
预期:所有四个服务都显示为 `active (running)`。
#### 2. 验证 MQTT 数据流
打开两个终端(或使用 `tmux`/`screen`):
```
# 终端 1 – 订阅所有 medtech 主题
mosquitto_sub -t "medtech/#" -v
# 终端 2 – 等待约 10 秒;你应该会看到类似如下的输出:
# medtech/vitals/latest {"heart_rate": 75, "spo2": 98, ...}
# medtech/predictions/sepsis {"risk": 0.12, "alert": false}
```
#### 3. 检查服务日志
```
journalctl -u medtech-vitals-publisher -n 50
journalctl -u medtech-edge-analytics -n 50
journalctl -u medtech-clinician-ui -n 50
```
#### 4. 验证镜像元数据
```
cat /etc/medtech-release
```
#### 5. 退出 QEMU
```
# 按 Ctrl+A 然后按 X
# 或者
shutdown -h now
```
### 生成 SBOM
```
bash scripts/generate-sbom.sh
# 输出:sbom/sbom.json (CycloneDX 1.4 格式)
```
### CI/CD
GitHub Actions (`.github/workflows/device-build-smart.yml`) 会自动:
1. 验证层结构
2. 为 pull request 构建 `core-image-minimal`,为推送到 `main` 的操作构建 `core-image-medtech`
3. 在 `main` 分支的构建上运行针对 medtech 的 manifest 和 Python 运行时检查
4. 将构建好的 `.ext4` 镜像作为 artifact 上传
5. 为 `core-image-medtech` 构建上传 SPDX SBOM
6. **将 kernel、rootfs 和 DTB 打包到 Docker 镜像中,并推送到 GHCR** (针对 main 分支为 `ghcr.io//medtech-device-os/qemu-image:latest`)
#### GHCR 镜像内容
推送到 GHCR 的 Docker 镜像包含:
- Yocto kernel 镜像(`Image` 或 `Image-qemuarm64.bin`)
- Rootfs 镜像(`*.ext4`)
- 设备树 blob(`*.dtb`,如果可用)
- SPDX SBOM 文件(仅限 `core-image-medtech`)
所有工件都位于容器内的 `/artifacts/` 中,以便于提取。
#### 构建工件、归档与保留
成功的工作流运行会将构建好的镜像归档在 GitHub Actions 工件中。
1. Pull request 运行会归档 `core-image-minimal-qemuarm64.ext4`。
2. 推送到 `main` 分支的运行会归档 `core-image-medtech-qemuarm64.ext4`。
3. PR 运行在 GitHub Actions 中的 artifact 名称:`qemu-image-minimal`。
4. `main` 分支运行在 GitHub Actions 中的 artifact 名称:`qemu-image-medtech`。
5. Artifact 保留期:30 天。
要在 GitHub 中查找成功构建的镜像:
1. 在 GitHub 上打开该仓库。
2. 转到 **Actions** 选项卡。
3. 打开您关注的 pull request 或 `main` 分支推送的工作流运行。
4. 在运行摘要中,打开 **Artifacts** 部分。
5. 下载 PR 运行的 `qemu-image-minimal` 或 `main` 分支运行的 `qemu-image-medtech`。
6. 在本地解压以获取构建好的 `.ext4` 镜像。
注意:
1. PR 运行旨在作为轻量级的健全性检查,因此归档的镜像为最小化镜像。
2. PR 合并后,推送到 `main` 的操作将运行完整的 `core-image-medtech` 构建,并单独归档该镜像。
3. 如果构建在打包步骤之前失败,最终的镜像 artifact 可能不存在,但工作流仍可上传用于调试失败的 artifact。
CI 注意事项:
1. CI 不会调用 `quick-setup.sh` 或 `setup-devenv.sh`;它运行显式的工作流步骤。
2. CI 在每次运行期间通过复制 `yocto/conf/bblayers.conf.sample` 来生成 `yocto/build/conf/bblayers.conf`。
3. 对 `yocto/build/conf/bblayers.conf` 的本地编辑不会影响 CI,除非更新并提交了示例文件和工作流。
4. 本地引导脚本可能会向 `yocto/build/conf/local.conf` 追加仅限 dev-container 的变通配置;这些不会改变 CI 行为。
#### 哪些文件会影响 CI 与本地构建?
影响 CI 行为的文件:
1. `.github/workflows/device-build-smart.yml` — CI 作业定义和构建步骤。
2. `yocto/conf/bblayers.conf.sample` — CI `bblayers.conf` 的来源。
3. `yocto/conf/local.conf.sample` — CI `local.conf` 的来源。
4. `yocto/meta-medtech/**` — CI 和本地构建均使用的 recipe 和 layer 元数据。
仅限本地/dev container 的文件:
1. `.devcontainer/Dockerfile` 和 `.devcontainer/devcontainer.json` — 本地容器设置。
2. `scripts/setup-devenv.sh`、`scripts/quick-setup.sh` 和 `scripts/clone-with-retry.sh` — 本地引导辅助工具。
3. `yocto/build/conf/bblayers.conf` 和 `yocto/build/conf/local.conf` — 生成的本地构建配置文件。
#### 本地可复现构建说明
Dev container 包含一些仅限本地的调整,以便在重新打开或重建容器后构建仍可复现:
1. 在 dev container 中安装缺失的 Yocto 主机工具。
2. 使用非 root 的 `builder` 用户,因为 BitBake 拒绝以 root 身份构建。
3. 确保 `/workspace` 可由 `builder` 写入。
4. 在存在代理或 TLS/证书问题的环境中,对层拉取使用重试和镜像回退。
5. 在需要时,向生成的本地 `local.conf` 中添加仅限本地的 `CONNECTIVITY_CHECK_URIS` 覆盖。
这些本地的变通方法旨在使 dev container 构建具有可复现性,而不改变 CI 流水线的行为。
### 磁盘空间优化
该构建针对 GitHub Actions 运行器进行了优化(磁盘空间限制为约 14 GB):
- **最小化镜像包**:移除了 `python3-pip`、`wget`、`nano`、`htop`、`rsyslog`、`mesa`(节省约 500 MB-1 GB)
- **无 SDK 构建**:`SDKMACHINE = ""` 阻止生成交叉编译 SDK(节省约 2-3 GB)
- **剥离调试符号**:`INHIBIT_PACKAGE_DEBUG_SPLIT = "1"`(节省约 1-2 GB)
- **无 API 文档**:`DISTRO_FEATURES:remove = "api-documentation"`(节省约 200-500 MB)
- **无 SPDX 源码**:`SPDX_INCLUDE_SOURCES = "0"`(节省约 500 MB-1 GB)
- **CI 预构建清理**:移除 dotnet、android、ghc、CodeQL(释放约 12-15 GB)
有关详细策略,请参见 [docs/DISK_OPTIMIZATION.md](docs/DISK_OPTIMIZATION.md)。
### 层结构
```
yocto/meta-medtech/
├── conf/layer.conf
├── classes/medtech-image.bbclass
├── recipes-core/medtech-system/medtech-system.bb
├── recipes-services/
│ ├── medtech-vitals-publisher/medtech-vitals-publisher_1.0.bb
│ ├── medtech-edge-analytics/medtech-edge-analytics_1.0.bb
│ └── medtech-clinician-ui/medtech-clinician-ui_1.0.bb
├── recipes-support/
│ ├── mosquitto/mosquitto_%.bbappend
│ ├── python3-paho-mqtt/python3-paho-mqtt_1.6.1.bb
│ └── tensorflow-lite/tensorflow-lite_2.14.0.bb
└── recipes-image/core-image-medtech/core-image-medtech.bb
```
## 文档索引
- [docs/README.md](docs/README.md) - 文档登陆页。
- [docs/yocto-ci-failure-detection.md](docs/yocto-ci-failure-detection.md) - CI 优先的故障分类运行手册。
- [docs/yocto-fetch-and-mirror-notes.md](docs/yocto-fetch-and-mirror-notes.md) - 拉取失败和镜像使用指南。
- [docs/yocto-generated-config-notes.md](docs/yocto-generated-config-notes.md) - 生成配置行为与偏移说明。
- [docs/yocto-local-recovery-notes.md](docs/yocto-local-recovery-notes.md) - 本地恢复步骤。
- [docs/yocto-single-recipe-build-notes.md](docs/yocto-single-recipe-build-notes.md) - 使用单 recipe 构建进行快速本地迭代。
- [docs/yocto-build-pause-resume-notes.md](docs/yocto-build-pause-resume-notes.md) - 暂停和恢复长时间构建。
- [docs/DISK_OPTIMIZATION.md](docs/DISK_OPTIMIZATION.md) - 磁盘压力缓解策略。
- [docs/SBOM_STRATEGY.md](docs/SBOM_STRATEGY.md) - SBOM 生成与合规性策略。
标签:arm64架构, DevSecOps, DNS 反向解析, GHCR, IoT操作系统, Kirkstone, Linux构建系统, MedTech, QEMU, SBOM, systemd, Yocto Linux, 上游代理, 仿真测试, 内联执行, 医疗合规, 医疗物联网, 医疗设备, 可重现构建, 安全合规, 完整性校验, 容器镜像仓库, 嵌入式Linux, 嵌入式系统, 开源操作系统, 开源框架, 持续部署, 持续集成, 服务编排, 硬件无关, 磁盘空间优化, 系统架构, 网络代理, 请求拦截, 跌倒检测, 软件物料清单, 边缘计算, 逆向工具, 镜像打包