... | ... | @@ -287,7 +287,7 @@ Finally, we re-populate the CAN message using the newly populated `proto_msg` ie |
|
|
|
|
|
## Example - 2 : Using Callbacks for Nanopb
|
|
|
|
|
|
The source files for this example can be found [here](https://gitlab.com/sibros_public/sibros-open-source/nanopb-examples/-/tree/master/ex2)
|
|
|
The source files for this example can be found [here](https://gitlab.com/sibros_public/sibros-open-source/nanopb-examples/-/tree/master/ex2).
|
|
|
|
|
|
A CAN message usually has a 8 byte data field (if using CAN-FD the data field is 64 bytes). Thus we modify the CAN message in the `proto` file such that the CAN proto message can encode 8 bytes of data at once.
|
|
|
|
... | ... | @@ -301,7 +301,7 @@ message proto_can_message { |
|
|
}
|
|
|
```
|
|
|
|
|
|
**Note:** The `int32` data type for data_byte member has changed to `bytes` data type, which is used to allocate variable-length storage for message fields. Refer the [Scalar Value Types](https://developers.google.com/protocol-buffers/docs/overview#scalar) section for more context.
|
|
|
**Note:** The `int32` data type for data_byte member has changed to `bytes` data type, which is used to allocate variable-length storage for message fields. Refer the [Scalar Value Types](https://developers.google.com/protocol-buffers/docs/overview#scalar) section for more context on data types.
|
|
|
|
|
|
### Compiling proto files and generation of C header(.h) file
|
|
|
|
... | ... | @@ -355,7 +355,7 @@ memset(can_msgs_to_encode.data, 0x0E, sizeof(can_msgs_to_encode.data)); |
|
|
```
|
|
|
Here, the data field of CAN message has 8 bytes, and each byte is set to the value `0x0E`.
|
|
|
|
|
|
Inside the `encode_packet` function `proto_can_message *proto_msg` (ie. The generated Proto C Structure) is populated as before from the `can_message_s *can_msg`. Since `data_bytes` member is of `pb_callback_t` it is populated as follows:
|
|
|
Inside the `encode_packet` function `proto_can_message *proto_msg` (ie. The generated Proto C Structure) is populated as before from the `can_message_s *can_msg`. Since `data_bytes` member is of `pb_callback_t` type it is populated as follows:
|
|
|
|
|
|
* `proto_msg->data_byte.arg = can_msg`: The `can_msg` can now be passed as an argument to callback function and it's variable amount of data bytes (8 in this case) can be encoded.
|
|
|
* `proto_msg->data_byte.funcs.encode = &callback_encode_can_bytes` : Will hold the function pointer for the callback funtion. The callback function definition is described below.
|
... | ... | @@ -459,7 +459,7 @@ static bool callback_decode_can_bytes(pb_istream_t *istream, const pb_field_t *f |
|
|
|
|
|
The source files for this example can be found [here](https://gitlab.com/sibros_public/sibros-open-source/nanopb-examples/-/tree/master/ex3)
|
|
|
|
|
|
Consider a scenario when we need to send multiple CAN frames and some other information (for eg. software version information) to the cloud in the form of encoded data bytes.
|
|
|
Consider a scenario when we need to send multiple CAN frames, each frame containing multiple data bytes and some other information (for eg. software version information) to the cloud in the form of encoded data bytes.
|
|
|
|
|
|
For this we need to define the following `.proto` file:
|
|
|
|
... | ... | @@ -565,7 +565,18 @@ So we need to have 2 callback functions: |
|
|
|
|
|
### Encoding
|
|
|
|
|
|
We start by passing `N` number of CAN messages to `encode_packet` function. The `can_msg_count` variable passes the number of CAN messages in the `can_msg` array.
|
|
|
First, we populate the software release information and sotware version string in the `proto_message *proto_msg` using the following function:
|
|
|
|
|
|
```c
|
|
|
void populate_version_info(proto_message *proto_msg, int32_t major_version, int32_t minor_version,
|
|
|
const char *sw_version) {
|
|
|
strcpy(proto_msg->sw_version, sw_version);
|
|
|
proto_msg->release_version.major_version = major_version;
|
|
|
proto_msg->release_version.minor_version = minor_version;
|
|
|
}
|
|
|
```
|
|
|
|
|
|
Then we start by passing `N` number of CAN messages to `encode_packet` function. The `can_msg_count` variable passes the number of CAN messages in the `can_msg` array.
|
|
|
```c
|
|
|
size_t encode_packet(proto_message *proto_pkt, serial_data_packet_s *packet, can_message_s *can_msg,
|
|
|
size_t can_msg_count)
|
... | ... | @@ -671,7 +682,7 @@ To decode the array of messages we register the callback `decode_callback_can_me |
|
|
return 0;
|
|
|
}
|
|
|
```
|
|
|
The `decode_callback_can_messages` callback is invoked for EACH repeated message. It again uses Nanopb's `pb_decode()` function to decode CAN message for a single message.
|
|
|
The `decode_callback_can_messages` is invoked for EACH repeated message. This callback uses Nanopb's `pb_decode()` function to decode a single CAN message.
|
|
|
|
|
|
```c
|
|
|
static bool decode_callback_can_messages(pb_istream_t *istream, const pb_field_t *field, void **arg) {
|
... | ... | @@ -706,7 +717,7 @@ static bool decode_callback_can_messages(pb_istream_t *istream, const pb_field_t |
|
|
}
|
|
|
```
|
|
|
|
|
|
`decode_callback_can_messages()` function internally call the `callback_decode_can_bytes` callback as illustrated in the second example to encoded the 8 bytes of CAN message's data field.
|
|
|
`decode_callback_can_messages()` function internally call the `callback_decode_can_bytes` callback as illustrated in the second example to decode the 8 bytes of CAN message's data field.
|
|
|
|
|
|
```c
|
|
|
/**
|
... | ... | |