Dynamic channel creation discussion

Yes sure one can solve some of the issues by writing rules. I’ve done so in the past myself to compensate, but I would argue that common problems should be solved in a common way by the framework, and thus make it more accessible to less tech-savvy users.

And with the KNX example provided by @Udo_Hartmann in an earlier reply, a rule writer might experience some unexpected behaviour.

One of the beauty of openhab is that it doesn’t force you to do something a certain way. I prefer not to set my items to UNDEF whenever the things go offline, because the item’s current state is valuable to me.

Here’s a few lines to make all items go UNDEF 5 seconds after their thing is no longer online. If someone wants this behaviour, simply create a similar and very simple rule to gain that behaviour on their system.

rule "Make linked items UNDEF when things are no longer online" do
  trigger "core.ThingStatusChangeTrigger", thingUID: "*", previousStatus: "ONLINE"
  run do |event|
    after 5.seconds do
      next if event.thing.online?

      event.thing.channels.each do |channel|
        channel.items.each { |item| item.update UNDEF }
      end
    end
  end
end

Are you sure it should not be NULL? See [mqtt] Treat incoming empty string as NULL for most types by ccutrer · Pull Request #16307 · openhab/openhab-addons · GitHub

While I agree with your sentiment against dynamic channels, one would think that the esphome binding got the channel details directly from the esphome device, and that information should be exactly the same as configured in your esphome yaml. The only downside is that this adds a tiny bit of delay on the initial connection.

So I would love to see the esphome binding allow static channel configuration method and when it is done statically, skip this interrogation step. I don’t know the ins and outs of the binding to understand / appreciate the challenges this may present though, and since it is not my binding, I have very little say in it.

For the time being, I am perfectly happy using mqtt + manual channel definition for my esphome devices. I generate my things + items programmatically, so I just need one template for each device type, and this is done the same way with the esphome configuration.

One thing about the ESPHome API I have been meaning to investigate is the ability for one esphome device to directly issue a command to another, bypassing mqtt and openhab. This would be handy for a switch to control a light, when openhab is down. However, AFAIK this is not supported.

In the other topic,

What about a utility that queries the ESPHome (using API or mqtt discovery), and generate the .things file.

Not sure at all. And from the linked discussion there seems to be confusion. If you look at the official bindings source code, there is no clear answer as well as both NULL and UNDEF are being used. Personally I am happy with either.

But as I wrote here;

Yes, but keep in mind that a single ESPHome component (ie climate) may provide multiple entities/channels, and retrieving those names from the esphome yaml would probably require parsing C++ code as well.

State updates from the device are done using a unique 32 bit key, and not by transmitting the full entity/channel name. The key is provided during the interrogation step. I’m not sure whether they are static across a reboot, but I’m pretty sure they won’t be static across a flashing process (ie version upgrade or modification).

So you cannot skip the interrogation step.

As I wrote in an earlier post:

Wouldn’t a “A python yaml to items generator” solve it?

Do you mean that if the device doesn’t actually provide all statically configured channels, the thing should refuse to go online? Opposed to some centralized logic checking for broken links every X seconds and informing you about the problem - and that applies for all kinds of thing types?

Wouldn’t a general tool be even more awesome? See Adjust width of F7 dialog + include clipboard icon - #5 by splatch

(Specific: In order to interrogate an ESPHome device you would have to provide credentials in most cases)

1 Like

Oh I wasn’t suggesting to use the esphome yaml to generate the channel details. On the contrary, my point was that the channels provided by the binding as a result of its interrogation should be exactly the same as the yaml, so there should be no reason to define it statically, in theory, if we trust the binding to work correctly.

Which yaml file are you referring to? I’m not going to make a second (wild) guess :wink:

Cheers

I was referring to the esphome yaml, and by that I don’t mean literally just what’s in the yaml, but the resulting esphome entities that would’ve otherwise been broadcasted through mqtt.

Having said that, the main reason I didn’t pursue using the esphome binding was because my esphome configs involve sending custom mqtt messages to communicate. I need (and tried) to refactor it into standard components, but there are some things that aren’t possible. I did ask the esphome folks about how to get around it but I was told that mqtt is the only way to do what I did. Hence I’m still using mqtt for now. It has been a while now, and I don’t remember the details exactly. I’d like to revisit it again one day.

I’m not suggesting anything. Just warning you that MQTT used to set the Item states to UNDEF when the Thing went offline and the maintainers made them take that behavior out as a misuse of the UNDEF state.

Honestly the reasoning never made sense to me and I personally continue to “misuse” UNDEF in this way. But I don’t need to get the maintainers to approve my personal rules.

And since switching to a status Item I really don’t want my items going to UNDEF just because the Thing went offline.

Why does everyone always assume the worst case when it comes to something like this?

If one is using managed Items it’s a simple script (6-10 lines at most, probably less in jRuby) to find all the equipment and add a status Item to them complete with links and profile config (I’ll post a rule template on request). Then you need one rule (template already posted) to detect when it goes offline and do something about it.

Me too now which is why I added the status Item.

Another approach is to use the Thing Status Reporting rule template to set the status Item or all the linked items to UNDEF too if you want.

I do that for a couple of Things with a status Item.

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.