mongoose/examples/uart-bridge/net.c
2022-06-08 13:22:09 +01:00

111 lines
3.7 KiB
C

// Copyright (c) 2022 Cesanta Software Limited
// All rights reserved
#include "mongoose.h"
static const char *s_tcp_url = "tcp://0.0.0.0:4001";
static const char *s_ws_url = "ws://0.0.0.0:4002";
static struct mg_connection *s_tcp_conn;
static struct mg_connection *s_ws_conn;
static int s_rx = 4;
static int s_tx = 5;
static int s_baud = 115200;
// Let users define their own UART API. If they don't, use a dummy one
#if defined(UART_API_IMPLEMENTED)
#else
void uart_init(int tx, int rx, int baud) {
// We use stdin/stdout as UART. Make stdin non-blocking
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
(void) tx, (void) rx, (void) baud;
}
void uart_write(const void *buf, size_t len) {
fwrite(buf, 1, len, stdout); // Write to stdout
fflush(stdout);
}
int uart_read(char *buf, size_t len) {
return read(0, buf, len); // Read from stdin
}
#endif
// Event handler for a connected Websocket client
static void ws_fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_HTTP_MSG) {
mg_ws_upgrade(c, evd, NULL);
} else if (ev == MG_EV_WS_OPEN) {
// c->is_hexdumping = 1;
c->label[0] = 'W'; // When WS handhake is done, mark us as WS client
} else if (ev == MG_EV_WS_MSG) {
struct mg_ws_message *wm = (struct mg_ws_message *) evd;
uart_write(wm->data.ptr, wm->data.len); // Send to UART
c->recv.len = 0; // Discard received data
} else if (ev == MG_EV_CLOSE) {
if (c->is_listening) s_ws_conn = NULL;
}
(void) fnd;
}
// Event handler for a connected TCP client
static void tcp_fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_OPEN) {
// c->is_hexdumping = 1;
c->label[0] = 'T'; // When client is connected, mark us as TCP client
} else if (ev == MG_EV_READ) {
uart_write(c->recv.buf, c->recv.len); // Send to UART
c->recv.len = 0; // Discard received data
} else if (ev == MG_EV_CLOSE) {
if (c->is_listening) s_tcp_conn = NULL;
}
(void) fnd, (void) evd;
}
// Software timer with a frequency close to the scheduling time slot
static void timer_fn(void *param) {
// Start listeners if they're stopped for any reason
struct mg_mgr *mgr = (struct mg_mgr *) param;
if (s_tcp_conn == NULL) s_tcp_conn = mg_listen(mgr, s_tcp_url, tcp_fn, 0);
if (s_ws_conn == NULL) s_ws_conn = mg_http_listen(mgr, s_ws_url, ws_fn, 0);
// Read UART
char buf[512];
int len = uart_read(buf, sizeof(buf));
if (len > 0) {
// Iterate over all connections. Send data to WS and TCP clients
for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
if (c->label[0] == 'W') mg_ws_send(c, buf, len, WEBSOCKET_OP_TEXT);
if (c->label[0] == 'T') mg_send(c, buf, len);
}
}
}
// HTTP request handler function
void uart_bridge_fn(struct mg_connection *c, int ev, void *ev_data,
void *fn_data) {
if (ev == MG_EV_OPEN && c->is_listening) {
mg_timer_add(c->mgr, 20, MG_TIMER_REPEAT, timer_fn, c->mgr);
uart_init(s_tx, s_rx, s_baud);
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/api/hi")) {
mg_http_reply(c, 200, "", "hi\n"); // Testing endpoint
} else if (mg_http_match_uri(hm, "/api/config/get")) {
mg_http_reply(
c, 200, "Content-Type: application/json\r\n",
"{\"tcp\":\"%s\",\"ws\":\"%s\",\"rx\":%d,\"tx\":%d,\"baud\":%d}\n",
s_tcp_url, s_ws_url, s_rx, s_tx, s_baud);
} else {
struct mg_http_serve_opts opts = {0};
#if 1
opts.root_dir = "/web_root";
opts.fs = &mg_fs_packed;
#else
opts.root_dir = "web_root";
#endif
mg_http_serve_dir(c, ev_data, &opts);
}
}
(void) fn_data;
}