Jelajahi Sumber

fix:更新aircloud协议,添加getip以及http上传文件协议

mw 5 bulan lalu
induk
melakukan
a14db3605d

TEMPAT SAMPAH
module/spec/image/C6RKbhiFAoRTHoxJWBLc9EUpnie.png


+ 334 - 36
module/spec/合宙IOT通用报文协议AirCloud_1.0.md

@@ -1,4 +1,4 @@
-# 合宙 IOT 通用报文协议 airCloud -- 1.0
+# 合宙 IOT 通用报文协议 AirCloud -- 1.0
 
 # 一、背景
 
@@ -32,25 +32,57 @@
 
 消息头一共 16 字节。
 
-1, 设备 ID - 8 字节
+### 2.1.1 设备 ID - 8 字节
 
-其中第一个字节,代表设备类型,4G,WiFi,BLE,等;
+其中第一个字节,代表设备类型,4G,WiFi,BLE,等。
+
+0x01 - 4G 设备;
+
+0x02 - WiFi 设备;
+
+0x03 - BLE 设备;
+
+0x04 - 以太网设备;
+
+0x05 - 4G 主控,多网融合设备;
+
+0x06 - WiFi 主控,多网融合设备
+
+0x07 - BLE 主控,多网融合设备;
+
+0x08 - 以太网主控,多网融合设备。
 
 剩余 7 字节为设备 ID,可以是 IMEI,也可以是 MAC, 也可以是 Chip ID,不做特殊约定。
 
+```
+其中, IMEI 在这里只放前面14个数字,第15个数字,参见3.3.1 小节计算出来。
+```
+
 设备 ID 采用 BCD 编码方式。
 
 设备 ID 长度不足 7 字节的,自动在高位补 0.
 
-2,流水号 - 2 字节
+例 1,一个 4G 设备, IMEI 是 861234567890123 的,设备的 8 个字节的内容是:
 
-3,消息长度 - 2 字节
+0x0186123456789012
+
+第 15 个数字 3, 是不在设备 ID 体现的。
+
+例 2,一个 WIFI 设备的 MAC 地址是 00-1A-2B-3C-4D-5E,该设备的 8 个字节的内容是:
 
 ```
-从版本标识开始的消息长度,最长不能大于 1400字节。
+0x 02 00 00 1A 2B 3C 4D 5E
 ```
 
-4,消息标识-4 字节
+### 2.1.2 流水号 - 2 字节
+
+### 2.1.3 消息长度 - 2 字节
+
+```
+从消息标识开始的消息长度,最长不能大于 1400字节。
+```
+
+### 2.1.4 消息标识-4 字节
 
 ```
 用来做协议和消息约定的32个bit。
@@ -61,7 +93,9 @@ bit4:    是否需要回复
 
 bit5:    是否携带鉴权 key
 
-其余26个bit 为0.
+bit6:    是否是 UDP 承载。
+
+其余25个bit 为0.
 ```
 
 ## 2.2 消息体
@@ -88,17 +122,17 @@ bit5:    是否携带鉴权 key
 <tr>
 <td>字段<br/></td><td>**字段名**<br/></td><td>**长度**<br/></td><td>含义<br/></td></tr>
 <tr>
-<td>消息头<br/></td><td>设备ID<br/></td><td>8<br/></td><td>第一个字节,代表设备类型,4G,WiFi,BLE,等;<br/>剩余7字节为设备ID,可以是IMEI,也可以是MAC, 也可以是Chip ID,不做特殊约定。 <br/></td></tr>
+<td>消息头<br/></td><td>设备ID<br/></td><td>8<br/><br/></td><td>第一个字节,代表设备类型,4G,WiFi,BLE,等;<br/>剩余7字节为设备ID,可以是IMEI,也可以是MAC, 也可以是Chip ID,不做特殊约定。 <br/>详细解释参见2.1.1节<br/></td></tr>
 <tr>
 <td>消息头<br/></td><td>流水号<br/></td><td>2<br/></td><td><br/></td></tr>
 <tr>
-<td>消息头<br/></td><td>消息长度<br/></td><td>2<br/></td><td>从消息标识开始的消息长度,最长不能大于 1400字节。<br/></td></tr>
+<td>消息头<br/></td><td>消息长度<br/></td><td>2<br/><br/></td><td>从消息体(既不包含消息头和认证key(可选))开始的消息长度,长度不做限制。<br/></td></tr>
 <tr>
