VE.Direct: simplify access to data
hand out const& to the data structs. this is possible now that this struct is "stable", i.e., not reset regularly.
This commit is contained in:
parent
ad125ea804
commit
b299b9dc6c
@ -33,7 +33,7 @@ private:
|
|||||||
|
|
||||||
bool _PublishFull;
|
bool _PublishFull;
|
||||||
|
|
||||||
void publish_mppt_data(const VeDirectMpptController::spData_t &spMpptData,
|
void publish_mppt_data(const VeDirectMpptController::data_t &mpptData,
|
||||||
const VeDirectMpptController::data_t &frame) const;
|
const VeDirectMpptController::data_t &frame) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -16,13 +16,13 @@ private:
|
|||||||
void publish(const String& subtopic, const String& payload);
|
void publish(const String& subtopic, const String& payload);
|
||||||
void publishBinarySensor(const char *caption, const char *icon, const char *subTopic,
|
void publishBinarySensor(const char *caption, const char *icon, const char *subTopic,
|
||||||
const char *payload_on, const char *payload_off,
|
const char *payload_on, const char *payload_off,
|
||||||
const VeDirectMpptController::spData_t &spMpptData);
|
const VeDirectMpptController::data_t &mpptData);
|
||||||
void publishSensor(const char *caption, const char *icon, const char *subTopic,
|
void publishSensor(const char *caption, const char *icon, const char *subTopic,
|
||||||
const char *deviceClass, const char *stateClass,
|
const char *deviceClass, const char *stateClass,
|
||||||
const char *unitOfMeasurement,
|
const char *unitOfMeasurement,
|
||||||
const VeDirectMpptController::spData_t &spMpptData);
|
const VeDirectMpptController::data_t &mpptData);
|
||||||
void createDeviceInfo(JsonObject &object,
|
void createDeviceInfo(JsonObject &object,
|
||||||
const VeDirectMpptController::spData_t &spMpptData);
|
const VeDirectMpptController::data_t &mpptData);
|
||||||
|
|
||||||
Task _loopTask;
|
Task _loopTask;
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ public:
|
|||||||
uint32_t getDataAgeMillis(size_t idx) const;
|
uint32_t getDataAgeMillis(size_t idx) const;
|
||||||
|
|
||||||
size_t controllerAmount() const { return _controllers.size(); }
|
size_t controllerAmount() const { return _controllers.size(); }
|
||||||
std::optional<VeDirectMpptController::spData_t> getData(size_t idx = 0) const;
|
std::optional<VeDirectMpptController::data_t> getData(size_t idx = 0) const;
|
||||||
|
|
||||||
// total output of all MPPT charge controllers in Watts
|
// total output of all MPPT charge controllers in Watts
|
||||||
int32_t getPowerOutputWatts() const;
|
int32_t getPowerOutputWatts() const;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void generateJsonResponse(JsonVariant& root, bool fullUpdate);
|
void generateJsonResponse(JsonVariant& root, bool fullUpdate);
|
||||||
static void populateJson(const JsonObject &root, const VeDirectMpptController::spData_t &spMpptData);
|
static void populateJson(const JsonObject &root, const VeDirectMpptController::data_t &mpptData);
|
||||||
void onLivedataStatus(AsyncWebServerRequest* request);
|
void onLivedataStatus(AsyncWebServerRequest* request);
|
||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
bool hasUpdate(size_t idx);
|
bool hasUpdate(size_t idx);
|
||||||
|
|||||||
@ -24,6 +24,7 @@ public:
|
|||||||
void loop(); // main loop to read ve.direct data
|
void loop(); // main loop to read ve.direct data
|
||||||
uint32_t getLastUpdate() const; // timestamp of last successful frame read
|
uint32_t getLastUpdate() const; // timestamp of last successful frame read
|
||||||
bool isDataValid() const; // return true if data valid and not outdated
|
bool isDataValid() const; // return true if data valid and not outdated
|
||||||
|
T const& getData() const { return _tmpFrame; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
VeDirectFrameHandler();
|
VeDirectFrameHandler();
|
||||||
@ -41,7 +42,7 @@ private:
|
|||||||
void rxData(uint8_t inbyte); // byte of serial data
|
void rxData(uint8_t inbyte); // byte of serial data
|
||||||
void processTextData(std::string const& name, std::string const& value);
|
void processTextData(std::string const& name, std::string const& value);
|
||||||
virtual bool processTextDataDerived(std::string const& name, std::string const& value) = 0;
|
virtual bool processTextDataDerived(std::string const& name, std::string const& value) = 0;
|
||||||
virtual void frameValidEvent() = 0;
|
virtual void frameValidEvent() { }
|
||||||
int hexRxEvent(uint8_t);
|
int hexRxEvent(uint8_t);
|
||||||
|
|
||||||
std::unique_ptr<HardwareSerial> _vedirectSerial;
|
std::unique_ptr<HardwareSerial> _vedirectSerial;
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
void VeDirectMpptController::init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging, uint16_t hwSerialPort)
|
void VeDirectMpptController::init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging, uint16_t hwSerialPort)
|
||||||
{
|
{
|
||||||
VeDirectFrameHandler::init("MPPT", rx, tx, msgOut, verboseLogging, hwSerialPort);
|
VeDirectFrameHandler::init("MPPT", rx, tx, msgOut, verboseLogging, hwSerialPort);
|
||||||
_spData = std::make_shared<veMpptStruct>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VeDirectMpptController::processTextDataDerived(std::string const& name, std::string const& value)
|
bool VeDirectMpptController::processTextDataDerived(std::string const& name, std::string const& value)
|
||||||
@ -80,6 +79,4 @@ void VeDirectMpptController::frameValidEvent() {
|
|||||||
_efficiency.addNumber(static_cast<double>(_tmpFrame.P * 100) / _tmpFrame.PPV);
|
_efficiency.addNumber(static_cast<double>(_tmpFrame.P * 100) / _tmpFrame.PPV);
|
||||||
_tmpFrame.E = _efficiency.getAverage();
|
_tmpFrame.E = _efficiency.getAverage();
|
||||||
}
|
}
|
||||||
|
|
||||||
_spData = std::make_shared<veMpptStruct>(_tmpFrame);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,12 +43,9 @@ public:
|
|||||||
void init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging, uint16_t hwSerialPort);
|
void init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging, uint16_t hwSerialPort);
|
||||||
|
|
||||||
using data_t = veMpptStruct;
|
using data_t = veMpptStruct;
|
||||||
using spData_t = std::shared_ptr<data_t const>;
|
|
||||||
spData_t getData() const { return _spData; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool processTextDataDerived(std::string const& name, std::string const& value) final;
|
bool processTextDataDerived(std::string const& name, std::string const& value) final;
|
||||||
void frameValidEvent() final;
|
void frameValidEvent() final;
|
||||||
spData_t _spData = nullptr;
|
|
||||||
MovingAverage<double, 5> _efficiency;
|
MovingAverage<double, 5> _efficiency;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -110,11 +110,3 @@ bool VeDirectShuntController::processTextDataDerived(std::string const& name, st
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* frameValidEvent
|
|
||||||
* This function is called at the end of the received frame.
|
|
||||||
*/
|
|
||||||
void VeDirectShuntController::frameValidEvent() {
|
|
||||||
veFrame = _tmpFrame;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -11,11 +11,9 @@ public:
|
|||||||
void init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging);
|
void init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging);
|
||||||
|
|
||||||
using data_t = veShuntStruct;
|
using data_t = veShuntStruct;
|
||||||
data_t veFrame{};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool processTextDataDerived(std::string const& name, std::string const& value) final;
|
bool processTextDataDerived(std::string const& name, std::string const& value) final;
|
||||||
void frameValidEvent() final;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern VeDirectShuntController VeDirectShunt;
|
extern VeDirectShuntController VeDirectShunt;
|
||||||
|
|||||||
@ -58,42 +58,33 @@ void MqttHandleVedirectHassClass::publishConfig()
|
|||||||
|
|
||||||
// device info
|
// device info
|
||||||
for (int idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
for (int idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
||||||
// ensure data is received from victron
|
auto optMpptData = VictronMppt.getData(idx);
|
||||||
if (!VictronMppt.isDataValid(idx)) {
|
if (!optMpptData.has_value()) { continue; }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<VeDirectMpptController::spData_t> spOptMpptData = VictronMppt.getData(idx);
|
publishBinarySensor("MPPT load output state", "mdi:export", "LOAD", "ON", "OFF", *optMpptData);
|
||||||
if (!spOptMpptData.has_value()) {
|
publishSensor("MPPT serial number", "mdi:counter", "SER", nullptr, nullptr, nullptr, *optMpptData);
|
||||||
continue;
|
publishSensor("MPPT firmware number", "mdi:counter", "FW", nullptr, nullptr, nullptr, *optMpptData);
|
||||||
}
|
publishSensor("MPPT state of operation", "mdi:wrench", "CS", nullptr, nullptr, nullptr, *optMpptData);
|
||||||
|
publishSensor("MPPT error code", "mdi:bell", "ERR", nullptr, nullptr, nullptr, *optMpptData);
|
||||||
VeDirectMpptController::spData_t &spMpptData = spOptMpptData.value();
|
publishSensor("MPPT off reason", "mdi:wrench", "OR", nullptr, nullptr, nullptr, *optMpptData);
|
||||||
|
publishSensor("MPPT tracker operation mode", "mdi:wrench", "MPPT", nullptr, nullptr, nullptr, *optMpptData);
|
||||||
publishBinarySensor("MPPT load output state", "mdi:export", "LOAD", "ON", "OFF", spMpptData);
|
publishSensor("MPPT Day sequence number (0...364)", "mdi:calendar-month-outline", "HSDS", NULL, "total", "d", *optMpptData);
|
||||||
publishSensor("MPPT serial number", "mdi:counter", "SER", nullptr, nullptr, nullptr, spMpptData);
|
|
||||||
publishSensor("MPPT firmware number", "mdi:counter", "FW", nullptr, nullptr, nullptr, spMpptData);
|
|
||||||
publishSensor("MPPT state of operation", "mdi:wrench", "CS", nullptr, nullptr, nullptr, spMpptData);
|
|
||||||
publishSensor("MPPT error code", "mdi:bell", "ERR", nullptr, nullptr, nullptr, spMpptData);
|
|
||||||
publishSensor("MPPT off reason", "mdi:wrench", "OR", nullptr, nullptr, nullptr, spMpptData);
|
|
||||||
publishSensor("MPPT tracker operation mode", "mdi:wrench", "MPPT", nullptr, nullptr, nullptr, spMpptData);
|
|
||||||
publishSensor("MPPT Day sequence number (0...364)", "mdi:calendar-month-outline", "HSDS", NULL, "total", "d", spMpptData);
|
|
||||||
|
|
||||||
// battery info
|
// battery info
|
||||||
publishSensor("Battery voltage", NULL, "V", "voltage", "measurement", "V", spMpptData);
|
publishSensor("Battery voltage", NULL, "V", "voltage", "measurement", "V", *optMpptData);
|
||||||
publishSensor("Battery current", NULL, "I", "current", "measurement", "A", spMpptData);
|
publishSensor("Battery current", NULL, "I", "current", "measurement", "A", *optMpptData);
|
||||||
publishSensor("Battery power (calculated)", NULL, "P", "power", "measurement", "W", spMpptData);
|
publishSensor("Battery power (calculated)", NULL, "P", "power", "measurement", "W", *optMpptData);
|
||||||
publishSensor("Battery efficiency (calculated)", NULL, "E", NULL, "measurement", "%", spMpptData);
|
publishSensor("Battery efficiency (calculated)", NULL, "E", NULL, "measurement", "%", *optMpptData);
|
||||||
|
|
||||||
// panel info
|
// panel info
|
||||||
publishSensor("Panel voltage", NULL, "VPV", "voltage", "measurement", "V", spMpptData);
|
publishSensor("Panel voltage", NULL, "VPV", "voltage", "measurement", "V", *optMpptData);
|
||||||
publishSensor("Panel current (calculated)", NULL, "IPV", "current", "measurement", "A", spMpptData);
|
publishSensor("Panel current (calculated)", NULL, "IPV", "current", "measurement", "A", *optMpptData);
|
||||||
publishSensor("Panel power", NULL, "PPV", "power", "measurement", "W", spMpptData);
|
publishSensor("Panel power", NULL, "PPV", "power", "measurement", "W", *optMpptData);
|
||||||
publishSensor("Panel yield total", NULL, "H19", "energy", "total_increasing", "kWh", spMpptData);
|
publishSensor("Panel yield total", NULL, "H19", "energy", "total_increasing", "kWh", *optMpptData);
|
||||||
publishSensor("Panel yield today", NULL, "H20", "energy", "total", "kWh", spMpptData);
|
publishSensor("Panel yield today", NULL, "H20", "energy", "total", "kWh", *optMpptData);
|
||||||
publishSensor("Panel maximum power today", NULL, "H21", "power", "measurement", "W", spMpptData);
|
publishSensor("Panel maximum power today", NULL, "H21", "power", "measurement", "W", *optMpptData);
|
||||||
publishSensor("Panel yield yesterday", NULL, "H22", "energy", "total", "kWh", spMpptData);
|
publishSensor("Panel yield yesterday", NULL, "H22", "energy", "total", "kWh", *optMpptData);
|
||||||
publishSensor("Panel maximum power yesterday", NULL, "H23", "power", "measurement", "W", spMpptData);
|
publishSensor("Panel maximum power yesterday", NULL, "H23", "power", "measurement", "W", *optMpptData);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
@ -102,9 +93,9 @@ void MqttHandleVedirectHassClass::publishConfig()
|
|||||||
void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char *icon, const char *subTopic,
|
void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char *icon, const char *subTopic,
|
||||||
const char *deviceClass, const char *stateClass,
|
const char *deviceClass, const char *stateClass,
|
||||||
const char *unitOfMeasurement,
|
const char *unitOfMeasurement,
|
||||||
const VeDirectMpptController::spData_t &spMpptData)
|
const VeDirectMpptController::data_t &mpptData)
|
||||||
{
|
{
|
||||||
String serial = spMpptData->SER;
|
String serial = mpptData.SER;
|
||||||
|
|
||||||
String sensorId = caption;
|
String sensorId = caption;
|
||||||
sensorId.replace(" ", "_");
|
sensorId.replace(" ", "_");
|
||||||
@ -139,7 +130,7 @@ void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root.createNestedObject("dev");
|
||||||
createDeviceInfo(deviceObj, spMpptData);
|
createDeviceInfo(deviceObj, mpptData);
|
||||||
|
|
||||||
if (Configuration.get().Mqtt.Hass.Expire) {
|
if (Configuration.get().Mqtt.Hass.Expire) {
|
||||||
root["exp_aft"] = Configuration.get().Mqtt.PublishInterval * 3;
|
root["exp_aft"] = Configuration.get().Mqtt.PublishInterval * 3;
|
||||||
@ -160,9 +151,9 @@ void MqttHandleVedirectHassClass::publishSensor(const char *caption, const char
|
|||||||
}
|
}
|
||||||
void MqttHandleVedirectHassClass::publishBinarySensor(const char *caption, const char *icon, const char *subTopic,
|
void MqttHandleVedirectHassClass::publishBinarySensor(const char *caption, const char *icon, const char *subTopic,
|
||||||
const char *payload_on, const char *payload_off,
|
const char *payload_on, const char *payload_off,
|
||||||
const VeDirectMpptController::spData_t &spMpptData)
|
const VeDirectMpptController::data_t &mpptData)
|
||||||
{
|
{
|
||||||
String serial = spMpptData->SER;
|
String serial = mpptData.SER;
|
||||||
|
|
||||||
String sensorId = caption;
|
String sensorId = caption;
|
||||||
sensorId.replace(" ", "_");
|
sensorId.replace(" ", "_");
|
||||||
@ -195,7 +186,7 @@ void MqttHandleVedirectHassClass::publishBinarySensor(const char *caption, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root.createNestedObject("dev");
|
JsonObject deviceObj = root.createNestedObject("dev");
|
||||||
createDeviceInfo(deviceObj, spMpptData);
|
createDeviceInfo(deviceObj, mpptData);
|
||||||
|
|
||||||
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
if (Utils::checkJsonOverflow(root, __FUNCTION__, __LINE__)) { return; }
|
||||||
|
|
||||||
@ -205,14 +196,14 @@ void MqttHandleVedirectHassClass::publishBinarySensor(const char *caption, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleVedirectHassClass::createDeviceInfo(JsonObject &object,
|
void MqttHandleVedirectHassClass::createDeviceInfo(JsonObject &object,
|
||||||
const VeDirectMpptController::spData_t &spMpptData)
|
const VeDirectMpptController::data_t &mpptData)
|
||||||
{
|
{
|
||||||
String serial = spMpptData->SER;
|
String serial = mpptData.SER;
|
||||||
object["name"] = "Victron(" + serial + ")";
|
object["name"] = "Victron(" + serial + ")";
|
||||||
object["ids"] = serial;
|
object["ids"] = serial;
|
||||||
object["cu"] = String("http://") + NetworkSettings.localIP().toString();
|
object["cu"] = String("http://") + NetworkSettings.localIP().toString();
|
||||||
object["mf"] = "OpenDTU";
|
object["mf"] = "OpenDTU";
|
||||||
object["mdl"] = spMpptData->getPidAsString();
|
object["mdl"] = mpptData.getPidAsString();
|
||||||
object["sw"] = AUTO_GIT_HASH;
|
object["sw"] = AUTO_GIT_HASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,21 +59,13 @@ void MqttHandleVedirectClass::loop()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
for (int idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
||||||
if (!VictronMppt.isDataValid(idx)) {
|
std::optional<VeDirectMpptController::data_t> optMpptData = VictronMppt.getData(idx);
|
||||||
continue;
|
if (!optMpptData.has_value()) { continue; }
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<VeDirectMpptController::spData_t> spOptMpptData = VictronMppt.getData(idx);
|
auto const& kvFrame = _kvFrames[optMpptData->SER];
|
||||||
if (!spOptMpptData.has_value()) {
|
publish_mppt_data(*optMpptData, kvFrame);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
VeDirectMpptController::spData_t &spMpptData = spOptMpptData.value();
|
|
||||||
|
|
||||||
VeDirectMpptController::data_t _kvFrame = _kvFrames[spMpptData->SER];
|
|
||||||
publish_mppt_data(spMpptData, _kvFrame);
|
|
||||||
if (!_PublishFull) {
|
if (!_PublishFull) {
|
||||||
_kvFrames[spMpptData->SER] = *spMpptData;
|
_kvFrames[optMpptData->SER] = *optMpptData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,79 +96,94 @@ void MqttHandleVedirectClass::loop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleVedirectClass::publish_mppt_data(const VeDirectMpptController::spData_t &spMpptData,
|
void MqttHandleVedirectClass::publish_mppt_data(const VeDirectMpptController::data_t ¤tData,
|
||||||
const VeDirectMpptController::data_t &frame) const {
|
const VeDirectMpptController::data_t &previousData) const {
|
||||||
String value;
|
String value;
|
||||||
String topic = "victron/";
|
String topic = "victron/";
|
||||||
topic.concat(spMpptData->SER);
|
topic.concat(currentData.SER);
|
||||||
topic.concat("/");
|
topic.concat("/");
|
||||||
|
|
||||||
if (_PublishFull || spMpptData->PID != frame.PID)
|
if (_PublishFull || currentData.PID != previousData.PID) {
|
||||||
MqttSettings.publish(topic + "PID", spMpptData->getPidAsString().data());
|
MqttSettings.publish(topic + "PID", currentData.getPidAsString().data());
|
||||||
if (_PublishFull || strcmp(spMpptData->SER, frame.SER) != 0)
|
|
||||||
MqttSettings.publish(topic + "SER", spMpptData->SER );
|
|
||||||
if (_PublishFull || strcmp(spMpptData->FW, frame.FW) != 0)
|
|
||||||
MqttSettings.publish(topic + "FW", spMpptData->FW);
|
|
||||||
if (_PublishFull || spMpptData->LOAD != frame.LOAD)
|
|
||||||
MqttSettings.publish(topic + "LOAD", spMpptData->LOAD ? "ON" : "OFF");
|
|
||||||
if (_PublishFull || spMpptData->CS != frame.CS)
|
|
||||||
MqttSettings.publish(topic + "CS", spMpptData->getCsAsString().data());
|
|
||||||
if (_PublishFull || spMpptData->ERR != frame.ERR)
|
|
||||||
MqttSettings.publish(topic + "ERR", spMpptData->getErrAsString().data());
|
|
||||||
if (_PublishFull || spMpptData->OR != frame.OR)
|
|
||||||
MqttSettings.publish(topic + "OR", spMpptData->getOrAsString().data());
|
|
||||||
if (_PublishFull || spMpptData->MPPT != frame.MPPT)
|
|
||||||
MqttSettings.publish(topic + "MPPT", spMpptData->getMpptAsString().data());
|
|
||||||
if (_PublishFull || spMpptData->HSDS != frame.HSDS) {
|
|
||||||
value = spMpptData->HSDS;
|
|
||||||
MqttSettings.publish(topic + "HSDS", value);
|
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->V != frame.V) {
|
|
||||||
value = spMpptData->V;
|
if (_PublishFull || strcmp(currentData.SER, previousData.SER) != 0) {
|
||||||
MqttSettings.publish(topic + "V", value);
|
MqttSettings.publish(topic + "SER", currentData.SER);
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->I != frame.I) {
|
|
||||||
value = spMpptData->I;
|
if (_PublishFull || strcmp(currentData.FW, previousData.FW) != 0) {
|
||||||
MqttSettings.publish(topic + "I", value);
|
MqttSettings.publish(topic + "FW", currentData.FW);
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->P != frame.P) {
|
|
||||||
value = spMpptData->P;
|
if (_PublishFull || currentData.LOAD != previousData.LOAD) {
|
||||||
MqttSettings.publish(topic + "P", value);
|
MqttSettings.publish(topic + "LOAD", currentData.LOAD ? "ON" : "OFF");
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->VPV != frame.VPV) {
|
|
||||||
value = spMpptData->VPV;
|
if (_PublishFull || currentData.CS != previousData.CS) {
|
||||||
MqttSettings.publish(topic + "VPV", value);
|
MqttSettings.publish(topic + "CS", currentData.getCsAsString().data());
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->IPV != frame.IPV) {
|
|
||||||
value = spMpptData->IPV;
|
if (_PublishFull || currentData.ERR != previousData.ERR) {
|
||||||
MqttSettings.publish(topic + "IPV", value);
|
MqttSettings.publish(topic + "ERR", currentData.getErrAsString().data());
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->PPV != frame.PPV) {
|
|
||||||
value = spMpptData->PPV;
|
if (_PublishFull || currentData.OR != previousData.OR) {
|
||||||
MqttSettings.publish(topic + "PPV", value);
|
MqttSettings.publish(topic + "OR", currentData.getOrAsString().data());
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->E != frame.E) {
|
|
||||||
value = spMpptData->E;
|
if (_PublishFull || currentData.MPPT != previousData.MPPT) {
|
||||||
MqttSettings.publish(topic + "E", value);
|
MqttSettings.publish(topic + "MPPT", currentData.getMpptAsString().data());
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->H19 != frame.H19) {
|
|
||||||
value = spMpptData->H19;
|
if (_PublishFull || currentData.HSDS != previousData.HSDS) {
|
||||||
MqttSettings.publish(topic + "H19", value);
|
MqttSettings.publish(topic + "HSDS", String(currentData.HSDS));
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->H20 != frame.H20) {
|
|
||||||
value = spMpptData->H20;
|
if (_PublishFull || currentData.V != previousData.V) {
|
||||||
MqttSettings.publish(topic + "H20", value);
|
MqttSettings.publish(topic + "V", String(currentData.V));
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->H21 != frame.H21) {
|
|
||||||
value = spMpptData->H21;
|
if (_PublishFull || currentData.I != previousData.I) {
|
||||||
MqttSettings.publish(topic + "H21", value);
|
MqttSettings.publish(topic + "I", String(currentData.I));
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->H22 != frame.H22) {
|
|
||||||
value = spMpptData->H22;
|
if (_PublishFull || currentData.P != previousData.P) {
|
||||||
MqttSettings.publish(topic + "H22", value);
|
MqttSettings.publish(topic + "P", String(currentData.P));
|
||||||
}
|
}
|
||||||
if (_PublishFull || spMpptData->H23 != frame.H23) {
|
|
||||||
value = spMpptData->H23;
|
if (_PublishFull || currentData.VPV != previousData.VPV) {
|
||||||
MqttSettings.publish(topic + "H23", value);
|
MqttSettings.publish(topic + "VPV", String(currentData.VPV));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.IPV != previousData.IPV) {
|
||||||
|
MqttSettings.publish(topic + "IPV", String(currentData.IPV));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.PPV != previousData.PPV) {
|
||||||
|
MqttSettings.publish(topic + "PPV", String(currentData.PPV));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.E != previousData.E) {
|
||||||
|
MqttSettings.publish(topic + "E", String(currentData.E));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.H19 != previousData.H19) {
|
||||||
|
MqttSettings.publish(topic + "H19", String(currentData.H19));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.H20 != previousData.H20) {
|
||||||
|
MqttSettings.publish(topic + "H20", String(currentData.H20));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.H21 != previousData.H21) {
|
||||||
|
MqttSettings.publish(topic + "H21", String(currentData.H21));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.H22 != previousData.H22) {
|
||||||
|
MqttSettings.publish(topic + "H22", String(currentData.H22));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_PublishFull || currentData.H23 != previousData.H23) {
|
||||||
|
MqttSettings.publish(topic + "H23", String(currentData.H23));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,7 +119,7 @@ uint32_t VictronMpptClass::getDataAgeMillis(size_t idx) const
|
|||||||
return millis() - _controllers[idx]->getLastUpdate();
|
return millis() - _controllers[idx]->getLastUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<VeDirectMpptController::spData_t> VictronMpptClass::getData(size_t idx) const
|
std::optional<VeDirectMpptController::data_t> VictronMpptClass::getData(size_t idx) const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
|
||||||
@ -129,7 +129,9 @@ std::optional<VeDirectMpptController::spData_t> VictronMpptClass::getData(size_t
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::optional<VeDirectMpptController::spData_t>{_controllers[idx]->getData()};
|
if (!_controllers[idx]->isDataValid()) { return std::nullopt; }
|
||||||
|
|
||||||
|
return _controllers[idx]->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t VictronMpptClass::getPowerOutputWatts() const
|
int32_t VictronMpptClass::getPowerOutputWatts() const
|
||||||
@ -138,7 +140,7 @@ int32_t VictronMpptClass::getPowerOutputWatts() const
|
|||||||
|
|
||||||
for (const auto& upController : _controllers) {
|
for (const auto& upController : _controllers) {
|
||||||
if (!upController->isDataValid()) { continue; }
|
if (!upController->isDataValid()) { continue; }
|
||||||
sum += upController->getData()->P;
|
sum += upController->getData().P;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
@ -150,7 +152,7 @@ int32_t VictronMpptClass::getPanelPowerWatts() const
|
|||||||
|
|
||||||
for (const auto& upController : _controllers) {
|
for (const auto& upController : _controllers) {
|
||||||
if (!upController->isDataValid()) { continue; }
|
if (!upController->isDataValid()) { continue; }
|
||||||
sum += upController->getData()->PPV;
|
sum += upController->getData().PPV;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
@ -162,7 +164,7 @@ double VictronMpptClass::getYieldTotal() const
|
|||||||
|
|
||||||
for (const auto& upController : _controllers) {
|
for (const auto& upController : _controllers) {
|
||||||
if (!upController->isDataValid()) { continue; }
|
if (!upController->isDataValid()) { continue; }
|
||||||
sum += upController->getData()->H19;
|
sum += upController->getData().H19;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
@ -174,7 +176,7 @@ double VictronMpptClass::getYieldDay() const
|
|||||||
|
|
||||||
for (const auto& upController : _controllers) {
|
for (const auto& upController : _controllers) {
|
||||||
if (!upController->isDataValid()) { continue; }
|
if (!upController->isDataValid()) { continue; }
|
||||||
sum += upController->getData()->H20;
|
sum += upController->getData().H20;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
@ -186,7 +188,7 @@ double VictronMpptClass::getOutputVoltage() const
|
|||||||
|
|
||||||
for (const auto& upController : _controllers) {
|
for (const auto& upController : _controllers) {
|
||||||
if (!upController->isDataValid()) { continue; }
|
if (!upController->isDataValid()) { continue; }
|
||||||
double volts = upController->getData()->V;
|
double volts = upController->getData().V;
|
||||||
if (min == -1) { min = volts; }
|
if (min == -1) { min = volts; }
|
||||||
min = std::min(min, volts);
|
min = std::min(min, volts);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,6 @@ void VictronSmartShunt::loop()
|
|||||||
|
|
||||||
if (VeDirectShunt.getLastUpdate() <= _lastUpdate) { return; }
|
if (VeDirectShunt.getLastUpdate() <= _lastUpdate) { return; }
|
||||||
|
|
||||||
_stats->updateFrom(VeDirectShunt.veFrame);
|
_stats->updateFrom(VeDirectShunt.getData());
|
||||||
_lastUpdate = VeDirectShunt.getLastUpdate();
|
_lastUpdate = VeDirectShunt.getLastUpdate();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,21 +123,17 @@ void WebApiWsVedirectLiveClass::generateJsonResponse(JsonVariant& root, bool ful
|
|||||||
root["vedirect"]["full_update"] = fullUpdate;
|
root["vedirect"]["full_update"] = fullUpdate;
|
||||||
|
|
||||||
for (size_t idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
for (size_t idx = 0; idx < VictronMppt.controllerAmount(); ++idx) {
|
||||||
std::optional<VeDirectMpptController::spData_t> spOptMpptData = VictronMppt.getData(idx);
|
auto optMpptData = VictronMppt.getData(idx);
|
||||||
if (!spOptMpptData.has_value()) {
|
if (!optMpptData.has_value()) { continue; }
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fullUpdate && !hasUpdate(idx)) { continue; }
|
if (!fullUpdate && !hasUpdate(idx)) { continue; }
|
||||||
|
|
||||||
VeDirectMpptController::spData_t &spMpptData = spOptMpptData.value();
|
String serial(optMpptData->SER);
|
||||||
|
|
||||||
String serial(spMpptData->SER);
|
|
||||||
if (serial.isEmpty()) { continue; } // serial required as index
|
if (serial.isEmpty()) { continue; } // serial required as index
|
||||||
|
|
||||||
const JsonObject &nested = array.createNestedObject(serial);
|
const JsonObject &nested = array.createNestedObject(serial);
|
||||||
nested["data_age_ms"] = VictronMppt.getDataAgeMillis(idx);
|
nested["data_age_ms"] = VictronMppt.getDataAgeMillis(idx);
|
||||||
populateJson(nested, spMpptData);
|
populateJson(nested, *optMpptData);
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastPublish = millis();
|
_lastPublish = millis();
|
||||||
@ -149,56 +145,56 @@ void WebApiWsVedirectLiveClass::generateJsonResponse(JsonVariant& root, bool ful
|
|||||||
root["dpl"]["PLLIMIT"] = PowerLimiter.getLastRequestedPowerLimit();
|
root["dpl"]["PLLIMIT"] = PowerLimiter.getLastRequestedPowerLimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsVedirectLiveClass::populateJson(const JsonObject &root, const VeDirectMpptController::spData_t &spMpptData) {
|
void WebApiWsVedirectLiveClass::populateJson(const JsonObject &root, const VeDirectMpptController::data_t &mpptData) {
|
||||||
// device info
|
// device info
|
||||||
root["device"]["PID"] = spMpptData->getPidAsString();
|
root["device"]["PID"] = mpptData.getPidAsString();
|
||||||
root["device"]["SER"] = spMpptData->SER;
|
root["device"]["SER"] = String(mpptData.SER);
|
||||||
root["device"]["FW"] = spMpptData->FW;
|
root["device"]["FW"] = String(mpptData.FW);
|
||||||
root["device"]["LOAD"] = spMpptData->LOAD ? "ON" : "OFF";
|
root["device"]["LOAD"] = mpptData.LOAD ? "ON" : "OFF";
|
||||||
root["device"]["CS"] = spMpptData->getCsAsString();
|
root["device"]["CS"] = mpptData.getCsAsString();
|
||||||
root["device"]["ERR"] = spMpptData->getErrAsString();
|
root["device"]["ERR"] = mpptData.getErrAsString();
|
||||||
root["device"]["OR"] = spMpptData->getOrAsString();
|
root["device"]["OR"] = mpptData.getOrAsString();
|
||||||
root["device"]["MPPT"] = spMpptData->getMpptAsString();
|
root["device"]["MPPT"] = mpptData.getMpptAsString();
|
||||||
root["device"]["HSDS"]["v"] = spMpptData->HSDS;
|
root["device"]["HSDS"]["v"] = mpptData.HSDS;
|
||||||
root["device"]["HSDS"]["u"] = "d";
|
root["device"]["HSDS"]["u"] = "d";
|
||||||
|
|
||||||
// battery info
|
// battery info
|
||||||
root["output"]["P"]["v"] = spMpptData->P;
|
root["output"]["P"]["v"] = mpptData.P;
|
||||||
root["output"]["P"]["u"] = "W";
|
root["output"]["P"]["u"] = "W";
|
||||||
root["output"]["P"]["d"] = 0;
|
root["output"]["P"]["d"] = 0;
|
||||||
root["output"]["V"]["v"] = spMpptData->V;
|
root["output"]["V"]["v"] = mpptData.V;
|
||||||
root["output"]["V"]["u"] = "V";
|
root["output"]["V"]["u"] = "V";
|
||||||
root["output"]["V"]["d"] = 2;
|
root["output"]["V"]["d"] = 2;
|
||||||
root["output"]["I"]["v"] = spMpptData->I;
|
root["output"]["I"]["v"] = mpptData.I;
|
||||||
root["output"]["I"]["u"] = "A";
|
root["output"]["I"]["u"] = "A";
|
||||||
root["output"]["I"]["d"] = 2;
|
root["output"]["I"]["d"] = 2;
|
||||||
root["output"]["E"]["v"] = spMpptData->E;
|
root["output"]["E"]["v"] = mpptData.E;
|
||||||
root["output"]["E"]["u"] = "%";
|
root["output"]["E"]["u"] = "%";
|
||||||
root["output"]["E"]["d"] = 1;
|
root["output"]["E"]["d"] = 1;
|
||||||
|
|
||||||
// panel info
|
// panel info
|
||||||
root["input"]["PPV"]["v"] = spMpptData->PPV;
|
root["input"]["PPV"]["v"] = mpptData.PPV;
|
||||||
root["input"]["PPV"]["u"] = "W";
|
root["input"]["PPV"]["u"] = "W";
|
||||||
root["input"]["PPV"]["d"] = 0;
|
root["input"]["PPV"]["d"] = 0;
|
||||||
root["input"]["VPV"]["v"] = spMpptData->VPV;
|
root["input"]["VPV"]["v"] = mpptData.VPV;
|
||||||
root["input"]["VPV"]["u"] = "V";
|
root["input"]["VPV"]["u"] = "V";
|
||||||
root["input"]["VPV"]["d"] = 2;
|
root["input"]["VPV"]["d"] = 2;
|
||||||
root["input"]["IPV"]["v"] = spMpptData->IPV;
|
root["input"]["IPV"]["v"] = mpptData.IPV;
|
||||||
root["input"]["IPV"]["u"] = "A";
|
root["input"]["IPV"]["u"] = "A";
|
||||||
root["input"]["IPV"]["d"] = 2;
|
root["input"]["IPV"]["d"] = 2;
|
||||||
root["input"]["YieldToday"]["v"] = spMpptData->H20;
|
root["input"]["YieldToday"]["v"] = mpptData.H20;
|
||||||
root["input"]["YieldToday"]["u"] = "kWh";
|
root["input"]["YieldToday"]["u"] = "kWh";
|
||||||
root["input"]["YieldToday"]["d"] = 3;
|
root["input"]["YieldToday"]["d"] = 3;
|
||||||
root["input"]["YieldYesterday"]["v"] = spMpptData->H22;
|
root["input"]["YieldYesterday"]["v"] = mpptData.H22;
|
||||||
root["input"]["YieldYesterday"]["u"] = "kWh";
|
root["input"]["YieldYesterday"]["u"] = "kWh";
|
||||||
root["input"]["YieldYesterday"]["d"] = 3;
|
root["input"]["YieldYesterday"]["d"] = 3;
|
||||||
root["input"]["YieldTotal"]["v"] = spMpptData->H19;
|
root["input"]["YieldTotal"]["v"] = mpptData.H19;
|
||||||
root["input"]["YieldTotal"]["u"] = "kWh";
|
root["input"]["YieldTotal"]["u"] = "kWh";
|
||||||
root["input"]["YieldTotal"]["d"] = 3;
|
root["input"]["YieldTotal"]["d"] = 3;
|
||||||
root["input"]["MaximumPowerToday"]["v"] = spMpptData->H21;
|
root["input"]["MaximumPowerToday"]["v"] = mpptData.H21;
|
||||||
root["input"]["MaximumPowerToday"]["u"] = "W";
|
root["input"]["MaximumPowerToday"]["u"] = "W";
|
||||||
root["input"]["MaximumPowerToday"]["d"] = 0;
|
root["input"]["MaximumPowerToday"]["d"] = 0;
|
||||||
root["input"]["MaximumPowerYesterday"]["v"] = spMpptData->H23;
|
root["input"]["MaximumPowerYesterday"]["v"] = mpptData.H23;
|
||||||
root["input"]["MaximumPowerYesterday"]["u"] = "W";
|
root["input"]["MaximumPowerYesterday"]["u"] = "W";
|
||||||
root["input"]["MaximumPowerYesterday"]["d"] = 0;
|
root["input"]["MaximumPowerYesterday"]["d"] = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user