I can tell you how I do it.
First of all, OH is not a great generic IT and network monitoring system so I only do this for the home automation relevant stuff.
Setting up the Items
I use the semantic model to organize my Items. This is important because everything that follows depends on that.
Each equipment that I care about has a status Item as a member of the Group. It doesn’t really matter what the name is, but it is semantically tagged with “Status”. Here’s an example from the Settings → Model page:
Toggling the Status Item when the device goes OFFLINE/ONLINE
This is going to depend on the device, Thing, and bindings. Some Things will report the online status of a device as a Channel on the Thing. Others will reliably detect when a device goes offline and set the status of the Thing to OFFLINE. Still others won’t do anything at all, and you need something else to tell you if the device went offline such as the Network binding to ping the device or just monitor the Items and you know it’s offline when the Item(s) stop updating.
This is why there is no generic solution to the problem. There is a huge variability in how one detects when a device has gone offline.
- For Things that offer a Channel, simply link the Channel to the Status Item. You may need to do a transform to convert the status to ON/OFF.
- For Things which change their own status use Thing Status Reporting [4.0.0.0;5.9.9.9]. The rule I pair with this rule template is as follows. Notice how I use a map to identify the Thing with the status Item. But were I to write this today I’d get to the Item through the Thing and the Links.:
configuration: {}
triggers: []
conditions:
- inputs: {}
id: "1"
configuration:
type: application/javascript
script: >
console.debug('Processing a Thing status change ' + ruleUID);
const key = ruleUID+'_thingToItem';
if(!cache.shared.exists(key)) {
console.info('Creating Thing to Status Item map');
cache.shared.put(key, { 'zwave:serial_zstick:zw_controller' : 'Zwave_Status',
'zigbee:coordinator_ember:zg_coordinator': 'Zigbee_Status',
'ipcamera:generic:garage_camera' : 'GarageCamera_Raw',
'mqtt:topic:broker:family' : 'FamilyRoomWaveplus_Status',
'mqtt:topic:broker:basement_waveplus' : 'BasementAirthingsWavePlus_Status'
});
}
const rval = cache.shared.get(key)[thingID] !== undefined;
console.debug('Run the actions? ' + rval);
return rval;
type: script.ScriptCondition
actions:
- inputs: {}
id: "2"
configuration:
type: application/javascript
script: >
console.debug('Thing process change running...');
console.debug('Thing ' + thingID + ' changed from ' + oldStatus + ' (' +
oldDetail + ') to '
+ newStatus + '(' + newDetail + ')');
const itemName = cache.shared.get(ruleUID+'_thingToItem')[thingID];
const newState = (newStatus == 'ONLINE') ? 'ON' : 'OFF';
console.debug(cache.shared.get(ruleUID+'_thingToItem'));
console.debug('Thing status update: ' + itemName + ' ' + newState);
items[itemName].postUpdate(newState);
type: script.ScriptAction
- For devices that you just have to monitor and set to OFF when it stops updating the Items you can use Basic Profiles - Transformation Services | openHAB or Threshold Alert and Open Reminder [4.0.0.0;5.9.9.9]. I use the latter and the rule I pair with the rule template is as follows. Notice how I navigate the semantic model to find the status Item.
configuration: {}
triggers: []
conditions:
- inputs: {}
id: "2"
configuration:
type: application/javascript
script: >
const equipment = items[alertItem].semantics.equipment;
const statusItem = equipment.members.find(i =>
i.tags.includes['Status']);
if(equipment === null || statusItem === null) {
console.warn(alertItem + ' does not belong to an equipment or equipment doesn\'t have a Status Item!');
return false;
}
else {
const statusItem = items[equipment.name+'_Status'];
console.info('Sensor status reporting called for ' + alertItem + ', equipment ' + equipment.label + ', is alerting ' + isAlerting + ', and is initial alert ' + isInitialAlert
+ ', current equipment state is ' + statusItem.state);
// Sensor is offline Sensor back online
return (isAlerting && statusItem.state != 'OFF') || (!isAlerting && statusItem.state != 'ON');
}
type: script.ScriptCondition
actions:
- inputs: {}
id: "1"
configuration:
type: application/javascript
script: >
const equipment = items[alertItem].semantics.equipment;
const statusItem = equipment.members.find(i =>
i.tags.includes('Status'));
const refid = statusItem+'_offline_alert';
if(isAlerting && statusItem.state != 'OFF') {
statusItem.postUpdate('OFF');
console.info(equipment.label + ' is offline!')
actions.notificationBuilder(equipment.label + ' has stopped reporting!')
.addUserId('rlkoshak@gmail.com')
.withTag('Alarm')
.withTitle(equipment.label + 'Stopped!')
.withIcon('if:wpf:online')
.withReferenceId(refid)
.send();
}
else if(!isAlerting && statusItem.state != 'ON') {
statusItem.postUpdate('ON');
console.info(equipment.label + ' is back online');
actions.notificationBuilder("hide notification").withReferenceId(refid).hide().send();
}
else {
console.info('Sensor status update alerting ' + isAlerting + ' initial ' + isInitialAlert + ' equipment ' + equipment.label + ' status ' + statusItem.state);
}
type: script.ScriptAction
I don’t have a great approach to dealing with restarts but where needed I use Restart Expire [4.0.0.0;5.9.9.9] to update the Items being monitored by Threshold Alert with whatever state they got restored to from persistence during startup. I’ve modified my Threshold Alert rule to trigger on state updates instead of changes, so this update causes Threshold Alert to start monitoring the Item again. If it doesn’t get updated again the status will be set to OFF.
Monitoring the status from the UI
I’m a strong proponent of not showing stuff that doesn’t need to be shown. So I have a widget that only shows those services/equipment that are offline. If it’s online, there’s nothing to show.
Like the rule templates above, I’ve posted this to the marketplace as well: Service Status Standalone Widget
The widget assumes that any Item tagged with “Status” represents the online status of a service and it will only show it if that Item happens to be OFF.
All the rule templates and the widget can be installed through the Add-on Store. Read each for any additional requirements (e.g. the rule templates posted above require JS Scripting and openHAB-rules-tools to be installed (you can install OHRT from openhabian-config, using Install openHAB Rules Tools [5.0.0.0;5.9.9.9] or manually using npm).
Reacting
As you can see above, all I really do when a device goes offline is to publish a notification and cancel the notification when it comes back online. But you can do anything you want in the rule called by Threshold Alert.
You can use a GenericTrigger or the rule template I posted above (which uses a GenericTrigger). I believe for some cases they added an ability to trigger one rule with a wild card ThingStatusEvent but I don’t know the details.
Items have metadata, but Things do not.
Yes, in JS Scripting and Blockly and jRuby it’s easy to get a Thing’s status in a rule.
The rule template I posted above triggers on all ThingStatusInfo events for all things. So you can use that trigger as an example or just install and use that rule template.