ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
udp_telemetry.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file udp_telemetry.h
6 * @brief Fire-and-forget UDP telemetry cast (PC_ENABLE_UDP_TELEMETRY).
7 *
8 * Builds a metric line in InfluxDB line protocol -
9 * `measurement,tag=v field=val,field2=val2 timestamp` (optional tags + trailing
10 * timestamp; integer fields carry the `i` suffix, unsigned `u`, floats are plain)
11 * - into a caller buffer, then casts it to a configured
12 * collector over UDP (pc_udp_sendto), zero-heap and fire-and-forget (no ACK, no
13 * retry). The line builder is pure and host-tested; only the send touches the
14 * network (ESP32; a no-op on host builds).
15 *
16 * @author Douglas Quigg (dstroy0)
17 * @date 2026
18 */
19
20#ifndef PROTOCORE_UDP_TELEMETRY_H
21#define PROTOCORE_UDP_TELEMETRY_H
22
23#include "protocore_config.h"
24#include <stddef.h>
25#include <stdint.h>
26
27#if PC_ENABLE_UDP_TELEMETRY
28
29// ---------------------------------------------------------------------------
30// Host-testable line builder (InfluxDB line protocol)
31// ---------------------------------------------------------------------------
32
33/** @brief Builder for one telemetry line over a caller buffer. */
34struct pc_line
35{
36 char *buf; ///< destination buffer.
37 size_t cap; ///< buffer capacity in bytes.
38 size_t pos; ///< bytes written so far (excludes the null terminator).
39 bool overflow; ///< true once a write did not fit (line is then unusable).
40 bool have_fields; ///< true once at least one field is present (comma control).
41};
42
43/** @brief Start a line for @p measurement (bound to @p buf / @p cap). */
44void pc_line_init(pc_line *l, char *buf, size_t cap, const char *measurement);
45
46/**
47 * @brief Append a `,key=value` tag (InfluxDB tag set, part of the series key).
48 *
49 * Tags MUST be added before any field (they sit between the measurement and the
50 * fields); adding one after a field fails the line closed. Key and value are
51 * escaped per line protocol (comma / equals / space backslash-escaped).
52 */
53void pc_line_add_tag(pc_line *l, const char *key, const char *val);
54
55/**
56 * @brief Append the trailing ` <timestamp>` (line protocol; nanoseconds by default
57 * on InfluxDB). Call after all fields; a line with no field fails closed.
58 */
59void pc_line_set_timestamp(pc_line *l, int64_t timestamp);
60
61/** @brief Append `field=<v>i` (integer field). */
62void pc_line_add_int(pc_line *l, const char *field, int64_t v);
63
64/** @brief Append `field=<v>i` (unsigned integer field). */
65void pc_line_add_uint(pc_line *l, const char *field, uint64_t v);
66
67/** @brief Append `field=<v>` (float field, @p decimals places). */
68void pc_line_add_float(pc_line *l, const char *field, float v, uint8_t decimals);
69
70/** @brief Encoded length (bytes), excluding the null terminator. */
71size_t pc_line_len(const pc_line *l);
72
73/** @brief True if every field fit and the line has at least one field. */
74bool pc_line_ok(const pc_line *l);
75
76// ---------------------------------------------------------------------------
77// Cast (ESP32; no-op on host)
78// ---------------------------------------------------------------------------
79
80/** @brief Set the collector endpoint (dotted-quad IPv4 + UDP port). */
81void pc_udp_telemetry_begin(const char *collector_ip, uint16_t port);
82
83/** @brief Cast @p len raw bytes to the collector. @return false if not begun / host. */
84bool pc_udp_telemetry_send(const char *data, size_t len);
85
86/** @brief Cast a built line to the collector (no-op if the line overflowed). */
87bool pc_udp_telemetry_cast(const pc_line *l);
88
89#endif // PC_ENABLE_UDP_TELEMETRY
90#endif // PROTOCORE_UDP_TELEMETRY_H
User-facing configuration for ProtoCore.