纳米PB 帮助!对嵌套的重复项目进行编码,但不确定我是否正确定义了架构
NanoPB Help! encoding nested repeated items and not sure I have the schema defined properly
我正在为电池组定义故障。
包由一个或多个模块组成。
模块由 6 个单元组成。
我已经能够得到减去重复模块的包信息。我相信我重复的模块现在正在编码但出现错误:
Decoding failed: parent stream too short
目前我的原型是这样的
syntax = "proto2";
package TeslaBMS;
message Pack {
required int32 numberOfModules = 2;
required float currentVoltage = 3;
required float averagePacktemp = 4;
repeated Module modules = 5;
message Module {
required int32 id = 1;
required float moduleVoltage = 2;
required float moduleTemp = 3;
required float lowestCellVolt = 4;
required float highestCellVolt = 5;
// repeated Cell cells = 6;
// message Cell{
// required int32 cellId = 1;
// required float cellVolt = 2;
// required string balanceState = 3;
// }
}
}
产生这些结构定义
/* Struct definitions */
typedef struct _TeslaBMS_Pack {
int32_t numberOfModules;
float currentVoltage;
float averagePacktemp;
pb_callback_t modules;
} TeslaBMS_Pack;
typedef struct _TeslaBMS_Pack_Module {
int32_t id;
float moduleVoltage;
float moduleTemp;
float lowestCellVolt;
float highestCellVolt;
} TeslaBMS_Pack_Module;
我制作了一个 typedef 结构来保存模块数组
typedef struct{
TeslaBMS_Pack_Module modarr[MAX_MODULE_ADDR];
int listSize = 0;
}
ModuleList;
这些是构建模块数组的一些辅助函数
modulelist_add_module
用于解码,module_array_maker
用于编码
根据我能找到的示例,这是我的 encode/decode。
编码:
void encoder(){
// Setup pack message
TeslaBMS_Pack mypack = TeslaBMS_Pack_init_zero;
// stream to write buffer
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
// set deffinitions
mypack.averagePacktemp = bms.getAvgTemperature();
mypack.currentVoltage = bms.getPackVoltage();
mypack.numberOfModules = bms.getNumOfModules();
ModuleList modArr;
module_array_maker(&modArr);
// set the arg to data needed
mypack.modules.arg = &modArr;
// encode the modules
mypack.modules.funcs.encode = modules_encode;
//encode the pack
status = pb_encode(&stream, TeslaBMS_Pack_fields, &mypack);
message_length = stream.bytes_written;
if (!status) printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
}
对重复模块字段的回调进行编码
bool modules_encode(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
{
ModuleList *source = (ModuleList*)(*arg);
for(int i=0; i<bms.getNumOfModules();i++)
{
printf(" \n Mod %i is at %f \n",(int)source->modarr[i].id, source->modarr[i].moduleVoltage);
if (!pb_encode_tag_for_field(stream, field))
{
const char * error = PB_GET_ERROR(stream);
printf("encode_modules error: %s", error);
return false;
}
if (!(stream, TeslaBMS_Pack_Module_fields, &source->modarr[i]))
{
const char * error = PB_GET_ERROR(stream);
printf("SimpleMessage_encode_numbers error: %s", error);
return false;
}
}
return true;
}
解码:
void decode(){
/* Allocate space for the decoded message. */
TeslaBMS_Pack myPack = TeslaBMS_Pack_init_zero;
/* Create a stream that reads from the buffer. */
ModuleList modArr;
module_array_maker(&modArr);
myPack.modules.arg = &modArr;
myPack.modules.funcs.decode = modules_decode;
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
/* Now we are ready to decode the message. */
status = pb_decode(&stream, TeslaBMS_Pack_fields, &myPack);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
}
else
{
/* Print the data contained in the message. */
printf("\n********MESSAGE FROM NANOPB!*********\n");
// printf("Number Of Modules in Pack: ", myPack.numberOfModules);
printf("Pack Voltage: %.3f\n", myPack.currentVoltage);
printf("Average Temp: %.3f\n", myPack.averagePacktemp);
printf("Number of modules: %i\n", (int)myPack.numberOfModules);
for (size_t i = 0; i < myPack.numberOfModules ; i++)
{
printf("\n ************ Module %i ************\n", modArr.modarr[i].id);
printf(" Voltage: %.3f Temperature: %.3f \n" ,modArr.modarr[i].moduleVoltage, modArr.modarr[i].moduleTemp);
}
printf("********MESSAGE FROM NANOPB!*********\n");
}
}
解码模块回调
bool modules_decode(pb_istream_t *istream, const pb_field_t *field, void **arg){
ModuleList * dest = (ModuleList*)(*arg);
TeslaBMS_Pack_Module module;
if(!pb_decode(istream, TeslaBMS_Pack_Module_fields, &module)){
const char * error = PB_GET_ERROR(istream);
printf("module_decode error: %s", error);
return false;
}
modulelist_add_module(dest, module);
return true;
}
忘记更新了。
看来我们只需要为消息多 space 一点。我们采用了预期的最大消息大小,并添加了更多字节以传递到编码器函数并将编码器函数从:void encoder()
更改为: size_t encoder(pb_byte_t *buffer, size_t length)
设置和调用编码和解码
pb_byte_t buffer[128];
size_t msg_length = encoder(buffer, sizeof(buffer));
decode(buffer, msg_length);
编码函数:
size_t encoder(pb_byte_t *buffer, size_t length) {
// Setup pack message
TeslaBMS_Pack mypack = TeslaBMS_Pack_init_zero;
// stream to write buffer
pb_ostream_t stream = pb_ostream_from_buffer(buffer, length);
// set definitions
mypack.averagePacktemp = bms.getAvgTemperature();
mypack.currentVoltage = bms.getPackVoltage();
mypack.numberOfModules = bms.getNumOfModules();
ModuleList modArr;
module_array_maker(&modArr);
mypack.modules.arg = &modArr;
mypack.modules.funcs.encode = modules_encode;
//encode the pack
bool status = pb_encode(&stream, TeslaBMS_Pack_fields, &mypack);
if (!status) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
}
printf("Encoded %d bytes\n", stream.bytes_written);
return stream.bytes_written;
}
解码函数已更改为接受 2 个参数
void decode(pb_byte_t *buffer, size_t message_length){
/* Allocate space for the decoded message. */
TeslaBMS_Pack myPack = TeslaBMS_Pack_init_zero;
ModuleList modArr;
module_array_maker(&modArr);
myPack.modules.arg = &modArr;
myPack.modules.funcs.decode = modules_decode;
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
bool status = pb_decode(&stream, TeslaBMS_Pack_fields, &myPack);
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return;
}
/* Print the data contained in the message. */
printf("\n********MESSAGE FROM NANOPB!*********\n");
// printf("Number Of Modules in Pack: ", myPack.numberOfModules);
printf("Pack Voltage: %.3f\n", myPack.currentVoltage);
printf("Average Temp: %.3f\n", myPack.averagePacktemp);
printf("Number of modules: %i\n", (int)myPack.numberOfModules);
for (size_t i = 0; i < myPack.numberOfModules ; i++)
{
printf("\n ************ Module %i ************\n", modArr.modarr[i].id);
printf(" Voltage: %.3f Temperature: %.3f \n" ,modArr.modarr[i].moduleVoltage, modArr.modarr[i].moduleTemp);
}
printf("********MESSAGE FROM NANOPB!*********\n");
}
我正在为电池组定义故障。 包由一个或多个模块组成。 模块由 6 个单元组成。
我已经能够得到减去重复模块的包信息。我相信我重复的模块现在正在编码但出现错误:
Decoding failed: parent stream too short
目前我的原型是这样的
syntax = "proto2";
package TeslaBMS;
message Pack {
required int32 numberOfModules = 2;
required float currentVoltage = 3;
required float averagePacktemp = 4;
repeated Module modules = 5;
message Module {
required int32 id = 1;
required float moduleVoltage = 2;
required float moduleTemp = 3;
required float lowestCellVolt = 4;
required float highestCellVolt = 5;
// repeated Cell cells = 6;
// message Cell{
// required int32 cellId = 1;
// required float cellVolt = 2;
// required string balanceState = 3;
// }
}
}
产生这些结构定义
/* Struct definitions */
typedef struct _TeslaBMS_Pack {
int32_t numberOfModules;
float currentVoltage;
float averagePacktemp;
pb_callback_t modules;
} TeslaBMS_Pack;
typedef struct _TeslaBMS_Pack_Module {
int32_t id;
float moduleVoltage;
float moduleTemp;
float lowestCellVolt;
float highestCellVolt;
} TeslaBMS_Pack_Module;
我制作了一个 typedef 结构来保存模块数组
typedef struct{
TeslaBMS_Pack_Module modarr[MAX_MODULE_ADDR];
int listSize = 0;
}
ModuleList;
这些是构建模块数组的一些辅助函数
modulelist_add_module
用于解码,module_array_maker
用于编码
根据我能找到的示例,这是我的 encode/decode。
编码:
void encoder(){
// Setup pack message
TeslaBMS_Pack mypack = TeslaBMS_Pack_init_zero;
// stream to write buffer
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
// set deffinitions
mypack.averagePacktemp = bms.getAvgTemperature();
mypack.currentVoltage = bms.getPackVoltage();
mypack.numberOfModules = bms.getNumOfModules();
ModuleList modArr;
module_array_maker(&modArr);
// set the arg to data needed
mypack.modules.arg = &modArr;
// encode the modules
mypack.modules.funcs.encode = modules_encode;
//encode the pack
status = pb_encode(&stream, TeslaBMS_Pack_fields, &mypack);
message_length = stream.bytes_written;
if (!status) printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
}
对重复模块字段的回调进行编码
bool modules_encode(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
{
ModuleList *source = (ModuleList*)(*arg);
for(int i=0; i<bms.getNumOfModules();i++)
{
printf(" \n Mod %i is at %f \n",(int)source->modarr[i].id, source->modarr[i].moduleVoltage);
if (!pb_encode_tag_for_field(stream, field))
{
const char * error = PB_GET_ERROR(stream);
printf("encode_modules error: %s", error);
return false;
}
if (!(stream, TeslaBMS_Pack_Module_fields, &source->modarr[i]))
{
const char * error = PB_GET_ERROR(stream);
printf("SimpleMessage_encode_numbers error: %s", error);
return false;
}
}
return true;
}
解码:
void decode(){
/* Allocate space for the decoded message. */
TeslaBMS_Pack myPack = TeslaBMS_Pack_init_zero;
/* Create a stream that reads from the buffer. */
ModuleList modArr;
module_array_maker(&modArr);
myPack.modules.arg = &modArr;
myPack.modules.funcs.decode = modules_decode;
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
/* Now we are ready to decode the message. */
status = pb_decode(&stream, TeslaBMS_Pack_fields, &myPack);
/* Check for errors... */
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
}
else
{
/* Print the data contained in the message. */
printf("\n********MESSAGE FROM NANOPB!*********\n");
// printf("Number Of Modules in Pack: ", myPack.numberOfModules);
printf("Pack Voltage: %.3f\n", myPack.currentVoltage);
printf("Average Temp: %.3f\n", myPack.averagePacktemp);
printf("Number of modules: %i\n", (int)myPack.numberOfModules);
for (size_t i = 0; i < myPack.numberOfModules ; i++)
{
printf("\n ************ Module %i ************\n", modArr.modarr[i].id);
printf(" Voltage: %.3f Temperature: %.3f \n" ,modArr.modarr[i].moduleVoltage, modArr.modarr[i].moduleTemp);
}
printf("********MESSAGE FROM NANOPB!*********\n");
}
}
解码模块回调
bool modules_decode(pb_istream_t *istream, const pb_field_t *field, void **arg){
ModuleList * dest = (ModuleList*)(*arg);
TeslaBMS_Pack_Module module;
if(!pb_decode(istream, TeslaBMS_Pack_Module_fields, &module)){
const char * error = PB_GET_ERROR(istream);
printf("module_decode error: %s", error);
return false;
}
modulelist_add_module(dest, module);
return true;
}
忘记更新了。
看来我们只需要为消息多 space 一点。我们采用了预期的最大消息大小,并添加了更多字节以传递到编码器函数并将编码器函数从:void encoder()
更改为: size_t encoder(pb_byte_t *buffer, size_t length)
设置和调用编码和解码
pb_byte_t buffer[128];
size_t msg_length = encoder(buffer, sizeof(buffer));
decode(buffer, msg_length);
编码函数:
size_t encoder(pb_byte_t *buffer, size_t length) {
// Setup pack message
TeslaBMS_Pack mypack = TeslaBMS_Pack_init_zero;
// stream to write buffer
pb_ostream_t stream = pb_ostream_from_buffer(buffer, length);
// set definitions
mypack.averagePacktemp = bms.getAvgTemperature();
mypack.currentVoltage = bms.getPackVoltage();
mypack.numberOfModules = bms.getNumOfModules();
ModuleList modArr;
module_array_maker(&modArr);
mypack.modules.arg = &modArr;
mypack.modules.funcs.encode = modules_encode;
//encode the pack
bool status = pb_encode(&stream, TeslaBMS_Pack_fields, &mypack);
if (!status) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
}
printf("Encoded %d bytes\n", stream.bytes_written);
return stream.bytes_written;
}
解码函数已更改为接受 2 个参数
void decode(pb_byte_t *buffer, size_t message_length){
/* Allocate space for the decoded message. */
TeslaBMS_Pack myPack = TeslaBMS_Pack_init_zero;
ModuleList modArr;
module_array_maker(&modArr);
myPack.modules.arg = &modArr;
myPack.modules.funcs.decode = modules_decode;
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
bool status = pb_decode(&stream, TeslaBMS_Pack_fields, &myPack);
if (!status)
{
printf("Decoding failed: %s\n", PB_GET_ERROR(&stream));
return;
}
/* Print the data contained in the message. */
printf("\n********MESSAGE FROM NANOPB!*********\n");
// printf("Number Of Modules in Pack: ", myPack.numberOfModules);
printf("Pack Voltage: %.3f\n", myPack.currentVoltage);
printf("Average Temp: %.3f\n", myPack.averagePacktemp);
printf("Number of modules: %i\n", (int)myPack.numberOfModules);
for (size_t i = 0; i < myPack.numberOfModules ; i++)
{
printf("\n ************ Module %i ************\n", modArr.modarr[i].id);
printf(" Voltage: %.3f Temperature: %.3f \n" ,modArr.modarr[i].moduleVoltage, modArr.modarr[i].moduleTemp);
}
printf("********MESSAGE FROM NANOPB!*********\n");
}