2

我正在尝试将数据流式传输到微控制器上 SD 卡上的日志文件,该微控制器从某些传感器读取并将值存储在文件中。

为了序列化数据,我将使用 NanoPB,它是 C 的 protobuf 实现,非常节省资源。

日志文件的结构如下: 它需要写一个由 GUID 和固件版本组成的短标题。在标头之后,数据流应该是连续的,它应该记录来自传感器的字段,而不是标头值(这应该只在开始时出现一次)。

限制是我只能使用一个 .proto 文件进行序列化和反序列化,并且我想避免使用 .proto 中的“重复”字段然后使用 nanopb 的 C 实现而出现的 Pb_callback 函数。https://jpa.kapsi.fi/nanopb/docs/concepts.html

我尝试过的实现如下(字段只是示例):

syntax = "proto3";

import "timestamp.proto";
import "nanopb.proto";

message LogHeader {
    string firmware = 1 [(nanopb).max_size = 11];  
    string GUID = 2 [(nanopb).max_size = 11];       
}

message Sensors {
    int32 TimeStamp = 3;        
    // Sensory data
    int32 Sens1 = 4;
    int32 Sens2 = 5;
    int32 Sens3 = 6;
    int32 Sens4 = 7;
    int32 Sense5 = 8;

}

我们的想法是拥有一个处理后看起来像这样的日志文件:

firmware "1.0.0"
GUID "1231214211321" (example)
Timestamp 123123
Sens1 2343
Sens2 13123
Sens3 13443
Sens4 1231
Sens5 190
Timestamp 123124
Sens1 2345
Sens2 2312
...

但是,如果所有字段都在同一条消息中,则每次重复都会记录 GUID 和固件。而如果我将其拆分为 2 条消息,我将无法使用一个 proto 文件一次性反序列化它们。我需要知道前两条消息的长度,对它们进行反序列化,然后从那里开始记录日志。

4

1 回答 1

1

我想避免使用 .proto 中的“重复”字段而出现的 Pb_callback 函数

请注意,您可以max_count像为字符串指定一样指定重复字段max_size,然后您将获得一个简单的数组而不是回调。

而如果我将其拆分为 2 条消息,我将无法使用一个 proto 文件一次性反序列化它们。

Protobuf 反序列化需要知道消息类型。处理此问题的最常见方法是使用带有子消息的单个顶级消息:

message LogMessage {
   optional LogHeader header = 1;
   optional Sensors sensors = 2;
}

然后,您可以设置标题和传感器字段中的一个或两个,并将has_headerandhas_sensors设置为 true 或 false 以指示您是否要包含该子字段。但无论内容如何,​​您总是将序列化和反序列化为LogMessage,因此不同消息类型之间不会混淆。

我需要知道前两条消息的长度,对它们进行反序列化,然后从那里开始记录日志。

是的,这也是 protobuf 的常见初学者问题。Protobuf 消息本身不对其长度进行编码,因此如果您在单个文件中有多个消息,则需要以某种方式将它们分开。

一种很常见的方法是添加一个长度前缀,就像 nanopb 的pb_encode_delimited()pb_decode_delimited(). C++ protobuf 库也支持这种格式。然而,这样做的一个缺点是许多命令行工具,例如protoc不支持分隔格式,例如 Python protobuf 库使得解码它们有些复杂

另一种选择是使整个文件看起来像是一条消息,但将其写入多个部分。Protobuf 具有合并功能,也就是说,如果您只是一个接一个地附加消息,它们就会合并在一起。这可以通过在 中包含重复字段来完成LogMessage

message LogMessage {
   optional LogHeader header = 1;
   repeated Sensors sensors = 2 [(nanopb).max_count = 1];
}

现在,如果您对 的多个副本进行编码LogMessage,每个副本都有一个sensors条目,它们将合并在一起。然后,如果您解码文件,它将看起来像一个LogMessage包含多个sensors条目的文件。

于 2019-10-23T08:32:25.660 回答