So I am getting on with this, and I almost succeeded in registering more than one MQTT topic. The thing is HA “sees” only one entity (“auto-discovery-light-1” in my example) but it stops here and the other one “auto-discovery-light-2” never shows up in HA entities panel.
This is strange because using a tool like MQTTfx I can see that this topic is properly registered with Mosquitto and I even can send / receive commands to / from it like ha/light/auto-discovery-light-2/cmd/ON
So the part I can’t figure out is what to do on HA side to get the second entity showing.
Fore reference, here is the code I use on the ESP8266 side (it’s a bit long, but easily readeable)
#include <Arduino.h>
#include "EspMQTTClient.h"
#include "HAMqttDevice.h"
#include <ESP_EEPROM.h>
// MQTT client setup
EspMQTTClient client(
"************", // Wifi ssid
"************", // Wifi password
"************", // MQTT broker ip
"************", // MQTT username
"************", // MQTT password
"auto_discovery_test_lights" // MQTT Client name
);
// Home Assitant device creation for MQTT discovery
HAMqttDevice light1("auto-discovery-light-1", HAMqttDevice::LIGHT);
HAMqttDevice light2("auto-discovery-light-2", HAMqttDevice::LIGHT);
// Pin assignation
const int light1Pin = D0;
const int light2Pin = D1;
// Current status of the light
struct LightValues
{
bool light1On;
bool light2On;
};
struct LightValues lightValues = {false, false};
void setup()
{
Serial.begin(115200);
pinMode(light1Pin, OUTPUT);
pinMode(light2Pin, OUTPUT);
// Charge saved values from eeprom
EEPROM.begin(sizeof(lightValues));
if (EEPROM.percentUsed() >= 0)
EEPROM.get(0, lightValues);
// Setup the parameters of the device for MQTT discovery in HA
light1.enableAttributesTopic();
light2.enableAttributesTopic();
client.enableHTTPWebUpdater();
client.setMaxPacketSize(512);
client.enableDebuggingMessages();
}
void onConnectionEstablished()
{
// Subscribe to the command topic ("cmd_t") of this device for light1
client.subscribe(light1.getCommandTopic(), [](const String &payload) {
// Turn the light on/off depending on the command received from Home Assitant
if (payload.equals("ON"))
lightValues.light1On = true;
else if (payload.equals("OFF"))
lightValues.light1On = false;
// Confirm to Home Assitant that we received the command and updated the state.
// HA will then update the state of the device in HA
client.publish(light1.getStateTopic(), payload);
// Save the new state in memory
EEPROM.put(0, lightValues.light1On);
EEPROM.commit();
});
// Subscribe to the command topic ("cmd_t") of this device for light2
client.subscribe(light2.getCommandTopic(), [](const String &payload) {
// Turn the light on/off depending on the command received from Home Assitant
if (payload.equals("ON"))
lightValues.light2On = true;
else if (payload.equals("OFF"))
lightValues.light2On = false;
// Confirm to Home Assitant that we received the command and updated the state.
// HA will then update the state of the device in HA
client.publish(light2.getStateTopic(), payload);
// Save the new state in memory
EEPROM.put(0, lightValues.light2On);
EEPROM.commit();
});
// Subscribe to Home Assitant connection status events.
client.subscribe("ha/status", [](const String &payload) {
// When the status of Home assistant get online, publish the device config
if (payload.equals("online"))
{
client.publish(light1.getConfigTopic(), light1.getConfigPayload());
client.publish(light2.getConfigTopic(), light2.getConfigPayload());
// After sending the device config to HA, wait a little to allow HA to create the entity.
client.executeDelayed(5 * 1000, []() {
// Send the current state of the light
client.publish(light1.getStateTopic(), lightValues.light1On ? "ON" : "OFF");
client.publish(light2.getStateTopic(), lightValues.light2On ? "ON" : "OFF");
// Send the IP address of the device to HA
light1
.clearAttributes()
.addAttribute("IP", WiFi.localIP().toString());
light2
.clearAttributes()
.addAttribute("IP", WiFi.localIP().toString());
client.publish(light1.getAttributesTopic(), light1.getAttributesPayload());
client.publish(light2.getAttributesTopic(), light2.getAttributesPayload());
});
}
});
}
void loop()
{
client.loop();
if (lightValues.light1On)
digitalWrite(light1Pin, LOW);
else
digitalWrite(light1Pin, HIGH);
if (lightValues.light2On)
digitalWrite(light2Pin, LOW);
else
digitalWrite(light2Pin, HIGH);
}
I just had a look at the logs and this is what I found :
2021-04-21 12:01:27 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on ha/light/auto-discovery-light-1/config: b'{"~":"ha/light/auto-discovery-light-1","name":"auto-discovery-light-1","cmd_t":"~/cmd","stat_t":"~/state","json_attr_t":"~/attr"}'
2021-04-21 12:01:27 DEBUG (MainThread) [homeassistant.components.mqtt.discovery] Process discovery payload {'name': 'auto-discovery-light-1', 'command_topic': 'ha/light/auto-discovery-light-1/cmd', 'state_topic': 'ha/light/auto-discovery-light-1/state', 'json_attributes_topic': 'ha/light/auto-discovery-light-1/attr', 'platform': 'mqtt'}
2021-04-21 12:01:27 INFO (MainThread) [homeassistant.components.mqtt.discovery] Component has already been discovered: light auto-discovery-light-1, sending update
2021-04-21 12:01:27 INFO (MainThread) [homeassistant.components.mqtt.mixins] Got update for entity with hash: ('light', 'auto-discovery-light-1') '{'name': 'auto-discovery-light-1', 'command_topic': 'ha/light/auto-discovery-light-1/cmd', 'state_topic': 'ha/light/auto-discovery-light-1/state', 'json_attributes_topic': 'ha/light/auto-discovery-light-1/attr', 'platform': 'mqtt'}'
2021-04-21 12:01:27 INFO (MainThread) [homeassistant.components.mqtt.mixins] Ignoring unchanged update for: light.auto_discovery_light_1
2021-04-21 12:01:27 DEBUG (MainThread) [homeassistant.components.mqtt.discovery] Pending discovery for ('light', 'auto-discovery-light-1'): deque([])
2021-04-21 12:01:27 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on ha/light/auto-discovery-light-2/config: b'{"~":"ha/light/auto-discovery-light-2","name":"auto-discovery-light-2"}'
2021-04-21 12:01:27 DEBUG (MainThread) [homeassistant.components.mqtt.discovery] Process discovery payload {'name': 'auto-discovery-light-2', 'platform': 'mqtt'}
2021-04-21 12:01:27 INFO (MainThread) [homeassistant.components.mqtt.discovery] Found new component: light auto-discovery-light-2
2021-04-21 12:01:27 ERROR (MainThread) [homeassistant.util.logging] Exception in async_discover when dispatching 'mqtt_discovery_new_light_mqtt': ({'name': 'auto-discovery-light-2', 'platform': 'mqtt'},)
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/mqtt/mixins.py", line 160, in async_discover
config = schema(discovery_payload)
File "/usr/local/lib/python3.8/site-packages/voluptuous/validators.py", line 218, in __call__
return self._exec((Schema(val) for val in self.validators), v)
File "/usr/local/lib/python3.8/site-packages/voluptuous/validators.py", line 341, in _exec
raise e if self.msg is None else AllInvalid(self.msg, path=path)
File "/usr/local/lib/python3.8/site-packages/voluptuous/validators.py", line 337, in _exec
v = func(v)
File "/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
File "/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py", line 817, in validate_callable
return schema(data)
File "/usr/src/homeassistant/homeassistant/components/mqtt/light/__init__.py", line 26, in validate_mqtt_light
return schemas[value[CONF_SCHEMA]](value)
File "/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
File "/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py", line 594, in validate_dict
return base_validate(path, iteritems(data), out)
File "/usr/local/lib/python3.8/site-packages/voluptuous/schema_builder.py", line 432, in validate_mapping
raise er.MultipleInvalid(errors)
voluptuous.error.MultipleInvalid: required key not provided @ data['command_topic']
2021-04-21 12:01:27 DEBUG (MainThread) [homeassistant.components.mqtt.discovery] Pending discovery for ('light', 'auto-discovery-light-2'): deque([])
2021-04-21 12:01:32 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on ha/light/auto-discovery-light-1/state: b'OFF'
2021-04-21 12:01:32 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on ha/light/auto-discovery-light-1/attr: b'{"IP":"192.168.10.64"}'
HA raises an error regarding the discovery of the 2nd topic :
2021-04-21 12:01:27 ERROR (MainThread) [homeassistant.util.logging] Exception in async_discover when dispatching 'mqtt_discovery_new_light_mqtt': ({'name': 'auto-discovery-light-2', 'platform': 'mqtt'},)