dawidchyrzynski / arduino-home-assistant

ArduinoHA allows to integrate an Arduino/ESP based device with Home Assistant using MQTT.
https://dawidchyrzynski.github.io/arduino-home-assistant/
GNU Affero General Public License v3.0
485 stars 116 forks source link

Dynamic entries creation? #103

Open Elektrik1 opened 1 year ago

Elektrik1 commented 1 year ago

Hey there, I am interested whether it is possible to create entries (particularly HASwitch) dynamically - in loop(). Tried to initiate HASwitch class in loop - no errors appear, but no data to MQTT and HA is sent. Is there any option to add entries dynamically on the fly?

dawidchyrzynski commented 1 year ago

Hi @Elektrik1,

Can you provide more details about your use case? Theoretically, it should be possible if the entity remains in the memory for a lifetime.

Elektrik1 commented 1 year ago

Assume we have such program:

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>
#include <ArduinoHA.h>

WiFiClient espClient;

HADevice device;
HAMqtt mqtt(espClient, device);

bool created = false;

void setup() {
  byte mac[WL_MAC_ADDR_LENGTH];
  WiFi.macAddress(mac);
  device.setUniqueId(mac, sizeof(mac));

  device.setName("Test");
  device.setSoftwareVersion("1.0.0");
  device.setModel("TP01");

  mqtt.begin("192.168.1.1");
}

void loop() {
  mqtt.loop();

  if(!created){
    HASwitch led("led", false);
    led.setName("My LED");
    created = true;
  }
}

It works fine if I declare HASwitch in setup(), before mqtt.begin, however if I create HASwitch instance within the loop() dynamically - it does not appear in HA and no errors are produced. The problem is HASwitch count changes during the loops (it is configurable externally), therefore I ask if there is a possibility to create HASwitch instances on the fly.

dawidchyrzynski commented 1 year ago

That's expected behaviour. In this particular case the HASwitch is a local variable which gets destroyed with its scope (after created = true;. Try this:

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>
#include <ArduinoHA.h>

WiFiClient espClient;

HADevice device;
HAMqtt mqtt(espClient, device);
HASwitch* switchPtr = nullptr;

void setup() {
  byte mac[WL_MAC_ADDR_LENGTH];
  WiFi.macAddress(mac);
  device.setUniqueId(mac, sizeof(mac));

  device.setName("Test");
  device.setSoftwareVersion("1.0.0");
  device.setModel("TP01");

  mqtt.begin("192.168.1.1");
}

void loop() {
  mqtt.loop();

  if(!switchPtr){
    switchPtr = new HASwitch("led", false);
    switchPtr->setName("My LED");
  }
}
Elektrik1 commented 1 year ago

It works! Thank you very much, that is exactly what I tried to do.

Elektrik1 commented 1 year ago

I am reopening this, because I think it is related. There is a problem, that if I create HADevice at runtime dynamically (after mqtt is connected), there is no way to force config publish and subscribe to command topic (onMqttConnected() in base is protected), therefore I found no way to signal the HA about new device, and therefore the callback is not received by onCommand(). I think it should be exposed the same way as setAvailability() is.

rikki78 commented 1 year ago

Hi, When dynamically creating these sensors and naming it, the name given needs to remain available for the library. So when using the same buffer (for example to create more sensors at a time and naming them), all sensors will get the same name. Is there a way to make the library copy the name so the application can make dynamic names?