1 /*
2  * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "messages.h"
6 
7 #include <stdint.h>
8 #include <string.h>
9 
10 #include <zephyr/drivers/uart.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/net/buf.h>
14 #include <zephyr/zbus/zbus.h>
15 LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL);
16 
17 const static struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(uart1));
18 
19 ZBUS_CHAN_DECLARE(sensor_data_chan);
20 
21 ZBUS_CHAN_DEFINE(version_chan,	     /* Name */
22 		 struct version_msg, /* Message type */
23 
24 		 NULL,		       /* Validator */
25 		 NULL,		       /* User data */
26 		 ZBUS_OBSERVERS_EMPTY, /* observers */
27 		 ZBUS_MSG_INIT(.major = 0, .minor = 1,
28 			       .build = 1023) /* Initial value major 0, minor 1, build 1023 */
29 );
30 
31 static bool start_measurement_from_bridge;
32 ZBUS_CHAN_DEFINE(start_measurement_chan, /* Name */
33 		 struct action_msg,	 /* Message type */
34 
35 		 NULL,					    /* Validator */
36 		 &start_measurement_from_bridge,	    /* User data */
37 		 ZBUS_OBSERVERS(proxy_lis, peripheral_sub), /* observers */
38 		 ZBUS_MSG_INIT(false)			    /* Initial value */
39 );
40 
encoder(const struct zbus_channel * chan)41 static uint8_t encoder(const struct zbus_channel *chan)
42 {
43 	if (chan == &sensor_data_chan) {
44 		return 1;
45 	} else if (chan == &start_measurement_chan) {
46 		return 2;
47 	}
48 	return 0;
49 }
50 
decoder(uint8_t chan_idx)51 static const struct zbus_channel *decoder(uint8_t chan_idx)
52 {
53 	if (chan_idx == 1) {
54 		return &sensor_data_chan;
55 	} else if (chan_idx == 2) {
56 		return &start_measurement_chan;
57 	}
58 	return NULL;
59 }
60 
proxy_callback(const struct zbus_channel * chan)61 static void proxy_callback(const struct zbus_channel *chan)
62 {
63 	bool *generated_by_the_bridge = zbus_chan_user_data(chan);
64 
65 	if (*generated_by_the_bridge) {
66 		LOG_DBG("discard loopback event (channel %s)", zbus_chan_name(chan));
67 
68 		*generated_by_the_bridge = false;
69 	} else {
70 		uart_poll_out(uart_dev, '$');
71 
72 		uart_poll_out(uart_dev, encoder(chan));
73 
74 		for (int i = 0; i < zbus_chan_msg_size(chan); ++i) {
75 			uart_poll_out(uart_dev, ((unsigned char *)zbus_chan_const_msg(chan))[i]);
76 		}
77 
78 		uart_poll_out(uart_dev, '*');
79 
80 		LOG_DBG("sending message to host (channel %s)", zbus_chan_name(chan));
81 	}
82 }
83 
84 ZBUS_LISTENER_DEFINE(proxy_lis, proxy_callback);
85 
main(void)86 int main(void)
87 {
88 	LOG_DBG("[Mock Proxy] Started.");
89 	return 0;
90 }
91 
decode_sentence(struct net_buf_simple * rx_buf)92 static void decode_sentence(struct net_buf_simple *rx_buf)
93 {
94 	if (rx_buf->len <= 1) {
95 		LOG_DBG("[Mock Proxy RX] Discard invalid sequence");
96 		/* '*' indicates the end of a sentence. Sometimes it is
97 		 * necessary to flush more than on ensure sending it from
98 		 * the python script. The code must discard when there is no
99 		 * other data at the buffer.
100 		 */
101 	} else {
102 		if ('$' == net_buf_simple_pull_u8(rx_buf)) {
103 			LOG_DBG("[Mock Proxy RX] Found sentence");
104 
105 			const struct zbus_channel *chan = decoder(net_buf_simple_pull_u8(rx_buf));
106 
107 			__ASSERT_NO_MSG(chan != NULL);
108 
109 			if (!zbus_chan_claim(chan, K_MSEC(250))) {
110 				memcpy(zbus_chan_msg(chan),
111 				       net_buf_simple_pull_mem(rx_buf, zbus_chan_msg_size(chan)),
112 				       zbus_chan_msg_size(chan));
113 
114 				bool *generated_by_the_bridge = zbus_chan_user_data(chan);
115 				*generated_by_the_bridge = true;
116 
117 				zbus_chan_finish(chan);
118 
119 				LOG_DBG("Publishing channel %s", zbus_chan_name(chan));
120 
121 				zbus_chan_notify(chan, K_MSEC(500));
122 			}
123 		}
124 		net_buf_simple_init(rx_buf, 0);
125 	}
126 }
127 
mock_proxy_rx_thread(void)128 static void mock_proxy_rx_thread(void)
129 {
130 	LOG_DBG("[Mock Proxy RX] Started.");
131 
132 	uint8_t byte;
133 	struct net_buf_simple *rx_buf = NET_BUF_SIMPLE(64);
134 
135 	net_buf_simple_init(rx_buf, 0);
136 
137 	while (1) {
138 		while (uart_poll_in(uart_dev, &byte) < 0) {
139 			/* Allow other thread/workqueue to work. */
140 			k_msleep(50);
141 		}
142 		if (byte == '*') {
143 			decode_sentence(rx_buf);
144 		} else {
145 			net_buf_simple_add_u8(rx_buf, byte);
146 		}
147 	}
148 }
149 
150 K_THREAD_DEFINE(mock_proxy_rx_thread_tid, 2048, mock_proxy_rx_thread, NULL, NULL, NULL, 5, 0, 1500);
151