Nanopb: декодирование дополнительных сообщений приводит к неправильным данным

#c #protocol-buffers #sensors #protobuf-c #nanopb

#c #буферы протокола #датчики #protobuf-c #нанопб

Вопрос:

У меня запущены различные типы датчиков, которые создают периодические события и публикуют данные в Интернете. Существует общая структура событий, содержащая информацию о датчике, и вложенное сообщение, содержащее данные, в зависимости от типа датчика. Структура событий выглядит следующим образом:

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

И конкретная структура Sensor1Event для датчика nr 1:

 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;
 

Я создал функцию обратного вызова encode pb_callback_t, которая предназначена для кодирования вложенного сообщения.

Вот мой подход:

 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 = amp;s1evt;
SEvent.sensor1_event.funcs.encode = amp;encode_sensor_data;
pb_encode(amp;stream, Event_fields, amp;SEvent);
 

Функция encode_sensor_data:

 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, amp;evt);
   
    
}
 

Как только данные отправляются и декодируются в получателе, данные вложенных сообщений являются мусором. Однако кодирование типа и адреса всегда корректно. Я совершенно не понимаю, в чем может быть причина. Любая помощь или совет будут высоко оценены!

Комментарии:

1. Это может помочь включить фактические данные (шестнадцатеричный дамп), которые вы получаете на приемнике. Затем вы можете использовать, например protoc --decode_raw , чтобы посмотреть, что в нем, и сравнить с файлом .proto.

Ответ №1:

 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, amp;evt);    
}
 

Я думаю, что ваша проблема может быть здесь. Аргумент amp;evt создаст указатель на указатель на сообщение. Однако pb_encode_submessage() ожидается получение указателя на вложенное сообщение, а не двойного указателя.

Таким образом, попробуйте просто pb_encode_submessage(stream, Sensor1Event_fields, evt) вместо этого.

К сожалению, система типов языка C не позволяет обнаружить такую ошибку во время компиляции.

Комментарии:

1. Это была абсолютная проблема … Чертовы указатели … снова достали меня. Спасибо!