The Flow Exchange(r) - Exchange Your Flows with Others!

Sensor (or any device) Connection Check.


Sometimes, you’ll discover a sensor or other device doesn’t report it’s status or value anymore, but it does NOT notify you of being offline…

Well, this flow checks the, most recent update time of your sensors.
You can run the flow every day, twice a day, just add or remove a time triggercard.
The ‘inactive time’ can be edited as well (24hrs as default) and you can choose to not send notifications when all sensors did report inside the ‘inactive timer’ timeframe.


Apps used:


  • For now, in the imported flow, you’ll have to replace the ‘dummy’ DeviceCapabilities cards with HomeyScript THEN card “Run 'CODE' _with ARGUMENT_, and return 'TEXT-TAG'”.
    But first copy the script inside them:
    • use CTRL+A and then CTRL+C,
    • to paste it later on, use CTRL+A and then CTRL+V in the HomeyScript card.
      A how-to screenvid (of a similar flowcard):
      Peek 2022-09-23 16-02

The script used here (latest version: check here):

Click to view the script
// Version 0.3b 
// Script checks devices based on the last updated time against a threshold
// Focuses on temperature sensors and specified device classes

const NotReportingThreshold = 0.8; // 0.8 hours, which is 48 minutes
const thresholdInMillis = NotReportingThreshold * 3600000; // Convert hours to milliseconds

let DevicesNotReporting = [];
let devices = await Homey.devices.getDevices();
let notReportingCount = 0; // Variable to keep track of the count

// Function to format date as "dd-mm-yyyy, hh:mm:ss"
function formatDate(date) {
    if (!date) return "Unknown"; // Return 'Unknown' if date is null or invalid

    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}`;
}

for (const device of Object.values(devices)) {
    // Exclude Virtual Devices and specific apps
    if (device.driverUri && device.driverUri.match('vdevice|nl.qluster-it.DeviceCapabilities|nl.fellownet.chronograph|net.i-dev.betterlogic|com.swttt.devicegroups|com.gruijter.callmebot|com.netscan')) continue; 

    // Include by regex device name, focusing on temperature-related devices
    if (!device.name || !device.name.match(/temperature/i)) continue;

    // Exclude devices based on specific name patterns (if necessary, uncomment and modify)
    // if (device.name.match(/Flood|TVOC|Netatmo Rain|Motion|Flora|Rear gate Vibration Sensor|Vibration Sensor Attic Doors/i)) continue;

    // Include devices based on device class
    if (!device.class || !device.class.match(/sensor|button|remote|socket|lights/i)) continue;

    let IsReporting = false;
    let lastUpdated = null;

    for (const capability of Object.values(device.capabilitiesObj)) {
        if (!capability.lastUpdated) continue; // Skip capabilities without lastUpdated info
        let timeSinceReport = Date.now() - new Date(capability.lastUpdated).getTime();
        if (timeSinceReport < thresholdInMillis) {
            IsReporting = true;
            break;
        }
        // Track the most recent update
        if (!lastUpdated || new Date(capability.lastUpdated) > new Date(lastUpdated)) {
            lastUpdated = new Date(capability.lastUpdated);
        }
    }

    if (!IsReporting) {
        let deviceInfo = `${device.name} (${formatDate(lastUpdated)} - ${device.class}) (NOK)`;
        DevicesNotReporting.push(deviceInfo);
        console.log('NOK:', deviceInfo);

        // Increment the count
        notReportingCount++;
    } else {
        let deviceInfo = `${device.name} (${formatDate(lastUpdated)} - ${device.class}) (OK)`;
        console.log('OK:', deviceInfo);
    }
}

// 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;

// Original script by Robert Klep
// https://community.homey.app/t/a-script-to-check-sensor-last-update/63142/9


Output example:


TEF:

[tef:FLOWS:"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":/tef]
11 Likes