encode/decode of repeated nested field

172 views
Skip to first unread message

Ahren Swett

unread,
Feb 9, 2021, 2:11:47 PM2/9/21
to nanopb
Thanks for reading I have had a bear of a time trying to encode a nested message. I have gotten the first message to encode/ decode but the callback is kicking my butt. here is 
----------------------------------------------------------------------------------------------------------------------------------
my protofile
----------------------------------------------------------------------------------------------------------------------------------
syntax = "proto2";
package TeslaBMS;

message Pack {
   required int32 numberOfModules = 3;
   required float currentVoltage = 4;
   required float averagePacktemp = 5;
   repeated Module modules = 6;

     message Module {
        required int32 id = 1;
        required float moduleVoltage = 2;
        required float moduleTemp = 3;
        required float lowestCellVolt = 4;
        required float highestCellVolt = 5;
     }
}
----------------------------------------------------------------------------------------------------------------------------------
Structs Created
----------------------------------------------------------------------------------------------------------------------------------
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;
----------------------------------------------------------------------------------------------------------------------------------
My encode is
----------------------------------------------------------------------------------------------------------------------------------
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();

// ?????? I know I have to get the data and pass it in,
// but not sure how to pass it from this array ???????
BMSModule moduleArray[(bms.getNumOfModules())];
for (int i = 0; i < bms.getNumOfModules(); i++)
   {
       moduleArray[i] = bms.getModules(i);
   }. 
// set the arg to data needed
mypack.modules.arg = &moduleArray;
// encode the modules
mypack.modules.funcs.encode = write_modules;
//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));
----------------------------------------------------------------------------------------------------------------------------------
My Callback
----------------------------------------------------------------------------------------------------------------------------------
bool write_modules(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
{
TeslaBMS_Pack_Module mod = TeslaBMS_Pack_Module_init_default;
// Not sure how to set a dynamic id here based on the module # being encoded.
printf("index %i \n",(int)(field->index));
mod.id = (int)(field->index);
mod.highestCellVolt= bms.getModules(field->index).getHighestCellVolt();
mod.lowestCellVolt= bms.getModules(field->index).getLowestCellVolt();
mod.moduleTemp=bms.getModules(field->index).getTemperature();
mod.moduleVoltage = bms.getModules(field->index).getModuleVoltage();
// this prints but is always the last module value I'm guessing the (int)(field->index) is not returning the current index but last as it always lines up with the total# of modules
printf(" \n Mod %i is at %f \n",(int)mod.id, mod.moduleVoltage);
if (!pb_encode_tag_for_field(stream, field))  return false;
//not sure this is right either.
return pb_encode_submessage(stream, &TeslaBMS_Pack_Module_msg, &mod);
}
----------------------------------------------------------------------------------------------------------------------------------
My decode 
----------------------------------------------------------------------------------------------------------------------------------
void decode(){
TeslaBMS_Pack myPack = TeslaBMS_Pack_init_zero;
pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
status = pb_decode(&stream, TeslaBMS_Pack_fields, &myPack);
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 (int i=0; i <(int)myPack.numberOfModules;i++)
      {
         
         printf("\n myPack.modules \n");
       }
printf("********MESSAGE FROM NANOPB!*********\n");
}
}
----------------------------------------------------------------------------------------------------------------------------------

I know I need a decode call back but so stuck 


Ahren Swett

unread,
Feb 9, 2021, 7:46:01 PM2/9/21
to nanopb
have made some changes to encode / decode the error I am now getting is that the parent stream is to short. this is coming from decode. as far as I can tell encode is working properly.

typedef struct{
TeslaBMS_Pack_Module modarr[MAX_MODULE_ADDR];
int listSize = 0;
}
ModuleList;

// add module to list
void modulelist_add_module(ModuleList * modList, TeslaBMS_Pack_Module module) {
if (modList->listSize < MAX_MODULE_ADDR) {
modList->modarr[modList->listSize] = module;
modList->listSize++;
}
}

void module_array_maker(ModuleList *list){
for (int i = 1; i <= bms.getNumOfModules(); i++) {
TeslaBMS_Pack_Module myModule = TeslaBMS_Pack_Module_init_zero;

BMSModule thisTestModule = bms.getModules(i);

myModule.id = i;
myModule.moduleVoltage = thisTestModule.getModuleVoltage();
myModule.moduleTemp = thisTestModule.getTemperature();
myModule.lowestCellVolt = thisTestModule.getLowestCellVolt();
myModule.highestCellVolt = thisTestModule.getHighestCellVolt();
list->modarr[i-1] = myModule;
}
}


/* Module encode callback */
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;
}


/* Decode module callback*/
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;
}

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();

printf("There will be %i modules for this test",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));
}

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);
Reply all
Reply to author
Forward
0 new messages