-<td>消息头<br/></td><td>消息标识<br/></td><td>4<br/></td><td>bit0-3: 协议版本号;<br/>bit4:    是否需要回复<br/>bit5:    是否携带鉴权 key<br/>其余26个bit 为0.<br/></td></tr>
+<td>消息头<br/></td><td>消息标识<br/></td><td>4<br/><br/></td><td>bit0-3: 协议版本号;<br/>bit4:    是否需要回复<br/>bit5:    是否是 UDP承载    <br/>其余26个bit 为0.<br/></td></tr>
 <tr>
-<td>认证key(可选)<br/></td><td>key<br/></td><td>64<br/></td><td>用于 UDP 报文的鉴权<br/></td></tr>
+<td>认证key(可选)<br/></td><td>key<br/></td><td>64<br/><br/></td><td>用于 UDP 报文的鉴权<br/></td></tr>
 <tr>
-<td>TLV1<br/></td><td>字段类型<br/></td><td>2<br/></td><td> 前面12个bit, 代表字段含义,比如温度,湿度,转速,工作或者停止,等等;<br/>   后面4bit,代表数据类型(整数,浮点,bool,ascii,binary)<br/></td></tr>
+<td>TLV1<br/></td><td>字段类型<br/></td><td>2<br/></td><td> bit0 到 bit11, 代表字段含义,比如温度,湿度,转速,工作或者停止,等等;<br/>bit12到bit15,代表数据类型(整数,浮点,bool,ascii,binary)<br/></td></tr>
 <tr>
 <td>TLV1<br/></td><td>长度<br/></td><td>2<br/></td><td><br/></td></tr>
 <tr>
@@ -176,7 +210,6 @@ unique_id:muc 通过 mcu.unique_id()获取的唯一 id,需要转为十六进
 2. 内容:任何上行数据包都算作心跳,遵循 airCloud 协议即可。
 3. 超时: 若两个心跳周期未收到任何数据包,服务器将发起断链。
 
-
 # 三、字段类型定义
 
 字段类型一共 2 字节,分为两部分:  **字段含义和数据类型**,其中字段含义 12bit,数据类型 4bit。
@@ -191,11 +224,11 @@ unique_id:muc 通过 mcu.unique_id()获取的唯一 id,需要转为十六进
 
 0002 - 布尔值
 
-0003 - ASCII 字符串
+0003 - ASCII 可打印字符串,是可打印的字符串,直接 copy 出来就可以在文本编辑器人眼查看的。每个字节的值都在 0x20 到 0x2E 之间。
 
-0004 - binary 字符串
+0004 - binary 字符串,不一定可打印, 每个字节是任意的。
 
-0005 - UNICODE 字符串
+0005 - UNICODE 字符串,UTF-8 编码方式。
 
 ## 3.2 字段含义
 
@@ -227,6 +260,10 @@ unique_id:muc 通过 mcu.unique_id()获取的唯一 id,需要转为十六进
 
 22 - iRTU 上行回复,
 
+23 - 文件上传开始通知 - 上行(设备通知服务器开始上传文件)
+
+24 - 文件上传完成通知 - 上行(上传完成后通知服务器结果)
+
 ### 3.2.2 业务字段类型
 
 #### 3.2.2.1 传感类 256-511
@@ -281,7 +318,7 @@ unique_id:muc 通过 mcu.unique_id()获取的唯一 id,需要转为十六进
 
 771 - 电量(mV)
 
-772 - 驻留小区
+772 - 驻留频段
 
 773 - 驻留小区和临区
 
@@ -301,6 +338,18 @@ unique_id:muc 通过 mcu.unique_id()获取的唯一 id,需要转为十六进
 
 781 - 当前联网方式(4G/WiFi/以太网)
 
+782 - 4G 信号强度
+
+783 - ICCID
+
+784 - 文件上传类型(图片/音频)
+
+785 - 文件名称
+
+786 - 文件大小
+
+787 - 上传结果状态
+
 #### 3.2.2.5 软件数据 1024-1279
 
 1024 - Lua 核心库错误上报(用于 LuatOS 自动化测试)
