Strange phenomenon, 3 exactly the same Aqara Zigbee Plugs in the same location, after 6 months one loses Zigbee connection

I am experiencing a strange issue with three Aqara Smart Plugs placed side by side in my garden shed. One of these plugs consistently loses its Zigbee connection.

I find this peculiar as I have a sufficient number of End Devices, and if the network was unstable due to distance, all three plugs should be affected.

I wonder if the plugs are positioned too close together (approximately 10 cm apart).

Could this plug be faulty? Would a different brand of smart plug be a solution?

Think you can test this easy yourselves, isn’t it?

Further more, search this forum for simular problems, that is common on this forum.
And see the cases mentioned at the bottom of this page.

How does this show? What error messages?
Do you get “Device left zigbee network” messages?
Did you switch positions? F.i. if the ‘faulty’ unit is in the middle, put it on the right or left position, to see if the issue stays with the same unit or not.

Tried a power reset already? (Unplug the plug for at least 15 minutes)

Unplug Homey for at least 15 minutes, the zigbee mesh should build itself from scratch, maybe the ‘faulty’ unit uses an other route and might work better.

And / Or,
Plug it in next to Homey for X days to see if the unit itself may be faulty.

@JPe4619 , No, I haven’t tried that yet, and yes, I can and will do that. However, I wanted to anticipate the possibility of someone immediately suggesting that distance might be a known interfering factor. Moreover, this setup worked fine for about 6 months.

I have also searched the forum for a similar issue, as I know that is common practice on the forum, but I couldn’t find a comparable situation. However, given your response, I may have overlooked something.

@Peter_Kawa I appreciate you taking the time to give me such constructive feedback.

How does this show? What error messages?
The Plug is turned off and doesn’t react to any action (Turn On/Off)
Insights aren’t updated.

Did you switch positions? F.i. if the ‘faulty’ unit is in the middle, put it on the right or left position, to see if the issue stays with the same unit or not.
Yes I did but no luck.

Tried a power reset already? (Unplug the plug for at least 15 minutes)
Trying that right at this moment.

Will try the last two tips as my last resorts !

1 Like

YW, Joep. Thanks!

This is crucial info you’d add to your problem description.
Because we all assume things (which we shouldn’t do eheh), I automatically assumed the plug (connection) was faulty since you installed it.

The chance of the plug itself just starting to break down, is much higher now, in my opinion.
Maybe there’s moisture inside or such?

@Peter_Kawa , I will add that to the description.

It is difficult to concisely and clearly specify the problem without creating a ‘title’ that is five lines long.

Thanks, yes it’s hard to add all required info you think is important.
But I meant to adjust the post, not the title :grimacing:
But it’s fine now.

Looks like forcing the Zigbee network to rebuild fixed the problem.

With the help of ChatGPT, I’ve created a customized script (based on scripts by @Sharkys and @Caseda , thank you) to track which Zigbee devices are ‘offline’ over an extended period.

1 Like

Share! Share! :grimacing:

1 Like

Of course but note, I am not a programmer, and the basic script was the hard labour of @Sharkys and @Caseda. I only adjusted it to my taste. So I can post the info on my Hdashboard

For the screenshot below I’ve temporary adjusted the Threshold

// Version 2.11
// Script checks LastSeen property of Zigbee devices
// Get top 30 devices that are offline, and track longest offline time and device

const NotReportingThreshold = 2.0; // 2.0 hours
const thresholdInMillis = NotReportingThreshold * 3600000; // Convert hours to milliseconds

const includeEndDevices = true;  // You can set this to false if you don't want to include end devices
const includeRouters = true;     // You can set this to false if you don't want to include router devices

let DevicesNotReporting = [];
let DevicesReporting = [];

// Function to calculate offline time in minutes
function getOfflineTimeInMinutes(lastSeenDate) {
  const currentTime = Date.now();
  return Math.floor((currentTime - lastSeenDate.getTime()) / 60000); // Convert ms to minutes
}

// Function to format text to exactly 30 characters with hidden spaces if shorter
function formatText(text) {
  if (text.length > 30) {
    return text.slice(0, 30); // Trim to 30 characters if too long
  } else {
    return text.padEnd(30, '\u00A0'); // Add no-break space if shorter than 30 characters
  }
}

// Function to format date to DD-MM-YYYY - hh:mm
function formatDate(date) {
  const day = String(date.getDate()).padStart(2, '0');
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const year = date.getFullYear();
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  return `${day}-${month}-${year} - ${hours}:${minutes}`;
}

