目录

MoonBit IoT API Server

这是一个使用 MoonBit 从零设计并实现的工程化 IoT 后端服务。项目采用清晰的 package 分层组织 HTTP、认证、业务逻辑、数据访问、代码生成和 AI 对话能力, 使用 Halo 提供 HTTP 服务,使用 morm 管理 SQLite 表结构和实体映射。

本项目不是对其他语言项目的移植。代码、package 边界、运行时、数据访问和测试均按 MoonBit 的类型系统、异步模型和工具链重新设计并实现。

当前实现重点是后台管理、认证、系统资源、文件上传凭证、AI 对话运行时和 IoT 基础数据模型。MQTT、gRPC、设备数据写入链路还没有接入。

功能范围

已实现:

  • Halo HTTP API 服务入口。
  • SQLite 本地持久化和启动时自动建表、升级表结构。
  • .env 配置加载,统一管理 HTTP、SQLite、S3、Redis 和模型服务配置。
  • JWT 登录、登出、当前用户信息、权限和菜单接口。
  • S3 直传凭证生成,用于前端上传文件。
  • 用户、租户、角色、权限、菜单、用户授权关系 CRUD。
  • 角色、权限、菜单和附件软删除、恢复、永久删除。
  • 权限树下拉和角色权限树形配置返回。
  • 附件、登录日志、操作日志、租户配置 CRUD。
  • IoT 基础表模型:产品、设备、指标、Modbus 点位、设备影子、事件、命令。
  • 系统租户、管理员、固定权限、菜单、角色初始化。
  • MoonBitAI 对话运行时、Redis 事件持久化、取消和启动恢复。
  • AI SDK / assistant-ui 与 OpenAI-compatible 两套聊天 API。
  • calculatorget_current_time 内置工具和 reasoning / <think> 拆分。

暂未实现:

  • MQTT 设备数据接入。
  • TCP/UDP Modbus 数据接入。
  • IoT 数据 gRPC 服务。
  • IoT 数据实时写入和时序存储。
  • OpenAPI 文档自动生成;当前路由清单见 API.md

文档导航

  • API.md:当前全部 HTTP API 路由和功能清单。
  • PACKAGES.md:MoonBit package、工程分层和 MoonBitAI 接入说明。
  • pkg/moonbitai/README.md:MoonBitAI 详细使用方法和组装示例。
  • db_gen/README.md:model / mapper 代码生成器配置与命令。
  • apply.md:项目申报书一页版,可按参赛信息直接修改。

快速启动

安装依赖后应用项目维护的 Halo 流式响应补丁和 morm SQLite 资源清理补丁:

moon update
patch --forward -p1 -d .mooncakes/wflixu/Halo < patches/wflixu-halo.patch
patch --forward -p1 -d .mooncakes/oboard/morm < patches/oboard-morm.patch

注意:moon update 会刷新 .mooncakes 依赖目录,因此每次执行 moon update 后都需要 紧接着重新应用上面的两个补丁。如果编译提示 set_stream_response 不存在,说明 Halo 补丁没有成功应用;如果 SQLite 语句失败后关闭数据库时发生 abort(),说明 morm 补丁 没有成功应用。

如果 patch 提示补丁已经应用并跳过,说明当前依赖目录已经是正确状态,可以直接 执行启动命令。

首次使用时复制配置文件:

cp .env.example .env

按需修改 .env。常用配置:

APP_PORT=8080
SQLITE_DSN=moonbit_iot.db
S3_ENDPOINT=http://127.0.0.1:9000
S3_REGION=us-east-1
S3_ACCESS_KEY=access-key
S3_SECRET_KEY=secret-key
S3_BUCKET=moonbit-iot
S3_USE_PATH_STYLE=true
S3_PUBLIC_BASE_URL=https://cdn.example.com/assets
S3_PUBLIC_PREFIX=public-files
OPENAI_API_KEY=
OPENAI_BASE_URL=https://api.openai.com/v1
MODEL_NAME=
OPENAI_TIMEOUT_SECONDS=120
REDIS_ADDR=127.0.0.1:6379
REDIS_USERNAME=
REDIS_PASSWORD=
REDIS_DB=0
REDIS_TTL_SECONDS=604800
REDIS_POOL_SIZE=4
MOONBITAI_KEY_PREFIX=moonbitai
AI_MAX_CONCURRENT_RUNS=4
AI_MAX_TOOL_STEPS=8
AI_RUN_TIMEOUT_SECONDS=600

