Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用ProtoBuf将数据流传输到带有头的日志文件_C_Logging_Protocol Buffers_Proto_Nanopb - Fatal编程技术网

C 使用ProtoBuf将数据流传输到带有头的日志文件

C 使用ProtoBuf将数据流传输到带有头的日志文件,c,logging,protocol-buffers,proto,nanopb,C,Logging,Protocol Buffers,Proto,Nanopb,我试图将数据流传输到微控制器SD卡上的日志文件中,该微控制器从一些传感器读取数据并将值存储在文件中 为了序列化数据,我将使用NanoPB,这是C语言的protobuf实现,它非常节省资源 日志文件具有以下结构:它需要写入一个由GUID和固件版本组成的短头。在报头之后,数据流应该是连续的,它应该记录来自传感器的字段,而不是报头值(这应该只发生一次并且在开始时发生) 限制是我只能使用一个.proto文件进行序列化和反序列化,我希望避免使用.proto中的“重复”字段然后使用nanopb的C实现而产生

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

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

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

限制是我只能使用一个.proto文件进行序列化和反序列化,我希望避免使用.proto中的“重复”字段然后使用nanopb的C实现而产生的Pb_回调函数

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

}

这样做的想法是,一旦处理,日志文件将如下所示:

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和固件。然而,如果我把它分成两条消息,我就不能用一个proto文件一次性反序列化它们。我需要知道前两条消息的长度,对它们进行反序列化,然后从日志开始

我希望避免在.proto中使用“重复”字段而产生的Pb_回调函数

请注意,您可以为重复字段指定
max\u count
,就像为字符串指定
max\u size
一样,然后您将得到一个简单数组,而不是回调

然而,如果我把它分成两条消息,我就不能用一个proto文件一次性反序列化它们

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

message LogMessage {
   optional LogHeader header = 1;
   optional Sensors sensors = 2;
}
然后,您可以将标题和传感器字段中的一个或两个设置为true或false,并将
has_header
has_sensors
设置为true或false,以指示是否要包含该子字段。但无论内容如何,您总是将其序列化和反序列化为
LogMessage
,因此不同的消息类型之间没有混淆

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

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

A是添加长度前缀,如nanopb的
pb\u encode\u delimited()
pb\u decode\u delimited()
所做。此格式也由C++原BoFF库支持。然而,这样做的一个缺点是许多命令行工具(如
protoc
)不支持分隔格式,例如pythonProtobuf库会对它们进行解码

另一个选项是使整个文件看起来像一条消息,但将其分为多个部分。ProtoBuf具有合并功能,即,如果您只是在消息之后追加消息,它们将合并在一起。这可以通过在
日志消息中包含重复字段来实现:

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

现在,如果您对
LogMessage
的多个副本进行编码,每个副本都有一个
传感器
条目,它们将合并在一起。然后,如果您解码该文件,它将显示为一条带有多个传感器的
日志消息

如果我理解正确,不是吗。max\u count是指您期望的最大重复次数(我不知道)?我不明白你为什么把它设为1。我知道这是为了避免回调,但为什么要1?感谢@jpa.@A.San的解释。如果您一次只想对一个子消息进行编码,1就足够了。但是,是的,你将无法用nanopb解码组合消息,你需要回调。好的,在这种情况下,我只需要用nanopb编码并在其他地方解码。所以这应该完成编码的工作。
message LogMessage {
   optional LogHeader header = 1;
   repeated Sensors sensors = 2 [(nanopb).max_count = 1];
}