// Function to check the last seen state of Zigbee devices
async function checkZigbeeLastSeen() {
  const startTime = Date.now(); // Start time to calculate control time

  try {
    const result = await Homey.zigbee.getState();

    let longestOfflineDevice = null;
    let longestOfflineTime = 0;

    for (const device of Object.values(result.nodes)) {
      // Filter out devices with 'Lamp' in the name
      if (device.name.toLowerCase().includes('lamp')) continue;

      // Filter devices based on inclusion criteria for routers and end devices
      if (device.class && !device.class.match(/sensor|button|remote|socket|lights/i)) continue;
      if (device.name.match(/dimmer|light|bulb|spot/i)) continue;

      // If routers or end devices are not to be included, skip those
      if (!includeRouters && device.type.toLowerCase() === 'router') continue;
      if (!includeEndDevices && device.type.toLowerCase() === 'enddevice') continue;

      const lastSeenDate = new Date(device.lastSeen);
      const offlineTimeInMinutes = getOfflineTimeInMinutes(lastSeenDate);

      // If device is offline, add to DevicesNotReporting
      if (offlineTimeInMinutes >= NotReportingThreshold * 60) { // Threshold in minutes
        DevicesNotReporting.push({
          name: formatText(device.name), // Format name to 30 characters with hidden spaces
          offlineTime: offlineTimeInMinutes // Keep offline time as a number for sorting
        });
      } else {
        // If device is online, add to DevicesReporting
        DevicesReporting.push({
          name: formatText(device.name),
          offlineTime: offlineTimeInMinutes
        });
      }

      // Track the device with the longest offline time (even if it's above the threshold)
      if (offlineTimeInMinutes > longestOfflineTime) {
        longestOfflineTime = offlineTimeInMinutes;
        longestOfflineDevice = device.name;
      }
    }

    // Sort DevicesNotReporting by two criteria:
    // 1. Offline time (longest first)
    // 2. Device name (alphabetically)
    DevicesNotReporting.sort((a, b) => {
      if (b.offlineTime !== a.offlineTime) {
        return b.offlineTime - a.offlineTime; // Sort by offline time first (descending)
      }
      return a.name.localeCompare(b.name); // If offline times are equal, sort by name (ascending)
    });

    // Sort DevicesReporting (online devices) by device name (alphabetically)
    DevicesReporting.sort((a, b) => a.name.localeCompare(b.name));

    // Take the top 30 offline devices
    const top30DevicesNotReporting = DevicesNotReporting.slice(0, 30);
    const tagDataNotReporting = top30DevicesNotReporting.map((device) => 
      `${device.name}\nOffline: ${device.offlineTime} minuten`
    ).join('\n\n');

    // Online devices tag data (without offline time) - remove the blank line
    const tagDataReporting = DevicesReporting.map((device) => 
      `${device.name}`
    ).join('\n');

    // Save to the appropriate tags
    await tag('201TA01 - Zigbee Not Online', tagDataNotReporting);
    await tag('201TA02 - Zigbee Wel Online', tagDataReporting);

    // Save the longest offline time in the appropriate tag (numeric)
    await tag('201TA03 - Zigbee Langste Offline Tijd', `${longestOfflineTime} minuten`);

    // Save the device with the longest offline time in the appropriate tag
    await tag('201TA04 - Zigbee Apparaat Langste Offline', longestOfflineDevice);

    // Save the longest offline time as a numeric value for use in formulas
    await tag('201TA05 - Zigbee Langste Offline Tijd (numeric)', longestOfflineTime);

    // Save the number of offline devices
    const offlineDeviceCount = DevicesNotReporting.length;
    await tag('201TA06 - Zigbee Aantal Offline', offlineDeviceCount);

    // Save the NotReportingThreshold value in a numeric tag for use in formulas
    await tag('201TA07 - Zigbee Not Reporting Tijd', NotReportingThreshold * 60); // in minutes

    // Save the control time in minutes
    const controlTimeInMinutes = Math.floor((Date.now() - startTime) / 60000); // Time in minutes
    await tag('201TA08 - Zigbee Controle Tijd', `${NotReportingThreshold * 60} minuten`);

    // Save the last check time in the desired format
    const lastCheckTime = formatDate(new Date());
    await tag('201TA09 - Zigbee Last Check', lastCheckTime);

    // Return output for script
    return `Top 30 NOK devices:\n${tagDataNotReporting}\n\nTop Online devices:\n${tagDataReporting}\n\nLangste Offline Tijd: ${longestOfflineTime} minuten\nApparaat Langste Offline: ${longestOfflineDevice}\nAantal Offline Devices: ${offlineDeviceCount}\nControle Tijd: ${NotReportingThreshold * 60} minuten\nLaatste Controle Tijd: ${lastCheckTime}`;
  } catch (error) {
    console.error('Failed: Getting ZigBee state', error);
    return `Error in retrieving ZigBee state`;
  }
}

// Execute the Zigbee check function
const result = await checkZigbeeLastSeen();

// Return the final value
return result;

There is only one thing I need to look into, the card running the script isn’t “using” the “yes” connector but for the time being I use both the connectors.

2 Likes

Very nice, Joep. Thanks!

Which Hscript card do you use in the flow screenshot?
I think you’ll just need THEN “run code”, you seem to have used the AND “run code” card, which is a conditional card.
That one can return in true or false, depending on the return you program.

Hey Peter,

Stupid me, you’re absolutly right … Chose the wrong card, and didn’t check this.

Anyway, the plug dropped out again, removed the plug from the shed, put in the living room, dropped out again …

I use the 3 plugs for measuring the power used by 3 MEL Units.
The airco Units are also used for heating the diffent zones in the house.
Dropping out isn’t a problem for measuring the power, but when they drop out the Airco’s are also offline, and no heat doesn’t improve the WAF.

For now I removed the plug but I am wondering now what would be a more failproofer way.
Using a other brand.
Using Zwave or Wifi ?
Looking for a way what is NC in stead of NO.