v0.7.1: rename C core header to victronble_core.h (fixes #2)
src/ held both VictronBLE.h and victronble.h. On case-insensitive filesystems (Windows, macOS) extracting the library ZIP overwrote one with the other and the Arduino build failed. The core header is now victronble_core.h in include/ and src/, and every include is updated. include/victronble.h stays as a deprecated forwarder so 0.7.0 Zephyr and host code still builds; it is never in src/. check_version.sh now fails if two tracked paths differ only in case.
This commit is contained in:
1 parent
22af47854d
commit
318e221170
18 files changed
+247
-219
No files matched your search
@@ -488,7 +488,7 @@ The library keeps everything platform-independent except the BLE radio:
|
||||
|
||||
```
|
||||
include/
|
||||
├── victronble.h Pure C99 core API — decode one advert, no I/O
|
||||
├── victronble_core.h Pure C99 core API — decode one advert, no I/O
|
||||
└── victronble_zephyr.h Zephyr observer API
|
||||
src/
|
||||
├── victronble_core.c Decrypt + parse; no BLE, no alloc, reentrant
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Version History
|
||||
|
||||
## 0.7.1 (2026-10-09)
|
||||
|
||||
### Fixed
|
||||
- The library ZIP no longer breaks on Windows and other case-insensitive
|
||||
filesystems. `src/` held both `VictronBLE.h` and `victronble.h`, so
|
||||
extracting one overwrote the other (issue #2, with thanks for the report
|
||||
and the workaround). The C core header is now `victronble_core.h` in both
|
||||
`include/` and `src/`. Code that includes `victronble.h` from `include/`
|
||||
(Zephyr, host builds) still works through a deprecated forwarder.
|
||||
- `check_version.sh` now fails if two tracked paths differ only in case.
|
||||
|
||||
## 0.7.0 (2026-08-21)
|
||||
|
||||
Pure C core + Zephyr support. One repo now serves three ecosystems: Arduino
|
||||
|
||||
+10
-1
@@ -4,7 +4,8 @@
|
||||
#
|
||||
# Read-only: confirms the version matches in both manifests and that a matching
|
||||
# git tag (vX.Y.Z) exists. Run it before tagging a release. Non-zero exit if the
|
||||
# versions disagree or the tag is missing.
|
||||
# versions disagree, the tag is missing, or two tracked paths differ only in
|
||||
# case (they collide when the ZIP is extracted on Windows or macOS).
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -31,4 +32,12 @@ else
|
||||
echo "FAIL no git tag v$json -- create one to release: git tag v$json"; fail=1
|
||||
fi
|
||||
|
||||
clash=$(git ls-files | tr '[:upper:]' '[:lower:]' | sort | uniq -d)
|
||||
if [ -z "$clash" ]; then
|
||||
echo "ok no paths differ only in case"
|
||||
else
|
||||
echo "FAIL paths differ only in case (breaks Windows/macOS extract):"
|
||||
echo "$clash" | sed 's/^/ /'; fail=1
|
||||
fi
|
||||
|
||||
exit "$fail"
|
||||
+2
-2
@@ -98,7 +98,7 @@ done you can unit-test the parser on your workstation for the first time.
|
||||
- Freestanding-safe: `<stdint.h>`, `<stddef.h>`, `<string.h>`, `<math.h>` only.
|
||||
- Reentrant. No file-scope mutable state in the parse path.
|
||||
|
||||
### `include/victronble.h`
|
||||
### `include/victronble_core.h`
|
||||
|
||||
```c
|
||||
#ifndef VICTRONBLE_H
|
||||
@@ -339,7 +339,7 @@ victronble/
|
||||
├── zephyr/
|
||||
│ └── module.yml
|
||||
├── include/
|
||||
│ └── victronble.h # pure C core
|
||||
│ └── victronble_core.h # pure C core
|
||||
│ └── victronble_zephyr.h # Zephyr-specific observer API
|
||||
├── src/
|
||||
│ ├── victronble_core.c # pure C99, no dependencies
|
||||
|
||||
@@ -79,6 +79,6 @@ victronble_device_type_str()
|
||||
victronble_state_str()
|
||||
```
|
||||
|
||||
That is the whole portable core. See `include/victronble.h` for the record
|
||||
That is the whole portable core. See `include/victronble_core.h` for the record
|
||||
structures, and `samples/observer/` for the same printing logic driven by a
|
||||
live BLE scan under Zephyr.
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "victronble.h"
|
||||
#include "victronble_core.h"
|
||||
|
||||
/*
|
||||
* Sample advertisement from the library's own test vectors
|
||||
|
||||
+5
-203
@@ -1,206 +1,8 @@
|
||||
/**
|
||||
* victronble — pure C99 decoder for Victron Energy "Instant Readout" BLE
|
||||
* advertisements (manufacturer ID 0x02E1, record type 0x10, AES-128-CTR).
|
||||
*
|
||||
* This is the portable core of the VictronBLE library: no Arduino, no BLE
|
||||
* stack, no allocation, no I/O, reentrant. Feed it one manufacturer-specific
|
||||
* data blob (starting at the company ID) plus the device's 16-byte
|
||||
* advertisement key; get a decoded record back. Transport (scanning), device
|
||||
* registries, rate limiting and logging belong to the platform wrappers
|
||||
* (Arduino C++ class, Zephyr module).
|
||||
*
|
||||
* Copyright (c) 2025-2026 Scott Penrose
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
/* Deprecated: the core header was renamed to victronble_core.h in 0.7.1.
|
||||
* This forwarder keeps 0.7.0 Zephyr and host code building. It lives only in
|
||||
* include/, never in src/, where it would clash with VictronBLE.h on
|
||||
* case-insensitive filesystems (issue #2). */
|
||||
#ifndef VICTRONBLE_H
|
||||
#define VICTRONBLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "victronble_core.h"
|
||||
#endif
|
||||
|
||||
#define VICTRONBLE_COMPANY_ID 0x02E1u /* Victron Energy BV */
|
||||
#define VICTRONBLE_KEY_LEN 16
|
||||
#define VICTRONBLE_MAX_CIPHER_LEN 21 /* encrypted payload in one advert */
|
||||
#define VICTRONBLE_MIN_MFG_LEN 10 /* header before the ciphertext */
|
||||
|
||||
typedef enum {
|
||||
VICTRONBLE_OK = 0,
|
||||
VICTRONBLE_ERR_NOT_VICTRON = -1, /* company ID mismatch */
|
||||
VICTRONBLE_ERR_SHORT = -2, /* truncated advertisement */
|
||||
VICTRONBLE_ERR_NOT_PRODUCT = -3, /* not a product-advertisement record */
|
||||
VICTRONBLE_ERR_KEY_MISMATCH = -4, /* key check byte failed */
|
||||
VICTRONBLE_ERR_UNSUPPORTED = -5, /* known record type, no decoder */
|
||||
VICTRONBLE_ERR_CRYPTO = -6, /* AES backend failed */
|
||||
} victronble_err_t;
|
||||
|
||||
/* Values are the raw Victron record-type IDs. The inverter family
|
||||
* (0x03/0x06/0x0B/0x0C) all decode to VICTRONBLE_DEV_INVERTER. */
|
||||
typedef enum {
|
||||
VICTRONBLE_DEV_UNKNOWN = 0x00,
|
||||
VICTRONBLE_DEV_SOLAR_CHARGER = 0x01,
|
||||
VICTRONBLE_DEV_BATTERY_MONITOR = 0x02,
|
||||
VICTRONBLE_DEV_INVERTER = 0x03,
|
||||
VICTRONBLE_DEV_DCDC_CONVERTER = 0x04,
|
||||
VICTRONBLE_DEV_SMART_LITHIUM = 0x05,
|
||||
VICTRONBLE_DEV_INVERTER_RS = 0x06,
|
||||
VICTRONBLE_DEV_GX_DEVICE = 0x07,
|
||||
VICTRONBLE_DEV_AC_CHARGER = 0x08,
|
||||
VICTRONBLE_DEV_BATTERY_PROTECT = 0x09,
|
||||
VICTRONBLE_DEV_LYNX_SMART_BMS = 0x0A,
|
||||
VICTRONBLE_DEV_MULTI_RS = 0x0B,
|
||||
VICTRONBLE_DEV_VE_BUS = 0x0C,
|
||||
VICTRONBLE_DEV_DC_ENERGY_METER = 0x0D,
|
||||
VICTRONBLE_DEV_ORION_XS = 0x0F,
|
||||
} victronble_device_type_t;
|
||||
|
||||
/* Charger states shared by solar / AC chargers (VE.Direct "CS"). */
|
||||
enum {
|
||||
VICTRONBLE_STATE_OFF = 0,
|
||||
VICTRONBLE_STATE_LOW_POWER = 1,
|
||||
VICTRONBLE_STATE_FAULT = 2,
|
||||
VICTRONBLE_STATE_BULK = 3,
|
||||
VICTRONBLE_STATE_ABSORPTION = 4,
|
||||
VICTRONBLE_STATE_FLOAT = 5,
|
||||
VICTRONBLE_STATE_STORAGE = 6,
|
||||
VICTRONBLE_STATE_EQUALIZE = 7,
|
||||
VICTRONBLE_STATE_INVERTING = 9,
|
||||
VICTRONBLE_STATE_POWER_SUPPLY = 11,
|
||||
VICTRONBLE_STATE_EXTERNAL_CONTROL = 252,
|
||||
};
|
||||
|
||||
/* Fields the wire encodes as "not available" are NAN (test with isnan()).
|
||||
* Integer fields keep the raw value; sentinels are documented per field. */
|
||||
|
||||
typedef struct {
|
||||
uint8_t state; /* VICTRONBLE_STATE_* */
|
||||
uint8_t error;
|
||||
float battery_voltage; /* V */
|
||||
float battery_current; /* A */
|
||||
float pv_power; /* W */
|
||||
uint32_t yield_today_wh; /* Wh */
|
||||
float load_current; /* A, NAN if no load output */
|
||||
} victronble_solar_charger_t;
|
||||
|
||||
typedef struct {
|
||||
float voltage; /* V */
|
||||
float current; /* A */
|
||||
float temperature; /* degC, NAN unless aux mode = temperature */
|
||||
float aux_voltage; /* V, NAN unless aux mode = aux voltage */
|
||||
uint16_t remaining_minutes; /* time-to-go; 0xFFFF = not available */
|
||||
float consumed_ah; /* Ah, negative = consumed */
|
||||
float soc; /* % */
|
||||
uint8_t aux_mode; /* 0=aux V, 1=midpoint, 2=temperature, 3=none */
|
||||
uint16_t alarm; /* raw 16-bit alarm bitmask */
|
||||
} victronble_battery_monitor_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t alarms; /* raw alarm bits: 0x01 lowV, 0x02 highV,
|
||||
* 0x04 highT, 0x08 overload */
|
||||
float battery_voltage; /* V */
|
||||
float battery_current; /* A */
|
||||
float ac_power; /* W (signed) */
|
||||
} victronble_inverter_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state; /* charge state */
|
||||
uint8_t error;
|
||||
float input_voltage; /* V */
|
||||
float output_voltage; /* V */
|
||||
float output_current; /* A */
|
||||
} victronble_dcdc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t error;
|
||||
float voltage1, current1; /* output 1 (V, A), NAN if absent */
|
||||
float voltage2, current2; /* output 2 */
|
||||
float voltage3, current3; /* output 3 */
|
||||
float temperature; /* degC, NAN if not available */
|
||||
float ac_current; /* A, NAN if not available */
|
||||
} victronble_ac_charger_t;
|
||||
|
||||
typedef struct {
|
||||
victronble_device_type_t type; /* decoded family (inverter collapsed) */
|
||||
uint8_t record_type; /* raw record type from the wire */
|
||||
uint16_t model_id;
|
||||
uint8_t readout_type;
|
||||
uint16_t nonce; /* data counter, as received */
|
||||
union {
|
||||
victronble_solar_charger_t solar;
|
||||
victronble_battery_monitor_t batmon;
|
||||
victronble_inverter_t inverter;
|
||||
victronble_dcdc_t dcdc;
|
||||
victronble_ac_charger_t ac;
|
||||
} u;
|
||||
} victronble_record_t;
|
||||
|
||||
/**
|
||||
* Decode one Victron manufacturer-data blob.
|
||||
*
|
||||
* @param mfg Manufacturer-specific data, starting at the company ID.
|
||||
* @param len Length of @p mfg in bytes.
|
||||
* @param key 16-byte per-device advertisement key.
|
||||
* @param out Populated on VICTRONBLE_OK; untouched otherwise.
|
||||
*
|
||||
* Reentrant, allocation-free, no I/O. Duplicate suppression (nonce
|
||||
* tracking) is the caller's job — the nonce is returned in @p out.
|
||||
*/
|
||||
victronble_err_t victronble_decode(const uint8_t *mfg, size_t len,
|
||||
const uint8_t key[VICTRONBLE_KEY_LEN],
|
||||
victronble_record_t *out);
|
||||
|
||||
/** Cheap pre-filter: company ID + product-advertisement record, no crypto. */
|
||||
bool victronble_is_product_adv(const uint8_t *mfg, size_t len);
|
||||
|
||||
/** Key check byte test — pick the right key from several without decrypting. */
|
||||
bool victronble_key_matches(const uint8_t *mfg, size_t len,
|
||||
const uint8_t key[VICTRONBLE_KEY_LEN]);
|
||||
|
||||
/** Parse a 32-hex-char advertisement key. Returns false on bad input. */
|
||||
bool victronble_parse_key(const char *hex, uint8_t key[VICTRONBLE_KEY_LEN]);
|
||||
|
||||
const char *victronble_strerror(victronble_err_t err);
|
||||
const char *victronble_device_type_str(victronble_device_type_t type);
|
||||
/** Short lower-case charger-state label ("bulk", "float", ...). */
|
||||
const char *victronble_state_str(uint8_t state);
|
||||
|
||||
/**
|
||||
* AES-128-CTR transform hook.
|
||||
*
|
||||
* @param key 16-byte key.
|
||||
* @param iv 16-byte initial counter block (nonce in the low bytes, rest 0).
|
||||
* @param in Ciphertext.
|
||||
* @param out Plaintext. May alias @p in.
|
||||
* @param len Byte count, not necessarily a multiple of 16.
|
||||
* @param user Opaque context supplied at registration.
|
||||
* @return 0 on success, negative on failure.
|
||||
*/
|
||||
typedef int (*victronble_aes_ctr_fn)(const uint8_t key[16],
|
||||
const uint8_t iv[16],
|
||||
const uint8_t *in, uint8_t *out,
|
||||
size_t len, void *user);
|
||||
|
||||
/** Override the AES backend at runtime (NULL restores the default). */
|
||||
void victronble_set_aes_ctr(victronble_aes_ctr_fn fn, void *user);
|
||||
|
||||
/**
|
||||
* Default AES backend. Weak symbol: the bundled software AES
|
||||
* (victronble_aes_sw.c) provides it; an alternative backend (PSA, mbedTLS,
|
||||
* hardware) may define it strong and the linker drops the bundled code.
|
||||
*/
|
||||
int victronble_aes_ctr_default(const uint8_t key[16], const uint8_t iv[16],
|
||||
const uint8_t *in, uint8_t *out,
|
||||
size_t len, void *user);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VICTRONBLE_H */
|
||||
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* victronble_core — pure C99 decoder for Victron Energy "Instant Readout" BLE
|
||||
* advertisements (manufacturer ID 0x02E1, record type 0x10, AES-128-CTR).
|
||||
*
|
||||
* This is the portable core of the VictronBLE library: no Arduino, no BLE
|
||||
* stack, no allocation, no I/O, reentrant. Feed it one manufacturer-specific
|
||||
* data blob (starting at the company ID) plus the device's 16-byte
|
||||
* advertisement key; get a decoded record back. Transport (scanning), device
|
||||
* registries, rate limiting and logging belong to the platform wrappers
|
||||
* (Arduino C++ class, Zephyr module).
|
||||
*
|
||||
* Copyright (c) 2025-2026 Scott Penrose
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
#ifndef VICTRONBLE_CORE_H
|
||||
#define VICTRONBLE_CORE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define VICTRONBLE_COMPANY_ID 0x02E1u /* Victron Energy BV */
|
||||
#define VICTRONBLE_KEY_LEN 16
|
||||
#define VICTRONBLE_MAX_CIPHER_LEN 21 /* encrypted payload in one advert */
|
||||
#define VICTRONBLE_MIN_MFG_LEN 10 /* header before the ciphertext */
|
||||
|
||||
typedef enum {
|
||||
VICTRONBLE_OK = 0,
|
||||
VICTRONBLE_ERR_NOT_VICTRON = -1, /* company ID mismatch */
|
||||
VICTRONBLE_ERR_SHORT = -2, /* truncated advertisement */
|
||||
VICTRONBLE_ERR_NOT_PRODUCT = -3, /* not a product-advertisement record */
|
||||
VICTRONBLE_ERR_KEY_MISMATCH = -4, /* key check byte failed */
|
||||
VICTRONBLE_ERR_UNSUPPORTED = -5, /* known record type, no decoder */
|
||||
VICTRONBLE_ERR_CRYPTO = -6, /* AES backend failed */
|
||||
} victronble_err_t;
|
||||
|
||||
/* Values are the raw Victron record-type IDs. The inverter family
|
||||
* (0x03/0x06/0x0B/0x0C) all decode to VICTRONBLE_DEV_INVERTER. */
|
||||
typedef enum {
|
||||
VICTRONBLE_DEV_UNKNOWN = 0x00,
|
||||
VICTRONBLE_DEV_SOLAR_CHARGER = 0x01,
|
||||
VICTRONBLE_DEV_BATTERY_MONITOR = 0x02,
|
||||
VICTRONBLE_DEV_INVERTER = 0x03,
|
||||
VICTRONBLE_DEV_DCDC_CONVERTER = 0x04,
|
||||
VICTRONBLE_DEV_SMART_LITHIUM = 0x05,
|
||||
VICTRONBLE_DEV_INVERTER_RS = 0x06,
|
||||
VICTRONBLE_DEV_GX_DEVICE = 0x07,
|
||||
VICTRONBLE_DEV_AC_CHARGER = 0x08,
|
||||
VICTRONBLE_DEV_BATTERY_PROTECT = 0x09,
|
||||
VICTRONBLE_DEV_LYNX_SMART_BMS = 0x0A,
|
||||
VICTRONBLE_DEV_MULTI_RS = 0x0B,
|
||||
VICTRONBLE_DEV_VE_BUS = 0x0C,
|
||||
VICTRONBLE_DEV_DC_ENERGY_METER = 0x0D,
|
||||
VICTRONBLE_DEV_ORION_XS = 0x0F,
|
||||
} victronble_device_type_t;
|
||||
|
||||
/* Charger states shared by solar / AC chargers (VE.Direct "CS"). */
|
||||
enum {
|
||||
VICTRONBLE_STATE_OFF = 0,
|
||||
VICTRONBLE_STATE_LOW_POWER = 1,
|
||||
VICTRONBLE_STATE_FAULT = 2,
|
||||
VICTRONBLE_STATE_BULK = 3,
|
||||
VICTRONBLE_STATE_ABSORPTION = 4,
|
||||
VICTRONBLE_STATE_FLOAT = 5,
|
||||
VICTRONBLE_STATE_STORAGE = 6,
|
||||
VICTRONBLE_STATE_EQUALIZE = 7,
|
||||
VICTRONBLE_STATE_INVERTING = 9,
|
||||
VICTRONBLE_STATE_POWER_SUPPLY = 11,
|
||||
VICTRONBLE_STATE_EXTERNAL_CONTROL = 252,
|
||||
};
|
||||
|
||||
/* Fields the wire encodes as "not available" are NAN (test with isnan()).
|
||||
* Integer fields keep the raw value; sentinels are documented per field. */
|
||||
|
||||
typedef struct {
|
||||
uint8_t state; /* VICTRONBLE_STATE_* */
|
||||
uint8_t error;
|
||||
float battery_voltage; /* V */
|
||||
float battery_current; /* A */
|
||||
float pv_power; /* W */
|
||||
uint32_t yield_today_wh; /* Wh */
|
||||
float load_current; /* A, NAN if no load output */
|
||||
} victronble_solar_charger_t;
|
||||
|
||||
typedef struct {
|
||||
float voltage; /* V */
|
||||
float current; /* A */
|
||||
float temperature; /* degC, NAN unless aux mode = temperature */
|
||||
float aux_voltage; /* V, NAN unless aux mode = aux voltage */
|
||||
uint16_t remaining_minutes; /* time-to-go; 0xFFFF = not available */
|
||||
float consumed_ah; /* Ah, negative = consumed */
|
||||
float soc; /* % */
|
||||
uint8_t aux_mode; /* 0=aux V, 1=midpoint, 2=temperature, 3=none */
|
||||
uint16_t alarm; /* raw 16-bit alarm bitmask */
|
||||
} victronble_battery_monitor_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t alarms; /* raw alarm bits: 0x01 lowV, 0x02 highV,
|
||||
* 0x04 highT, 0x08 overload */
|
||||
float battery_voltage; /* V */
|
||||
float battery_current; /* A */
|
||||
float ac_power; /* W (signed) */
|
||||
} victronble_inverter_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state; /* charge state */
|
||||
uint8_t error;
|
||||
float input_voltage; /* V */
|
||||
float output_voltage; /* V */
|
||||
float output_current; /* A */
|
||||
} victronble_dcdc_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t error;
|
||||
float voltage1, current1; /* output 1 (V, A), NAN if absent */
|
||||
float voltage2, current2; /* output 2 */
|
||||
float voltage3, current3; /* output 3 */
|
||||
float temperature; /* degC, NAN if not available */
|
||||
float ac_current; /* A, NAN if not available */
|
||||
} victronble_ac_charger_t;
|
||||
|
||||
typedef struct {
|
||||
victronble_device_type_t type; /* decoded family (inverter collapsed) */
|
||||
uint8_t record_type; /* raw record type from the wire */
|
||||
uint16_t model_id;
|
||||
uint8_t readout_type;
|
||||
uint16_t nonce; /* data counter, as received */
|
||||
union {
|
||||
victronble_solar_charger_t solar;
|
||||
victronble_battery_monitor_t batmon;
|
||||
victronble_inverter_t inverter;
|
||||
victronble_dcdc_t dcdc;
|
||||
victronble_ac_charger_t ac;
|
||||
} u;
|
||||
} victronble_record_t;
|
||||
|
||||
/**
|
||||
* Decode one Victron manufacturer-data blob.
|
||||
*
|
||||
* @param mfg Manufacturer-specific data, starting at the company ID.
|
||||
* @param len Length of @p mfg in bytes.
|
||||
* @param key 16-byte per-device advertisement key.
|
||||
* @param out Populated on VICTRONBLE_OK; untouched otherwise.
|
||||
*
|
||||
* Reentrant, allocation-free, no I/O. Duplicate suppression (nonce
|
||||
* tracking) is the caller's job — the nonce is returned in @p out.
|
||||
*/
|
||||
victronble_err_t victronble_decode(const uint8_t *mfg, size_t len,
|
||||
const uint8_t key[VICTRONBLE_KEY_LEN],
|
||||
victronble_record_t *out);
|
||||
|
||||
/** Cheap pre-filter: company ID + product-advertisement record, no crypto. */
|
||||
bool victronble_is_product_adv(const uint8_t *mfg, size_t len);
|
||||
|
||||
/** Key check byte test — pick the right key from several without decrypting. */
|
||||
bool victronble_key_matches(const uint8_t *mfg, size_t len,
|
||||
const uint8_t key[VICTRONBLE_KEY_LEN]);
|
||||
|
||||
/** Parse a 32-hex-char advertisement key. Returns false on bad input. */
|
||||
bool victronble_parse_key(const char *hex, uint8_t key[VICTRONBLE_KEY_LEN]);
|
||||
|
||||
const char *victronble_strerror(victronble_err_t err);
|
||||
const char *victronble_device_type_str(victronble_device_type_t type);
|
||||
/** Short lower-case charger-state label ("bulk", "float", ...). */
|
||||
const char *victronble_state_str(uint8_t state);
|
||||
|
||||
/**
|
||||
* AES-128-CTR transform hook.
|
||||
*
|
||||
* @param key 16-byte key.
|
||||
* @param iv 16-byte initial counter block (nonce in the low bytes, rest 0).
|
||||
* @param in Ciphertext.
|
||||
* @param out Plaintext. May alias @p in.
|
||||
* @param len Byte count, not necessarily a multiple of 16.
|
||||
* @param user Opaque context supplied at registration.
|
||||
* @return 0 on success, negative on failure.
|
||||
*/
|
||||
typedef int (*victronble_aes_ctr_fn)(const uint8_t key[16],
|
||||
const uint8_t iv[16],
|
||||
const uint8_t *in, uint8_t *out,
|
||||
size_t len, void *user);
|
||||
|
||||
/** Override the AES backend at runtime (NULL restores the default). */
|
||||
void victronble_set_aes_ctr(victronble_aes_ctr_fn fn, void *user);
|
||||
|
||||
/**
|
||||
* Default AES backend. Weak symbol: the bundled software AES
|
||||
* (victronble_aes_sw.c) provides it; an alternative backend (PSA, mbedTLS,
|
||||
* hardware) may define it strong and the linker drops the bundled code.
|
||||
*/
|
||||
int victronble_aes_ctr_default(const uint8_t key[16], const uint8_t iv[16],
|
||||
const uint8_t *in, uint8_t *out,
|
||||
size_t len, void *user);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VICTRONBLE_CORE_H */
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <zephyr/bluetooth/addr.h>
|
||||
#include <zephyr/sys/slist.h>
|
||||
|
||||
#include "victronble.h"
|
||||
#include "victronble_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "victronble",
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1",
|
||||
"description": "Portable Arduino library for reading Victron Energy device data via Bluetooth Low Energy (BLE) advertisements. Runs on ESP32, ESP32-S3, ESP32-C3 and nRF52 (nRF52840, nRF52832). Supports SmartSolar MPPT, SmartShunt, BMV, MultiPlus, Orion, Blue Smart AC chargers and other Victron devices. No external crypto dependency. Also ships a Zephyr module (CONFIG_VICTRONBLE) and a dependency-free pure C99 core usable on any platform.",
|
||||
"keywords": "victron, ble, zephyr, bluetooth, solar, mppt, battery, smartshunt, smartsolar, bmv, inverter, multiplus, esp32, esp32-s3, esp32-c3, nrf52, nrf52840, nrf52832, xiao, iot, energy, monitoring",
|
||||
"repository": {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name=VictronBLE
|
||||
version=0.7.0
|
||||
version=0.7.1
|
||||
author=Scott Penrose
|
||||
maintainer=Scott Penrose <scottp@dd.com.au>
|
||||
sentence=Portable library for reading Victron Energy device data via BLE on ESP32/S3/C3 and nRF52 (nRF52840/nRF52832)
|
||||
|
||||
@@ -62,7 +62,7 @@ static const struct {
|
||||
|
||||
/*
|
||||
* A float field the device did not send comes back as NAN (see
|
||||
* include/victronble.h). Render that as "n/a" rather than letting "nan" leak
|
||||
* include/victronble_core.h). Render that as "n/a" rather than letting "nan" leak
|
||||
* into the log — a missing load-current reading is not a fault. The unit goes
|
||||
* in here too, so an absent field reads "n/a" and not "n/a A".
|
||||
*
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include "VictronBLE.h"
|
||||
#include "victronble.h"
|
||||
#include "victronble_core.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
#define VICTRON_BLE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "victronble.h" // pure C core: decode + decrypt (src/victronble_core.c)
|
||||
#include "victronble_core.h" // pure C core: decode + decrypt (src/victronble_core.c)
|
||||
|
||||
// --- Platform BLE backend selection ---
|
||||
// The BLE scanning layer is the only platform-specific part of the library.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
#include "victronble.h"
|
||||
#include "victronble_core.h"
|
||||
#include "crypto/vble_aes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* License: MIT
|
||||
*/
|
||||
|
||||
#include "victronble.h"
|
||||
#include "victronble_core.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
* path, so route to the canonical core header in include/. Zephyr and host
|
||||
* builds add include/ directly and never see this file first — both paths
|
||||
* end up in the same header (it has an include guard). */
|
||||
#include "../include/victronble.h"
|
||||
#include "../include/victronble_core.h"
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "victronble.h"
|
||||
#include "victronble_core.h"
|
||||
#include "test_vectors.h"
|
||||
|
||||
static int failures;
|
||||
|
||||
Reference in new issue
Block a user