#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. Это была абсолютная проблема … Чертовы указатели … снова достали меня. Спасибо!