# iotlcm-bot 独立飞书应用机器人:读取 Worker 终态 Run JSON,渲染并发送全量同步结果卡片。 本服务是 [iotlcm](https://git.5iot.com/iotlcm-public) 物联网卡全生命周期管理平台的配套组件,用于把异步全量同步(卡状态、流量、IMEI 等)的执行结果推送到飞书群。 ## 特性 - **零外部依赖**:只依赖 `gopkg.in/yaml.v3`,不需要 Redis、数据库或 Worker HTTP 接口 - **只读归档**:只读挂载 Worker 的归档目录,按 `runId` 去重后发送 - **多类卡片**:全量同步汇总卡、告警卡、供料提醒卡 - **健康自检**:检测归档目录被宿主删除(inode 丢失)这类静默故障并告警 - **单镜像**:`scratch` 基础镜像,非 root 运行 ## V1 范围 - 只接受 `version=1` 且包含 `run` 和非空 `rounds` 的归档 JSON - 不兼容旧版 `rounds=[]` 文件 - 不读取 Redis、Worker HTTP 接口或日志 - 不实现 Replay、事件回调、卡片按钮和错误聚合 ## 快速开始 ```bash go mod tidy go test ./... ``` 本地渲染一张卡片(不调用飞书 API): ```bash go run ./cmd/iotlcm-bot render --file testdata/current-run.json go run ./cmd/iotlcm-bot render --file testdata/current-run.json --json ``` ## 配置 配置文件为 `config.yaml`。**公开版里的飞书凭据是占位符**,真实值请用环境变量或本地覆盖文件注入: ```yaml environment: preview archiveDir: /data/full-sync stateDir: ./state pollInterval: 10s feishu: appId: "${FEISHU_APP_ID}" appSecret: "${FEISHU_APP_SECRET}" chatId: "${FEISHU_CHAT_ID}" ``` | 配置项 | 说明 | | --- | --- | | `archiveDir` | Worker 归档目录(只读挂载) | | `stateDir` | 已发送 Run 的标记目录(可写) | | `pollInterval` | 扫描间隔,默认 `10s` | | `feishu.appId` / `appSecret` | 飞书应用凭据 | | `feishu.chatId` | 目标群 ID | ## 命令 | 命令 | 作用 | | --- | --- | | `watch` | 常驻扫描归档目录,自动发送新 Run(默认模式) | | `send` | 发送指定 Run JSON | | `send-text` | 向配置里的群发一条纯文本(用于连通性验证) | | `render` | 只渲染卡片内容,不调用飞书 API | ```bash go run ./cmd/iotlcm-bot watch --config /path/to/iotlcm-bot.yaml go run ./cmd/iotlcm-bot send --config /path/to/iotlcm-bot.yaml --file /path/to/run.json go run ./cmd/iotlcm-bot send --config /path/to/iotlcm-bot.yaml --file /path/to/run.json --force ``` `--force` 用于确需重发时;正常运行不要使用。发送成功会写入 `state/sent/.json`,同一 Run 再次执行会跳过。 ## 容器化部署 ```bash docker build -t iotlcm-bot:latest . docker run -d \ -v /host/worker/full-sync:/data/full-sync:ro \ -v /host/bot/state:/data/state \ -v /host/bot/config.yaml:/app/config/config.yaml:ro \ iotlcm-bot:latest ``` 容器内路径约定: | 容器内路径 | 用途 | 挂载方式 | | --- | --- | --- | | `/data/full-sync` | Worker 归档目录 | **只读** | | `/data/state` | 已发送标记 | 可写 | | `/app/config/config.yaml` | 配置文件 | 只读 | ## 目录结构 ```text iotlcm-bot/ ├── cmd/iotlcm-bot/main.go # CLI 入口 ├── internal/ │ ├── archive/ # 归档 JSON 解析 │ ├── config/ # 配置加载 │ ├── feishu/ # 飞书 API 客户端 │ ├── notify/ # 通知服务与健康自检 │ ├── render/ # 卡片渲染 │ └── state/ # 已发送标记 ├── config.yaml # 配置(公开版为占位值) ├── testdata/ # 测试用归档样例 └── Dockerfile ``` ## 常见问题 **卡片不发送?** 检查归档目录是否可读、`runId` 是否已发送过(`state/sent/` 下有标记则跳过)、群机器人是否被移出。 **日志刷满?** `watch` 模式对同一文件只记一次错误,文件被重写后会重新记录。 **归档目录被宿主删了?** Bot 会检测到(inode 丢失)并降级告警——此时应检查宿主的日志清理脚本是否误删了挂载源目录。 ## 相关项目 - [iotlcm-worker-svr](https://git.5iot.com/iotlcm-public/iotlcm-worker-svr) —— 异步执行中枢,产出归档 JSON - [iotlcm-openapi](https://git.5iot.com/iotlcm-public/iotlcm-openapi) —— 对外 API 网关 ## License [Apache License 2.0](./LICENSE)