You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Wrapper for structuring and sending protobuf Ethernet messages over MQTT.
7
+
* This API sits above the lower-level u_nx_ethernet.h driver layer. Messages with nonstandard formats can still be sent using the u_nx_ethernet.h API directly.
8
+
*/
9
+
10
+
#include<stddef.h>
11
+
#include<stdbool.h>
12
+
#include"serverdata.pb.h"
13
+
14
+
/* Helper macros. */
15
+
#definePB_STR_HELPER(x) #x // Helper for PB_TOSTR(). Probably should never use directly.
16
+
#definePB_TOSTR(x) PB_STR_HELPER(x) // Converts a macro's value into a string.
17
+
#definePB_COUNT_ARGS(...) (sizeof((float[]){ __VA_ARGS__ }) / sizeof(float)) // Returns the number of arguments passed into it.
18
+
#definePB_STR_LEN(s) (sizeof(s) - 1) // Returns the length of a string literal.
19
+
20
+
/* CONFIG: Compile-time validation of topic size, unit size, and number of values. */
21
+
#definePB_MAX_TOPIC_LENGTH 100 // Maximum length of topic string literal (in characters).
22
+
#definePB_MAX_UNIT_LENGTH 15 // Maximum length of unit string literal (in characters).
23
+
#definePB_MIN_DATAPOINTS 1 // Minimum number of datapoints (i.e., variable `...` arguments passed into `nx_protobuf_mqtt_message_create()`).
24
+
#definePB_MAX_DATAPOINTS 5 // Maximum number of datapoints (i.e., variable `...` arguments passed into `nx_protobuf_mqtt_message_create()`).
25
+
#definePB_VALIDATE_ARGS(topic, unit, num_values) \
26
+
do { \
27
+
_Static_assert( \
28
+
PB_STR_LEN(topic) <= PB_MAX_TOPIC_LENGTH, \
29
+
"MQTT topic parameter exceeds maximum length of " PB_TOSTR(PB_MAX_TOPIC_LENGTH) " allowed by `nx_protobuf_mqtt_message_create()`."\
30
+
); \
31
+
_Static_assert( \
32
+
PB_STR_LEN(unit) <= PB_MAX_UNIT_LENGTH, \
33
+
"MQTT unit parameter exceeds maximum length of " PB_TOSTR(PB_MAX_UNIT_LENGTH) " allowed by `nx_protobuf_mqtt_message_create()`." \
34
+
); \
35
+
_Static_assert( \
36
+
(num_values) >= PB_MIN_DATAPOINTS, \
37
+
"Must pass at least " PB_TOSTR(PB_MIN_DATAPOINTS) " value into the variable argument of `nx_protobuf_mqtt_message_create()`." \
38
+
); \
39
+
_Static_assert( \
40
+
(num_values) <= PB_MAX_DATAPOINTS, \
41
+
"Cannot pass more than " PB_TOSTR(PB_MAX_DATAPOINTS) " values into the variable argument of `nx_protobuf_mqtt_message_create()`." \
42
+
); \
43
+
} while (0)
44
+
45
+
/**
46
+
* @brief Creates and formats a `ethernet_mqtt_message_t` object, and returns it to the caller.
* @param unit (const char*) String literal representing the unit of the message's data.
49
+
* @param ... (float) The data to be sent in the message. This is a variable argument, so it can be repeated depending on how many datapoints you want to send. If you pass in more datapoints than allowed, you will get a compile-time error.
50
+
* @return An `ethernet_mqtt_message_t` object.
51
+
* @note If message creation was not completed for any reason, .initialized will be false in the returned `ethernet_mqtt_message_t` object. You may still use the object as you please (including attempting to initialize it again), but attempting to send the message (via `nx_protobuf_mqtt_message_send()`) will return an error.
52
+
*/
53
+
#definenx_protobuf_mqtt_message_create(topic, unit, ...) \
54
+
({ \
55
+
PB_VALIDATE_ARGS(topic, unit, PB_COUNT_ARGS(__VA_ARGS__)); \
56
+
_nx_protobuf_mqtt_message_create( \
57
+
(topic), PB_STR_LEN(topic), \
58
+
(unit), PB_STR_LEN(unit), \
59
+
(float[]){ __VA_ARGS__ }, \
60
+
PB_COUNT_ARGS(__VA_ARGS__) \
61
+
); \
62
+
})
63
+
64
+
65
+
/* Ethernet MQTT Message. */
66
+
typedefstruct {
67
+
constchar*topic;
68
+
inttopic_size;
69
+
serverdata_v2_ServerDataprotobuf;
70
+
boolinitialized;
71
+
} ethernet_mqtt_message_t;
72
+
73
+
/**
74
+
* @brief Dispatches a `ethernet_mqtt_message_t` message over MQTT.
75
+
* @param message The message to send.
76
+
* @return U_SUCCESS if successful, U_ERROR is not successful.
// NOTE: If using the `nx_protobuf_mqtt_message_create()` macro (as intended), the static asserts should catch this. This is just an extra check in case a caller uses this function directly for whatever reason.
23
+
24
+
/* Enforce unit length. */
25
+
if(unit_len>PB_MAX_UNIT_LENGTH) {
26
+
PRINTLN_ERROR("MQTT Unit string length exceeds maximum length of %d (Topic: %s, Current Unit String Length: %d).", PB_MAX_UNIT_LENGTH, topic, unit_len);
// NOTE: If using the `nx_protobuf_mqtt_message_create()` macro (as intended), the static asserts should catch this. This is just an extra check in case a caller uses this function directly for whatever reason.
30
+
31
+
/* Enforce minimum number of datapoints. */
32
+
if(values_size<PB_MIN_DATAPOINTS) {
33
+
PRINTLN_ERROR("Message must have at least %d datapoints (Topic: %s, Current values_size: %d).", PB_MIN_DATAPOINTS, topic, values_size);
// NOTE: If using the `nx_protobuf_mqtt_message_create()` macro (as intended), the static asserts should catch this. This is just an extra check in case a caller uses this function directly for whatever reason.
37
+
38
+
/* Enforce maximum number of datapoints. */
39
+
if(values_size>PB_MAX_DATAPOINTS) {
40
+
PRINTLN_ERROR("Message cannot have more than %d datapoints (Topic: %s, Current values_size: %d).", PB_MAX_DATAPOINTS, topic, values_size);
// NOTE: If using the `nx_protobuf_mqtt_message_create()` macro (as intended), the static asserts should catch this. This is just an extra check in case a caller uses this function directly for whatever reason.
44
+
45
+
/* Get the PTP time and convert to appropriate protobuf time. */
/* Pack the `ethernet_mqtt_message_t` object and return it as successfully initialized. */
70
+
message.topic=topic;
71
+
message.topic_size=topic_len+1; // u_TODO - for some reason you need to do + 1 here or else it will cut the last letter off of the topic in MQTT ui. The macro probably just calculates the topic length with one less than it should or something
0 commit comments