1 /*
2 * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <stdint.h>
7
8 #include <zephyr/kernel.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/zbus/zbus.h>
11 LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL);
12
13 struct version_msg {
14 uint8_t major;
15 uint8_t minor;
16 uint16_t build;
17 };
18
19 struct acc_msg {
20 int x;
21 int y;
22 int z;
23 };
24
25 ZBUS_CHAN_DEFINE(version_chan, /* Name */
26 struct version_msg, /* Message type */
27
28 NULL, /* Validator */
29 NULL, /* User data */
30 ZBUS_OBSERVERS_EMPTY, /* observers */
31 ZBUS_MSG_INIT(.major = 0, .minor = 1,
32 .build = 2) /* Initial value major 0, minor 1, build 2 */
33 );
34
35 ZBUS_CHAN_DEFINE(acc_data_chan, /* Name */
36 struct acc_msg, /* Message type */
37
38 NULL, /* Validator */
39 NULL, /* User data */
40 ZBUS_OBSERVERS(foo_lis, bar_sub), /* observers */
41 ZBUS_MSG_INIT(.x = 0, .y = 0, .z = 0) /* Initial value */
42 );
43
simple_chan_validator(const void * msg,size_t msg_size)44 static bool simple_chan_validator(const void *msg, size_t msg_size)
45 {
46 ARG_UNUSED(msg_size);
47
48 const int *simple = msg;
49
50 if ((*simple >= 0) && (*simple < 10)) {
51 return true;
52 }
53
54 return false;
55 }
56
57 ZBUS_CHAN_DEFINE(simple_chan, /* Name */
58 int, /* Message type */
59
60 simple_chan_validator, /* Validator */
61 NULL, /* User data */
62 ZBUS_OBSERVERS_EMPTY, /* observers */
63 0 /* Initial value is 0 */
64 );
65
listener_callback_example(const struct zbus_channel * chan)66 static void listener_callback_example(const struct zbus_channel *chan)
67 {
68 const struct acc_msg *acc = zbus_chan_const_msg(chan);
69
70 LOG_INF("From listener -> Acc x=%d, y=%d, z=%d", acc->x, acc->y, acc->z);
71 }
72
73 ZBUS_LISTENER_DEFINE(foo_lis, listener_callback_example);
74
75 ZBUS_SUBSCRIBER_DEFINE(bar_sub, 4);
76
subscriber_task(void)77 static void subscriber_task(void)
78 {
79 const struct zbus_channel *chan;
80
81 while (!zbus_sub_wait(&bar_sub, &chan, K_FOREVER)) {
82 struct acc_msg acc;
83
84 if (&acc_data_chan == chan) {
85 zbus_chan_read(&acc_data_chan, &acc, K_MSEC(500));
86
87 LOG_INF("From subscriber -> Acc x=%d, y=%d, z=%d", acc.x, acc.y, acc.z);
88 }
89 }
90 }
91
92 K_THREAD_DEFINE(subscriber_task_id, CONFIG_MAIN_STACK_SIZE, subscriber_task, NULL, NULL, NULL, 3, 0,
93 0);
94
print_channel_data_iterator(const struct zbus_channel * chan,void * user_data)95 static bool print_channel_data_iterator(const struct zbus_channel *chan, void *user_data)
96 {
97 int *count = user_data;
98
99 LOG_INF("%d - Channel %s:", *count, zbus_chan_name(chan));
100 LOG_INF(" Message size: %d", zbus_chan_msg_size(chan));
101 LOG_INF(" Observers:");
102
103 ++(*count);
104
105 struct zbus_channel_observation *observation;
106
107 for (int16_t i = chan->data->observers_start_idx, limit = chan->data->observers_end_idx;
108 i < limit; ++i) {
109 STRUCT_SECTION_GET(zbus_channel_observation, i, &observation);
110
111 __ASSERT(observation != NULL, "observation must be not NULL");
112
113 LOG_INF(" - %s", observation->obs->name);
114 }
115
116 struct zbus_observer_node *obs_nd, *tmp;
117
118 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&chan->data->observers, obs_nd, tmp, node) {
119 LOG_INF(" - %s", obs_nd->obs->name);
120 }
121
122 return true;
123 }
124
print_observer_data_iterator(const struct zbus_observer * obs,void * user_data)125 static bool print_observer_data_iterator(const struct zbus_observer *obs, void *user_data)
126 {
127 int *count = user_data;
128
129 LOG_INF("%d - %s %s", *count,
130 obs->type == ZBUS_OBSERVER_LISTENER_TYPE ? "Listener" : "Subscriber",
131 zbus_obs_name(obs));
132
133 ++(*count);
134
135 return true;
136 }
137
main(void)138 int main(void)
139 {
140 int err, value;
141 struct acc_msg acc1 = {.x = 1, .y = 1, .z = 1};
142 const struct version_msg *v = zbus_chan_const_msg(&version_chan);
143
144 LOG_INF("Sensor sample started raw reading, version %u.%u-%u!", v->major, v->minor,
145 v->build);
146
147 int count = 0;
148
149 LOG_INF("Channel list:");
150 zbus_iterate_over_channels_with_user_data(print_channel_data_iterator, &count);
151
152 count = 0;
153
154 LOG_INF("Observers list:");
155 zbus_iterate_over_observers_with_user_data(print_observer_data_iterator, &count);
156 zbus_chan_pub(&acc_data_chan, &acc1, K_SECONDS(1));
157
158 k_msleep(1000);
159
160 acc1.x = 2;
161 acc1.y = 2;
162 acc1.z = 2;
163 zbus_chan_pub(&acc_data_chan, &(acc1), K_SECONDS(1));
164
165 value = 5;
166 err = zbus_chan_pub(&simple_chan, &value, K_MSEC(200));
167
168 if (err == 0) {
169 LOG_INF("Pub a valid value to a channel with validator successfully.");
170 }
171
172 value = 15;
173 err = zbus_chan_pub(&simple_chan, &value, K_MSEC(200));
174
175 if (err == -ENOMSG) {
176 LOG_INF("Pub an invalid value to a channel with validator successfully.");
177 }
178 return 0;
179 }
180