本地 .env 由 Git 忽略并保留,不应提交或输出其中的密钥。OpenAI 或 Redis 不可用时,普通 IoT/管理 API 仍正常启动,聊天 API 返回 503

启动服务:

moon run cmd/server

初始化内置数据也可以单独执行:

moon run cmd/init-data

服务默认监听:

http://127.0.0.1:8080

健康检查:

curl http://127.0.0.1:8080/health

默认登录账号由初始化逻辑创建:

{
  "tenantCode": "system",
  "account": "admin@example.com",
  "password": "admin123456"
}

登录示例:

curl -X POST http://127.0.0.1:8080/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"tenantCode":"system","account":"admin@example.com","password":"admin123456"}'

主要 API

认证:

  • POST /api/auth/login
  • POST /api/auth/logout
  • GET /api/auth/me
  • PUT /api/auth/me/profile
  • PUT /api/auth/me/preferences
  • GET /api/auth/me/permissions
  • GET /api/auth/me/menus
  • POST /api/auth/files/upload-credential

用户:

  • GET /api/users
  • POST /api/users/search
  • POST /api/users/select
  • POST /api/users/export
  • POST /api/users
  • PUT /api/users/:id
  • PUT /api/users/batch
  • DELETE /api/users/:id
  • DELETE /api/users/batch

后台管理:

  • /api/manager/tenants
  • /api/manager/roles
  • /api/manager/permissions
  • /api/manager/menus
  • /api/manager/user-permissions

最新管理接口补充:

  • POST /api/manager/permissions/select-tree
  • PUT /api/manager/roles/:id/restore
  • PUT /api/manager/permissions/:id/restore
  • PUT /api/manager/menus/:id/restore
  • DELETE /api/manager/{roles|permissions|menus}/:id/permanent
  • DELETE /api/manager/{roles|permissions|menus}/batch/permanent

系统资源:

  • /api/system/attachments
  • /api/system/login-logs
  • /api/system/operation-logs
  • /api/system/configs

附件支持:

  • PUT /api/system/attachments/:id/restore
  • DELETE /api/system/attachments/:id/permanent
  • DELETE /api/system/attachments/batch/permanent

AI SDK / assistant-ui(使用项目 {code,message,data} JSON 包装,SSE 不包装):

  • POST /api/chat/completions
  • POST /api/chat/sessions/:sessionId
  • GET /api/chat/sessions/:sessionId
  • DELETE /api/chat/sessions/:sessionId
  • POST /api/chat/sessions/:sessionId/runs/:run_id
  • POST /api/chat/sessions/:sessionId/runs/:run_id/cancel

OpenAI-compatible(返回原生 completion、chunk 和 error body):

  • POST /api/v1/chat/completions
  • POST /api/v1/sessions/:sessionId
  • GET /api/v1/sessions/:sessionId
  • DELETE /api/v1/sessions/:sessionId
  • POST /api/v1/sessions/:sessionId/runs/:run_id
  • POST /api/v1/sessions/:sessionId/runs/:run_id/cancel

两套路由都使用现有 JWT。外部 session 会映射为 tenant_id:user_id:session_id,响应仍返回原 session ID。事件订阅优先读取 Last-Event-ID header,并从该事件之后继续回放。

AI SDK 创建 run 示例:

curl -X POST http://127.0.0.1:8080/api/chat/sessions/demo-session \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-4.1-mini","messages":[{"id":"m1","role":"user","parts":[{"type":"text","text":"计算 12 * 8"}]}]}'

使用响应中的 run_id 订阅 AI SDK SSE:

curl -N -X POST http://127.0.0.1:8080/api/chat/sessions/demo-session/runs/$RUN_ID \
  -H "Authorization: Bearer $TOKEN"

断线后从已收到事件的下一条恢复:

curl -N -X POST http://127.0.0.1:8080/api/chat/sessions/demo-session/runs/$RUN_ID \
  -H "Authorization: Bearer $TOKEN" \
  -H "Last-Event-ID: $LAST_EVENT_ID"

OpenAI-compatible 非流式请求使用 "stream":false,流式请求使用 "stream":true

curl -N -X POST http://127.0.0.1:8080/api/v1/chat/completions \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"model":"gpt-4.1-mini","stream":true,"messages":[{"role":"user","content":"现在几点"}]}'

