1 /*
2  * Copyright (c) 2011 Petteri Aimonen
3  * Copyright (c) 2021 Basalte bv
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/printk.h>
10 
11 #include <pb_encode.h>
12 #include <pb_decode.h>
13 #include "src/simple.pb.h"
14 
encode_message(uint8_t * buffer,size_t buffer_size,size_t * message_length)15 bool encode_message(uint8_t *buffer, size_t buffer_size, size_t *message_length)
16 {
17 	bool status;
18 
19 	/* Allocate space on the stack to store the message data.
20 	 *
21 	 * Nanopb generates simple struct definitions for all the messages.
22 	 * - check out the contents of simple.pb.h!
23 	 * It is a good idea to always initialize your structures
24 	 * so that you do not have garbage data from RAM in there.
25 	 */
26 	SimpleMessage message = SimpleMessage_init_zero;
27 
28 	/* Create a stream that will write to our buffer. */
29 	pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
30 
31 	/* Fill in the lucky number */
32 	message.lucky_number = 13;
33 	for (int i = 0; i < CONFIG_SAMPLE_BUFFER_SIZE; ++i) {
34 		message.buffer[i] = (uint8_t)(i * 2);
35 	}
36 #ifdef CONFIG_SAMPLE_UNLUCKY_NUMBER
37 	message.unlucky_number = 42;
38 #endif
39 
40 	/* Now we are ready to encode the message! */
41 	status = pb_encode(&stream, SimpleMessage_fields, &message);
42 	*message_length = stream.bytes_written;
43 
44 	if (!status) {
45 		printk("Encoding failed: %s\n", PB_GET_ERROR(&stream));
46 	}
47 
48 	return status;
49 }
50 
decode_message(uint8_t * buffer,size_t message_length)51 bool decode_message(uint8_t *buffer, size_t message_length)
52 {
53 	bool status;
54 
55 	/* Allocate space for the decoded message. */
56 	SimpleMessage message = SimpleMessage_init_zero;
57 
58 	/* Create a stream that reads from the buffer. */
59 	pb_istream_t stream = pb_istream_from_buffer(buffer, message_length);
60 
61 	/* Now we are ready to decode the message. */
62 	status = pb_decode(&stream, SimpleMessage_fields, &message);
63 
64 	/* Check for errors... */
65 	if (status) {
66 		/* Print the data contained in the message. */
67 		printk("Your lucky number was %d!\n", (int)message.lucky_number);
68 		printk("Buffer contains: ");
69 		for (int i = 0; i < CONFIG_SAMPLE_BUFFER_SIZE; ++i) {
70 			printk("%s%d", ((i == 0) ? "" : ", "), (int) message.buffer[i]);
71 		}
72 		printk("\n");
73 #ifdef CONFIG_SAMPLE_UNLUCKY_NUMBER
74 		printk("Your unlucky number was %d!\n", (int)message.unlucky_number);
75 #endif
76 	} else {
77 		printk("Decoding failed: %s\n", PB_GET_ERROR(&stream));
78 	}
79 
80 	return status;
81 }
82 
main(void)83 int main(void)
84 {
85 	/* This is the buffer where we will store our message. */
86 	uint8_t buffer[SimpleMessage_size];
87 	size_t message_length;
88 
89 	/* Encode our message */
90 	if (!encode_message(buffer, sizeof(buffer), &message_length)) {
91 		return 0;
92 	}
93 
94 	/* Now we could transmit the message over network, store it in a file or
95 	 * wrap it to a pigeon's leg.
96 	 */
97 
98 	/* But because we are lazy, we will just decode it immediately. */
99 	decode_message(buffer, message_length);
100 	return 0;
101 }
102