diff --git a/include/MqttHandleVedirectHass.h b/include/MqttHandleVedirectHass.h new file mode 100644 index 00000000..cda5a92a --- /dev/null +++ b/include/MqttHandleVedirectHass.h @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#pragma once + +#include +#include "VeDirectFrameHandler.h" + +class MqttHandleVedirectHassClass { +public: + void init(); + void loop(); + void publishConfig(); + void forceUpdate(); + +private: + void publish(const String& subtopic, const String& payload); + void publishBinarySensor(const char* caption, const char* subTopic, const char* payload_on, const char* payload_off); + void createDeviceInfo(JsonObject& object); + + bool _wasConnected = false; + bool _updateForced = false; +}; + +extern MqttHandleVedirectHassClass MqttHandleVedirectHass; \ No newline at end of file diff --git a/src/MqttHandlVedirectHass.cpp b/src/MqttHandlVedirectHass.cpp new file mode 100644 index 00000000..1c7d68f5 --- /dev/null +++ b/src/MqttHandlVedirectHass.cpp @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2022 Thomas Basler and others + */ +#include "MqttHandleVedirectHass.h" +#include "Configuration.h" +#include "MqttSettings.h" +#include "NetworkSettings.h" +#include "MessageOutput.h" + +MqttHandleVedirectHassClass MqttHandleVedirectHass; + +void MqttHandleVedirectHassClass::init() +{ +} + +void MqttHandleVedirectHassClass::loop() +{ + if (_updateForced) { + publishConfig(); + _updateForced = false; + } + + if (MqttSettings.getConnected() && !_wasConnected) { + // Connection established + _wasConnected = true; + publishConfig(); + } else if (!MqttSettings.getConnected() && _wasConnected) { + // Connection lost + _wasConnected = false; + } +} + +void MqttHandleVedirectHassClass::forceUpdate() +{ + _updateForced = true; +} + +void MqttHandleVedirectHassClass::publishConfig() +{ + if ((!Configuration.get().Mqtt_Hass_Enabled) || + (!Configuration.get().Vedirect_Enabled)) { + return; + } + + if (!MqttSettings.getConnected()) { + return; + } + if (VeDirect.veMap.find("SER") == VeDirect.veMap.end()) { + return; + } + + publishBinarySensor("Load output state", "victron/LOAD", "ON", "OFF"); + + yield(); +} + + +void MqttHandleVedirectHassClass::publishBinarySensor(const char* caption, const char* subTopic, const char* payload_on, const char* payload_off) +{ + String serial = VeDirect.veMap["SER"]; + + String sensorId = caption; + sensorId.replace(" ", "_"); + sensorId.toLowerCase(); + + String configTopic = "binary_sensor/dtu_victron_" + serial + + "/" + sensorId + + "/config"; + + // String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic; // TODO extend with serial + String statTopic = MqttSettings.getPrefix() + subTopic; + + DynamicJsonDocument root(1024); + root[F("name")] = String("Victron ") + caption; + root[F("uniq_id")] = serial + "_" + sensorId; + root[F("stat_t")] = statTopic; + root[F("pl_on")] = payload_on; + root[F("pl_off")] = payload_off; + + JsonObject deviceObj = root.createNestedObject("dev"); + createDeviceInfo(deviceObj); + + char buffer[512]; + serializeJson(root, buffer); + publish(configTopic, buffer); +} + +void MqttHandleVedirectHassClass::createDeviceInfo(JsonObject& object) +{ + object[F("name")] = "Victron"; + object[F("ids")] = VeDirect.veMap["SER"]; + object[F("cu")] = String(F("http://")) + NetworkSettings.localIP().toString(); + object[F("mf")] = F("OpenDTU"); + object[F("mdl")] = VeDirect.getPidAsString(VeDirect.veMap["PID"].c_str()); + object[F("sw")] = AUTO_GIT_HASH; +} + +void MqttHandleVedirectHassClass::publish(const String& subtopic, const String& payload) +{ + String topic = Configuration.get().Mqtt_Hass_Topic; + topic += subtopic; + MqttSettings.publishGeneric(topic.c_str(), payload.c_str(), Configuration.get().Mqtt_Hass_Retain); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 87e8a840..e3ea2388 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ #include "VeDirectFrameHandler.h" #include "MqttHandleDtu.h" #include "MqttHandleHass.h" +#include "MqttHandleVedirectHass.h" #include "MqttHandleInverter.h" #include "MqttHandleVedirect.h" #include "MqttSettings.h" @@ -89,6 +90,7 @@ void setup() MqttHandleInverter.init(); MqttHandleVedirect.init(); MqttHandleHass.init(); + MqttHandleVedirectHass.init(); MessageOutput.println(F("done")); // Initialize WebApi @@ -194,6 +196,10 @@ void loop() } MqttHandleHass.loop(); yield(); + if (Configuration.get().Vedirect_Enabled) { + MqttHandleVedirectHass.loop(); + yield(); + } WebApi.loop(); yield(); Display.loop(); diff --git a/webapp_dist/index.html.gz b/webapp_dist/index.html.gz index f7547917..0830730b 100644 Binary files a/webapp_dist/index.html.gz and b/webapp_dist/index.html.gz differ diff --git a/webapp_dist/js/app.js.gz b/webapp_dist/js/app.js.gz index 677042a5..b2677779 100644 Binary files a/webapp_dist/js/app.js.gz and b/webapp_dist/js/app.js.gz differ diff --git a/webapp_dist/zones.json.gz b/webapp_dist/zones.json.gz index 45374b96..f1ea50bf 100644 Binary files a/webapp_dist/zones.json.gz and b/webapp_dist/zones.json.gz differ