Arduino sketch for auto dsicovery of ESP32

Hello,

I was searching a day…

Can anyone guide me for autodiscovery in openhab passing by MQTT ? Tutorial ? Example Code ?

I have been able to auto-integrate a ESP32 code for controlling a HeatPump (F1p on github) using HA autodiscovery. It has also auto-integrate HomeAssistant…. Without much control from me.

I wanted to come back to understand what happens and I erase these integrations. And it is no more recognize :(:::

I tried this simple example to understand but it is not recognize either :

Please help me

/**************************************************************************************************************************************************
* File name     : ESP32_HA_Discovery.c
* Compiler      : 
* Autor         : VIGASAN   
* Created       : 27/01/2023
* Modified      : 
* Last modified :
*
*
* Description   : 
*
* Other info    : Discovery MQTT Device Example
**************************************************************************************************************************************************/


/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------Include Files----------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
//#include "DHT.h"


/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------Local definitions------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
#define PERIOD_MILLSEC_1000    1000
#define PERIOD_MILLSEC_500     500
#define PERIOD_MILLSEC_250     250

#define DHTTYPE             DHT22

/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------I/O Definitions--------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
const int IN_DETECT = 5; 
const int DHTPIN = 22;

/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------ Configuration --------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
const char*         g_ssid = "NicoBrez";
const char*         g_password = "ecole2vaumeilh";
const char*         g_mqtt_server = "192.168.1.13";                           // MQTT Server IP, same of Home Assistant
const char*         g_mqttUser = "nico";                                 // MQTT Server User Name
const char*         g_mqttPsw = "nicouille";                                   // MQTT Server password
int                 g_mqttPort = 1883;                                        // MQTT Server Port

// Variable used for MQTT Discovery
const char*         g_deviceModel = "ESP32C3";                            // Hardware Model
const char*         g_swVersion = "1.0";                                      // Firmware Version
const char*         g_manufacturer = "Vigasan";                               // Manufacturer Name
String              g_deviceName = "CustomSensor";                            // Device Name
String              g_mqttStatusTopic = "esp32iotsensor/" + g_deviceName;     // MQTT Topic
            

/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------Public variables-------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
WiFiClient          g_WiFiClient;
PubSubClient        g_mqttPubSub(g_WiFiClient);
unsigned long       g_Time = 0;
int                 g_count = 0;
int                 g_input_Door; 
int                 g_old_input_Door = 0;
String              g_strDoorStatus;
int                 g_mqttCounterConn = 0;
float               g_Humidity = 0.0;
float               g_Temperature = 0.0;
bool                g_InitSystem = true;
String              g_UniqueId;
bool                g_SendMqttData = false;
//uDHT                 g_dht(DHTPIN, DHTTYPE);
             
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------ SETUP ----------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
void setup() 
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Input output Pin definitions
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    pinMode(IN_DETECT, INPUT);

    //g_dht.begin();

    Serial.begin(115200);
    delay(500);

    Serial.println("");
    Serial.println("");
    Serial.println("----------------------------------------------");
    Serial.print("MODEL: ");
    Serial.println(g_deviceModel);
    Serial.print("DEVICE: ");
    Serial.println(g_deviceName);
    Serial.print("SW Rev: ");
    Serial.println(g_swVersion);
    Serial.println("----------------------------------------------");
   
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Wifi Init
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    setup_wifi();

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // MQTT Init
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    g_mqttPubSub.setServer(g_mqtt_server, g_mqttPort);
    g_mqttPubSub.setCallback(MqttReceiverCallback);
}


