/* * Copyright (c) 2022 Rodrigo Peixoto * SPDX-License-Identifier: Apache-2.0 */ #include "messages.h" #include #include #include #include #include #include #include LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL); const static struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(uart1)); ZBUS_CHAN_DECLARE(sensor_data_chan); ZBUS_CHAN_DEFINE(version_chan, /* Name */ struct version_msg, /* Message type */ NULL, /* Validator */ NULL, /* User data */ ZBUS_OBSERVERS_EMPTY, /* observers */ ZBUS_MSG_INIT(.major = 0, .minor = 1, .build = 1023) /* Initial value major 0, minor 1, build 1023 */ ); static bool start_measurement_from_bridge; ZBUS_CHAN_DEFINE(start_measurement_chan, /* Name */ struct action_msg, /* Message type */ NULL, /* Validator */ &start_measurement_from_bridge, /* User data */ ZBUS_OBSERVERS(proxy_lis, peripheral_sub), /* observers */ ZBUS_MSG_INIT(false) /* Initial value */ ); static uint8_t encoder(const struct zbus_channel *chan) { if (chan == &sensor_data_chan) { return 1; } else if (chan == &start_measurement_chan) { return 2; } return 0; } static const struct zbus_channel *decoder(uint8_t chan_idx) { if (chan_idx == 1) { return &sensor_data_chan; } else if (chan_idx == 2) { return &start_measurement_chan; } return NULL; } static void proxy_callback(const struct zbus_channel *chan) { bool *generated_by_the_bridge = zbus_chan_user_data(chan); if (*generated_by_the_bridge) { LOG_DBG("discard loopback event (channel %s)", zbus_chan_name(chan)); *generated_by_the_bridge = false; } else { uart_poll_out(uart_dev, '$'); uart_poll_out(uart_dev, encoder(chan)); for (int i = 0; i < zbus_chan_msg_size(chan); ++i) { uart_poll_out(uart_dev, ((unsigned char *)zbus_chan_const_msg(chan))[i]); } uart_poll_out(uart_dev, '*'); LOG_DBG("sending message to host (channel %s)", zbus_chan_name(chan)); } } ZBUS_LISTENER_DEFINE(proxy_lis, proxy_callback); int main(void) { LOG_DBG("[Mock Proxy] Started."); return 0; } static void decode_sentence(struct net_buf_simple *rx_buf) { if (rx_buf->len <= 1) { LOG_DBG("[Mock Proxy RX] Discard invalid sequence"); /* '*' indicates the end of a sentence. Sometimes it is * necessary to flush more than on ensure sending it from * the python script. The code must discard when there is no * other data at the buffer. */ } else { if ('$' == net_buf_simple_pull_u8(rx_buf)) { LOG_DBG("[Mock Proxy RX] Found sentence"); const struct zbus_channel *chan = decoder(net_buf_simple_pull_u8(rx_buf)); __ASSERT_NO_MSG(chan != NULL); if (!zbus_chan_claim(chan, K_MSEC(250))) { memcpy(zbus_chan_msg(chan), net_buf_simple_pull_mem(rx_buf, zbus_chan_msg_size(chan)), zbus_chan_msg_size(chan)); bool *generated_by_the_bridge = zbus_chan_user_data(chan); *generated_by_the_bridge = true; zbus_chan_finish(chan); LOG_DBG("Publishing channel %s", zbus_chan_name(chan)); zbus_chan_notify(chan, K_MSEC(500)); } } net_buf_simple_init(rx_buf, 0); } } static void mock_proxy_rx_thread(void) { LOG_DBG("[Mock Proxy RX] Started."); uint8_t byte; struct net_buf_simple *rx_buf = NET_BUF_SIMPLE(64); net_buf_simple_init(rx_buf, 0); while (1) { while (uart_poll_in(uart_dev, &byte) < 0) { /* Allow other thread/workqueue to work. */ k_msleep(50); } if (byte == '*') { decode_sentence(rx_buf); } else { net_buf_simple_add_u8(rx_buf, byte); } } } K_THREAD_DEFINE(mock_proxy_rx_thread_tid, 2048, mock_proxy_rx_thread, NULL, NULL, NULL, 5, 0, 1500);