@@ -343,7 +392,7 @@ V:实际的 iRTU 下行命令的全文
 
 举例:
 
-T: 0x0017      ----- 信令类型 21
+T: 0x0015      ----- 信令类型 21
 
 L:   0x000B       ---- 11 个字节
 
@@ -359,13 +408,61 @@ V:实际的 iRTU 上行命令全文
 
 举例:
 
-T: 0x0017      ----- 信令类型 22
+T: 0x0016      ----- 信令类型 22
 
-L:   0x000B       ---- 14 个字节
+L:   0x000E       ---- 14 个字节
 
 V: 字符串: “rrpc,getcsq,17”
 
-# 四、airCloud 和遥测的关系
+23 - 文件上传开始通知 - 上行(设备通知服务器开始上传文件)
+
+作用:通过 TCP/MQTT 通知服务器有文件上传。
+
+TLV 结构:
+
+- T: 0x0017 (信令类型 23)
+- L: 实际长度
+- V: 包含以下子 TLV:
+
+  - 文件上传类型 (1291): 整数(1:图片, 2:音频)
+  - 文件名称 (1292): ASCII 字符串
+  - 文件大小 (1293): 整数
+
+24 - 文件上传完成通知 - 上行(上传完成后通知服务器结果)
+
+作用:通过 TCP/MQTT 通知服务器文件上传成功。
+
+TLV 结构:
+
+- T: 0x0018 (信令类型 24)
+- L: 实际长度
+- V: 包含以下子 TLV:
+
+  - 文件上传类型 (1291): 整数
+  - 文件名称 (1292): ASCII 字符串
+  - 上传结果状态 (1294): 整数
+    - 0: 上传成功
+    - 1: 上传失败
+
+## 3.3 附加信息
+
+### 3.3.1 IMEI 第 15 位的计算方法
+
+IMEI 的第 15 位数字是校验位,由 Luhn 算法计算得出,用于确保 IMEI 的有效性。具体计算方法如下:
+
+1. **计算偶数位数字乘以 2 后的各位数字之和**:从左到右将 IMEI 的前 14 位数字中的偶数位数字分别乘以 2,然后计算这些乘积的个位数字和十位数字之和。例如,对于数字 5×2=10,其个位数字和十位数字之和为 0+1=1;对于 9×2=18,其个位数字和十位数字之和为 8+1=9。
+2. **计算奇数位数字之和**:将 IMEI 的前 14 位数字中的奇数位数字相加。
+3. **计算总和**:将第一步得到的偶数位数字之和与第二步得到的奇数位数字之和相加。
+4. **确定校验位**:如果第三步计算出来的数值个位为 0,则校验位为 0;否则,校验位为 10 减个位数值。
+
+例如,对于 IMEI 前 14 位数字 35890180697241,计算过程如下:
+
+- 偶数位:5×2=10,9×2=18,1×2=2,0×2=0,9×2=18,2×2=4,1×2=2。个位数之和为 0+8+2+0+8+4+2=24,十位数之和为 1+1+1=3。
+- 奇数位:3+8+0+8+6+7+4=36。
+- 偶数位与奇数位数字之和:24+3+36=63。
+- 第 15 位校验码为:10-3=7。
+
+# 四、AirCloud 和遥测的关系
 
 遥测的目的是检测设备的 mobile 信息,证明设备还活着,还具备通信能力;
 
@@ -373,29 +470,124 @@ airCloud 协议,目的是合宙设备驱动的业务,都有被记录到数
 
 # 五、支持的通信承载
 