/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------ LOOP -----------------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
void loop() 
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // MQTT Connection
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    if(WiFi.status() == WL_CONNECTED)
    {
        if(!g_mqttPubSub.connected())
            MqttReconnect();
        else
            g_mqttPubSub.loop();
    }

    if(g_InitSystem)
    {
        delay(100);
        g_InitSystem = false;
        Serial.println("INIT SYSTEM...");
        MqttHomeAssistantDiscovery();     // Send Discovery Data
    }

    if(millis() - g_Time > PERIOD_MILLSEC_1000)  
    {
        g_Time = millis();

        ////////////////////////////////////////////////////////////////
        // DIGITAL INPUTS
        ////////////////////////////////////////////////////////////////
        g_input_Door = digitalRead(IN_DETECT); 
        
        if(g_input_Door == 0) 
            g_strDoorStatus = "ON";
        else
            g_strDoorStatus = "OFF";

        if(g_old_input_Door != g_input_Door)
        {
            g_old_input_Door = g_input_Door;
            g_SendMqttData = true;
            Serial.print("Door Status: ");
            Serial.println(g_strDoorStatus);
        }
        
            ////////////////////////////////////////////////////////////////
            // TEMPERATURE HUMIDITY
            ////////////////////////////////////////////////////////////////
            //g_Temperature = g_dht.readTemperature();
            //g_Humidity = g_dht.readHumidity();

            g_Temperature += 0.1;
            g_Humidity += 0.2;


            Serial.print("Temperature: ");
            Serial.print(g_Temperature);
            Serial.println(" °C");

            Serial.print("Humidity: ");
            Serial.print(g_Humidity);
            Serial.println(" %");
            
            g_SendMqttData = true;

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // SEND MQTT DATA
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
        if(g_SendMqttData == true)        
        {
            StaticJsonDocument<200> payload;  
            payload["temp"] = g_Temperature;
            payload["hum"] = g_Humidity;
            payload["inputstatus"] = g_strDoorStatus;

            String strPayload;
            serializeJson(payload, strPayload);

            if(g_mqttPubSub.connected())
            {
                g_mqttPubSub.publish(g_mqttStatusTopic.c_str(), strPayload.c_str()); 
                Serial.println("MQTT: Send Data!!!");
                Serial.println(" ");
                Serial.println(" ");
                g_SendMqttData = false;
            }
        }
    }
}


/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------ Public Functions -----------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------------------------------------------------------------*/
void setup_wifi() 
{
    int counter = 0;
    byte mac[6];
    delay(10);
    // We start by connecting to a WiFi network
    Serial.print("Connecting to ");
    Serial.println(g_ssid);

    WiFi.begin(g_ssid, g_password);

    WiFi.macAddress(mac);
    g_UniqueId =  String(mac[0],HEX) +String(mac[1],HEX) +String(mac[2],HEX) +String(mac[3],HEX) + String(mac[4],HEX) + String(mac[5],HEX);

    Serial.print("Unique ID: ");
    Serial.println(g_UniqueId);    
   
    while(WiFi.status() != WL_CONNECTED && counter++ < 8) 
    {
        delay(1000);
        Serial.print(".");
    }
    Serial.println("");

    if(WiFi.status() == WL_CONNECTED)
    {
        Serial.println("WiFi connected");
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP());
    } else
    {
        Serial.println("WiFi NOT connected!!!");
    }
}

void MqttReconnect() 
{
    // Loop until we're reconnected
    while (!g_mqttPubSub.connected()  && (g_mqttCounterConn++ < 4))
    {
        Serial.print("Attempting MQTT connection...");
        // Attempt to connect
        if (g_mqttPubSub.connect(g_deviceName.c_str(), g_mqttUser, g_mqttPsw)) 
        {
            Serial.println("connected");
            // Subscribe
            g_mqttPubSub.subscribe("homeassistant/status");
            delay(100);
        } else 
        {
            Serial.print("failed, rc=");
            Serial.print(g_mqttPubSub.state());
            Serial.println(" try again in 1 seconds");
            delay(1000);
        }
    }  
    g_mqttCounterConn = 0;
}

