Files
VictronBLE/include/victronble_zephyr.h
T
scottpandClaude Fable 5 037af33154 v0.7.0: pure C core + Zephyr module
- Extract all decode/decrypt into a dependency-free C99 core
  (include/victronble.h, src/victronble_core.c): victronble_decode(),
  is_product_adv/key_matches pre-filters, NAN sentinels, LE accessors.
- AES-128-CTR behind a hook: weak-symbol bundled tiny-AES default,
  runtime override (victronble_set_aes_ctr) for PSA/mbedTLS/hardware.
- Arduino VictronBLE class becomes a thin wrapper over the core
  (registry + nonce dedup + rate limit); public C++ API unchanged,
  NAN converted back to the legacy 0 convention.
- Host test vectors (tests/vectors): openssl-generated ciphertext,
  independent of the bundled AES; all five payload shapes + negatives.
- Zephyr module: zephyr/module.yml + Kconfig (CONFIG_VICTRONBLE) +
  observer backend (victronble_zephyr.{h,c}) — scan cb pre-filters and
  queues, dedicated decode thread, listener callbacks, slow passive
  scan defaults, stats counters. docs/ZEPHYR_PORT.md records the plan.
- library.properties: fix URL (gitea, not the nonexistent GitHub).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 11:59:19 +10:00

72 lines
2.2 KiB
C

/**
* victronble — Zephyr BLE observer API.
*
* Passive-scans for Victron Instant Readout advertisements, decodes them
* off the BT RX thread (frames are queued to a dedicated decode thread)
* and delivers records to registered listeners.
*
* The application owns the Bluetooth stack: call bt_enable() before
* victronble_start(). Enable with CONFIG_VICTRONBLE=y (needs
* CONFIG_BT_OBSERVER=y).
*
* Copyright (c) 2026 Scott Penrose
* License: MIT
*/
#ifndef VICTRONBLE_ZEPHYR_H
#define VICTRONBLE_ZEPHYR_H
#include <zephyr/bluetooth/addr.h>
#include <zephyr/sys/slist.h>
#include "victronble.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Listener; register with victronble_cb_register(). Callbacks run on the
* module's decode thread. */
struct victronble_cb {
/** A monitored device published a new record. */
void (*record)(const bt_addr_le_t *addr, int8_t rssi,
const victronble_record_t *rec);
/** Optional: a monitored device's advertisement failed to decode. */
void (*decode_error)(const bt_addr_le_t *addr, victronble_err_t err);
sys_snode_t node;
};
struct victronble_stats {
uint32_t adverts; /* Victron product adverts seen (any device) */
uint32_t queued; /* frames queued for a monitored device */
uint32_t dropped; /* frames lost to a full queue */
uint32_t decoded; /* records decoded OK */
uint32_t duplicates; /* suppressed by nonce dedup */
uint32_t errors; /* decode failures */
};
/** Register a listener. Returns -EALREADY if already registered. */
int victronble_cb_register(struct victronble_cb *cb);
/** Monitor a device. @p key is its 16-byte advertisement key (VictronConnect
* → Product Info). Returns -ENOMEM when full, -EALREADY if present. */
int victronble_device_add(const bt_addr_le_t *addr,
const uint8_t key[VICTRONBLE_KEY_LEN]);
/** Stop monitoring a device. Returns -ENOENT if unknown. */
int victronble_device_remove(const bt_addr_le_t *addr);
/** Start the passive scan (bt_enable() must have succeeded first). */
int victronble_start(void);
/** Stop the scan. Queued frames still drain to callbacks. */
int victronble_stop(void);
void victronble_get_stats(struct victronble_stats *out);
#ifdef __cplusplus
}
#endif
#endif /* VICTRONBLE_ZEPHYR_H */