ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
gateway.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_GATEWAY_H
5#define PROTOCORE_GATEWAY_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file gateway.h
13 * @brief Radio / wireless gateway bridge (PROTOCORE_ENABLE_GATEWAY) - the v5 southbound-to-
14northbound bridge.
15 *
16 * The generic gateway pattern that ties the hardware-ingest pipeline to the web stack. A
17 * southbound radio (LoRa / nRF24 / CC1101 / Zigbee / Z-Wave / ... reached over SPI / I2C /
18 * UART) is a **port**. When it receives a frame - the data-ready ISR reads it over DMA
19 * (mmgr/dma), posts it onto the FORWARD lane (services/system/preempt_queue), and a per-radio
20 * codec extracts the source node address and payload - you call protocore_gateway_uplink(). The
21 * gateway **envelopes** the frame (source address, port, RSSI, a sequence number) and
22 * **publishes it northbound** through the uplink callback, which you wire to MQTT / HTTP /
23 * WebSocket / UDP. A northbound command runs the other way through protocore_gateway_downlink() to the
24 * port's transmit callback (the radio's SPI / UART write).
25 *
26 * The radio transmit and the northbound publish are **callbacks** - the seam a real radio
27 * driver and a real protocol binding plug into - so the bridge is fully host- and
28 * device-testable with no radio hardware (the tests / example supply capturing callbacks
29 * and feed simulated frames). This is the northbound half; the DMA + FORWARD lane carry the
30 * bytes, and each radio's frame format is its own codec.
31 *
32 * Per-port uplink rate cap (fail-closed), a routing-key helper (protocore_gateway_topic() formats
33 * `<prefix>/<port>/<addr>`), and static tables (zero heap): PROTOCORE_GW_MAX_PORTS ports.
34 *
35 * @c work is PROTOCORE_GATEWAY_BORROW bytes the CALLER took, at an address it knows. It is not held past the call, so
36nothing here aliases it. How those bytes are
37 * carved is this module's and is never named here.
38 *
39 * @author Douglas Quigg (dstroy0)
40 * @date 2026
41 */
42
43/** @brief Southbound radio / bus kind a port bridges (informational + topic hint). */
59
60/**
61 * @brief A northbound message: a southbound frame enveloped with its routing metadata.
62 * @ref payload points at the caller's bytes and is valid only for the duration of
63 * the uplink callback - copy what you publish asynchronously.
64 */
65typedef struct
66{
67 const uint8_t *payload; ///< frame payload bytes
68 uint32_t seq; ///< per-gateway uplink sequence (wraps)
69 uint16_t len; ///< payload length
70 uint16_t src_addr; ///< source node address on the radio
71 int16_t rssi; ///< received signal strength (0 if the driver has none)
72 uint8_t port_id; ///< the port the frame arrived on
73 protocore_gateway_kind kind; ///< protocore_gateway_kind of that port
75
76/**
77 * @brief Northbound publish: emit @p msg to MQTT / HTTP / WebSocket / UDP.
78 * @return true if the northbound stack accepted it; false drops (counted).
79 */
81
82/**
83 * @brief Southbound transmit (downlink): send @p payload to @p dst_addr on @p port_id.
84 * @return true if the radio accepted the frame; false drops (counted).
85 */
86typedef proto_bool (*protocore_gateway_tx_fn)(uint8_t port_id, uint16_t dst_addr, const uint8_t *payload, uint16_t len,
87 void *ctx);
88
89/** @brief Southbound port (radio / bus) configuration passed to protocore_gateway_add_port(). */
90typedef struct
91{
92 uint8_t port_id; ///< caller-assigned id (used in topics and up/down-link calls).
93 protocore_gateway_kind kind; ///< protocore_gateway_kind.
94 protocore_gateway_tx_fn tx; ///< downlink transmit (may be null for a receive-only port).
95 void *ctx; ///< opaque, forwarded to @ref tx.
96 uint16_t rate_cap; ///< max uplink frames/second from this port (0 = unlimited).
98
99/** @brief Gateway counters (monotonic since the last protocore_gateway_reset()). */
100typedef struct
101{
102 uint32_t up_in; ///< protocore_gateway_uplink() calls
103 uint32_t up_published; ///< frames the uplink callback accepted
104 uint32_t up_dropped; ///< uplinks dropped (rate cap / no sink / refused / bad port)
105 uint32_t down_in; ///< protocore_gateway_downlink() calls
106 uint32_t down_sent; ///< downlinks the port transmit accepted
107 uint32_t down_dropped; ///< downlinks dropped (bad port / no tx / refused)
109
110/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
111typedef struct
112{
113 void (*reset)(uint8_t *);
114 proto_bool (*add_port)(uint8_t *, const protocore_gateway_port_config *);
115 void (*set_uplink_cb)(uint8_t *, protocore_gateway_uplink_fn, void *);
116 void (*set_topic_prefix)(uint8_t *, const char *);
117 proto_bool (*uplink)(uint8_t *, uint8_t, uint16_t, const uint8_t *, uint16_t, int16_t);
118 proto_bool (*downlink)(uint8_t *, uint8_t, uint16_t, const uint8_t *, uint16_t);
119 uint16_t (*topic)(uint8_t *, const protocore_gateway_msg *, char *, uint16_t);
120 void (*get_stats)(uint8_t *, protocore_gateway_stats *);
121} GatewayNs;
122PROTOCORE_NS_LAYOUT(GatewayNs, reset, add_port, set_uplink_cb, set_topic_prefix, uplink, downlink, topic, get_stats);
123
124/**
125 * @brief Clear all ports, the uplink sink, the topic prefix, and stats.
126 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
127 */
128void protocore_gateway_reset(uint8_t *work);
129/**
130 * @brief Register a southbound port.
131 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
132 * @param cfg Cfg
133 * @return PROTO_TRUE on success.
134 */
136/**
137 * @brief Install the northbound publish callback (required to publish .
138 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
139 * @param fn Fn
140 * @param ctx Ctx
141 */
143/**
144 * @brief Set the topic prefix used by protocore_gateway_topic() .
145 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
146 * @param prefix Prefix
147 */
148void protocore_gateway_set_topic_prefix(uint8_t *work, const char *prefix);
149/**
150 * @brief Bridge a received southbound frame northbound: envelope it and .
151 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
152 * @param port_id Port id
153 * @param src_addr Src addr
154 * @param payload Payload
155 * @param len Len
156 * @param rssi Rssi
157 * @return PROTO_TRUE on success.
158 */
159proto_bool protocore_gateway_uplink(uint8_t *work, uint8_t port_id, uint16_t src_addr, const uint8_t *payload,
160 uint16_t len, int16_t rssi);
161/**
162 * @brief Bridge a northbound command southbound: transmit it on port_id's .
163 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
164 * @param port_id Port id
165 * @param dst_addr Dst addr
166 * @param payload Payload
167 * @param len Len
168 * @return PROTO_TRUE on success.
169 */
170proto_bool protocore_gateway_downlink(uint8_t *work, uint8_t port_id, uint16_t dst_addr, const uint8_t *payload,
171 uint16_t len);
172/**
173 * @brief Format a northbound routing key `<prefix>/<port>/<addr>` for msg .
174 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
175 * @param msg Msg
176 * @param buf Buf
177 * @param buflen Buflen
178 * @return The uint16_t.
179 */
180uint16_t protocore_gateway_topic(uint8_t *work, const protocore_gateway_msg *msg, char *buf, uint16_t buflen);
181/**
182 * @brief Copy the current gateway counters into out. The uplink rate window .
183 * @param work PROTOCORE_GATEWAY_BORROW bytes the caller took. Not held past the call.
184 * @param out Out
185 */
187
188/**
189 * @brief Northbound publish: emit @p msg to MQTT / HTTP / WebSocket / UDP.
190 * @return true if the northbound stack accepted it; false drops (counted).
191 */
192typedef proto_bool (*protocore_gateway_uplink_fn)(const protocore_gateway_msg *msg, void *ctx);
193/**
194 * @brief The PROTOCORE_GATEWAY_BORROW bytes this module's state lives in.
195 *
196 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
197 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
198 * walks, so the state lasts the life of the program.
199 *
200 * @return the span.
201 */
203
204/** @brief Module namespace. */
213
215
216#endif // PROTOCORE_GATEWAY_H
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
proto_bool(* protocore_gateway_tx_fn)(uint8_t port_id, uint16_t dst_addr, const uint8_t *payload, uint16_t len, void *ctx)
Southbound transmit (downlink): send payload to dst_addr on port_id.
Definition gateway.h:86
void protocore_gateway_get_stats(uint8_t *work, protocore_gateway_stats *out)
Copy the current gateway counters into out. The uplink rate window .
void protocore_gateway_set_topic_prefix(uint8_t *work, const char *prefix)
Set the topic prefix used by protocore_gateway_topic() .
void protocore_gateway_reset(uint8_t *work)
Clear all ports, the uplink sink, the topic prefix, and stats.
proto_bool protocore_gateway_add_port(uint8_t *work, const protocore_gateway_port_config *cfg)
Register a southbound port.
proto_bool(* protocore_gateway_uplink_fn)(const protocore_gateway_msg *msg, void *ctx)
Northbound publish: emit msg to MQTT / HTTP / WebSocket / UDP.
Definition gateway.h:80
PROTOCORE_NS GatewayNs Gateway PROTOCORE_UNUSED
Module namespace.
Definition gateway.h:205
uint8_t * protocore_gateway_span(void)
The PROTOCORE_GATEWAY_BORROW bytes this module's state lives in.
@ PROTOCORE_GW_LORA
Definition gateway.h:47
@ PROTOCORE_GW_THREAD
Definition gateway.h:50
@ PROTOCORE_GW_WISUN
Definition gateway.h:55
@ PROTOCORE_GW_ZIGBEE
Definition gateway.h:51
@ PROTOCORE_GW_NFC
Definition gateway.h:56
@ PROTOCORE_GW_BLE
Definition gateway.h:57
@ PROTOCORE_GW_OTHER
Definition gateway.h:46
@ PROTOCORE_GW_SIGFOX
Definition gateway.h:54
@ PROTOCORE_GW_NRF24
Definition gateway.h:48
@ PROTOCORE_GW_ENOCEAN
Definition gateway.h:53
@ PROTOCORE_GW_ZWAVE
Definition gateway.h:52
@ PROTOCORE_GW_CC1101
Definition gateway.h:49
uint16_t protocore_gateway_topic(uint8_t *work, const protocore_gateway_msg *msg, char *buf, uint16_t buflen)
Format a northbound routing key <prefix>/<port>/<addr> for msg .
proto_bool protocore_gateway_uplink(uint8_t *work, uint8_t port_id, uint16_t src_addr, const uint8_t *payload, uint16_t len, int16_t rssi)
Bridge a received southbound frame northbound: envelope it and .
proto_bool protocore_gateway_downlink(uint8_t *work, uint8_t port_id, uint16_t dst_addr, const uint8_t *payload, uint16_t len)
Bridge a northbound command southbound: transmit it on port_id's .
void protocore_gateway_set_uplink_cb(uint8_t *work, protocore_gateway_uplink_fn fn, void *ctx)
Install the northbound publish callback (required to publish .
enum PROTO_ENUM_PACKED protocore_gateway_kind
Southbound radio / bus kind a port bridges (informational + topic hint).
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition gateway.h:112
void(* reset)(uint8_t *)
Definition gateway.h:113
A northbound message: a southbound frame enveloped with its routing metadata. payload points at the c...
Definition gateway.h:66
uint8_t port_id
the port the frame arrived on
Definition gateway.h:72
protocore_gateway_kind kind
protocore_gateway_kind of that port
Definition gateway.h:73
uint16_t len
payload length
Definition gateway.h:69
uint16_t src_addr
source node address on the radio
Definition gateway.h:70
const uint8_t * payload
frame payload bytes
Definition gateway.h:67
int16_t rssi
received signal strength (0 if the driver has none)
Definition gateway.h:71
uint32_t seq
per-gateway uplink sequence (wraps)
Definition gateway.h:68
Southbound port (radio / bus) configuration passed to protocore_gateway_add_port().
Definition gateway.h:91
protocore_gateway_kind kind
protocore_gateway_kind.
Definition gateway.h:93
void * ctx
opaque, forwarded to tx.
Definition gateway.h:95
protocore_gateway_tx_fn tx
downlink transmit (may be null for a receive-only port).
Definition gateway.h:94
uint8_t port_id
caller-assigned id (used in topics and up/down-link calls).
Definition gateway.h:92
uint16_t rate_cap
max uplink frames/second from this port (0 = unlimited).
Definition gateway.h:96
Gateway counters (monotonic since the last protocore_gateway_reset()).
Definition gateway.h:101
uint32_t down_dropped
downlinks dropped (bad port / no tx / refused)
Definition gateway.h:107
uint32_t up_in
protocore_gateway_uplink() calls
Definition gateway.h:102
uint32_t up_dropped
uplinks dropped (rate cap / no sink / refused / bad port)
Definition gateway.h:104
uint32_t down_in
protocore_gateway_downlink() calls
Definition gateway.h:105
uint32_t down_sent
downlinks the port transmit accepted
Definition gateway.h:106
uint32_t up_published
frames the uplink callback accepted
Definition gateway.h:103
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97