Skip to content

Commit

Permalink
Add support for Domoticz MQTT integration (#3359)
Browse files Browse the repository at this point in the history
* initial changes to add domoticz support

* error correction

* further changes

* further changes

* Refactoring

* further refactoring

* further refactoring

* Update DomoticzTopicIn.md

* Update NUMBER.DomoticzIDX.md

* Update DomoticzTopicIn.md

* Update NUMBER.DomoticzIDX.md

* Update config.ini

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update DomoticzTopicIn.md

---------

Co-authored-by: CaCO3 <[email protected]>
  • Loading branch information
gneluka and caco3 authored Dec 1, 2024
1 parent 2c7740e commit 08baf18
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 22 deletions.
2 changes: 2 additions & 0 deletions code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ struct NumberPost {
float AnalogToDigitTransitionStart; // AnalogToDigitTransitionStartValue; FIXME: need a better description; When is the digit > x.1, i.e. when does it start to tilt?
int Nachkomma; // decimalPlaces; usually defined by the number of analog ROIs; affected by DecimalShift

string DomoticzIdx; // Domoticz counter Idx

string FieldV1; // influxdbFieldName_v1; Name of the Field in InfluxDBv1
string MeasurementV1; // influxdbMeasurementName_v1; Name of the Measurement in InfluxDBv1

Expand Down
70 changes: 55 additions & 15 deletions code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
ListFlowControll = NULL;
disabled = false;
keepAlive = 25*60;
domoticzintopic = "";
}

ClassFlowMQTT::ClassFlowMQTT()
Expand Down Expand Up @@ -105,43 +106,44 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
splitted = ZerlegeZeile(aktparamgraph);
if ((toUpper(splitted[0]) == "CACERT") && (splitted.size() > 1))
std::string _param = GetParameterName(splitted[0]);
if ((toUpper(_param) == "CACERT") && (splitted.size() > 1))
{
this->caCertFilename = splitted[1];
}
if ((toUpper(splitted[0]) == "CLIENTCERT") && (splitted.size() > 1))
if ((toUpper(_param) == "CLIENTCERT") && (splitted.size() > 1))
{
this->clientCertFilename = splitted[1];
}
if ((toUpper(splitted[0]) == "CLIENTKEY") && (splitted.size() > 1))
if ((toUpper(_param) == "CLIENTKEY") && (splitted.size() > 1))
{
this->clientKeyFilename = splitted[1];
}
if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
if ((toUpper(_param) == "USER") && (splitted.size() > 1))
{
this->user = splitted[1];
}
if ((toUpper(splitted[0]) == "PASSWORD") && (splitted.size() > 1))
if ((toUpper(_param) == "PASSWORD") && (splitted.size() > 1))
{
this->password = splitted[1];
}
if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1))
if ((toUpper(_param) == "URI") && (splitted.size() > 1))
{
this->uri = splitted[1];
}
if ((toUpper(splitted[0]) == "RETAINMESSAGES") && (splitted.size() > 1))
if ((toUpper(_param) == "RETAINMESSAGES") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE") {
SetRetainFlag = true;
setMqtt_Server_Retain(SetRetainFlag);
}
}
if ((toUpper(splitted[0]) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
if ((toUpper(_param) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
SetHomeassistantDiscoveryEnabled(true);
}
if ((toUpper(splitted[0]) == "METERTYPE") && (splitted.size() > 1)) {
if ((toUpper(_param) == "METERTYPE") && (splitted.size() > 1)) {
/* Use meter type for the device class
Make sure it is a listed one on https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes */
if (toUpper(splitted[1]) == "WATER_M3") {
Expand Down Expand Up @@ -176,15 +178,26 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
}
}

if ((toUpper(splitted[0]) == "CLIENTID") && (splitted.size() > 1))
if ((toUpper(_param) == "CLIENTID") && (splitted.size() > 1))
{
this->clientname = splitted[1];
}

if (((toUpper(splitted[0]) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
if (((toUpper(_param) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
{
maintopic = splitted[1];
}

if (((toUpper(_param) == "DOMOTICZTOPICIN")) && (splitted.size() > 1))
{
this->domoticzintopic = splitted[1];
}

if (((toUpper(_param) == "DOMOTICZIDX")) && (splitted.size() > 1))
{
handleIdx(splitted[0], splitted[1]);
}

}

/* Note:
Expand All @@ -193,6 +206,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
* To work around this, we delay the start and trigger it from ClassFlowControll::ReadParameter() */

mqttServer_setMainTopic(maintopic);
mqttServer_setDmoticzInTopic(domoticzintopic);

return true;
}
Expand All @@ -210,7 +224,7 @@ bool ClassFlowMQTT::Start(float AutoInterval)

mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval);

bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, LWT_TOPIC, LWT_CONNECTED,
bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, domoticzintopic, LWT_TOPIC, LWT_CONNECTED,
LWT_DISCONNECTED, caCertFilename, clientCertFilename, clientKeyFilename,
keepAlive, SetRetainFlag, (void *)&GotConnected);

Expand All @@ -235,6 +249,8 @@ bool ClassFlowMQTT::doFlow(string zwtime)
std::string resultchangabs = "";
string zw = "";
string namenumber = "";
string domoticzpayload = "";
string DomoticzIdx = "";
int qos = 1;

/* Send the the Homeassistant Discovery and the Static Topics in case they where scheduled */
Expand All @@ -258,16 +274,20 @@ bool ClassFlowMQTT::doFlow(string zwtime)
resultchangabs = (*NUMBERS)[i]->ReturnChangeAbsolute; // Units per round
resulttimestamp = (*NUMBERS)[i]->timeStamp;

DomoticzIdx = (*NUMBERS)[i]->DomoticzIdx;
domoticzpayload = "{\"command\":\"udevice\",\"idx\":" + DomoticzIdx + ",\"svalue\":\""+ result + "\"}";

namenumber = (*NUMBERS)[i]->name;
if (namenumber == "default")
namenumber = maintopic + "/";
else
namenumber = maintopic + "/" + namenumber + "/";

if ((domoticzintopic.length() > 0) && (result.length() > 0))
success |= MQTTPublish(domoticzintopic, domoticzpayload, qos, SetRetainFlag);

if (result.length() > 0)
if (result.length() > 0)
success |= MQTTPublish(namenumber + "value", result, qos, SetRetainFlag);

if (resulterror.length() > 0)
success |= MQTTPublish(namenumber + "error", resulterror, qos, SetRetainFlag);

Expand Down Expand Up @@ -325,6 +345,26 @@ bool ClassFlowMQTT::doFlow(string zwtime)

return true;
}

void ClassFlowMQTT::handleIdx(string _decsep, string _value)
{
string _digit, _decpos;
int _pospunkt = _decsep.find_first_of(".");
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
if (_pospunkt > -1)
_digit = _decsep.substr(0, _pospunkt);
else
_digit = "default";
for (int j = 0; j < flowpostprocessing->NUMBERS.size(); ++j)
{
if (_digit == "default") // Set to default first (if nothing else is set)
{
flowpostprocessing->NUMBERS[j]->DomoticzIdx = _value;
}
if (flowpostprocessing->NUMBERS[j]->name == _digit)
{
flowpostprocessing->NUMBERS[j]->DomoticzIdx = _value;
}
}
}

#endif //ENABLE_MQTT
4 changes: 2 additions & 2 deletions code/components/jomjol_flowcontroll/ClassFlowMQTT.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class ClassFlowMQTT :
bool SetRetainFlag;
int keepAlive; // Seconds
float roundInterval; // Minutes

std::string maintopic;
std::string maintopic, domoticzintopic;
void SetInitialParameter(void);
void handleIdx(string _decsep, string _value);

public:
ClassFlowMQTT();
Expand Down
5 changes: 3 additions & 2 deletions code/components/jomjol_mqtt/interface_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ bool mqtt_initialized = false;
bool mqtt_connected = false;

esp_mqtt_client_handle_t client = NULL;
std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic;
std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic, domoticz_in_topic;
std::string caCert, clientCert, clientKey;
int keepalive;
bool SetRetainFlag;
Expand Down Expand Up @@ -205,7 +205,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_


bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
std::string _maintopic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename,
int _keepalive, bool _SetRetainFlag, void *_callbackOnConnected) {
if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0))
Expand All @@ -222,6 +222,7 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
keepalive = _keepalive;
SetRetainFlag = _SetRetainFlag;
maintopic = _maintopic;
domoticz_in_topic = _domoticz_in_topic;
callbackOnConnected = ( void (*)(std::string, bool) )(_callbackOnConnected);

if (_clientcertfilename.length() && _clientkeyfilename.length()){
Expand Down
2 changes: 1 addition & 1 deletion code/components/jomjol_mqtt/interface_mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <functional>

bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
std::string _maintopic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename,
int _keepalive, bool SetRetainFlag, void *callbackOnConnected);
int MQTT_Init();
Expand Down
8 changes: 7 additions & 1 deletion code/components/jomjol_mqtt/server_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ std::string rateUnit = "Unit/Minute";
float roundInterval; // Minutes
int keepAlive = 0; // Seconds
bool retainFlag;
static std::string maintopic;
static std::string maintopic, domoticzintopic;
bool sendingOf_DiscoveryAndStaticTopics_scheduled = true; // Set it to true to make sure it gets sent at least once after startup



void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int _keepAlive, float _roundInterval) {
NUMBERS = _NUMBERS;
keepAlive = _keepAlive;
Expand Down Expand Up @@ -367,4 +368,9 @@ std::string mqttServer_getMainTopic() {
return maintopic;
}

void mqttServer_setDmoticzInTopic( std::string _domoticzintopic) {
domoticzintopic = _domoticzintopic;
}


#endif //ENABLE_MQTT
3 changes: 3 additions & 0 deletions code/components/jomjol_mqtt/server_mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int interval, f
void mqttServer_setMeterType(std::string meterType, std::string valueUnit, std::string timeUnit,std::string rateUnit);
void setMqtt_Server_Retain(bool SetRetainFlag);
void mqttServer_setMainTopic( std::string maintopic);
void mqttServer_setDmoticzInTopic( std::string domoticzintopic);


std::string mqttServer_getMainTopic();

void register_server_mqtt_uri(httpd_handle_t server);
Expand Down
6 changes: 6 additions & 0 deletions param-docs/parameter-pages/MQTT/DomoticzTopicIn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Parameter `DomoticzTopicIn`
Default Value: `domoticz/in`

Domoticz "in" topic as configured on the "MQTT Client Gateway" setup page on the Domoticz system. Used to publish counter/s value/s.

Parameter &lt;NUMBER&gt;.DomoticzIDX is required (see below).
4 changes: 4 additions & 0 deletions param-docs/parameter-pages/MQTT/NUMBER.DomoticzIDX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Parameter `<NUMBER>.DomoticzIDX`
Default Value: `0`

The Idx number for the counter device. Can be obtained from the devices setup page on the Domoticz system.
2 changes: 2 additions & 0 deletions sd-card/config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ HomeassistantDiscovery = false
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;DomoticzTopicIn = domoticz/in
;main.DomoticzIDX = 0

;[InfluxDB]
;Uri = undefined
Expand Down
Loading

0 comments on commit 08baf18

Please sign in to comment.