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
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) :