Skip to content

Commit 88314f9

Browse files
committed
Fix: properly format Victron MPPT firmware version
1 parent 90eb25f commit 88314f9

File tree

10 files changed

+59
-18
lines changed

10 files changed

+59
-18
lines changed

lib/VeDirectFrameHandler/VeDirectData.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,44 @@ frozen::string const& veStruct::getPidAsString() const
137137
return getAsString(values, productID_PID);
138138
}
139139

140+
/*
141+
* This function returns the firmware version as an integer, disregarding
142+
* release candidate marks.
143+
*/
144+
uint32_t veStruct::getFwVersionAsInteger() const
145+
{
146+
char const* strVersion = firmwareVer_FW;
147+
148+
// VE.Direct protocol manual states that the first char can be a non-digit,
149+
// in which case that char represents a release candidate version
150+
if (strVersion[0] < '0' || strVersion[0] > '9') { ++strVersion; }
151+
152+
return static_cast<uint32_t>(strtoul(strVersion, nullptr, 10));
153+
}
154+
155+
/*
156+
* This function returns the firmware version as readable text.
157+
*/
158+
String veStruct::getFwVersionFormatted() const
159+
{
160+
char const* strVersion = firmwareVer_FW;
161+
162+
// VE.Direct protocol manual states that the first char can be a non-digit,
163+
// in which case that char represents a release candidate version
164+
if (strVersion[0] < '0' || strVersion[0] > '9') { ++strVersion; }
165+
166+
String res(strVersion[0]);
167+
res += ".";
168+
res += strVersion + 1;
169+
170+
if (strVersion > firmwareVer_FW) {
171+
res += "-rc-";
172+
res += firmwareVer_FW[0];
173+
}
174+
175+
return res;
176+
}
177+
140178
/*
141179
* This function returns the state of operations (CS) as readable text.
142180
*/

lib/VeDirectFrameHandler/VeDirectData.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@
22

33
#include <frozen/string.h>
44
#include <frozen/map.h>
5+
#include <Arduino.h>
56

67
#define VE_MAX_VALUE_LEN 33 // VE.Direct Protocol: max value size is 33 including /0
78
#define VE_MAX_HEX_LEN 100 // Maximum size of hex frame - max payload 34 byte (=68 char) + safe buffer
89

910
typedef struct {
1011
uint16_t productID_PID = 0; // product id
1112
char serialNr_SER[VE_MAX_VALUE_LEN]; // serial number
12-
char firmwareNr_FW[VE_MAX_VALUE_LEN]; // firmware release number
13+
char firmwareVer_FW[VE_MAX_VALUE_LEN]; // firmware release number
1314
uint32_t batteryVoltage_V_mV = 0; // battery voltage in mV
1415
int32_t batteryCurrent_I_mA = 0; // battery current in mA (can be negative)
1516
float mpptEfficiency_Percent = 0; // efficiency in percent (calculated, moving average)
1617

1718
frozen::string const& getPidAsString() const; // product ID as string
19+
uint32_t getFwVersionAsInteger() const;
20+
String getFwVersionFormatted() const;
1821
} veStruct;
1922

