SatCat5
net_telemetry.h
Go to the documentation of this file.
1 // Copyright 2023-2025 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
85 
86 #pragma once
87 
88 #include <satcat5/eth_socket.h>
89 #include <satcat5/io_cbor.h>
90 #include <satcat5/list.h>
91 #include <satcat5/polling.h>
92 #include <satcat5/types.h>
93 #include <satcat5/udp_socket.h>
94 
95 // Enable this feature? (See types.h)
96 #if SATCAT5_CBOR_ENABLE
97 
98 namespace satcat5 {
99  namespace net {
105  class TelemetryCbor final
106  : public satcat5::cbor::MapWriter<s64>
107  , public satcat5::cbor::MapWriter<const char*>
108  {
109  public:
110  // Import specific functions to resolve ambiguous name issues.
111  // (Explicitly include both variants, unless they're equivalent.)
130 
133  : CborWriter(nullptr, &m_cbor, m_raw, SATCAT5_QCBOR_BUFFER, true) {}
134 
135  private:
136  QCBOREncodeContext m_cbor;
137  u8 m_raw[SATCAT5_QCBOR_BUFFER];
138  };
139 
144  public:
152  virtual void telem_ready(
153  u32 tier_id, unsigned nbytes, const void* data) = 0;
154 
155  protected:
158  ~TelemetrySink() SATCAT5_OPTIONAL_DTOR;
159 
161  satcat5::net::TelemetryAggregator* const m_tlm;
162 
163  private:
164  // Linked list of other TelemetrySink objects.
165  friend satcat5::util::ListCore;
166  satcat5::net::TelemetrySink* m_next;
167  };
168 
172  public:
175  virtual void telem_event(
176  u32 tier_id, satcat5::net::TelemetryCbor& cbor) = 0;
177  };
178 
182  class TelemetryTier final {
183  public:
188  u32 tier_id, unsigned interval_msec = 0);
189  ~TelemetryTier() SATCAT5_OPTIONAL_DTOR;
190 
192  void send_now();
193 
195  void set_interval(unsigned interval_msec);
196 
198  const u32 m_tier_id;
199 
200  private:
201  // Event notifications from the TelemetryAggregator.
203  void telem_poll(satcat5::net::TelemetryCbor& cbor);
204 
205  // Linked list of other TelemetryTier objects.
208 
209  // Internal state for this tier.
211  satcat5::net::TelemetrySource* const m_src;
212  unsigned m_time_interval;
213  unsigned m_time_count;
214  };
215 
220  public:
222  explicit TelemetryAggregator(bool concat_tiers);
223 
225  inline void telem_concat(bool concat_tiers)
226  { m_tlm_concat = concat_tiers; }
227 
231  void telem_send(TelemetryCbor& cbor, u32 tier_id);
232 
235  inline unsigned timer_interval() const
237 
238  protected:
239  // Timer event handler is called every N msec.
240  void timer_event() override;
241 
242  // Set per-tier or concatenated mode for this aggregator.
243  bool m_tlm_concat;
244 
245  // Linked-list of associated TelemetrySink objects.
248 
249  // Linked-list of associated TelemetryTier objects.
252 
253  // Statically allocated working buffer.
254  u8 m_buff[SATCAT5_QCBOR_BUFFER];
255  };
256 
260  public:
270  virtual void telem_rcvd(
271  u32 key, const QCBORItem& item,
272  QCBORDecodeContext* cbor) = 0;
273 
274  protected:
277  ~TelemetryWatcher() SATCAT5_OPTIONAL_DTOR;
278 
280  satcat5::net::TelemetryRx* const m_rx;
281 
282  private:
283  // Linked list for the net::TelemetryRx class.
284  friend satcat5::util::ListCore;
285  satcat5::net::TelemetryWatcher* m_next;
286  };
287 
290  struct TelemetryKey {
291  explicit TelemetryKey(const char* label);
292  TelemetryKey(const TelemetryKey& t) = default;
293  TelemetryKey& operator=(const TelemetryKey& t) = default;
294 
295  const char* key;
296  const u32 hash;
297  };
298 
302  public:
304  explicit TelemetryLogger(
305  satcat5::net::TelemetryRx* rx, const char* kstr = nullptr);
307  explicit TelemetryLogger(
308  satcat5::net::TelemetryRx* rx, u32 key);
309 
310  protected:
311  void telem_rcvd(
312  u32 key, const QCBORItem& item,
313  QCBORDecodeContext* cbor) override;
315  };
316 
319  class TelemetryRx {
320  public:
323  inline void add_watcher(TelemetryWatcher* callback)
324  { m_watchers.add(callback); }
325  inline void remove_watcher(TelemetryWatcher* callback)
326  { m_watchers.remove(callback); }
328 
331  void telem_packet(satcat5::io::LimitedRead& src);
332 
333  protected:
336  ~TelemetryRx() {}
337 
338  private:
340  void telem_item(QCBORDecodeContext* cbor, const QCBORItem& item);
341 
344  };
345 
350  public:
355 
357  void telem_ready(
358  u32 tier_id, unsigned nbytes, const void* data) override;
359 
360  protected:
361  satcat5::net::TelemetryRx* const m_dst;
362  };
363  }
364 
365  namespace eth {
368  class Telemetry final
372  {
373  public:
376  Telemetry(
377  satcat5::eth::Dispatch* eth, // Ethernet interface
378  bool concat_tiers = true); // Concatenate mode?
379  ~Telemetry() {}
380 
383  inline void connect(
384  const satcat5::eth::MacAddr& addr,
385  const satcat5::eth::MacType& type,
386  const satcat5::eth::VlanTag& vtag = satcat5::eth::VTAG_NONE)
387  { m_addr.connect(addr, type, vtag); }
388 
390  inline void close()
391  { m_addr.close(); }
392 
393  protected:
394  // Event handler for the TelemetrySink API.
396  u32 tier_id, unsigned nbytes, const void* data) override
397  { m_addr.write_packet(nbytes, data); }
398  };
399 
402  class TelemetryRx final
403  : public satcat5::net::Protocol
405  {
406  public:
408  TelemetryRx(
409  satcat5::eth::Dispatch* iface,
410  const satcat5::eth::MacType& type);
411  ~TelemetryRx() SATCAT5_OPTIONAL_DTOR;
412 
413  protected:
414  // Required callback from net::Protocol.
415  void frame_rcvd(satcat5::io::LimitedRead& src);
416 
417  satcat5::eth::Dispatch* const m_iface;
418  };
419  }
420 
421  namespace udp {
424  class Telemetry final
428  {
429  public:
432  Telemetry(
433  satcat5::udp::Dispatch* udp, // UDP interface
434  bool concat_tiers = true); // Concatenate mode?
435  ~Telemetry() {}
436 
439  inline void connect(
440  const satcat5::udp::Addr& dstaddr,
441  const satcat5::udp::Port& dstport = satcat5::udp::PORT_CBOR_TLM,
442  const satcat5::eth::VlanTag& vtag = satcat5::eth::VTAG_NONE)
443  { m_addr.connect(dstaddr, dstport, satcat5::udp::PORT_NONE, vtag);}
444 
446  inline void close()
447  { m_addr.close(); }
448 
449  protected:
450  // Event handler for the TelemetrySink API.
452  u32 tier_id, unsigned nbytes, const void* data) override
453  { m_addr.write_packet(nbytes, data); }
454  };
455 
458  class TelemetryRx final
459  : public satcat5::net::Protocol
461  {
462  public:
464  explicit TelemetryRx(
465  satcat5::udp::Dispatch* iface,
466  const satcat5::udp::Port& port = satcat5::udp::PORT_CBOR_TLM);
467  ~TelemetryRx() SATCAT5_OPTIONAL_DTOR;
468 
469  protected:
470  // Required callback from net::Protocol.
471  void frame_rcvd(satcat5::io::LimitedRead& src);
472 
473  satcat5::udp::Dispatch* const m_iface;
474  };
475  }
476 }
477 
478 #endif // SATCAT5_CBOR_ENABLE
CborWriter(satcat5::io::Writeable *dst, QCBOREncodeContext *encode, u8 *buff, unsigned size, bool automap=false)
Constructor requires child class to provide a working buffer.
Definition: io_cbor.cc:19
Write a series of key-value pairs to a CBOR Map.
Definition: io_cbor.h:302
Inheritable container for a eth::Address.
Definition: eth_address.h:60
Implemention of "net::Dispatch" for Ethernet frames.
Definition: eth_dispatch.h:21
Thin wrapper for sending CBOR telemetry over raw-Ethernet.
void connect(const satcat5::eth::MacAddr &addr, const satcat5::eth::MacType &type, const satcat5::eth::VlanTag &vtag=satcat5::eth::VTAG_NONE)
Set the destination MAC address and EtherType.
void telem_ready(u32 tier_id, unsigned nbytes, const void *data) override
This method is called for each outgoing telemetry message.
void close()
Close the connection and stop transmission.
Thin wrapper for receiving CBOR telemetry over raw-Ethernet.
Limited read of next N bytes.
Definition: io_readable.h:255
A net::Protocol is the counterpart to net::Dispatch that handles a particular data stream,...
Definition: net_protocol.h:28
Protocol-agnostic handler for one or more TelemetryTier objects.
unsigned timer_interval() const
Query the polling interval for this aggregator.
void telem_concat(bool concat_tiers)
Change to concatenated or per-tier mode.
Legacy ephemeral wrapper class for the CBOR encoder.
TelemetryCbor()
Default constructor initializes both variants.
Example TelemetryWatcher that logs received key/value pairs.
Loopback adapter for telemetry messages.
Parse incoming CBOR telemetry and notify TelemetryWatcher callbacks.
satcat5::util::List< satcat5::net::TelemetryWatcher > m_watchers
Linked list of registered callback objects.
void remove_watcher(TelemetryWatcher *callback)
Manage the list of registered callback objects.
TelemetryRx()
Constructor is only accessible to the child object.
void add_watcher(TelemetryWatcher *callback)
Manage the list of registered callback objects.
User data sinks must inherit from the TelemetrySink class.
satcat5::net::TelemetryAggregator *const m_tlm
Pointer to the parent object.
TelemetrySink(satcat5::net::TelemetryAggregator *tlm)
Only children can safely access constructor/destructor.
virtual void telem_ready(u32 tier_id, unsigned nbytes, const void *data)=0
This method is called for each outgoing telemetry message.
User data sources must inherit from the TelemetrySource class.
virtual void telem_event(u32 tier_id, satcat5::net::TelemetryCbor &cbor)=0
User method for writing each telemetry message.
Rate control for a particular telemetry "tier".
const u32 m_tier_id
Tier-ID for this object.
Callback API for incoming telemetry items.
virtual void telem_rcvd(u32 key, const QCBORItem &item, QCBORDecodeContext *cbor)=0
Callback for each received key/value pair.
Timer objects are polled after a fixed delay or at a regular interval.
Definition: polling.h:213
unsigned timer_interval() const
Accessor for recurring timer interval, if one is set.
Definition: polling.h:226
Inheritable container for a udp::Address.
Definition: udp_core.h:149
Dispatcher sorts incoming UDP messages by port index.
Definition: udp_dispatch.h:20
Thin wrapper for sending CBOR telemetry over UDP.
void connect(const satcat5::udp::Addr &dstaddr, const satcat5::udp::Port &dstport=satcat5::udp::PORT_CBOR_TLM, const satcat5::eth::VlanTag &vtag=satcat5::eth::VTAG_NONE)
Set the destination IP address and UDP port.
void close()
Close the connection and stop transmission.
void telem_ready(u32 tier_id, unsigned nbytes, const void *data) override
This method is called for each outgoing telemetry message.
Thin wrapper for receiving CBOR telemetry over UDP.
Helper functions for manipulating singly-linked lists.
Definition: list.h:52
CBOR (IETF RFC8949) Readable/Writeable interface.
#define SATCAT5_QCBOR_BUFFER
Set the default size for the QCBOR buffer.
Definition: io_cbor.h:52
Templated functions for manipulating singly-linked lists.
Core event-processing loop for SatCat5 software.
An Ethernet MAC address (with serializable interface).
Definition: eth_header.h:29
EtherType field (uint16) is used a protocol-ID [1536..65535].
Definition: eth_header.h:96
Header contents for an 802.1Q Virtual-LAN tag.
Definition: eth_header.h:124
IPv4 address is a 32-bit unsigned integer.
Definition: ip_core.h:15
UDP and TCP ports are both 16-bit unsigned integers.
Definition: ip_core.h:119
String constant, plus the CRC32 hash of that string.
const u32 hash
CRC32 of that string.
const char * key
String key.
Basic type aliases and prototypes used throughout SatCat5.