From 0863f8572c051f7c575d39765d4eb93f037d21f6 Mon Sep 17 00:00:00 2001 From: Scott Penrose Date: Mon, 29 Dec 2025 20:00:05 +1100 Subject: [PATCH] Finally working decode MPPT --- examples/MultiDevice/src/main.cpp | 32 ------------------------------- src/VictronBLE.cpp | 17 ++++++++-------- src/VictronBLE.h | 17 ++++++++-------- 3 files changed, 16 insertions(+), 50 deletions(-) diff --git a/examples/MultiDevice/src/main.cpp b/examples/MultiDevice/src/main.cpp index 8306fb2..7126308 100644 --- a/examples/MultiDevice/src/main.cpp +++ b/examples/MultiDevice/src/main.cpp @@ -176,38 +176,6 @@ void setup() { DEVICE_TYPE_SOLAR_CHARGER // Device type ); - // XXX These numbers make no sesne, one above is correct - wrong MAC? - victron.addDevice( - "Rainbow48Vb", // Device name - "3ffd00b83ffd00be", - "0ec3adf7433dd61793ff2f3b8ad32ed8", // Encryption key (32 hex chars) - DEVICE_TYPE_SOLAR_CHARGER // Device type - ); - - // WHY this one work? - victron.addDevice( - "Rainbow48Vc", // Device name - "3ffd00a83ffd00ae", - "0ec3adf7433dd61793ff2f3b8ad32ed8", // Encryption key (32 hex chars) - DEVICE_TYPE_SOLAR_CHARGER // Device type - ); - - // WHY this one work? - victron.addDevice( - "Rainbow48Vd", // Device name - "3fca91c83fca91ce", - "0ec3adf7433dd61793ff2f3b8ad32ed8", // Encryption key (32 hex chars) - DEVICE_TYPE_SOLAR_CHARGER // Device type - ); - - // WHY this one work? - victron.addDevice( - "Rainbow48Vf", // Device name - "3fcf38283fcf382e", - "0ec3adf7433dd61793ff2f3b8ad32ed8", // Encryption key (32 hex chars) - DEVICE_TYPE_SOLAR_CHARGER // Device type - ); - // Example: Solar Charger #1 /* victron.addDevice( diff --git a/src/VictronBLE.cpp b/src/VictronBLE.cpp index e4fb5ea..70e3a74 100644 --- a/src/VictronBLE.cpp +++ b/src/VictronBLE.cpp @@ -147,7 +147,7 @@ void VictronBLE::processDevice(BLEAdvertisedDevice advertisedDevice) { // Get MAC address from the advertised device String mac = macAddressToString(advertisedDevice.getAddress()); String normalizedMAC = normalizeMAC(mac); - + if (debugEnabled) { debugPrint("Raw MAC: " + mac + " -> Normalized: " + normalizedMAC); } @@ -244,16 +244,15 @@ bool VictronBLE::parseAdvertisement(const String& macAddress) { if (debugEnabled) { debugPrint("Vendor ID: 0x" + String(manufacturerData.vendorID, HEX)); + // XXX What is beaconType and modelID and readoutType debugPrint("Beacon Type: 0x" + String(manufacturerData.beaconType, HEX)); - debugPrint("Model ID: 0x" + String(manufacturerData.modelID, HEX)); - debugPrint("Readout Type: 0x" + String(manufacturerData.readoutType, HEX)); + // debugPrint("Model ID: 0x" + String(manufacturerData.modelID, HEX)); + // debugPrint("Readout Type: 0x" + String(manufacturerData.readoutType, HEX)); + // recordType - e.g. MPPT ? debugPrint("Record Type: 0x" + String(manufacturerData.victronRecordType, HEX)); debugPrint("Nonce: 0x" + String(manufacturerData.nonceDataCounter, HEX)); } - // Get device type from record type field - uint8_t deviceType = manufacturerData.victronRecordType; - // Build IV (initialization vector) from nonce // IV is 16 bytes: nonce (2 bytes little-endian) + zeros (14 bytes) uint8_t iv[16] = {0}; @@ -273,7 +272,7 @@ bool VictronBLE::parseAdvertisement(const String& macAddress) { // Parse based on device type bool parseOk = false; - switch (deviceType) { + switch (manufacturerData.victronRecordType) { case DEVICE_TYPE_SOLAR_CHARGER: if (deviceInfo->data && deviceInfo->data->deviceType == DEVICE_TYPE_SOLAR_CHARGER) { parseOk = parseSolarCharger(decrypted, sizeof(decrypted), @@ -306,7 +305,7 @@ bool VictronBLE::parseAdvertisement(const String& macAddress) { break; default: - debugPrint("Unknown device type: 0x" + String(deviceType, HEX)); + debugPrint("Unknown device type: 0x" + String(manufacturerData.victronRecordType, HEX)); return false; } @@ -315,7 +314,7 @@ bool VictronBLE::parseAdvertisement(const String& macAddress) { // Call appropriate callback if (callback) { - switch (deviceType) { + switch (manufacturerData.victronRecordType) { case DEVICE_TYPE_SOLAR_CHARGER: callback->onSolarChargerData(*(SolarChargerData*)deviceInfo->data); break; diff --git a/src/VictronBLE.h b/src/VictronBLE.h index 40b106e..aefdf3b 100644 --- a/src/VictronBLE.h +++ b/src/VictronBLE.h @@ -58,16 +58,15 @@ enum SolarChargerState { // Manufacturer data structure (outer envelope) typedef struct { - uint16_t vendorID; // Victron vendor ID (0x02E1) - uint8_t beaconType; // Should be 0x10 (Product Advertisement) - uint8_t modelID; // Model identifier byte - uint8_t readoutType; // Type of data readout - uint8_t victronRecordType; // Record type (device type) - uint16_t nonceDataCounter; // Nonce for encryption (IV bytes 0-1) - uint8_t encryptKeyMatch; // Should match pre-shared encryption key byte 0 - uint8_t victronEncryptedData[21]; // Encrypted payload (max 21 bytes) + uint16_t vendorID; // vendor ID + uint8_t beaconType; // Should be 0x10 (Product Advertisement) for the packets we want + uint8_t unknownData1[3]; // Unknown data + uint8_t victronRecordType; // Should be 0x01 (Solar Charger) for the packets we want + uint16_t nonceDataCounter; // Nonce + uint8_t encryptKeyMatch; // Should match pre-shared encryption key byte 0 + uint8_t victronEncryptedData[21]; // (31 bytes max per BLE spec - size of previous elements) + uint8_t nullPad; // extra byte because toCharArray() adds a \0 byte. } __attribute__((packed)) victronManufacturerData; - // Decrypted payload structures for each device type // Solar Charger decrypted payload