Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreasBoehm committed Aug 2, 2024
1 parent 4334e60 commit a11723b
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 50 deletions.
1 change: 1 addition & 0 deletions include/BatteryStats.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class BatteryStats {
public:
String const& getManufacturer() const { return _manufacturer; }
String const& getFwVersion() const { return _fwversion; }

// the last time *any* data was updated
uint32_t getAgeSeconds() const { return (millis() - _lastUpdate) / 1000; }
Expand Down
11 changes: 7 additions & 4 deletions include/MqttHandleBatteryHass.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
#pragma once

#include <ArduinoJson.h>
#include <TaskSchedulerDeclarations.h>
#include "MqttHassPublisher.h"

class MqttHandleBatteryHassClass {
class MqttHandleBatteryHassClass : public MqttHassPublisher {
public:
void init(Scheduler& scheduler);
void forceUpdate() { _doPublish = true; }

private:
void loop();
void publish(const String& subtopic, const String& payload);
void publishBinarySensor(const char* caption, const char* icon, const char* subTopic, const char* payload_on, const char* payload_off);
void publishSensor(const char* caption, const char* icon, const char* subTopic, const char* deviceClass = NULL, const char* stateClass = NULL, const char* unitOfMeasurement = NULL);
void createDeviceInfo(JsonObject& object);

void publishBinarySensor2(const char* caption, const char* icon, const char* sensorId, const char* subTopic);
JsonObject createDeviceInfo();

String configTopicPrefix();

Task _loopTask;

Expand Down
24 changes: 24 additions & 0 deletions include/MqttHassPublisher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 Thomas Basler and others
*/
#pragma once

#include <ArduinoJson.h>

class MqttHassPublisher {
public:
static void publish(const String& subtopic, const JsonDocument& payload);

protected:
static JsonObject createDeviceInfo(const String& name, const String& identifiers, const String& model, const String& sw_version, const bool& via_dtu);
static String getDtuUniqueId();

void publishBinarySensor(const String& unique_dentifier, const String& name, const String& icon, const String& sensorId, const String& statSubTopic);

virtual String configTopicPrefix();
virtual JsonObject createDeviceInfo();

private:
static String getDtuUrl();
};
98 changes: 52 additions & 46 deletions src/MqttHandleBatteryHass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "MqttHandleBatteryHass.h"
#include "Configuration.h"
#include "MqttSettings.h"
#include "MqttHandleHass.h"
#include "Utils.h"
#include "__compiled_constants.h"

Expand Down Expand Up @@ -159,7 +158,9 @@ void MqttHandleBatteryHassClass::loop()
publishSensor("Modules Blocking Charge", "mdi:counter", "modulesBlockingCharge");
publishSensor("Modules Blocking Discharge", "mdi:counter", "modulesBlockingDischarge");

publishBinarySensor("Alarm Discharge current", "mdi:alert", "alarm/overCurrentDischarge", "1", "0");
// publishBinarySensor("Alarm Discharge current", "mdi:alert", "alarm/overCurrentDischarge", "1", "0");
publishBinarySensor2("Alarm Discharge current", "mdi:alert", "alarm_discharge_current", "battery/alarm/overCurrentDischarge");

publishBinarySensor("Alarm High charge current", "mdi:alert", "alarm/overCurrentCharge", "1", "0");
publishBinarySensor("Alarm Voltage low", "mdi:alert", "alarm/underVoltage", "1", "0");
publishBinarySensor("Alarm Voltage high", "mdi:alert", "alarm/overVoltage", "1", "0");
Expand Down Expand Up @@ -218,8 +219,7 @@ void MqttHandleBatteryHassClass::publishSensor(const char* caption, const char*
root["unit_of_meas"] = unitOfMeasurement;
}

JsonObject deviceObj = root["dev"].to<JsonObject>();
createDeviceInfo(deviceObj);
root["dev"] = createDeviceInfo();

if (Configuration.get().Mqtt.Hass.Expire) {
root["exp_aft"] = Battery.getStats()->getMqttFullPublishIntervalMs() / 1000 * 3;
Expand All @@ -235,10 +235,28 @@ void MqttHandleBatteryHassClass::publishSensor(const char* caption, const char*
return;
}

char buffer[512];
serializeJson(root, buffer);
publish(configTopic, buffer);
MqttHassPublisher::publish(configTopic, root);
}

String MqttHandleBatteryHassClass::uniqueIdentifier(const char* sensorId)
{
return serial + "_" + sensorId;
}

String MqttHandleBatteryHassClass::configTopicPrefix()
{
return "dtu_battery_" + serial;
}

void MqttHandleBatteryHassClass::publishBinarySensor2(const char* caption, const char* icon, const char* sensorId, const char* subTopic)
{
MqttHassPublisher::publishBinarySensor(
uniqueIdentifier(sensorId),
caption,
icon,
sensorId,
subTopic
);
}

void MqttHandleBatteryHassClass::publishBinarySensor(const char* caption, const char* icon, const char* subTopic, const char* payload_on, const char* payload_off)
Expand All @@ -251,60 +269,48 @@ void MqttHandleBatteryHassClass::publishBinarySensor(const char* caption, const
sensorId.replace(":", "");
sensorId.toLowerCase();

String configTopic = "binary_sensor/dtu_battery_" + serial
String configTopic = "dtu_battery_" + serial
+ "/" + sensorId
+ "/config";

String statTopic = MqttSettings.getPrefix() + "battery/";
String statTopic = "battery/";
// omit serial to avoid a breaking change
// statTopic.concat(serial);
// statTopic.concat("/");
statTopic.concat(subTopic);

JsonDocument root;

root["name"] = caption;
root["uniq_id"] = serial + "_" + sensorId;
root["stat_t"] = statTopic;
root["pl_on"] = payload_on;
root["pl_off"] = payload_off;

if (icon != NULL) {
root["icon"] = icon;
}

auto deviceObj = root["dev"].to<JsonObject>();
createDeviceInfo(deviceObj);

if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
return;
}

char buffer[512];
serializeJson(root, buffer);
publish(configTopic, buffer);
// MqttHassPublisher::publishBinarySensor(
// serial + "_" + sensorId,
// caption,
// icon,
// configTopic,
// statTopic,
// payload_on,
// payload_off,
// createDeviceInfo()
// );
}

void MqttHandleBatteryHassClass::createDeviceInfo(JsonObject& object)
JsonObject MqttHandleBatteryHassClass::createDeviceInfo()
{
object["name"] = "Battery(" + serial + ")";
String name = "Battery(" + serial + ")";

auto& config = Configuration.get();
if (config.Battery.Provider == 1) {
object["name"] = "JK BMS (" + Battery.getStats()->getManufacturer() + ")";
name = "JK BMS (" + Battery.getStats()->getManufacturer() + ")";
}

object["ids"] = serial;
object["cu"] = MqttHandleHass.getDtuUrl();
object["mf"] = "OpenDTU";
object["mdl"] = Battery.getStats()->getManufacturer();
object["sw"] = __COMPILED_GIT_HASH__;
object["via_device"] = MqttHandleHass.getDtuUniqueId();
}
String firmareVersion = Battery.getStats()->getFwVersion();

void MqttHandleBatteryHassClass::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);
if (firmareVersion == "") {
firmareVersion = __COMPILED_GIT_HASH__;
}

return MqttHassPublisher::createDeviceInfo(
name,
serial,
Battery.getStats()->getManufacturer(),
firmareVersion,
true
);
}
80 changes: 80 additions & 0 deletions src/MqttHassPublisher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2024 Thomas Basler and others
*/
#include "MqttHassPublisher.h"
#include "MqttSettings.h"
#include "NetworkSettings.h"
#include "Utils.h"
#include "Configuration.h"

