Examples and samples ready for Zephyr release

This commit is contained in:
2026-08-26 00:58:57 +10:00
parent 67ff8721c0
commit 22af47854d
20 changed files with 1158 additions and 29 deletions
+7
View File
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(victronble_scan)
target_sources(app PRIVATE src/main.c)
+58
View File
@@ -0,0 +1,58 @@
# scan — find your Victron devices
Logs every Victron "Instant Readout" advertisement in range. **No
advertisement keys and no device list required**, so this is the first thing
to run: it tells you what you have and what its Bluetooth address is.
The whole sample is `victronble_watch_set(true)` plus `victronble_start()`
all the output comes from the library's own log module.
## Build and run
```sh
west build -p -b nrf52840dk/nrf52840 -d /tmp/vb_scan samples/scan \
-- -DZEPHYR_EXTRA_MODULES=$PWD
west flash -d /tmp/vb_scan
```
Console (115200 baud):
```
<inf> scan: VictronBLE discovery — logging every Victron advert in range
<inf> victronble: observing (interval 96 window 48)
<inf> victronble: watch: E4:05:42:34:14:F3 (random) rssi -67 type 0x01 (solar charger) len 31 keycheck 0x0d
<inf> victronble: watch: E6:45:59:78:3C:FB (random) rssi -82 type 0x02 (battery monitor) len 31 keycheck 0x3f
<inf> scan: stats: adverts 61 queued 61 dropped 0
```
Each line gives you everything you need for `samples/observer`:
| Field | Use |
|---|---|
| address + `(random)` | Victron uses **random** static addresses — that address type matters |
| `type` | which device family it is, before any decryption |
| `keycheck` | first byte of the advertisement key; confirms you copied the right key |
| `rssi` | how well you can hear it — useful for placing the node |
Nothing here is decrypted. Watch mode reads only the plaintext header, which
is why it works without keys.
## Next step
Copy the addresses into the `known_devices` table in
[`../observer/src/main.c`](../observer/src/main.c) along with each device's key
from VictronConnect (device → gear icon → Product info → *Instant readout via
Bluetooth*), then build `observer`.
## Notes
- Unregistered devices are **not** deduplicated by nonce, so expect roughly
one line per device per second. That is the point — it shows liveness.
- `prj.conf` raises the scan duty cycle to 60 ms / 30 ms
(`BT_GAP_SCAN_FAST_*`) instead of the library default 1.28 s / 11.25 ms.
Discovery should be quick; `observer` uses the low-power default.
- `CONFIG_VICTRONBLE_QUEUE_DEPTH=16` because watch mode queues every advert,
not just the ones from known devices. If `dropped` climbs on a busy site,
raise it further.
- `adverts 0` after a minute means either nothing is in range or the device
has *Instant readout via Bluetooth* switched off in VictronConnect.
+25
View File
@@ -0,0 +1,25 @@
# Bluetooth: observer role only — no connections, no pairing, no advertising.
CONFIG_BT=y
CONFIG_BT_OBSERVER=y
CONFIG_BT_DEVICE_NAME="victron-scan"
# Discovery hears every Victron in range, so the advertising-report pool and
# the library's decode queue both see more traffic than in normal operation.
CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=20
CONFIG_VICTRONBLE=y
# Watch mode queues every Victron advert, not just the registered ones.
CONFIG_VICTRONBLE_QUEUE_DEPTH=16
# No devices are registered — this sample never decrypts anything.
CONFIG_VICTRONBLE_MAX_DEVICES=1
# Discovery wants to find things quickly, so trade power for a much higher
# duty cycle than the library's defaults: 60 ms interval / 30 ms window
# (BT_GAP_SCAN_FAST_*) instead of 1.28 s / 11.25 ms.
CONFIG_VICTRONBLE_SCAN_INTERVAL=96
CONFIG_VICTRONBLE_SCAN_WINDOW=48
CONFIG_LOG=y
CONFIG_VICTRONBLE_LOG_LEVEL_INF=y
+10
View File
@@ -0,0 +1,10 @@
sample:
name: VictronBLE scan
description: List every Victron device advertising nearby, no keys required
tests:
sample.victronble.scan:
build_only: true
platform_allow:
- nrf52840dk/nrf52840
- rak4631/nrf52840
tags: bluetooth victron
+66
View File
@@ -0,0 +1,66 @@
/**
* VictronBLE Zephyr discovery sample.
*
* Turns on the library's watch mode and does nothing else. No advertisement
* keys, no device list: every Victron Instant Readout advert in range is
* logged with its address, RSSI, device type and key-check byte.
*
* Run this first to find out what you have and what its MAC address is, then
* put the addresses and keys into samples/observer.
*
* Copyright (c) 2026 Scott Penrose
* License: MIT
*/
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/logging/log.h>
#include "victronble_zephyr.h"
LOG_MODULE_REGISTER(scan, LOG_LEVEL_INF);
#define STATS_INTERVAL K_SECONDS(30)
int main(void)
{
struct victronble_stats stats;
int err;
LOG_INF("VictronBLE discovery — logging every Victron advert in range");
/* The application owns the Bluetooth stack: victronble_start() needs
* it up already. */
err = bt_enable(NULL);
if (err != 0) {
LOG_ERR("bt_enable failed (%d)", err);
return 0;
}
/* All output comes from the library's own log module (victronble).
* Unregistered devices are not nonce-deduplicated, so expect roughly
* one line per device per second. */
victronble_watch_set(true);
err = victronble_start();
if (err != 0) {
LOG_ERR("victronble_start failed (%d)", err);
return 0;
}
while (1) {
k_sleep(STATS_INTERVAL);
victronble_get_stats(&stats);
LOG_INF("stats: adverts %u queued %u dropped %u", stats.adverts,
stats.queued, stats.dropped);
if (stats.adverts == 0) {
LOG_WRN("nothing heard yet — check the device has "
"'Instant readout via Bluetooth' enabled in "
"VictronConnect");
}
}
return 0;
}