2023
struct veMpptStruct : veStruct {

lib/VeDirectFrameHandler/VeDirectFrameHandler.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ void VeDirectFrameHandler<T>::processTextData(std::string const& name, std::stri
247247
}
248248

249249
if (name == "FW") {
250-
strcpy(_tmpFrame.firmwareNr_FW, value.c_str());
250+
strcpy(_tmpFrame.firmwareVer_FW, value.c_str());
251251
return;
252252
}
253253

lib/VeDirectFrameHandler/VeDirectMpptController.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ void VeDirectMpptController::frameValidEvent() {
110110
// charger periodically sends human readable (TEXT) data to the serial port. For firmware
111111
// versions v1.53 and above, the charger always periodically sends TEXT data to the serial port.
112112
// --> We just use hex commandes for firmware >= 1.53 to keep text messages alive
113-
if (atoi(_tmpFrame.firmwareNr_FW) < 153) { return; }
113+
if (_tmpFrame.getFwVersionAsInteger() < 153) { return; }
114114

115115
using Command = VeDirectHexCommand;
116116
using Register = VeDirectHexRegister;

src/MqttHandleVedirect.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ void MqttHandleVedirectClass::publish_mppt_data(const VeDirectMpptController::da
110110

111111
PUBLISH(productID_PID, "PID", currentData.getPidAsString().data());
112112
PUBLISH(serialNr_SER, "SER", currentData.serialNr_SER);
113-
PUBLISH(firmwareNr_FW, "FW", currentData.firmwareNr_FW);
113+
PUBLISH(firmwareVer_FW, "FW", currentData.firmwareVer_FW);
114114
PUBLISH(loadOutputState_LOAD, "LOAD", (currentData.loadOutputState_LOAD ? "ON" : "OFF"));
115115
PUBLISH(currentState_CS, "CS", currentData.getCsAsString().data());
116116
PUBLISH(errorCode_ERR, "ERR", currentData.getErrAsString().data());

src/WebApi_ws_vedirect_live.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ void WebApiWsVedirectLiveClass::generateCommonJsonResponse(JsonVariant& root, bo
139139

140140
void WebApiWsVedirectLiveClass::populateJson(const JsonObject &root, const VeDirectMpptController::data_t &mpptData) {
141141
root["product_id"] = mpptData.getPidAsString();
142-
root["firmware_version"] = String(mpptData.firmwareNr_FW);
142+
root["firmware_version"] = mpptData.getFwVersionFormatted();
143143

144144
const JsonObject values = root["values"].to<JsonObject>();
145145

webapp/src/components/VedirectView.vue

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
{{ item.product_id }}
2222
</div>
2323
<div style="padding-right: 2em;">
24-
{{ $t('vedirecthome.SerialNumber') }} {{ serial }}
24+
{{ $t('vedirecthome.SerialNumber') }}: {{ serial }}
2525
</div>
2626
<div style="padding-right: 2em;">
27-
{{ $t('vedirecthome.FirmwareNumber') }} {{ item.firmware_version }}
27+
{{ $t('vedirecthome.FirmwareVersion') }}: {{ item.firmware_version }}
2828
</div>
2929
<div style="padding-right: 2em;">
30-
{{ $t('vedirecthome.DataAge') }} {{ $t('vedirecthome.Seconds', {'val': Math.floor(item.data_age_ms / 1000)}) }}
30+
{{ $t('vedirecthome.DataAge') }}: {{ $t('vedirecthome.Seconds', {'val': Math.floor(item.data_age_ms / 1000)}) }}
3131
</div>
3232
</div>
3333
</div>

webapp/src/locales/de.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@
152152
"LoadingInverter": "Warte auf Daten... (kann bis zu 10 Sekunden dauern)"
153153
},
154154
"vedirecthome": {
155-
"SerialNumber": "Seriennummer: ",
156-
"FirmwareNumber": "Firmware Version: ",
157-
"DataAge": "letzte Aktualisierung: ",
155+
"SerialNumber": "Seriennummer",
156+
"FirmwareVersion": "Firmware-Version",
157+
"DataAge": "letzte Aktualisierung",
158158
"Seconds": "vor {val} Sekunden",
159159
"Property": "Eigenschaft",
160160
"Value": "Wert",

webapp/src/locales/en.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@
152152
"LoadingInverter": "Waiting for data... (can take up to 10 seconds)"
153153
},
154154
"vedirecthome": {
155-
"SerialNumber": "Serial Number: ",
156-
"FirmwareNumber": "Firmware Number: ",
157-
"DataAge": "Data Age: ",
155+
"SerialNumber": "Serial Number",
156+
"FirmwareVersion": "Firmware Version",
157+
"DataAge": "Data Age",
158158
"Seconds": "{val} seconds",
159159
"Property": "Property",
160160
"Value": "Value",

webapp/src/locales/fr.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,10 @@
152152
"LoadingInverter": "Waiting for data... (can take up to 10 seconds)"
153153
},
154154
"vedirecthome": {
155-
"SerialNumber": "Serial Number: ",
156-
"FirmwareNumber": "Firmware Number: ",
157-
"DataAge": "Data Age: ",
158-
"Seconds": "{val} seconds",
155+
"SerialNumber": "Numéro de série",
156+
"FirmwareVersion": "Version du Firmware",
157+
"DataAge": "Âge des données",
158+
"Seconds": "{val} secondes",
159159
"Property": "Property",
160160
"Value": "Value",
161161
"Unit": "Unit",

0 commit comments

Comments
 (0)