void MqttHassPublisher::publish(const String& subtopic, const JsonDocument& payload)
{
String buffer;
serializeJson(payload, buffer);

String topic = Configuration.get().Mqtt.Hass.Topic;
topic += subtopic;
MqttSettings.publishGeneric(topic, buffer, Configuration.get().Mqtt.Hass.Retain);
}


JsonObject MqttHassPublisher::createDeviceInfo(
const String& name, const String& identifiers,
const String& model, const String& sw_version,
const bool& via_dtu)
{
JsonObject object;

object["name"] = name;
object["ids"] = identifiers;
object["cu"] = getDtuUrl(),
object["mf"] = "OpenDTU";
object["mdl"] = model;
object["sw"] = sw_version;

if (via_dtu) {
object["via_device"] = getDtuUniqueId();
}

return object;
}

void MqttHassPublisher::publishBinarySensor(
const String& unique_dentifier,
const String& name, const String& icon,
const String& sensorId, const String& statSubTopic)
{
JsonDocument root;

root["name"] = name;
root["uniq_id"] = unique_dentifier;
root["stat_t"] = MqttSettings.getPrefix() + "/" + statSubTopic;
root["pl_on"] = "1";
root["pl_off"] = "0";

if (icon != nullptr) {
root["icon"] = icon;
}

root["dev"] = createDeviceInfo();

if (!Utils::checkJsonAlloc(root, __FUNCTION__, __LINE__)) {
return;
}

publish(
"binary_sensor/" + configTopicPrefix() + "/" + sensorId + "/config",
root
);
}

String MqttHassPublisher::getDtuUniqueId()
{
return NetworkSettings.getHostname() + "_" + Utils::getChipId();
}

String MqttHassPublisher::getDtuUrl()
{
return String("http://") + NetworkSettings.localIP().toString();
}

0 comments on commit a11723b

Please sign in to comment.