BREAKING CHANGE: allow multiple OpenDTU-OnBattery instances at same HASS
This breaks existing HASS automation, as entity names and MQTT topics change! * include dtu-unique-id in DPL MQTT HASS topics to allow multiple DTUs to be controlled * fix filename "src/MqttHandlVedirectHass.cpp" * refactor: use values from 'MqttHandleHass', add 'via_device' to all HASS devices * set step size for power limiter voltage values
This commit is contained in:
parent
6ee6eaf0b2
commit
e3f9da75b9
@ -56,6 +56,9 @@ public:
|
|||||||
void publishConfig();
|
void publishConfig();
|
||||||
void forceUpdate();
|
void forceUpdate();
|
||||||
|
|
||||||
|
static String getDtuUniqueId();
|
||||||
|
static String getDtuUrl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loop();
|
void loop();
|
||||||
void publish(const String& subtopic, const String& payload);
|
void publish(const String& subtopic, const String& payload);
|
||||||
@ -71,9 +74,6 @@ private:
|
|||||||
|
|
||||||
static void createDeviceInfo(JsonDocument& doc, const String& name, const String& identifiers, const String& configuration_url, const String& manufacturer, const String& model, const String& sw_version, const String& via_device = "");
|
static void createDeviceInfo(JsonDocument& doc, const String& name, const String& identifiers, const String& configuration_url, const String& manufacturer, const String& model, const String& sw_version, const String& via_device = "");
|
||||||
|
|
||||||
static String getDtuUniqueId();
|
|
||||||
static String getDtuUrl();
|
|
||||||
|
|
||||||
Task _loopTask;
|
Task _loopTask;
|
||||||
|
|
||||||
bool _wasConnected = false;
|
bool _wasConnected = false;
|
||||||
|
|||||||
@ -13,9 +13,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
void loop();
|
void loop();
|
||||||
void publish(const String& subtopic, const String& payload);
|
void publish(const String& subtopic, const String& payload);
|
||||||
void publishNumber(const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, const int16_t min, const int16_t max);
|
void publishNumber(const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic, const char* unitOfMeasure, const int16_t min, const int16_t max, const float step);
|
||||||
void publishSelect(const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic);
|
void publishSelect(const char* caption, const char* icon, const char* category, const char* commandTopic, const char* stateTopic);
|
||||||
void createDeviceInfo(JsonObject& object);
|
void createDeviceInfo(JsonDocument& root);
|
||||||
|
|
||||||
Task _loopTask;
|
Task _loopTask;
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "MqttHandleBatteryHass.h"
|
#include "MqttHandleBatteryHass.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include "MqttSettings.h"
|
#include "MqttSettings.h"
|
||||||
|
#include "MqttHandleHass.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "__compiled_constants.h"
|
#include "__compiled_constants.h"
|
||||||
|
|
||||||
@ -294,10 +295,11 @@ void MqttHandleBatteryHassClass::createDeviceInfo(JsonObject& object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object["ids"] = serial;
|
object["ids"] = serial;
|
||||||
object["cu"] = String("http://") + NetworkSettings.localIP().toString();
|
object["cu"] = MqttHandleHass.getDtuUrl();
|
||||||
object["mf"] = "OpenDTU";
|
object["mf"] = "OpenDTU";
|
||||||
object["mdl"] = Battery.getStats()->getManufacturer();
|
object["mdl"] = Battery.getStats()->getManufacturer();
|
||||||
object["sw"] = __COMPILED_GIT_HASH__;
|
object["sw"] = __COMPILED_GIT_HASH__;
|
||||||
|
object["via_device"] = MqttHandleHass.getDtuUniqueId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleBatteryHassClass::publish(const String& subtopic, const String& payload)
|
void MqttHandleBatteryHassClass::publish(const String& subtopic, const String& payload)
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
* Copyright (C) 2022 Thomas Basler and others
|
* Copyright (C) 2022 Thomas Basler and others
|
||||||
*/
|
*/
|
||||||
#include "MqttHandlePowerLimiterHass.h"
|
#include "MqttHandlePowerLimiterHass.h"
|
||||||
|
#include "MqttHandleHass.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include "MqttSettings.h"
|
#include "MqttSettings.h"
|
||||||
#include "NetworkSettings.h"
|
#include "NetworkSettings.h"
|
||||||
@ -69,32 +70,32 @@ void MqttHandlePowerLimiterHassClass::publishConfig()
|
|||||||
|
|
||||||
// as this project revolves around Hoymiles inverters, 16 - 60 V is a reasonable voltage range
|
// as this project revolves around Hoymiles inverters, 16 - 60 V is a reasonable voltage range
|
||||||
publishNumber("DPL battery voltage start threshold", "mdi:battery-charging",
|
publishNumber("DPL battery voltage start threshold", "mdi:battery-charging",
|
||||||
"config", "threshold/voltage/start", "threshold/voltage/start", "V", 16, 60);
|
"config", "threshold/voltage/start", "threshold/voltage/start", "V", 16, 60, 0.1);
|
||||||
publishNumber("DPL battery voltage stop threshold", "mdi:battery-charging",
|
publishNumber("DPL battery voltage stop threshold", "mdi:battery-charging",
|
||||||
"config", "threshold/voltage/stop", "threshold/voltage/stop", "V", 16, 60);
|
"config", "threshold/voltage/stop", "threshold/voltage/stop", "V", 16, 60, 0.1);
|
||||||
|
|
||||||
if (config.Vedirect.Enabled) {
|
if (config.Vedirect.Enabled) {
|
||||||
publishNumber("DPL full solar passthrough start voltage",
|
publishNumber("DPL full solar passthrough start voltage",
|
||||||
"mdi:transmission-tower-import", "config",
|
"mdi:transmission-tower-import", "config",
|
||||||
"threshold/voltage/full_solar_passthrough_start",
|
"threshold/voltage/full_solar_passthrough_start",
|
||||||
"threshold/voltage/full_solar_passthrough_start", "V", 16, 60);
|
"threshold/voltage/full_solar_passthrough_start", "V", 16, 60, 0.1);
|
||||||
publishNumber("DPL full solar passthrough stop voltage",
|
publishNumber("DPL full solar passthrough stop voltage",
|
||||||
"mdi:transmission-tower-import", "config",
|
"mdi:transmission-tower-import", "config",
|
||||||
"threshold/voltage/full_solar_passthrough_stop",
|
"threshold/voltage/full_solar_passthrough_stop",
|
||||||
"threshold/voltage/full_solar_passthrough_stop", "V", 16, 60);
|
"threshold/voltage/full_solar_passthrough_stop", "V", 16, 60, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.Battery.Enabled && !config.PowerLimiter.IgnoreSoc) {
|
if (config.Battery.Enabled && !config.PowerLimiter.IgnoreSoc) {
|
||||||
publishNumber("DPL battery SoC start threshold", "mdi:battery-charging",
|
publishNumber("DPL battery SoC start threshold", "mdi:battery-charging",
|
||||||
"config", "threshold/soc/start", "threshold/soc/start", "%", 0, 100);
|
"config", "threshold/soc/start", "threshold/soc/start", "%", 0, 100, 1.0);
|
||||||
publishNumber("DPL battery SoC stop threshold", "mdi:battery-charging",
|
publishNumber("DPL battery SoC stop threshold", "mdi:battery-charging",
|
||||||
"config", "threshold/soc/stop", "threshold/soc/stop", "%", 0, 100);
|
"config", "threshold/soc/stop", "threshold/soc/stop", "%", 0, 100, 1.0);
|
||||||
|
|
||||||
if (config.Vedirect.Enabled) {
|
if (config.Vedirect.Enabled) {
|
||||||
publishNumber("DPL full solar passthrough SoC",
|
publishNumber("DPL full solar passthrough SoC",
|
||||||
"mdi:transmission-tower-import", "config",
|
"mdi:transmission-tower-import", "config",
|
||||||
"threshold/soc/full_solar_passthrough",
|
"threshold/soc/full_solar_passthrough",
|
||||||
"threshold/soc/full_solar_passthrough", "%", 0, 100);
|
"threshold/soc/full_solar_passthrough", "%", 0, 100, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +109,7 @@ void MqttHandlePowerLimiterHassClass::publishSelect(
|
|||||||
selectId.replace(" ", "_");
|
selectId.replace(" ", "_");
|
||||||
selectId.toLowerCase();
|
selectId.toLowerCase();
|
||||||
|
|
||||||
const String configTopic = "select/powerlimiter/" + selectId + "/config";
|
const String configTopic = "select/" + MqttHandleHass.getDtuUniqueId() + "/" + selectId + "/config";
|
||||||
|
|
||||||
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
||||||
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
||||||
@ -116,7 +117,7 @@ void MqttHandlePowerLimiterHassClass::publishSelect(
|
|||||||
JsonDocument root;
|
JsonDocument root;
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = selectId;
|
root["uniq_id"] = MqttHandleHass.getDtuUniqueId() + "_" + selectId;
|
||||||
if (strcmp(icon, "")) {
|
if (strcmp(icon, "")) {
|
||||||
root["ic"] = icon;
|
root["ic"] = icon;
|
||||||
}
|
}
|
||||||
@ -128,8 +129,7 @@ void MqttHandlePowerLimiterHassClass::publishSelect(
|
|||||||
options.add("1");
|
options.add("1");
|
||||||
options.add("2");
|
options.add("2");
|
||||||
|
|
||||||
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
createDeviceInfo(root);
|
||||||
createDeviceInfo(deviceObj);
|
|
||||||
|
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
return;
|
return;
|
||||||
@ -143,14 +143,14 @@ void MqttHandlePowerLimiterHassClass::publishSelect(
|
|||||||
void MqttHandlePowerLimiterHassClass::publishNumber(
|
void MqttHandlePowerLimiterHassClass::publishNumber(
|
||||||
const char* caption, const char* icon, const char* category,
|
const char* caption, const char* icon, const char* category,
|
||||||
const char* commandTopic, const char* stateTopic, const char* unitOfMeasure,
|
const char* commandTopic, const char* stateTopic, const char* unitOfMeasure,
|
||||||
const int16_t min, const int16_t max)
|
const int16_t min, const int16_t max, const float step)
|
||||||
{
|
{
|
||||||
|
|
||||||
String numberId = caption;
|
String numberId = caption;
|
||||||
numberId.replace(" ", "_");
|
numberId.replace(" ", "_");
|
||||||
numberId.toLowerCase();
|
numberId.toLowerCase();
|
||||||
|
|
||||||
const String configTopic = "number/powerlimiter/" + numberId + "/config";
|
const String configTopic = "number/" + MqttHandleHass.getDtuUniqueId() + "/" + numberId + "/config";
|
||||||
|
|
||||||
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
const String cmdTopic = MqttSettings.getPrefix() + "powerlimiter/cmd/" + commandTopic;
|
||||||
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
const String statTopic = MqttSettings.getPrefix() + "powerlimiter/status/" + stateTopic;
|
||||||
@ -158,7 +158,7 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
|
|||||||
JsonDocument root;
|
JsonDocument root;
|
||||||
|
|
||||||
root["name"] = caption;
|
root["name"] = caption;
|
||||||
root["uniq_id"] = numberId;
|
root["uniq_id"] = MqttHandleHass.getDtuUniqueId() + "_" + numberId;
|
||||||
if (strcmp(icon, "")) {
|
if (strcmp(icon, "")) {
|
||||||
root["ic"] = icon;
|
root["ic"] = icon;
|
||||||
}
|
}
|
||||||
@ -168,6 +168,7 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
|
|||||||
root["unit_of_meas"] = unitOfMeasure;
|
root["unit_of_meas"] = unitOfMeasure;
|
||||||
root["min"] = min;
|
root["min"] = min;
|
||||||
root["max"] = max;
|
root["max"] = max;
|
||||||
|
root["step"] = step;
|
||||||
root["mode"] = "box";
|
root["mode"] = "box";
|
||||||
|
|
||||||
auto const& config = Configuration.get();
|
auto const& config = Configuration.get();
|
||||||
@ -175,8 +176,7 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
|
|||||||
root["exp_aft"] = config.Mqtt.PublishInterval * 3;
|
root["exp_aft"] = config.Mqtt.PublishInterval * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject deviceObj = root["dev"].to<JsonObject>();
|
createDeviceInfo(root);
|
||||||
createDeviceInfo(deviceObj);
|
|
||||||
|
|
||||||
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
|
||||||
return;
|
return;
|
||||||
@ -187,14 +187,16 @@ void MqttHandlePowerLimiterHassClass::publishNumber(
|
|||||||
publish(configTopic, buffer);
|
publish(configTopic, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandlePowerLimiterHassClass::createDeviceInfo(JsonObject& object)
|
void MqttHandlePowerLimiterHassClass::createDeviceInfo(JsonDocument& root)
|
||||||
{
|
{
|
||||||
|
JsonObject object = root["dev"].to<JsonObject>();
|
||||||
object["name"] = "Dynamic Power Limiter";
|
object["name"] = "Dynamic Power Limiter";
|
||||||
object["ids"] = "0002";
|
object["ids"] = MqttHandleHass.getDtuUniqueId() + "_DPL";
|
||||||
object["cu"] = String("http://") + NetworkSettings.localIP().toString();
|
object["cu"] = MqttHandleHass.getDtuUrl();
|
||||||
object["mf"] = "OpenDTU";
|
object["mf"] = "OpenDTU";
|
||||||
object["mdl"] = "Dynamic Power Limiter";
|
object["mdl"] = "Dynamic Power Limiter";
|
||||||
object["sw"] = __COMPILED_GIT_HASH__;
|
object["sw"] = __COMPILED_GIT_HASH__;
|
||||||
|
object["via_device"] = MqttHandleHass.getDtuUniqueId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandlePowerLimiterHassClass::publish(const String& subtopic, const String& payload)
|
void MqttHandlePowerLimiterHassClass::publish(const String& subtopic, const String& payload)
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "MqttHandleVedirectHass.h"
|
#include "MqttHandleVedirectHass.h"
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include "MqttSettings.h"
|
#include "MqttSettings.h"
|
||||||
|
#include "MqttHandleHass.h"
|
||||||
#include "NetworkSettings.h"
|
#include "NetworkSettings.h"
|
||||||
#include "MessageOutput.h"
|
#include "MessageOutput.h"
|
||||||
#include "VictronMppt.h"
|
#include "VictronMppt.h"
|
||||||
@ -212,10 +213,11 @@ void MqttHandleVedirectHassClass::createDeviceInfo(JsonObject &object,
|
|||||||
String serial = mpptData.serialNr_SER;
|
String serial = mpptData.serialNr_SER;
|
||||||
object["name"] = "Victron(" + serial + ")";
|
object["name"] = "Victron(" + serial + ")";
|
||||||
object["ids"] = serial;
|
object["ids"] = serial;
|
||||||
object["cu"] = String("http://") + NetworkSettings.localIP().toString();
|
object["cu"] = MqttHandleHass.getDtuUrl();
|
||||||
object["mf"] = "OpenDTU";
|
object["mf"] = "OpenDTU";
|
||||||
object["mdl"] = mpptData.getPidAsString();
|
object["mdl"] = mpptData.getPidAsString();
|
||||||
object["sw"] = __COMPILED_GIT_HASH__;
|
object["sw"] = __COMPILED_GIT_HASH__;
|
||||||
|
object["via_device"] = MqttHandleHass.getDtuUniqueId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttHandleVedirectHassClass::publish(const String& subtopic, const String& payload)
|
void MqttHandleVedirectHassClass::publish(const String& subtopic, const String& payload)
|
||||||
Loading…
Reference in New Issue
Block a user