-## 5.1 TCP
+## 5.1、getip:
+
+### 通信协议要求
+
+1. 协议需要兼容老设备, 同时兼容负载均衡
+2. 便于扩展到更多二进制数据的上传
+3. 要包含鉴权, 上传后要自动归入设备对应的数据里
+
+### 通信逻辑
+
+1. 负载均衡服务器,支持生成图片上传的 url 和额外参数
+2. 设备通过调用 getip 接口, 获取图片上传所需要的 url 和参数列表
+3. 设备在指定条件下(定时/按键触发),使用上述参数执行上传
+4. 设备平台收到数据后, 需要展示到页面中
+
+### 通信接口设计
+
+#### 请求(https)
+
+```json
+URL             device.openluat.com/getip?key="....."
+METHOD          GET
+```
+
+key 表示用户的 key 通过 sha256 加密后的值
+
+#### 响应(json 格式)
+
+补充后的考虑如下:
+
+```json
+{
+  //设备连接信息 (MQTT/TCP)
+  "conninfo": {
+    "host": "xxx", // 服务器地址
+    "port": xxx, // 端口
+    "user_name": "xxx", // 用户名
+    "password": "xxxxxxxx", // 密码
+    "transport": "tcp",   //连接方式"tcp"或者"mqtt"
+  },
+
+  //图片上传信息
+  "imgupurl": "https://image.openluat.com/iot/upload/file",
+  "imgbody": {
+    "{data}": "f",
+    "auth": true,
+    "dir": "upload_image",
+    "mon": true,
+    "prefix": "123456789012_",
+    "index": true,
+    "thumb": "thumb",
+    "tip": "图片说明",
+    "rpt": false
+  },
+  "imgheader": {
+    "token": "2xb3….",
+    "salt": "80…",
+    "tu": 1
+  },
+
+  //音频上传信息
+  "audupurl": "https://audio.openluat.com/iot/upload/file",
+**  //下面具体字段还需要建栋确认。**
+  "audbody": {
+    "{data}": "audio_file", // 音频文件的字段名
+    "auth": true,
+    "dir": "upload_audio", // 服务端存储音频的目录
+    "mon": true,
+    "prefix": "123456789012_",
+    "index": true,
+    "size": 300, // 文件大小
+    "rpt": false//上传后成功是否返回详细信息。
+  },
+  "audheader": {
+    "token": "3yc4….",
+    "salt": "81…",
+    "tu": 1
+  }
+}
+```
+
+#### AirCloud 的调用 getip 的时机参考:
+
+1、首次没有获取 ip 前调用
+
+2、连接获取 ip 端口后,如果 TCP 断连先进行重连,如果 3 次重连失败就去调用 getip 重新获取 ip 及端口。
+
+3、更异常的情况:若 getip 如果失败,也应该尝试 3 次。
+
+## 5.2 TCP
 
 TCP server 收到数据后,直接发起写入数据库动作。
 
 TCP server 在接受了 socket 连接后,等待设备的鉴权请求,如果超时或者鉴权请求不通过,主动发起断链。
 
-## 5.2 MQTT
+## 5.3 MQTT
 
-### 5.2.1 MQTT 角色
+### 5.3.1 MQTT 角色
 
 ```
 有三个角色: 设备,Broker,ServClient。
 ```
 
-## 5.2.2 MQTT 主题
+## 5.3.2 MQTT 主题
 
 ```
 ServClient 订阅所有主题,设备只订阅跟自己相关的主题。
 
-设备的主题名字为: /AirPro/DeviceID/ServType
+设备的主题名字为: /AirCloud/direction/DeviceID/ServType
 ```
 
-其中, AirPro 是固定字符串;
+其中, AirCloud 是固定字符串;
+
+direction 是传输方向:
+
+(1)up:上行方向,表示从设备到服务器的通信
+
+(2)down:下行方向,表示从服务器到设备的通信
 
 DeviceID 是设备的 ID, 内容和消息头的 设备 ID 相同;
 
@@ -407,7 +599,25 @@ ServType 包括两种:
 
 其中, auth 是指鉴权报文, all 是指所有其他报文。
 
-## 5.2.3 鉴权
+目前的 topic 主题如下:
+
+设备鉴权上报:
+
+/AirCloud/up/DeviceID/auth
+
+设备数据上报:
+
+/AirCloud/up/DeviceID/all
+
+服务器鉴权响应下发:
+
+/AirCloud/down/DeviceID/auth
+
+服务器数据下发:
+
+/AirCloud/down/DeviceID/all
+
+## 5.3.3 鉴权
 
 ```
 设备和Broker建立MQTT 连接后,首先设备要发起鉴权,Broker把鉴权请求转发给ServClient,ServClient审核后,回复鉴权通过或者鉴权失败。
@@ -417,17 +627,105 @@ ServType 包括两种:
 如果设备超时没有发起鉴权,ServClient也要通知Broker,把设备断链。
 ```
 
