# iot-util 项目开发规范 ## 本地测试 - **规则**: 不进行本地启动测试,由用户自行在 IDEA 中运行验证。 - **约束**: 严禁使用任何方式启动或停止本地 Java 进程。 --- ## 项目概述 IoT 设备管理工具,对接中国移动 OneNET 平台(iot-api.heclouds.com),提供产品详情、设备列表、设备属性、物模型、数据点等查询功能,并附带 Web 管理界面。 - **框架**: Solon 3.10.5 - **认证**: Sa-Token 1.44.0(登录鉴权)+ HMAC-SHA1(IoT 平台鉴权) - **HTTP 客户端**: OkHttp 4.12.0 - **模板引擎**: FreeMarker - **JSON**: Jackson(solon-serialization-jackson 3.10.5) - **端口**: 8081(app.yml 配置) --- ## 目录结构 ``` src/main/java/com/yixiong/iot/ ├── App.java # 启动类 ├── config/ │ └── IotProperties.java # IoT 配置属性(对应 app.yml iot.* 节点) ├── controller/ │ ├── AuthController.java # 登录/登出页面路由 │ ├── PageController.java # 主页路由(注入 defaultProductId 到模板) │ ├── ProductController.java # GET /product/detail │ ├── DeviceController.java # GET /device/list|detail|event-log|datapoints │ ├── ThingModelController.java # GET|POST /thingmodel/* │ └── GlobalExceptionFilter.java # 全局异常过滤,统一返回 JSON ├── service/ │ ├── ProductService.java │ ├── DeviceService.java │ └── ThingModelService.java ├── model/ │ ├── IotResponse.java # 通用响应包装(code/msg/requestId/data) │ ├── OldIotResponse.java # 旧版响应(errno/error/data,已备用) │ ├── ProductDetailData.java │ ├── DeviceItem.java # 设备列表项 & 设备详情复用 │ ├── DeviceListData.java │ ├── DeviceEventItem.java │ ├── DeviceEventListData.java │ ├── DevicePropertyItem.java # 设备属性最新数据 │ ├── PropertyHistoryData.java # 属性历史包装(data.list) │ ├── PropertyHistoryItem.java │ ├── DatapointData.java # 数据点(含内部类 DatapointStream/DatapointItem) │ └── ThingModelData.java # 物模型(含内部类 Property/Event/Service) └── util/ ├── IotHttpClient.java # OkHttp 封装,HMAC 鉴权,正常响应 DEBUG 日志 └── IotTokenUtil.java # HMAC-SHA1 Token 生成 src/main/resources/ ├── app.yml └── templates/ ├── login.ftl # 登录页 └── index.ftl # 主页(产品详情 + 设备列表 Tab,多个弹窗) ``` --- ## API 路由一览 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/` | 主页(需登录) | | GET | `/auth/login` | 登录页 | | POST | `/auth/doLogin` | 登录处理 | | GET | `/auth/logout` | 登出 | | GET | `/product/detail?product_id=` | 产品详情 | | GET | `/device/list` | 设备列表(product_id 取配置默认值) | | GET | `/device/detail?device_name=` | 设备详情(product_id 取配置默认值) | | GET | `/device/event-log` | 设备事件记录 | | GET | `/device/datapoints` | 设备历史数据点 | | GET | `/thingmodel/query-thing-model` | 产品物模型(product_id 取配置默认值) | | GET | `/thingmodel/query-device-property?device_name=` | 设备属性最新数据 | | POST | `/thingmodel/query-device-property-detail` | 设备属性详情(下发命令) | | GET | `/thingmodel/query-property-history` | 设备属性历史记录(data 为 Object,结构不固定) | --- ## 配置说明(app.yml) ```yaml iot: auth: version: "2022-05-01" resource-name: "userid/459810" # IoT 平台用户 ID access-key: "..." # HMAC 密钥(Base64) signature-method: "sha1" expiration-seconds: 3600 http: base-url: "https://iot-api.heclouds.com" # 新版 API(HMAC 鉴权) default-product-id: "VGi8wC99jO" # 默认产品 ID,多数接口使用此值 old-base-url: "https://api.heclouds.com" # 旧版 API(api-key 鉴权,备用) api-key: "..." # 旧版 Master Key auth: username: admin password: ... # 登录密码 ``` --- ## 关键设计决策 ### IoT 平台鉴权 - 新版接口(`iot-api.heclouds.com`)使用 HMAC-SHA1 Token,放在 `Authorization` 请求头 - Token 格式:`version=...&res=...&et=...&method=sha1&sign=...`(查询字符串格式) - 每次请求实时生成 Token,避免过期 ### HTTP 客户端 - `IotHttpClient.execute()` 不对非 2xx 状态码抛异常,始终返回响应体 - 正常响应打 DEBUG 日志,非 2xx 打 WARN,网络异常打 ERROR - 全局日志级别 WARN,框架 INFO 日志屏蔽 ### 响应反序列化 - 各 Service 使用独立 `ObjectMapper`,配置 `SNAKE_CASE` 命名策略 + 忽略未知字段 - 属性历史接口(`/thingmodel/query-property-history`)的 `data` 结构不固定,反序列化为 `Object` 透传 ### 前端页面 - 纯原生 HTML/CSS/JS + FreeMarker,无第三方 UI 框架 - 主页两个 Tab:产品详情、设备列表;页面加载后自动触发两个查询 - 设备列表每行操作按钮:详情、数据点、事件记录、属性(均以弹窗展示) - 属性弹窗支持二级跳转:属性列表 → 历史记录弹窗 - 产品详情页有"物模型"按钮,展示属性/事件/服务功能点 ### 已知注意事项 - `DeviceDetailData.java` 和 `OldIotResponse.java` 为旧版 API 遗留,当前设备详情已改用新版接口(`/device/detail`),这两个类暂未删除 - `ThingModelData.ThingModelService` 内部类与 Spring 的 `@Service` 无关,是物模型的服务功能点 DTO