code updated.. v2 of script out now.
Hello everyone!
I wanted to share a solution I’ve developed for monitoring devices/sensors connectivity in my smart home setup. The problem I faced was not knowing if a sensor was working and sending up-to-date information. I’m sure everyone has had the problem with devices showing “last update 5 months ago” without knowing it.
This advanced flow has a time-based trigger, a HomeyScript, and sends notifications to my phone. Based on the criticality of the sensors/devices being monitored, I adjust the runtime on the flow trigger and what devices to monitor.
I have seen other solutions to the same problem on this forum, but I have found them a bit complicated to implement. If anyone else is in the same situation as me, feel free to test this flow and give feedback/further develop it to make it better.
How to use the flow
Step 1: Create the script While using your computer, log in to your Homey portal and press “Web app”. In the left-side banner, click “HomeyScript”. Then click “+ New HomeyScript”, give it a name like Device Monitor , and paste in the code below.
The best part is, you only have to do this once! You won’t need to edit the script itself again.
GitHub repo:
https://github.com/2re1million/homeydevicemonitor/blob/main/homeyDeviceMonitor.js
Full Code:
/*
=== Homey Device Monitor Script ===
* This script is configured directly from your Homey Flow using the "Arguments" field.
* This makes it highly reusable for different monitoring needs without editing the code.
*
* Example Argument for critical sensors:
* { "MAX_TIME_SINCE_UPDATE": 8, "DEVICE_IDS_TO_SHOW": ["id-1", "id-2"] }
*
* Example Argument for all lights:
* { "MAX_TIME_SINCE_UPDATE": 72, "DEVICE_CLASSES_TO_SHOW": ["light"] }
*/
// --- DEFAULT CONFIGURATION ---
// These settings are used if no arguments are provided in the Flow.
const defaultConfig = {
// Set to true to get a list of all devices and their IDs, useful for initial setup.
SHOW_ALL_DEVICES: false,
// Default classes to monitor. E.g., ['sensor', 'light']
DEVICE_CLASSES_TO_SHOW: [],
// Default IDs to monitor. E.g., ["id-1", "id-2"]
DEVICE_IDS_TO_SHOW: [],
// Default IDs to ignore.
DEVICE_IDS_TO_IGNORE: [],
// Default maximum time since last update (in hours).
MAX_TIME_SINCE_UPDATE: 48,
};
// --- SCRIPT STARTS HERE ---
// Merge arguments from Flow with default config
const flowArgs = args[0] ? JSON.parse(args[0]) : {};
const CONFIG = { ...defaultConfig, ...flowArgs };
// Function to format the time since last update
function formatTimeSince(date) {
if (!date) return 'Never';
const seconds = Math.floor((new Date() - new Date(date)) / 1000);
const intervals = [
{ label: 'month', seconds: 2592000 },
{ label: 'day', seconds: 86400 },
{ label: 'hour', seconds: 3600 },
{ label: 'minute', seconds: 60 },
];
for (const interval of intervals) {
const count = Math.floor(seconds / interval.seconds);
if (count >= 1) {
return `${count} ${interval.label}${count > 1 ? 's' : ''} ago`;
}
}
return 'Just now';
}
// Main function to monitor devices
async function runDeviceMonitor() {
let fullOutput = "";
let conciseOutput = "";
let issueCount = 0;
const devices = await Homey.devices.getDevices();
if (CONFIG.SHOW_ALL_DEVICES) {
let allDevicesList = '--- ALL DEVICES ---\n';
for (const device of Object.values(devices)) {
allDevicesList += `\nName: ${device.name}\nClass: ${device.class}\nID: ${device.id}\n`;
}
log(allDevicesList);
return true; // Stop execution after listing all devices
}
for (const device of Object.values(devices)) {
// Filter by class, if specified
if (CONFIG.DEVICE_CLASSES_TO_SHOW.length > 0 && !CONFIG.DEVICE_CLASSES_TO_SHOW.includes(device.class)) {
continue;
}
// Filter by specific IDs, if specified
if (CONFIG.DEVICE_IDS_TO_SHOW.length > 0 && !CONFIG.DEVICE_IDS_TO_SHOW.includes(device.id)) {
continue;
}
// Ignore specified IDs
if (CONFIG.DEVICE_IDS_TO_IGNORE.includes(device.id)) {
continue;
}
if (!device.capabilitiesObj || Object.keys(device.capabilitiesObj).length === 0) continue;
const mostRecentUpdate = Object.values(device.capabilitiesObj).reduce((latest, cap) => {
const capDate = new Date(cap.lastUpdated);
return capDate > latest ? capDate : latest;
}, new Date(0));
const timeSinceUpdateHours = (new Date() - mostRecentUpdate) / 3600000;
if (timeSinceUpdateHours >= CONFIG.MAX_TIME_SINCE_UPDATE) {
issueCount++;
const lastSeen = formatTimeSince(mostRecentUpdate);
fullOutput += `\n=== ${device.name} ===\nClass: ${device.class}\nLast Seen: ${lastSeen}\nID: ${device.id}\n`;
conciseOutput += `- ${device.name} (seen ${lastSeen})\n`;
}
}
if (issueCount === 0) {
// No issues found, clear tags and throw an error to stop the flow
await tag('full_report', '');
await tag('concise_report', '');
await tag('issue_count', 0);
throw new Error('No devices with issues found. Flow stopped.');
}
// Issues were found, set tags and log the output
const summary = `Found ${issueCount} device(s) needing attention.`;
await tag('full_report', `${summary}\n${fullOutput}`);
await tag('concise_report', `${summary}\n${conciseOutput}`);
await tag('issue_count', issueCount);
log(fullOutput);
log(summary);
return true;
}
// Run the monitor
return await runDeviceMonitor();
Step 2: Configure the script to suit your needs
Instead of editing the script file, you now configure everything in the Arguments field of the HomeyScript flow card.
First, you might need the IDs of your devices.
- To get a list of all your devices and their IDs, create a temporary flow, run the script, and put this text in the Arguments field:
{ "SHOW_ALL_DEVICES": true }. - Check the HomeyScript log to see the output, and copy the IDs you need.
Now you can configure your real monitoring flow. Here are the two main ways:
Option 1: Monitor a few specific devices (best if you have a few devices you want to monitor closely)
- In the Arguments field of the flow card, you’ll tell the script which devices to watch and how long to wait before notifying you.
- Example: To monitor 3 specific sensors and get an alert if they haven’t been seen for 8 hours , you would paste this into the Arguments field:
{
"MAX_TIME_SINCE_UPDATE": 8,
"DEVICE_IDS_TO_SHOW": [
"34sdf4-3433-332432-3sdfd",
"dsfs3d-3433-332432-3sdfd",
"55yytf4-3433-332432-3sdfd"
]
}
Option 2: Monitor whole groups of devices (best if there are many devices you want to monitor)
- You can tell the script to monitor all devices of a certain class, like all your lights or all your sensors.
- The different classes are:
sensor,light,other,speaker,thermostat,socket,tv,blinds,remote. - Example: To monitor all of your lights and sensors and get an alert if any of them haven’t been seen for 72 hours , paste this into the Arguments field:
{
"MAX_TIME_SINCE_UPDATE": 72,
"DEVICE_CLASSES_TO_SHOW": [
"light",
"sensor"
]
}
If you want to monitor a class but exclude one or two specific devices, you can add their IDs to an ignore list like this:
{
"MAX_TIME_SINCE_UPDATE": 72,
"DEVICE_CLASSES_TO_SHOW": ["light"],
"DEVICE_IDS_TO_IGNORE": ["id-of-light-to-ignore"]
}
ery important Sometimes the output of the code in the editor is Error . This is most likely because there are no faulty devices. The script is designed to do this to stop the flow from sending you a notification. You only get an alert when something is wrong!
Step 3: Create a new “Advanced Flow” and set it up like this This part is just like before. The key is to paste your configuration text from Step 2 into the Arguments field on the HomeyScript card.
It’s a time-based trigger card. Then the code card is: HomeyScript with “Run Script”. Select your new script from the list and paste your JSON configuration into the Arguments field. Then the notification card with you as a user, using the concise_report tag.
Step 4) Best Practices You can now easily create multiple flows for different needs without touching the script file.
For example, I have one flow that runs twice a day to check that my critical “water heater” and garage “dehumidifier” have been online in the last 8 hours.
Then I have a different flow with a weekly trigger to see if all devices with class sensor and light have been running for the last 168 hours.