取消会同时写入 Redis 持久标记并通知当前进程;服务重启后会扫描 recoverable run, 从 checkpoint 恢复,未完成的 partial assistant text 不会提交到正式会话历史。

临时设备状态示例接口:

  • GET /devices/statuses
  • POST /devices/statuses
  • GET /devices/statuses/:device_id
  • PUT /devices/statuses/:device_id
  • DELETE /devices/statuses/:device_id

项目结构

cmd/server                    HTTP API 入口
cmd/init-data                 初始化内置租户、管理员、权限、角色、菜单
cmd/repo-gen                  repository/model 代码生成器入口
configs                       .env 和环境变量配置加载
db_gen                        MoonBit 代码生成器配置
internal/bootstrap            DB、服务、启动上下文初始化
internal/ai                   OpenAI、Redis、工具与恢复任务组装
internal/router               Halo 路由注册
internal/middleware           认证、租户、操作日志等中间件
internal/handler              HTTP 入参、上下文、响应转换
internal/service              业务逻辑、权限规则、跨仓储编排
internal/repository/repo      对 service 暴露的 repository 聚合入口
internal/repository/gen       morm mapper 接口和生成实现
internal/model                morm 实体模型
pkg/response                  HTTP 响应结构
pkg/moonbitai                 可复用 AI 运行时和协议适配
integration/chat              Halo/JWT/SSE 与重启恢复集成测试
patches                       本地依赖补丁记录

数据库和模型

当前使用 SQLite。数据库路径由 DB_PATHSQLITE_DSN 控制,默认是 moonbit_iot.db

服务启动时会通过 morm 自动创建和升级表结构。当前主要表包括:

  • 身份和权限:tenantsusersrolespermissionsmenus
  • 授权关系:user_rolesrole_permissionsuser_permissions
  • 系统资源:attachmentslogin_logsoperation_logstenant_configs
  • IoT 模型:iot_productsiot_devicesiot_metricsiot_modbuses
  • IoT 数据状态:iot_device_shadowsiot_device_eventsiot_device_commands

type 是 MoonBit 关键字相关字段,模型里使用 tenant_typepermission_typemenu_type,数据库兼容列仍同步 type,用于保持稳定的 数据库列与 API 字段约定。

API 响应统一使用 snake_case。为兼容现有前端,部分请求仍同时接受 camelCase, 例如 parentIdpermissionIdscontentType;响应不会返回这些 camelCase 别名。

当前统一使用以下基础审计字段:

id created_at updated_at deleted_at created_by updated_by

已经移除旧的 deleteddeleted_by。附件统一使用 created_by;IoT 产品不再 包含 device_count;设备命令使用 device_idcommand_codeparamscronstatus

角色、权限、菜单、附件等软删除资源遵循:

  1. 普通 DELETE 写入 deleted_at,正常查询不再返回。
  2. PUT /:id/restore 清空 deleted_at
  3. DELETE /:id/permanent 只永久删除已经软删除的数据。

内置角色、权限和菜单禁止普通删除及永久删除。权限和菜单删除会作用于整棵子树; 软删除期间保留授权关系,恢复后原授权仍然生效。

代码生成器

代码生成器配置在 db_gen。详细用法见:

db_gen/README.md

常用命令:

moon run cmd/repo-gen -- db_gen/user.json5
moon run .mooncakes/oboard/morm/mormgen -- internal/model/user.mbt -o internal/model/user.g.mbt
moon info && moon fmt
moon test

注意:生成器会覆盖目标 model 和 mapper 接口文件。手写逻辑应放在 helper、 service、handler、repository 聚合层,不要写进生成文件。

开发检查

提交前建议执行:

moon info
moon fmt
moon test
moon test cmd/server --build-only
moon test cmd/init-data --build-only
moon test cmd/repo-gen --build-only

目前 operation_logs.method 会触发 MoonBit 保留字预警。该字段属于现有数据库 和 JSON 公共契约,不建议在没有完整字段升级方案时改名。

关于

MoonIoT 是一个基于 MoonBit 开发的轻量级物联网平台,面向智能硬件、传感器设备、工业设备、边缘网关以及校园实验室等物联网应用场景,提供统一的产品管理、设备管理、数据通信、消息处理和智能交互能力

402.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号