Dynamic channel creation discussion

I was reading the other topic because I use a lot of ESP’s. Maybe this MQTT topic is not for this one but I still wonder why is MQTT preferred?

I agree polling is bad for stable values. So for stable values (think switch) I let the ESP call the openHAB API to update the item when it changes.

When values changes all the time (think most environmental sensors or power consumption) I poll in the desired update frequency with the http binding. My assumption is that there’s not much difference in network load. And if you let the ESP respond in JSON configuration is easy.

Reason for me is the simple setup, no new technology to learn. But of course I’m curious. What would be the advantage of MQTT over this setup?

How do you do this?

@supersjel Why would you not rely on standard push message from the ESP in this case, but only for non-frequently changing values?

The preferred way is always to push, not to pull. The sensor knows best when new data is available.

That’s (always) right. But some sensors produce new data every 20 milliseconds. No point in sending that live-feed to openHAB. You decide what accuracy you need/want. And this is the case where I wonder. What’s the difference to ask openHAB to poll every 30 seconds OR let de sensor push every 30 seconds?

Don’t get my intention wrong … I try to understand what I would gain in switching to MQTT in a scenario like this. If there’s an advantage it’s worth considering …

If the data is important, then you’d want it every 20 milliseconds. If it’s not important, change the sensors (esphome? that’s in your control) not to flood the network and just provide the data at your desired interval.

And when this is done, then push is better than pull.

If you can’t change the sensor, and if by pulling, it will not flood the network, then I guess that’s the best you could do?

Maybe good to know I don’t use ESPHome, I got my own library for the ESP’s. Takes care of 95% of the standard things so you only add the code for the sensor/switch/whatever. It’s pretty standard, or maybe should I say … standard for an ESP programmer. The strength of ESPHome is avoiding this by the YAML config. Well, since you asked. Below are the two core functions.

@seimeThe standard push message from the ESP”. You mean “my” push, a ESPHome push or a MQTT push? For fast changing data letting openHAB poll it every 30 (or whatever) seconds seemed the easiest option. And (but that’s my question) I can’t see the difference between pusing and pulling because in this scenario all the data is transferred periodically anyways.

//add a postrequest, it will be send asynchrone/later
void WebServerCommand::_addRequest(const String &url, const char *contentType, const int requestType,const String &content,void (*response)(PostResponse &postResponse)){
	
  bool ok=false;
  for (int i=0;i<HTTP_POST_MAX;i++){
	if (_postRequests[i].url==""){
	  //empty slot, caller may erase vars, copy them
	  _postRequests[i] = {String(url),contentType,requestType,String(content),response};
	  ok=true;
	  break;
	}
  }
  
  if (!ok){
    //no more free slots, send error
	PostResponse postResponse={-2,""};
	response(postResponse);
  }
	
}


/*
  proces a PostRequest and sent result to callback
*/
void WebServerCommand::_doRequest(PostRequest &postRequest){
	
  if (WiFi.status() == WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
    PostResponse postResponse;

    //start a client for call
    bool ok=http.begin(client, postRequest.url); //HTTP
    if (ok){
      //URL accepted, add header
      http.addHeader(F("Content-Type"), postRequest.contentType);
      //http.addHeader(F("Content-Length"), String(value.length()));
  
      // send content
      if (postRequest.requestType==DO_POST){
          postResponse.httpCode = http.POST(postRequest.request);
      }else if (postRequest.requestType==DO_GET && postRequest.request==""){
        postResponse.httpCode = http.GET();
      } else {
        postResponse.httpCode = -3;
      }
    
      //check result
      if (postResponse.httpCode > 0) {
        //accepted
        if (postResponse.httpCode == HTTP_CODE_OK) {
          //ok, get response
          postResponse.response = http.getString();
        } else {
          //not ok, error code
          postResponse.response="";
        }
      } else {
        //error connection
        postResponse.response="";
      }
    } else {
	  //url not accepted
      postResponse.httpCode=-1;
      postResponse.response="";
    }

    //end
    http.end();
	
    //processing done, send result to callback
    postRequest.response(postResponse);
    
    //clear command to take next request
    postRequest = {"",_emptyContent,DO_NOTHING,"",_emptyHandler};

  }
	
}

Where are you posting the data to? openhab’s REST endpoint?

So when you need/want the “fast” data, MQTT is better.

For “slow” data it makes no difference pushing or polling? Or has MQTT also an advantage in this case?

(I can make the ESP do anything I want it to do :nerd_face: … or at least until it runs out of RAM)

MQTT is more lightweight than http so you save client resources. Since the MQTT broker coordinates the pushs it’s also possible to react with multiples clients to the published message.
Additionally your device is decoupled from openHAB, so you can e.g. rename the item without having to deploy new firmware.
Once you have an mqtt broker running there are no reasons to directly make http calls from the device. Instead use the broker as a central data exchange platfrom.

If you have a battery powered ESP this is terrible for efficiency. The battery will die fairly quickly because the ESP will have to maintain a WiFi connection at all times in case an HTTP request come in. If you have a mains powered device that doesn’t really matter of course.

If you are mains powered though, there are a few nice things that MQTT adds over polling using HTTP.

  • The LWT topic provides a very light weight method for detecting online status.
  • Retained messages are great for dealing with intermittent connectivity. The subscribers don’t have to be online when the publisher sends the message.
  • Almost everything in the open source home automation space supports MQTT. It’s kind of a lingua franca among IoT devices.
  • Depending on how the topics and messages are set up, configuring the MQTT Channel is likely less work than configuring the HTTP Channel.
  • Even if power management isn’t a concern, it’s often best when the sensor can decide when it needs to report a value (e.g. only report when there is a large enough change).

