this change adds support for a second Victron MPPT charge controller using a second serial connection. * Add device configuration for a second victron mppt * Update VedirectView for second victron mppt * Update MqttHandleVedirect for second victron mppt * Update MqttHandleVedirectHass for second victron mppt * Handle nonexisting victron controllers with optionals * Add bool-function to Battery and inherited classes, if uart port 2 is being used * Introduced a serial port manager. In order to prevent the battery and the Victron MPPT to use the same hw serial ports, this class keeps track of the used ports and their owners.
119 lines
3.7 KiB
C++
119 lines
3.7 KiB
C++
#include <functional>
|
|
|
|
#include "Configuration.h"
|
|
#include "MqttBattery.h"
|
|
#include "MqttSettings.h"
|
|
#include "MessageOutput.h"
|
|
|
|
bool MqttBattery::init(bool verboseLogging)
|
|
{
|
|
_verboseLogging = verboseLogging;
|
|
|
|
auto const& config = Configuration.get();
|
|
|
|
_socTopic = config.Battery.MqttSocTopic;
|
|
if (!_socTopic.isEmpty()) {
|
|
MqttSettings.subscribe(_socTopic, 0/*QoS*/,
|
|
std::bind(&MqttBattery::onMqttMessageSoC,
|
|
this, std::placeholders::_1, std::placeholders::_2,
|
|
std::placeholders::_3, std::placeholders::_4,
|
|
std::placeholders::_5, std::placeholders::_6)
|
|
);
|
|
|
|
if (_verboseLogging) {
|
|
MessageOutput.printf("MqttBattery: Subscribed to '%s' for SoC readings\r\n",
|
|
_socTopic.c_str());
|
|
}
|
|
}
|
|
|
|
_voltageTopic = config.Battery.MqttVoltageTopic;
|
|
if (!_voltageTopic.isEmpty()) {
|
|
MqttSettings.subscribe(_voltageTopic, 0/*QoS*/,
|
|
std::bind(&MqttBattery::onMqttMessageVoltage,
|
|
this, std::placeholders::_1, std::placeholders::_2,
|
|
std::placeholders::_3, std::placeholders::_4,
|
|
std::placeholders::_5, std::placeholders::_6)
|
|
);
|
|
|
|
if (_verboseLogging) {
|
|
MessageOutput.printf("MqttBattery: Subscribed to '%s' for voltage readings\r\n",
|
|
_voltageTopic.c_str());
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void MqttBattery::deinit()
|
|
{
|
|
if (!_voltageTopic.isEmpty()) {
|
|
MqttSettings.unsubscribe(_voltageTopic);
|
|
}
|
|
|
|
if (!_socTopic.isEmpty()) {
|
|
MqttSettings.unsubscribe(_socTopic);
|
|
}
|
|
}
|
|
|
|
std::optional<float> MqttBattery::getFloat(std::string const& src, char const* topic) {
|
|
float res = 0;
|
|
|
|
try {
|
|
res = std::stof(src);
|
|
}
|
|
catch(std::invalid_argument const& e) {
|
|
MessageOutput.printf("MqttBattery: Cannot parse payload '%s' in topic '%s' as float\r\n",
|
|
src.c_str(), topic);
|
|
return std::nullopt;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void MqttBattery::onMqttMessageSoC(espMqttClientTypes::MessageProperties const& properties,
|
|
char const* topic, uint8_t const* payload, size_t len, size_t index, size_t total)
|
|
{
|
|
auto soc = getFloat(std::string(reinterpret_cast<const char*>(payload), len), topic);
|
|
if (!soc.has_value()) { return; }
|
|
|
|
if (*soc < 0 || *soc > 100) {
|
|
MessageOutput.printf("MqttBattery: Implausible SoC '%.2f' in topic '%s'\r\n",
|
|
*soc, topic);
|
|
return;
|
|
}
|
|
|
|
_stats->setSoC(*soc, 0/*precision*/, millis());
|
|
|
|
if (_verboseLogging) {
|
|
MessageOutput.printf("MqttBattery: Updated SoC to %d from '%s'\r\n",
|
|
static_cast<uint8_t>(*soc), topic);
|
|
}
|
|
}
|
|
|
|
void MqttBattery::onMqttMessageVoltage(espMqttClientTypes::MessageProperties const& properties,
|
|
char const* topic, uint8_t const* payload, size_t len, size_t index, size_t total)
|
|
{
|
|
auto voltage = getFloat(std::string(reinterpret_cast<const char*>(payload), len), topic);
|
|
if (!voltage.has_value()) { return; }
|
|
|
|
// since this project is revolving around Hoymiles microinverters, which can
|
|
// only handle up to 65V of input voltage at best, it is safe to assume that
|
|
// an even higher voltage is implausible.
|
|
if (*voltage < 0 || *voltage > 65) {
|
|
MessageOutput.printf("MqttBattery: Implausible voltage '%.2f' in topic '%s'\r\n",
|
|
*voltage, topic);
|
|
return;
|
|
}
|
|
|
|
_stats->setVoltage(*voltage, millis());
|
|
|
|
if (_verboseLogging) {
|
|
MessageOutput.printf("MqttBattery: Updated voltage to %.2f from '%s'\r\n",
|
|
*voltage, topic);
|
|
}
|
|
}
|
|
|
|
bool MqttBattery::usesHwPort2() {
|
|
return false;
|
|
}
|