diff --git a/include/BatteryStats.h b/include/BatteryStats.h index 287f0d1b1..916bf3115 100644 --- a/include/BatteryStats.h +++ b/include/BatteryStats.h @@ -17,7 +17,7 @@ class BatteryStats { uint32_t getAgeSeconds() const { return (millis() - _lastUpdate) / 1000; } bool updateAvailable(uint32_t since) const { return _lastUpdate > since; } - uint8_t getSoC() const { return _SoC; } + uint8_t getSoC() const { return _soc; } uint32_t getSoCAgeSeconds() const { return (millis() - _lastUpdateSoC) / 1000; } float getVoltage() const { return _voltage; } @@ -36,18 +36,26 @@ class BatteryStats { protected: virtual void mqttPublish() const; + + void setSoC(float soc, uint8_t precision, uint32_t timestamp) { + _soc = soc; + _socPrecision = precision; + _lastUpdateSoC = timestamp; + } + void setVoltage(float voltage, uint32_t timestamp) { _voltage = voltage; _lastUpdateVoltage = timestamp; } String _manufacturer = "unknown"; - uint8_t _SoC = 0; - uint32_t _lastUpdateSoC = 0; uint32_t _lastUpdate = 0; private: uint32_t _lastMqttPublish = 0; + float _soc = 0; + uint8_t _socPrecision = 0; // decimal places + uint32_t _lastUpdateSoC = 0; float _voltage = 0; // total battery pack voltage uint32_t _lastUpdateVoltage = 0; }; @@ -61,7 +69,6 @@ class PylontechBatteryStats : public BatteryStats { private: void setManufacturer(String&& m) { _manufacturer = std::move(m); } - void setSoC(uint8_t SoC) { _SoC = SoC; _lastUpdateSoC = millis(); } void setLastUpdate(uint32_t ts) { _lastUpdate = ts; } float _chargeVoltage; @@ -155,9 +162,7 @@ class MqttBatteryStats : public BatteryStats { // we do NOT publish the same data under a different topic. void mqttPublish() const final { } - // the SoC is the only interesting value in this case, which is already - // displayed at the top of the live view. do not generate a card. + // if the voltage is subscribed to at all, it alone does not warrant a + // card in the live view, since the SoC is already displayed at the top void getLiveViewData(JsonVariant& root) const final { } - - void setSoC(uint8_t SoC) { _SoC = SoC; _lastUpdateSoC = _lastUpdate = millis(); } }; diff --git a/src/BatteryStats.cpp b/src/BatteryStats.cpp index 976694bf6..807f1a4c2 100644 --- a/src/BatteryStats.cpp +++ b/src/BatteryStats.cpp @@ -56,7 +56,7 @@ void BatteryStats::getLiveViewData(JsonVariant& root) const root[F("manufacturer")] = _manufacturer; root[F("data_age")] = getAgeSeconds(); - addLiveViewValue(root, "SoC", _SoC, "%", 0); + addLiveViewValue(root, "SoC", _soc, "%", _socPrecision); addLiveViewValue(root, "voltage", _voltage, "V", 2); } @@ -212,7 +212,7 @@ void BatteryStats::mqttPublish() const { MqttSettings.publish(F("battery/manufacturer"), _manufacturer); MqttSettings.publish(F("battery/dataAge"), String(getAgeSeconds())); - MqttSettings.publish(F("battery/stateOfCharge"), String(_SoC)); + MqttSettings.publish(F("battery/stateOfCharge"), String(_soc)); MqttSettings.publish(F("battery/voltage"), String(_voltage)); } @@ -334,9 +334,9 @@ void JkBmsBatteryStats::updateFrom(JkBms::DataPointContainer const& dp) auto oSoCValue = dp.get(); if (oSoCValue.has_value()) { - _SoC = *oSoCValue; auto oSoCDataPoint = dp.getDataPointFor(); - _lastUpdateSoC = oSoCDataPoint->getTimestamp(); + BatteryStats::setSoC(*oSoCValue, 0/*precision*/, + oSoCDataPoint->getTimestamp()); } auto oVoltage = dp.get(); @@ -367,8 +367,8 @@ void JkBmsBatteryStats::updateFrom(JkBms::DataPointContainer const& dp) void VictronSmartShuntStats::updateFrom(VeDirectShuntController::veShuntStruct const& shuntData) { BatteryStats::setVoltage(shuntData.V, millis()); + BatteryStats::setSoC(static_cast(shuntData.SOC) / 10, 1/*precision*/, millis()); - _SoC = shuntData.SOC / 10; _current = shuntData.I; _modelName = shuntData.getPidAsString().data(); _chargeCycles = shuntData.H4; @@ -387,7 +387,6 @@ void VictronSmartShuntStats::updateFrom(VeDirectShuntController::veShuntStruct c _alarmHighTemperature = shuntData.AR & 64; _lastUpdate = VeDirectShunt.getLastUpdate(); - _lastUpdateSoC = VeDirectShunt.getLastUpdate(); } void VictronSmartShuntStats::getLiveViewData(JsonVariant& root) const { diff --git a/src/MqttBattery.cpp b/src/MqttBattery.cpp index f44299415..963fc82c2 100644 --- a/src/MqttBattery.cpp +++ b/src/MqttBattery.cpp @@ -82,7 +82,7 @@ void MqttBattery::onMqttMessageSoC(espMqttClientTypes::MessageProperties const& return; } - _stats->setSoC(static_cast(*soc)); + _stats->setSoC(*soc, 0/*precision*/, millis()); if (_verboseLogging) { MessageOutput.printf("MqttBattery: Updated SoC to %d from '%s'\r\n", diff --git a/src/PylontechCanReceiver.cpp b/src/PylontechCanReceiver.cpp index 8091f1df1..e19cff599 100644 --- a/src/PylontechCanReceiver.cpp +++ b/src/PylontechCanReceiver.cpp @@ -136,7 +136,7 @@ void PylontechCanReceiver::loop() } case 0x355: { - _stats->setSoC(static_cast(this->readUnsignedInt16(rx_message.data))); + _stats->setSoC(static_cast(this->readUnsignedInt16(rx_message.data)), 0/*precision*/, millis()); _stats->_stateOfHealth = this->readUnsignedInt16(rx_message.data + 2); if (_verboseLogging) { @@ -282,7 +282,7 @@ void PylontechCanReceiver::dummyData() }; _stats->setManufacturer("Pylontech US3000C"); - _stats->setSoC(42); + _stats->setSoC(42, 0/*precision*/, millis()); _stats->_chargeVoltage = dummyFloat(50); _stats->_chargeCurrentLimitation = dummyFloat(33); _stats->_dischargeCurrentLimitation = dummyFloat(12);