I’m sure there are more. There are some disadvantages too (which is why I assume the ESPHome developers decided to develop their own new protocol).

  • Requires a separate broker.
  • From the OH perspective it likely requires more configuration than using an ESPHome add-on.
  • The MQTT Broker becomes a single point of failure, though there are high availability brokers available.

Don’t base the push on time, base it on how much the reading has changed from the last reading. Does ESPHome not support this? That seems like a super basic requirement to me.

Then you definitely should write your code so it only pushes when the sensor changes enough. That’s what really matters. Not just that it’s been 30 seconds.

And I’ll add an additional advantage to MQTT. Adding support to your ESP is going to likely be a lot less code and require less memory on the ESP. It’s a few lines of code (6 is the minimum IIRC but if you want to do stuff on connection or disconnection it’s going to be more, see pubsubclient/examples at master · knolleary/pubsubclient · GitHub) to import the library (which is smaller than the HTTP libraries by a lot) and one line of code to publish message.

It would be something like the following as a minimum MQTT config on the ESP:

#include <PubSubClient.h>
const char* mqtt_server = "broker.mqtt-dashboard.com";

PubSubClient client(espClient);

void setup() {
  client.setServer(mqtt_server, 1883); // your port may be different
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
    client.publish("outTopic", msg); // msg would be what ever data you want to publish
  }
}

You can register functions to be called on client to handle connections, disconnections, and to subscribe to topics. But for a simple sensor you just need to connect and publish.

I wouldn’t say that. When you need/want:

  • less work on both sides
  • energy efficiency because you are battery powered, MQTT lets you go into deep sleep
  • you want the sensor to decide when to send the data (see above about not sending every reading, just send changes that are large enough to be relevant and maybe every 30 seconds if the change hasn’t been enough)
  • you want easy and timely online/offline detection
  • have an unreliable network (which isn’t likely here but worth mentioning)
1 Like

@rlkoshak : Thanx for this elaborate answer that tells about a lot of considerations! The thought about discarding fixed time in favor of big changes is very interesting.

WiFi communication can be combined with deep sleep but you’re right. It has quite a big overhead on startup time. So is only useful in very low update frequencies. Most of my devices are main operated, and I like them have their own webinterface. To change settings, realtime view logging of the device, OTA updates and as a backup in case openHAB is down. So WiFi and WebServer are already active. But if the MQTT library is lightweight I’m sure I can combine them. I’ll look into that and change one of the devices to get a hands on experience.

As for the reliable network, that is required. My wife will probably divorce me in case of internet issues :rofl:

If you give me a crash course in java I’ll gladly create a PR. I looked at the developer docs but I don’t even know where to start :confused: .
Since I’m fluent in python I created it there so at least every HABApp user can benefit from my knowledge.

In theory - yes. I’m not talking about the esphome binding but dynamic discovery in general. Battery powered devices have long sleep times so it’s possible that it’ll take multiple days (or even weeks) for the discovery to complete. It a systematic issue because discovery can not advance when the device is asleep. That means after an openHAB restart e.g. your battery powered smoke alarm will not report a fire to openHAB.
Also while this discovery is easy in theory the devil is in the detail and I’ve experienced (and am still experiencing) failures with discovery which lead to things with incomplete channels. The thing then still shows “ONLINE” so it’s not clear there is something wrong. There are very hard to track down errors and even if you find them there is no fix. Your device just won’t properly work.

Does that mean after a device reboot or a firmware update the interrogation has to be done again?

No - the thing should still go online. online/offline should only reflect whether the thing is reachable.


The root cause of all this is that the thing stayed more or less the same since it was introduced in OH2 but development moved forward and the thing is not a good fit any more.
There is no differentiation between thing and device settings. There is no differentiation between static thing data (e.g. a discovery result) and runtime data (e.g. last message received). There are no dedicated steps for channel discovery, channel verification and no steps for subscribing for status updates.
It’s not possible to manually interact with the thing representation (e.g. put Z-Wave stick in inclusion mode or poll values). There is no standardized way to manually interact with the device of the thing (e.g. switch an output on/off).
Only a massive refactor of the thing will properly fix these systematic issues. Everything until then will only be a workaround and obfuscate the real issue.

So I actually built the REST service yesterday; Add REST call to get orphan links · seime/openhab-core@7015eaf · GitHub.

On the frontend side I have a working version locally, but then I hit some 80 codestyle errors - leading to this post: Vue/Javascript code formatting in MainUI

The interrogation happens on every connect and takes probably less than a second (the more entities (“channels”) on the device, the more messages)

Agreed.

But I won’t bet any money on this happening to OH.

1 Like

Maybe I’m missing something but you can put the Z-wave controller in inclusion mode. That’s literally what happens when you go to the inbox and initiate a scan for new devices for the Z-wave binding. And you can put it in exclusion mode from the Thing’s page.

To poll for values, send REFRESH as a command to the Item linked to one of the Channels and it will refresh the value. I don’t know if it will only refresh that one Item or all Items linked to that one Thing.

The REFRESH command is standard. I don’t know if how Z-Wave handles inclusion/exclusion is.

Maybe I should have picked exclusion mode as an example because inclusion mode works - as you correctly pointed out - by scanning for new devices.
All the other available manual actions are implemented as thing config parameters. That means when you press that button you are actually changing the thing configuration even though it actually stays the same.
That’s the reason why it’s impossible to textually configure the z-wave stick because then the configuration can not be changed any more and thus the stick can not perform any actions.
It’s misuse of the thing configuration to overcome the thing limitations.
I’ve created an issue where I describe it in depth.

That will only issue a poll for the linked command class (if we speak z-wave), not all the thing values.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.