Skip to content

Commit cf0010b

Browse files
committed
generic battery live view
this implements the battery live view component of the web application such that it works very generically. * lines in the status card are now generated from a list of values. * a value can be a string rather than a ValueObject, in which case it is used to place a translated text. * warnings and alarms are also generated from a list.
1 parent ca75a06 commit cf0010b

File tree

7 files changed

+186
-282
lines changed

7 files changed

+186
-282
lines changed

include/BatteryStats.h

+10
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ class BatteryStats {
2727
bool isValid() const { return _lastUpdateSoC > 0 && _lastUpdate > 0; }
2828

2929
protected:
30+
template<typename T>
31+
void addLiveViewValue(JsonVariant& root, std::string const& name,
32+
T&& value, std::string const& unit, uint8_t precision) const;
33+
void addLiveViewText(JsonVariant& root, std::string const& name,
34+
std::string const& text) const;
35+
void addLiveViewWarning(JsonVariant& root, std::string const& name,
36+
bool warning) const;
37+
void addLiveViewAlarm(JsonVariant& root, std::string const& name,
38+
bool alarm) const;
39+
3040
String _manufacturer = "unknown";
3141
uint8_t _SoC = 0;
3242
uint32_t _lastUpdateSoC = 0;

src/BatteryStats.cpp

+73-49
Original file line numberDiff line numberDiff line change
@@ -3,81 +3,105 @@
33
#include "MqttSettings.h"
44
#include "JkBmsDataPoints.h"
55

6+
template<typename T>
7+
void BatteryStats::addLiveViewValue(JsonVariant& root, std::string const& name,
8+
T&& value, std::string const& unit, uint8_t precision) const
9+
{
10+
auto jsonValue = root["values"][name];
11+
jsonValue["v"] = value;
12+
jsonValue["u"] = unit;
13+
jsonValue["d"] = precision;
14+
}
15+
16+
void BatteryStats::addLiveViewText(JsonVariant& root, std::string const& name,
17+
std::string const& text) const
18+
{
19+
root["values"][name] = text;
20+
}
21+
22+
void BatteryStats::addLiveViewWarning(JsonVariant& root, std::string const& name,
23+
bool warning) const
24+
{
25+
if (!warning) { return; }
26+
root["issues"][name] = 1;
27+
}
28+
29+
void BatteryStats::addLiveViewAlarm(JsonVariant& root, std::string const& name,
30+
bool alarm) const
31+
{
32+
if (!alarm) { return; }
33+
root["issues"][name] = 2;
34+
}
35+
636
void BatteryStats::getLiveViewData(JsonVariant& root) const
737
{
838
root[F("manufacturer")] = _manufacturer;
939
root[F("data_age")] = getAgeSeconds();
10-
root[F("stateOfCharge")]["v"] = _SoC;
11-
root[F("stateOfCharge")]["u"] = "%";
12-
root[F("stateOfCharge")]["d"] = 0;
40+
41+
addLiveViewValue(root, "SoC", _SoC, "%", 0);
1342
}
1443

1544
void PylontechBatteryStats::getLiveViewData(JsonVariant& root) const
1645
{
1746
BatteryStats::getLiveViewData(root);
1847

19-
root[F("chargeVoltage")]["v"] = _chargeVoltage;
20-
root[F("chargeVoltage")]["u"] = "V";
21-
root[F("chargeCurrentLimitation")]["v"] = _chargeCurrentLimitation;
22-
root[F("chargeCurrentLimitation")]["u"] = "A";
23-
root[F("dischargeCurrentLimitation")]["v"] = _dischargeCurrentLimitation;
24-
root[F("dischargeCurrentLimitation")]["u"] = "A";
25-
root[F("stateOfHealth")]["v"] = _stateOfHealth;
26-
root[F("stateOfHealth")]["u"] = "%";
27-
root[F("voltage")]["v"] = _voltage;
28-
root[F("voltage")]["u"] = "V";
29-
root[F("current")]["v"] = _current;
30-
root[F("current")]["u"] = "A";
31-
root[F("temperature")]["v"] = _temperature;
32-
root[F("temperature")]["u"] = "°C";
33-
34-
// Alarms
35-
root["alarms"][F("dischargeCurrent")] = _alarmOverCurrentDischarge;
36-
root["alarms"][F("chargeCurrent")] = _alarmOverCurrentCharge;
37-
root["alarms"][F("lowTemperature")] = _alarmUnderTemperature;
38-
root["alarms"][F("highTemperature")] = _alarmOverTemperature;
39-
root["alarms"][F("lowVoltage")] = _alarmUnderVoltage;
40-
root["alarms"][F("highVoltage")] = _alarmOverVoltage;
41-
root["alarms"][F("bmsInternal")] = _alarmBmsInternal;
42-
43-
// Warnings
44-
root["warnings"][F("dischargeCurrent")] = _warningHighCurrentDischarge;
45-
root["warnings"][F("chargeCurrent")] = _warningHighCurrentCharge;
46-
root["warnings"][F("lowTemperature")] = _warningLowTemperature;
47-
root["warnings"][F("highTemperature")] = _warningHighTemperature;
48-
root["warnings"][F("lowVoltage")] = _warningLowVoltage;
49-
root["warnings"][F("highVoltage")] = _warningHighVoltage;
50-
root["warnings"][F("bmsInternal")] = _warningBmsInternal;
51-
52-
// Misc
53-
root[F("chargeEnabled")] = _chargeEnabled;
54-
root[F("dischargeEnabled")] = _dischargeEnabled;
55-
root[F("chargeImmediately")] = _chargeImmediately;
48+
// values go into the "Status" card of the web application
49+
addLiveViewValue(root, "chargeVoltage", _chargeVoltage, "V", 1);
50+
addLiveViewValue(root, "chargeCurrentLimitation", _chargeCurrentLimitation, "A", 1);
51+
addLiveViewValue(root, "dischargeCurrentLimitation", _dischargeCurrentLimitation, "A", 1);
52+
addLiveViewValue(root, "stateOfHealth", _stateOfHealth, "%", 0);
53+
addLiveViewValue(root, "voltage", _voltage, "V", 2);
54+
addLiveViewValue(root, "current", _current, "A", 1);
55+
addLiveViewValue(root, "temperature", _temperature, "°C", 1);
56+
57+
addLiveViewText(root, "chargeEnabled", (_chargeEnabled?"yes":"no"));
58+
addLiveViewText(root, "dischargeEnabled", (_dischargeEnabled?"yes":"no"));
59+
addLiveViewText(root, "chargeImmediately", (_chargeImmediately?"yes":"no"));
60+
61+
// alarms and warnings go into the "Issues" card of the web application
62+
addLiveViewWarning(root, "highCurrentDischarge", _warningHighCurrentDischarge);
63+
addLiveViewAlarm(root, "overCurrentDischarge", _alarmOverCurrentDischarge);
64+
65+
addLiveViewWarning(root, "highCurrentCharge", _warningHighCurrentCharge);
66+
addLiveViewAlarm(root, "overCurrentCharge", _alarmOverCurrentCharge);
67+
68+
addLiveViewWarning(root, "lowTemperature", _warningLowTemperature);
69+
addLiveViewAlarm(root, "underTemperature", _alarmUnderTemperature);
70+
71+
addLiveViewWarning(root, "highTemperature", _warningHighTemperature);
72+
addLiveViewAlarm(root, "overTemperature", _alarmOverTemperature);
73+
74+
addLiveViewWarning(root, "lowVoltage", _warningLowVoltage);
75+
addLiveViewAlarm(root, "underVoltage", _alarmUnderVoltage);
76+
77+
addLiveViewWarning(root, "highVoltage", _warningHighVoltage);
78+
addLiveViewAlarm(root, "overVoltage", _alarmOverVoltage);
79+
80+
addLiveViewWarning(root, "bmsInternal", _warningBmsInternal);
81+
addLiveViewAlarm(root, "bmsInternal", _alarmBmsInternal);
5682
}
5783

5884
void JkBmsBatteryStats::getLiveViewData(JsonVariant& root) const
5985
{
86+
BatteryStats::getLiveViewData(root);
87+
6088
using Label = JkBms::DataPointLabel;
6189

6290
auto oVoltage = _dataPoints.get<Label::BatteryVoltageMilliVolt>();
6391
if (oVoltage.has_value()) {
64-
root[F("voltage")]["v"] = static_cast<float>(*oVoltage) / 1000;
65-
root[F("voltage")]["u"] = "V";
66-
root[F("voltage")]["d"] = 2;
92+
addLiveViewValue(root, "voltage",
93+
static_cast<float>(*oVoltage) / 1000, "V", 2);
6794
}
6895

6996
auto oCurrent = _dataPoints.get<Label::BatteryCurrentMilliAmps>();
7097
if (oCurrent.has_value()) {
71-
root[F("current")]["v"] = static_cast<float>(*oCurrent) / 1000;
72-
root[F("current")]["u"] = "A";
73-
root[F("current")]["d"] = 2;
98+
addLiveViewValue(root, "current",
99+
static_cast<float>(*oCurrent) / 1000, "A", 2);
74100
}
75101

76102
auto oTemperature = _dataPoints.get<Label::BatteryTempOneCelsius>();
77103
if (oTemperature.has_value()) {
78-
root[F("temperature")]["v"] = *oTemperature;
79-
root[F("temperature")]["u"] = "°C";
80-
root[F("temperature")]["d"] = 0;
104+
addLiveViewValue(root, "temperature", *oTemperature, "°C", 0);
81105
}
82106
}
83107

0 commit comments

Comments
 (0)