From 41abea549c894acbd742dd05482d94980d2184c0 Mon Sep 17 00:00:00 2001 From: Daniel Brunner Date: Mon, 24 Jun 2024 18:07:06 +0200 Subject: [PATCH] Add initial sources --- README.md | 18 ++++ fronius-goecontroller-adapter.pro | 3 + main.cpp | 144 ++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 README.md create mode 100644 fronius-goecontroller-adapter.pro create mode 100644 main.cpp diff --git a/README.md b/README.md new file mode 100644 index 0000000..188c32b --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# fronius-goecontroller-adapter + +This little command line tool will fetch the solar power values from a fronius inverter and apply it via MQTT to a go-e controller. + +The idea is that it will add the power to category "HOME" and "SOLAR". + +## Build instructions +At the moment the IP of the inverter and the hostname of the MQTT server and the serial number of the go-e controller are all hardcoded. Patch these before compiling! + +Tested on a raspberry pi with a proper OS (not dumbian). + +``` +git clone https://github.com/0xFEEDC0DE64/fronius-goecontroller-adapter.git +cd fronius-goecontroller-adapter +qmake6 +make +./fronius-goecontroller-adapter +``` \ No newline at end of file diff --git a/fronius-goecontroller-adapter.pro b/fronius-goecontroller-adapter.pro new file mode 100644 index 0000000..5ee6c33 --- /dev/null +++ b/fronius-goecontroller-adapter.pro @@ -0,0 +1,3 @@ +QT += core network mqtt + +SOURCES += main.cpp \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..9d2a9bc --- /dev/null +++ b/main.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication app{argc, argv}; + + QMqttClient client; + client.setHostname("localhost"); + client.setPort(1883); + + QNetworkAccessManager manager; + + QTimer timer; + QObject::connect(&timer, &QTimer::timeout, [&](){ + QNetworkRequest request{QUrl{"http://192.168.1.110/solar_api/v1/GetPowerFlowRealtimeData.fcgi"}}; + auto reply = manager.get(request); + QObject::connect(reply, &QNetworkReply::finished, [&,reply](){ + struct Helper { + ~Helper() { reply->deleteLater(); } + QNetworkReply *reply; + } helper { reply }; + + auto content = reply->readAll(); + + if (reply->error() != QNetworkReply::NoError) + { + qCritical() << "request failed:" << reply->error(); + qDebug() << content; + } + + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(content, &error); + if (error.error != QJsonParseError::NoError) + { + qCritical() << "json parsing failed:" << error.errorString(); + qDebug() << content; + return; + } + + if (!doc.isObject()) + { + qCritical() << "json is not an object"; + qDebug() << content; + return; + } + + const auto &rootObj = doc.object(); + qDebug() << "finished"; + + if (!rootObj.contains("Body")) + { + qCritical() << "json does not contain Body"; + qDebug() << content; + return; + } + + const auto &body = rootObj.value("Body"); + + if (!body.isObject()) + { + qCritical() << "json Body is not an object"; + qDebug() << content; + return; + } + + const auto &bodyObj = body.toObject(); + + if (!bodyObj.contains("Data")) + { + qCritical() << "json does not contain Data"; + qDebug() << content; + return; + } + + const auto &data = bodyObj.value("Data"); + + if (!data.isObject()) + { + qCritical() << "json Data is not an object"; + qDebug() << content; + return; + } + + const auto &dataObj = data.toObject(); + + if (!dataObj.contains("Site")) + { + qCritical() << "json does not contain Site"; + qDebug() << content; + return; + } + + const auto &site = dataObj.value("Site"); + + if (!site.isObject()) + { + qCritical() << "json Site is not an object"; + qDebug() << content; + return; + } + + const auto &siteObj = site.toObject(); + + if (!siteObj.contains("P_PV")) + { + qCritical() << "json does not contain P_PV"; + qDebug() << content; + return; + } + + const auto &p_pv = siteObj.value("P_PV").toDouble(); + + qDebug() << "P_PV" << p_pv; + client.publish(QMqttTopicName{"go-eController/909648/ecp/set"}, QString{"[%0,null,null,null,%0]"}.arg(p_pv).toUtf8()); + }); + }); + timer.setInterval(1000); + + QObject::connect(&client, &QMqttClient::connected, &timer, qOverload<>(&QTimer::start)); + QObject::connect(&client, &QMqttClient::connected, &timer, [](){ + qDebug() << "mqtt connected"; + }); + QObject::connect(&client, &QMqttClient::disconnected, &timer, &QTimer::stop); + QObject::connect(&client, &QMqttClient::disconnected, &timer, [](){ + qDebug() << "mqtt disconnected"; + }); + QObject::connect(&client, &QMqttClient::errorChanged, [](QMqttClient::ClientError error){ + qCritical() << "mqtt error:" << error; + }); + qDebug() << "connecting to mqtt..."; + client.connectToHost(); + + return app.exec(); +} \ No newline at end of file