机器人通信协议
- 协议要“前瞻性设计”,避免未来修改的代价过高。
- 安全第一,传输的数据必须加密且可验证。
- 保持协议的“简洁性”与“可读性”之间的平衡。
# 📖 背景介绍
物联网(IoT)设备之间的通信需要一个可靠、高效、可扩展的协议,来保证设备可以正确理解彼此的数据。想象一下,如果不同品牌的智能家居设备都用自己的语言沟通,那场面会有多混乱?😵
一个好的协议能解决:
- 设备之间的互操作性 🏠🔗💡
- 数据传输的安全性 🔐
- 低功耗、低延迟的优化 ⚡
所以,在物联网项目中,协议设计至关重要!那么,好的协议设计有哪些特征呢?
# 🛠 最初构思
在 IoT 场景下,我们需要的协议应具备以下特性:
- 简洁性:传输的数据尽量精简,减少带宽消耗。
- 扩展性:协议要支持未来功能的拓展,而不会破坏现有功能。
- 安全性:防止中间人攻击、篡改等安全风险。
- 兼容性:确保不同版本、不同厂商的设备能互相通信。
🎯 目标:设计一个既通用又高效的协议!
# 🔍 协议分析 BLE 消息协议
syntax = "proto3";
package xxx.proto.xxx.ble;
// BLE消息
message BleMessage {
// 消息类型
uint32 type = 1;
// 消息内容
bytes body = 2;
}
// BLE消息类型
enum BleMessageType {
// 未知消息
BLE_MESSAGE_TYPE_UNKNOWN = 0;
// BLE认证AEAD消息(AuthAead)
BLE_MESSAGE_TYPE_AUTH_AEAD = 1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
syntax = "proto3";
package xxx.proto.xxx.auth;
// 认证状态
enum AuthState {
// 未知状态
AUTH_STATE_UNKNOWN = 0;
// 认证请求
AUTH_STATE_REQUEST = 1;
// 认证请求(使用快速认证)
AUTH_STATE_REQUEST_TICKET = 2;
// 认证成功
AUTH_STATE_OK = 3;
// 认证失败
AUTH_STATE_FAILED = 4;
}
// 认证消息类型
enum AuthMessageType {
// 未知消息
AUTH_MESSAGE_TYPE_UNKNOWN = 0;
// APP对Robot认证,请求消息
AUTH_MESSAGE_TYPE_APP_ROBOT_REQUEST = 1;
// APP对ROBOT认证,响应消息
AUTH_MESSAGE_TYPE_APP_ROBOT_RESPONSE = 2;
}
// 认证消息,编码后被AEAD作为msg加密存储于AuthAead的enc中
message AuthMessage {
// 认证状态
AuthState state = 1;
// 会话票据,用于快速认证
optional bytes session_ticket = 2;
// 认证消息类型
uint32 type = 3;
// 认证消息体,根据type解码
bytes body = 4;
}
// 关联数据(明文编码)
message AssociatedData {
// 顺序号
uint32 seq = 1;
// 时间戳
uint64 timestamp = 2;
// 协议版本
uint32 version = 3;
}
// 认证AEAD
message AuthAead {
// 关联数据
AssociatedData ad = 1;
// 关联数据编码数据
bytes ad_bytes = 2;
// nonce随机数
bytes nonce = 3;
// 密文
bytes enc = 4;
// MAC
bytes mac = 5;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
syntax = "proto3";
package xxx.proto.xxx.auth;
// 位置
message PointLla {
float long = 1;
float lat = 2;
float alt = 3;
}
// APP对robot认证,请求消息
message AppRobotAuthRequestMessage {
// 设备Id
string device_id = 1;
// 软件版本
string app_version = 2;
// 位置
PointLla app_lla = 3;
// 用户Id
string user_id = 4;
// robot sn
string robot_sn = 5;
}
// Robot对App认证,响应消息
message AppRobotAuthResponseMessage {
// 响应的认证请求seq值
uint32 ack_seq = 1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
这个协议设计主要用于 BLE(Bluetooth Low Energy)
通信,涉及认证(Authentication
)和消息传递,包含以下核心部分:
BleMessage
:通用BLE
消息结构,定义消息类型和内容。AuthMessage
和AuthAead
:认证相关消息,支持AEAD(Authenticated Encryption with Associated Data)
加密,提供认证状态、会话票据和加密数据。AppRobotAuthRequestMessage
和AppRobotAuthResponseMessage
:具体的认证请求和响应消息,用于APP
(地面站)对Robot
(机器人)的认证。 设计目标是实现安全的、低功耗的认证协议,适用于资源受限的BLE
环境。
# 🚀 设计亮点
模块化设计: 协议分为多个独立的消息类型(
BleMessage
、AuthMessage
、AuthAead
等),层次清晰,便于扩展和维护。 使用枚举(BleMessageType
、AuthState
、AuthMessageType
)定义状态和类型,具有良好的可读性和类型安全性。支持
AEAD
加密:AuthAead
消息包含nonce
(随机数)、enc
(密文)、mac
(消息认证码)和ad
(关联数据),采用AEAD
加密方案,确保安全性。 关联数据(AssociatedData
)包含seq
(顺序号)、timestamp
(时间戳)和version
(协议版本),可以防止重放攻击和版本不匹配问题。灵活性:
BleMessage
和AuthMessage
使用bytes
类型的body
字段,允许根据type
动态解码具体内容,具有较好的扩展性。session_ticket
字段(在AuthMessage
中)支持快速认证,适合需要频繁认证的场景。 具体认证消息:AppRobotAuthRequestMessage
包含设备 ID、软件版本、位置信息等,提供了足够的上下文用于认证决策。AppRobotAuthResponseMessage
使用ack_seq
回应请求的顺序号,便于请求-响应匹配。轻量化:
Protobuf
本身是二进制序列化格式,相较于 JSON 或 XML,数据体积更小,非常适合 BLE 的带宽受限环境。
# 🏗 实施 & 遇到的挑战
在设计协议的过程中,我们遇到了一些挑战:
如何保证向后兼容性?
- 方案:使用
optional
字段,避免破坏旧版解析。
- 方案:使用
如何保证消息的安全性?
- 方案:引入
AEAD
(认证加密)机制,确保消息完整性。
- 方案:引入
如何降低带宽消耗?
- 方案:
- 使用
enum
代替字符串,减少数据传输量。 - 合理设计数据结构,避免冗余字段。
- 使用
- 方案:
# 🎭 结尾
协议设计就像编写一首交响乐 🎵,需要优雅的结构、和谐的组合,更重要的是要让所有乐器(设备)都能顺畅地演奏出相同的旋律。
“复杂的系统,往往起源于一个简单、优雅的设计。”——Alan Kay
协议设计是一个不断打磨的过程,但只要遵循 “简洁、扩展、安全” 的原则,就能打造出稳定可靠的物联网通信框架!🚀