void MqttHomeAssistantDiscovery()
{
    String discoveryTopic;
    String payload;
    String strPayload;
    if(g_mqttPubSub.connected())
    {
        Serial.println("SEND HOME ASSISTANT DISCOVERY!!!");
        StaticJsonDocument<600> payload;
        JsonObject device;
        JsonArray identifiers;

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Temperature
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        discoveryTopic = "homeassistant/sensor/esp32iotsensor/" + g_deviceName + "_temp" + "/config";
        
        payload["name"] = g_deviceName + ".temp";
        payload["uniq_id"] = g_UniqueId + "_temp";
        payload["stat_t"] = g_mqttStatusTopic;
        payload["dev_cla"] = "temperature";
        payload["val_tpl"] = "{{ value_json.temp | is_defined }}";
        payload["unit_of_meas"] = "°C";
        device = payload.createNestedObject("device");
        device["name"] = g_deviceName;
        device["model"] = g_deviceModel;
        device["sw_version"] = g_swVersion;
        device["manufacturer"] = g_manufacturer;
        identifiers = device.createNestedArray("identifiers");
        identifiers.add(g_UniqueId);

        serializeJsonPretty(payload, Serial);
        Serial.println(" ");
        serializeJson(payload, strPayload);

        g_mqttPubSub.publish(discoveryTopic.c_str(), strPayload.c_str());



        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Humidity
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        discoveryTopic = "homeassistant/sensor/esp32iotsensor/" + g_deviceName + "_hum" + "/config";
        
        payload["name"] = g_deviceName + ".hum";
        payload["uniq_id"] = g_UniqueId + "_hum";
        payload["stat_t"] = g_mqttStatusTopic;
        payload["dev_cla"] = "humidity";
        payload["val_tpl"] = "{{ value_json.hum | is_defined }}";
        payload["unit_of_meas"] = "%";
        device = payload.createNestedObject("device");
        device["name"] = g_deviceName;
        device["model"] = g_deviceModel;
        device["sw_version"] = g_swVersion;
        device["manufacturer"] = g_manufacturer;
        identifiers = device.createNestedArray("identifiers");
        identifiers.add(g_UniqueId);

        serializeJsonPretty(payload, Serial);
        Serial.println(" ");
        serializeJson(payload, strPayload);

        g_mqttPubSub.publish(discoveryTopic.c_str(), strPayload.c_str());


        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // Binary Door
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    

        discoveryTopic = "homeassistant/binary_sensor/esp32iotsensor/" + g_deviceName + "_door" + "/config";
        
        payload["name"] = g_deviceName + ".door";
        payload["uniq_id"] = g_UniqueId + "_door";
        payload["stat_t"] = g_mqttStatusTopic;
        payload["dev_cla"] = "door";
        payload["val_tpl"] = "{{ value_json.inputstatus | is_defined }}";
        device = payload.createNestedObject("device");
        device["name"] = g_deviceName;
        device["model"] = g_deviceModel;
        device["sw_version"] = g_swVersion;
        device["manufacturer"] = g_manufacturer;
        identifiers = device.createNestedArray("identifiers");
        identifiers.add(g_UniqueId);

        serializeJsonPretty(payload, Serial);
        Serial.println(" ");
        serializeJson(payload, strPayload);

        g_mqttPubSub.publish(discoveryTopic.c_str(), strPayload.c_str());


    }
}

void MqttReceiverCallback(char* topic, byte* inFrame, unsigned int length) 
{
    Serial.print("Message arrived on topic: ");
    Serial.print(topic);
    Serial.print(". Message: ");
    byte state = 0;
    String messageTemp;
    
    for (int i = 0; i < length; i++) 
    {
        Serial.print((char)inFrame[i]);
        messageTemp += (char)inFrame[i];
    }
    Serial.println();
  
    if(String(topic) == String("homeassistant/status")) 
    {
        if(messageTemp == "online")
            MqttHomeAssistantDiscovery();
    }
}

The last script is a Arduino Script.

I am able to receive its MQTT messages on a linux terminal.

Ultimate precision :

I can listen at message from the topic “esp32iotsensor/CustomSensor” (topic where the states are send)

but not from : homeassistant/sensor/esp32iotsensor/CustomSensor_hum/config (the subscription topic for auto discovery at start)

Try the Homie autodescovery

Thanks for your answer. I tried your library but there is too much dependancies and I prefer to continue with HA integration because the code I found on Github.

Finally I use my code for my heatpump, subscribe to the dicovery topic : homeassistant/sensor/HP_Id/ac/config/

and I success to listen at the publication :

{“device”:{“identifiers”:“EcodanBridge-HP_Id”},

“origin”:{“name”:“Nico”},

“unique_id”:“ashp_bridge_rssi_HP_Id”,

“name”:“Bridge WiFi Signal”,

“stat_t”:“Ecodan/ASHP/Status/WiFiStatus”,

“unit_of_meas”:“dBm”,

“dev_cla”:“signal_strength”,

“stat_cla”:“measurement”,

“val_tpl”:“{{ value_json.RSSI }}”}

The most weird is that HomeAssistant don’t recognize it either, nor OH.

Thks for help