Nanopb: Submessage decoding results in incorrect data

546 views Asked by At

I have various sensor types running, creating periodic events and publishing the data online. There's an overall event structure containing information about the sensor and a submessage containing data depending on what type of sensor it is. The event structure looks like this:

typedef struct _Event {
    PayloadType type;
    pb_callback_t address;
    pb_size_t which_payload;
    union {
        UnknownEvent unknown_event;
        Sensor1Event sensor1_event;
    } payload;
} Event;

And the specific Sensor1Event for sensor nr 1 structure:

typedef struct _Sensor1Event {
    uint64_t device_id;
    uint64_t time;
    Sensor1EventType type;
    uint16_t lux;
    uint16_t co2;
    uint16_t voc;
    uint8_t mic;
    uint8_t temp;
    uint8_t humidity;
    uint16_t in_count;
    uint16_t out_count;
    int16_t aggregated_count;
} Sensor1Event;

I created an encode pb_callback_t callback function that aims to encode the submessage.

Here's my approach:

Event SEvent = Event_init_zero;
Sensor1Event s1evt = {0,0,0, 0, 0,0,temp_processed, 0,0,0,0}; //fill with dummy vals for now
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));

... ...

SEvent.address = adr; //predetermined address assigned here
SEvent.type = PayloadType_Sensor1; // predefined value here
SEvent.sensor1_event.arg = &s1evt;
SEvent.sensor1_event.funcs.encode = &encode_sensor_data;
pb_encode(&stream, Event_fields, &SEvent);

The encode_sensor_data function:

bool encode_data(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
{
  
    Sensor1Event * evt = (Sensor1Event *)(*arg);
 
  

    if (!pb_encode_tag_for_field(stream, field))
        return false;

    
    return pb_encode_submessage(stream, Sensor1Event_fields, &evt);
   
    
}

Once the data gets sent and decoded at the receiver, the submessage data is garbage. The encoding of the type and address is always correct however. I'm completely lost as to what the cause might be. Any help or advise would be much appreciated!

1

There are 1 answers

1
jpa On BEST ANSWER
bool encode_data(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg)
{  
    Sensor1Event * evt = (Sensor1Event *)(*arg);
    .....
    return pb_encode_submessage(stream, Sensor1Event_fields, &evt);    
}

I think your problem might be here. The argument &evt will create a pointer to the pointer to the message. However, pb_encode_submessage() expects to receive a pointer to the submessage, not a double-pointer.

Thus, try just pb_encode_submessage(stream, Sensor1Event_fields, evt) instead.

It is unfortunate that C language's type system does not allow detecting such a mistake at compile time.