-## 5.3 UDP
+## 5.4 UDP
 
-airCloud 当前不推荐 UDP 协议。
+AirCloud 当前不推荐 UDP 协议。
 
 如果必须要用 UDP 的话,需要在消息标识的第 6 个 bit 设为 1, 并在消息头和 TLV 中间,放置 64 字节的 key。
 
 服务器需要对每个 UDP 消息,进行 key 的合法性检查。
 
-## 5.4 HTTP
+## 5.5 HTTP
+
+通过 getip 获取的上报 url
+
+### 设备上传流程:
+
+#### 设备上传图片文件流程如下:
+
+##### 请求(https)
+
+```json
+URL           "https://image.openluat.com/iot/upload/file" , 根据getip的返回的数据决定,不能写死
+METHOD         POST
+HEADERS       根据getip的返回数据进行填充,对应"imgheader"
+BODY          mulitpart格式
+
+其中, body中文件的key 要使用 {data} 对应的值
+```
+
+##### 响应(json 格式)
+
+正常返回码 200, 其他一律作为错误
+
+响应内容
+
+```json
+{
+  "code":0,//code为0表示成功
+  "value": {//这个是rpt请求参数为true的返回。如果没有携带rpt,则value返回"上传成功"
+        "uri": "/vsna/luatos/336677/upload_image/2025-09/86453607261497520250908144614.png",
+        "size": "26.00KB",
+        "thumb": "/vsna/luatos/336677/upload_image/2025-09/86453607261497520250908144614s.png"
+    }
+}
+```
+
+#### 设备上传音频文件流程如下:
+
+##### 请求(https)
+
+```json
+URL           "https://audio.openluat.com/iot/upload/file" , 根据getip的返回的数据决定,不能写死
+METHOD         POST
+HEADERS       根据getip的返回数据进行填充,对应"audheader"
+BODY          mulitpart格式
+
+其中, body中文件的key 要使用 {data} 对应的值
+```
+
+##### 响应(json 格式)
+
+正常返回码 200, 其他一律作为错误
+
+响应内容
+
+```json
+{
+  "code":0,//code为0表示成功
+  "value": {//这个是rpt请求参数为true的返回。如果没有携带rpt,则value返回"上传成功"
+        "uri": "/vsna/luatos/336677/upload_image/2025-09/xxx.mp3",
+        "size": "26.00KB",
+        "thumb": "/vsna/luatos/336677/upload_image/2025-09/xxx.mp3"
+    }
+}
+```
+
+#### 调用时机
+
+按业务逻辑而定
+
+### Aircloud 协议 http 文件上传:
+
+## 上传控制信令:
+
+23 - 文件上传开始通知 - 上行(设备通知服务器开始上传文件)
+
+24 - 文件上传完成通知 - 上行(上传完成后通知服务器结果)
+
+## 增加业务字段类型:
+
+784 - 文件上传类型(图片/音频)
+
+785 - 文件名称
+
+786 - 文件大小
+
+787 - 上传结果状态
+
+## http 文件上传的逻辑大概是:
 
-airCloud 当前不支持 HTTP UDP 协议。
+![](image/C6RKbhiFAoRTHoxJWBLc9EUpnie.png)
 
 # 六、云端后台实现
 
@@ -457,11 +755,11 @@ airCloud 当前不支持 HTTP UDP 协议。
 
 ### 7.1.2 合宙批量挂测
 
-合宙的量产小板,用 airCloud 批量挂测,做压力测试。
+合宙的量产小板,用 AirCloud 批量挂测,做压力测试。
 
 ### 7.1.3 iRTU 内置支持
 
-IRTU 取消对第三方云平台的支持, 只内置合宙 airCloud 协议。
+IRTU 取消对第三方云平台的支持, 只内置合宙 AirCloud 协议。
 
 ## 7.2 客户收费标准
 
@@ -507,7 +805,7 @@ IRTU 取消对第三方云平台的支持, 只内置合宙 airCloud 协议。
 
 # 八,扩展库实现
 
-exiot 扩展库, 调用 socket 核心库,mqtt 核心库,exnetif 扩展库。
+excloud 扩展库, 调用 socket 核心库,mqtt 核心库,exnetif 扩展库。
 
 扩展卡包含如下成员函数: