A script to check sensor last update

As there is for some time options to see Lastseen timestamp for Zigbee devices, here is the script for Zigbee devices only, which might be more accurate for Zigbee devices. Thanks @Caseda for your overview script :wink:

Version 0.3 - updated for HomeyScript v. 3.5.1
Version 0.3b - fixed for THEN card (returning TEXT value), primary use-better use is for AND card though
Version 0.4 - added option to filter out routers and/or end devices

// Version 0.4
// Script checks LastSeen property of Zigbee device
// Using 2 hours default threshold
// Thanks Caseda for [Homey Pro] overview script, which this was originally inspired by
// Thanks to ChatGPT for consultations ;-)

const NotReportingThreshold = 2; // 2 hours
const thresholdInMillis = NotReportingThreshold * 3600000; // convert hours to milliseconds

const includeEndDevices = true; // Option to include end devices
const includeRouters = true; // Option to include router devices

let ZigbeeDevicesLastSeen = [];
let notReportingCount = 0;
let DevicesNotReporting = [];

// Function to format a date as "dd-mm-yyyy, hh:mm:ss"
function formatDate(date) {
  const day = date.getDate().toString().padStart(2, '0');
  const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Months are 0-indexed
  const year = date.getFullYear().toString();
  const hours = date.getHours().toString().padStart(2, '0');
  const minutes = date.getMinutes().toString().padStart(2, '0');
  const seconds = date.getSeconds().toString().padStart(2, '0');

  return `${day}-${month}-${year}, ${hours}:${minutes}:${seconds}`;
}

// Function to check last seen state of Zigbee devices
async function checkZigbeeLastSeen() {
  try {
    const result = await Homey.zigbee.getState();

    const okDevices = [];
    const nokDevices = [];
    const routerDevices = [];
    const endDevices = [];

    for (const device of Object.values(result.nodes)) {
      // Filter devices to check
      if (device.class && !device.class.match(/sensor|button|remote|socket|lights/i)) continue; // Include device types
      if (device.name.match(/dimmer|light|bulb|spot/i)) continue; // Exclude by regex device name

      // Include devices based on type
      if (!includeRouters && device.type.toLowerCase() === 'router') continue;
      if (!includeEndDevices && device.type.toLowerCase() === 'enddevice') continue;

      // Include last seen information
      const lastSeenDate = new Date(device.lastSeen);
      const lastSeenFormatted = formatDate(lastSeenDate);

      // Check against NotReportingThreshold
      const currentTime = Date.now();
      const timeSinceLastSeen = currentTime - lastSeenDate.getTime();

      let deviceName = device.name + ' ' + lastSeenFormatted + ' (' + device.type.toLowerCase() + ')';
      if (timeSinceLastSeen >= thresholdInMillis) {
        deviceName += ' (NOK)';
        nokDevices.push(deviceName);
        notReportingCount++; // Increment the count of not reporting devices
        DevicesNotReporting.push(deviceName); // Add the device to the list of not reporting devices
      } else {
        deviceName += ' (OK)';
        okDevices.push(deviceName);
      }

      if (device.type.toLowerCase() === 'router') routerDevices.push(deviceName);
      if (device.type.toLowerCase() === 'enddevice') endDevices.push(deviceName);
    }

    // Log Zigbee devices and their types
    console.log(okDevices.length, 'OK Zigbee devices', '(' + routerDevices.length + ' Router, ' + endDevices.length + ' End device based on selection)');
    console.log(nokDevices.length, 'NOK Zigbee devices');
    console.log('---------------------------------------------');
    console.log('OK ZigBee device(s):');
    console.log(okDevices.join('\r\n'));
    console.log('---------------------------------------------');
    console.log('NOK ZigBee device(s):');
    console.log(nokDevices.join('\r\n'));
    console.log('---------------------------------------------');

    // Output for script AND card
    await tag('InvalidatedDevices', DevicesNotReporting.join('\n'));
    await tag('notReportingCount', notReportingCount);

    // Define a return value
    const myTag = `Not Reporting Count: ${notReportingCount}\nDevices Not Reporting:\n${DevicesNotReporting.join('\n')}`;

    // Return the defined value
    return myTag;
  } catch (error) {
    console.error('Failed: Getting ZigBee state', error);
    // Output for script AND card
    await tag('InvalidatedDevices', '');
    await tag('notReportingCount', -1); // Set to -1 to indicate an error

    // Define a return value for error state
    const myTag = `Error in retrieving ZigBee state`;

    // Return the defined value
    return myTag;
  }
}

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

// Return the defined value
return myTag;


Example of 2 hours threshold (not 10) :

picture

5 Likes