浅浅的 Protobuf通信协议

发布于:2022-11-01 ⋅ 阅读:(684) ⋅ 点赞:(0)

Protobuf通信协议详解:代码演示、详细原理介绍等

一、什么是protobuf

protobuf数据在数据传输的过程中需要编码和解码。如下的一个 control.proto 文件就是一个protobuf文件:

control.proto

syntax = "proto3";

package XGrobot;

enum MoveMode {
    highSpeed = 0;
    mediumSpeed = 1;
    lowSpeed = 2;
  }

message MoveCmd {
    MoveMode movemode = 1; //机器人的移动速度挡位
    int32 moveSpeed = 2;//速度
    int32 direction = 3;//方向
}

在先不考虑语法的基础下,可以看到protobuf文件和类似的jons已经HTML文件等完全不同。

protobuf文件更类似于C的头文件,并且可以定义数据变量。

在实际使用的过程中,可以将control.proto文件作为小车的单片机和上位机进行通信的传输协议。但是最不同的点在于protobuf的使用需要进行编码和解码。数据发送前将数据按照格式编码,拿到数据后按照格式解码。而编解码的格式基础就是control.proto文件内容。

二、常用的probuf函数

单片机端一般安装nanopb来生成代码
linux 上一使用protobuf3点几版本以上的来使用。通过指令生成对应的代码。
protobuf仓库:

https://github.com/protocolbuffers/protobuf

protobuf-c仓库: protobuf-c是对于protobuf的仓库的补充

https://github.com/protobuf-c/protobuf-c

不错的参考文章

干货 | protobuf-c之嵌入式平台使用
Protobuf:一种更小、更快、更高效的协议
STM32 | protobuf在STM32平台的移植使用
【嵌入式Nanopb协议】——[1]总览

三、重要函数

linux上使用:


Protobuf protobufmessage;     // 一个储存protobuf数据的实例

protobufmessage.set_movespeed(666);    // 给一个数据的元素赋值
protobufmessage.set_movemode(XGrobot::lowSpeed);
protobufmessage.set_direction(66);

bool 
SerializeToString(string* output) const;把message编码进output。
bool ParseFromString(const string& data);从string解码到message
bool SerializeToArray(char* buf,int size) const;把message编码进数组buf.
bool ParseFromArray(const char* buf,int size);把buf解码到message。
///此解码方法效率较ParseFromString高很多,所以一般用这种方法解码,而且IO函数一般是以char交流的,不是string。
bool SerializeToOstream(ostream output) const;把message编码进ostream
bool ParseFromIstream(istream* input);从istream解码到message

单片机上使用

uint8_t buffer[64] = {0};
Protobuf protobufmessage;     // 一个储存protobuf数据的实例

pb_ostream_t o_stream = {0};
pb_istream_t i_stream = {0};

 // 组包
 movecmd.movemode  = XGrobot_MoveMode_lowSpeed;
 movecmd.moveSpeed = 100;
 movecmd.direction = 99;
 o_stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
 pb_encode(&o_stream, protobufmessage_fields, &protobufmessage);

for(int i=0; i<64; i++)
{
	printf("%x ",buffer[i]);
}
printf("\r\n");
 // 解包
 i_stream = pb_istream_from_buffer(buffer, sizeof(buffer));
 pb_decode(&i_stream, protobufmessage_fields, &protobufmessage);
 printf("movemode = %d\r\n", protobufmessage.movemode);
 printf("moveSpeed = %d\r\n", protobufmessage.moveSpeed);
 printf("direction = %d\r\n", protobufmessage.direction);
本文含有隐藏内容,请 开通VIP 后查看