我有一个设备,我通过发送和接收特定的二进制数据包结构与之通信。该设备具有定义良好的 API,但它可以返回 100 多种可能的消息类型。使用什么好的设计来处理这些不同的消息类型?
这是伪代码中的一个例子,我忽略了成帧和校验和字节以使其更清晰。
// I receive this message, where 0x00 indicates the device status,
//and each other byte is a particular error or status
message = [0x00, 0x01, 0x01, 0x04]
// The next message I receive, where 0x10 indicates system time,
// and the rest of the fields are the integer clock seconds of the device.
message = [0x10, 0x00, 0x32, 0xFF, 0x8E]
// 100 other message types....
如您所见,我收到的每条消息都需要处理略有不同的处理方式,具有不同的含义。我最初打算使用一个巨大的 switch 语句case 0x00: process_errors() case 0x10: process_time()
但我很好奇是否有更好的设计可以用来增加添加新消息类型的灵活性、更好的可用性等。
您可以尝试使用 TLV(标签长度值)实现。它适用于处理数据流。
标记- 这将是数据的字节(根据您的示例),用于标识随后的消息类型。为了使用它,您应该事先知道哪种消息类型具有多少数据。例如,在0x00(设备状态)的情况下,您现在应该事先知道接下来的 3 个字节是数据。
长度- 数据字节的长度
值- 实际数据
您可以执行以下操作:
1)准备系统支持的不同消息的标签和长度的映射。
2)连续接收字节数据。
3) 读取第一个字节(这将是标签)并确定它是什么类型的消息。在您的情况下,这将为您提供0x00、0x10等4
)请参阅您的标签和长度信息地图。您将确定需要进一步读取多少字节的数据。
5)一旦你读取了数据部分,你的接收者应该准备好接收下一条消息(准备读取下一个标签)
这都是关于阅读消息的。获得消息及其数据后,您可以根据需要使用它。例如,除了与 Tag 对应的消息长度外,您还可以注册一个函数。这将允许您调用特定函数及其所需的参数。
设备状态
Data Tag = 00
Data Length = 03
Data Value = 01 01 04
系统时间
Data Tag = 10
Data Length = 04
Data Value = 00 32 FF 8E