Issue with initialising of things using MQTT and EVCC after reboot of RP (openhabian)

I am experiencing a reproducible problem with the initialising of things after a reboot of my RP (openhabian). To me this looks like a race condition, openhab starts at the same time as EVCC, MQTT and Zigbee2MQTT + ZWave-js. As a result, some of the things for EVCC and for Zigbee / Zwave nodes stay UNINITIALISED or in ERROR communicating or OFFLINE. I presume because the startup of openhab is faster than the startup of the other packages. The problem is reproducible, in that it happens after each reboot, only that it is not always the same nodes, of course.

I found a hack to fix this, namely a small JS script:

rules.JSRule({
  name: "JS: Thing_Status update on Trigger_Things",
  description: "Updates all Thing_Status items on command",
  triggers: [
    triggers.GenericCronTrigger("0 9,39 * ? * * *")
  ],
  //conditions: [
  // () => items.getItem("Delayed_Startup").state === "ON"
  //],
  execute: () => {
    logger.info("JS ---> Run Thing Status update");

    const group = items.getItem("Thing_Status");

    group.members.forEach((item) => {
      const meta = item.getMetadata("thingUID");
      if (!meta) {
        logger.warn(`JS ---> Status item ${item.itemName} has no Metadata for ThingUID`);
        return;
      }

      const thing = things.getThing(meta.value);
      if (!thing) {
        logger.warn(`JS ---> Thing not found for UID: ${meta.value}`);
        return;
      }

      const thingStatus = thing.status;
      // check if not ONLINE and try to recover
      if (!thingStatus || thingStatus.toString() !== "ONLINE") {
        logger.info(`JS --> Thing ${meta.value} is ${thingStatus.toString()}, trying to recover by disabling/enabling the thing`);
        // disable
        thing.setEnabled(false);
        // wait 30 sec
        java.lang.Thread.sleep(30000);
        // enable
        thing.setEnabled(true);
      }
    });
  }
});

I am storing the UI in the metadata of items that I arrange in a group, as you can see, to make this work. After this rule has run the first time, all things are ONLINE.

I was wondering, to me this setup of using MQTT + Zigbee/Zwave and/or EVCC looks rather standard, do others have a similar issue at startup ? Is there a way to fix this centrally instead of this hack ?

I suspect you are correct in your assessment as to the root cause. However, the Things shouldn’t get stuck even if OH comes up before the other services.

I don’t know about EVCC but the rest use MQTT. So as long as your MQTT broker comes up first there should be no problem initializing the MQTT Things. And the MQTT broker is really lightweight, it should come up first naturally.

The first thing I would do is try to confirm this is indeed a problem with OH coming up before the other services and which other services are a problem.

It is possible to make OH depend on these other services coming up first before starting but that can cause its own problems. So it’s important to verify that this is really the problem.

What happens if you just restart OH after all these other services are running. Do the Things come online in that case?

Finally, your rule is more complicated than it needs to be. To reproduce exactly what your rule does without the extra Items and metadata and such, you could just do the following:

const offlineThings = things.getThings()
                            .filter( t => t.status != "ONLINE" )
                            .filter( t => t.uid.includes('mqtt') || t.uid.includes('homeassistant') || t.uid.includes('evcc' );
offlineThings.forEach( t => {
  t.setEnabled(false);
  setTimeout(() => t.setEnabled(true), 30000);
});

But assuming the Items in the Group are linked to the Things you care about, you could also use the following to get the Thing linked to the Item:

const channelID = items.itemChannelLink(item).channelUID();
const thingID = channelID.slice(0, channelID.lastIndexOf(':'));
const thing = things.getThing(thingID);

Or, using the raw Java Object which lets you avoid the string manipulation, but you have to convert the String at the end to a JS String.

const thingID = String(items.itemChannelLink(item).rawItemChannelLink
                                                  .getLinkedUID()
                                                  .getThingUID().toString());
const thing = things.getThing(thingID);

Note, I just typed in the above, there might be typos or other errors.

Hi, thanks for the answer. I will rerun some of my tests just restarting openhab, in case. I see that in another discussion on EVCC they discuss this here: EVCC discussion

thanks as well for the coding tips. I am using the meta data in a slightly more complex set of rules, my code extract was just a part of it. I look into your suggestions if I could simplify my code. Best.

I can confirm this behavior.
I have Zigbee2mqtt running on a separate Raspberry, but the MQTT broker is on the same system as openHAB. When I restart this system (OH + broker), all Zigbee2MQTT items remain offline. I then have to restart Zigbee2MQTT once, and everything is back

This implies there some message that Zigbee2MQTT is publishing indicating online status in some way that should be retained but isn’t. If OH happened to not be online when the message was sent, OH never gets the message and the thinks the Thing is not online.

yes, I was wondering if there is a setting that is missing in my Zigbee2MQTT or ZWave-JS setups, but could not find it. The retain flags seem to be set.