With this settings.proto
file
syntax = "proto3";
message SerialPort
{
int32 baudrate = 3;
}
message Settings
{
SerialPort serialInterface = 1;
int32 test = 2;
}
I try to encode a message that only has the baudrate set with this:
#include "Arduino.h"
#include <stdio.h>
#include <stdlib.h>
#include "settings.pb.h"
#include <pb_encode.h>
#include <pb_decode.h>
#include <pb_common.h>
#include <pb.h>
void setup() {
// Create a Settings message with a non-zero baudrate
Settings settings = Settings_init_zero;
settings.serialInterface.baudrate = 9600;
// Allocate a buffer to hold the encoded message
uint8_t buffer[Settings_size] = {0};
// Encode the message into the buffer
pb_ostream_t stream = pb_ostream_from_buffer(buffer, Settings_size);
pb_encode(&stream, Settings_fields, &settings);
printf("written %d\r\n", stream.bytes_written);
// Print the contents of the buffer (for debugging purposes)
for (int i = 0; i < Settings_size; i++)
{
printf("%X ", buffer[i]);
}
printf("\n");
delay(100000);
}
void loop(){}
I expected an encoded array, but I get the following output:
written 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
If I add settings.test = 1000;
to the code, I get the output:
written 3
10 E8 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Testing with Python, I get the same 3 bytes output with a message that only has the test:
import settings_pb2
import google.protobuf.message
from google.protobuf.json_format import MessageToJson
from cobs import cobs
import binascii
import base64
s = project_settings_pb2.Settings()
s.test = 1000
print(MessageToJson(s))
try:
s_pb_encoded = s.SerializeToString()
except google.protobuf.message.EncodeError as e:
log.exception(e)
exit(1)
print(f"encoded {(''.join(f'0x{c:02x} ' for c in s_pb_encoded))}")
and if I add s.serialInterface.baudrate = 9600
i get
{
"test": 1000,
"serialInterface": {
"baudrate": 9600
}
}
encoded 0x10 0xe8 0x07 0x52 0x03 0x18 0x80 0x4b
So it looks like the way I encode with Nanopb does not include submessages. What am I doing wrong?
Submessage fields have a separate boolean has_field
that determines whether the submessage is present. You need to set it to true
.