This template supervises not ignored Things. When a Thing is offline, it changes the item Things online item
to off
and creates a new item under Parent item
with the label set to the label of the Thing that is offline. Then it switches that item to off
.
When the Thing is online again, the created item is not deleted but switched to on
. That way offline/online history is kept and you can analyse, when Things were offline to find potential problems.
To setup this template, follow these steps.
Prepare the item:
- Click on
Settings
→Model
- On the right, click on
Add Equipment
- Name:
OnlineThings
, Label:Online Things
- Click
Create
- Click
Add Metadata
→State Description
- Toggle on
Read only
andSave
(top right) - Click on
Online Things
to open it - Click
Edit
on top right - Set
Members Base Type
toSwitch
- Click
Save
(top right)
Install the template:
- Click on
Settings
and then onAutomation
- Scroll to
Rule Templates
and click onShow xx more
- Click the
ADD
button onOffline Things Display
- Click the large
ADD
button on the pop up
Setup the rule:
- Go to
Rules
and create a rule fromOffline Things display
. - Select the above item
Online Things
asParent item
,Ignored Things item
andThings online item
. - Force a Thing to be offline by e.g. removing power from it
- Check the item
Online Things
, it should go tooff
and an item named after the offline Thing should be created inside.
Ignore a Thing:
- Go to
Settings
→Things
- In the list, on the Thing you want to ignore, click the square
Copy UID
- Click on
Settings
→Model
- Click on
Online Things
- On the right, click on
Online Things
to open it - Click
Edit
on top right - Paste into
Add tag
and pressenter
- Click
Save
(top right)
Show it on a page:
- Click on
Settings
→Pages
- Click on
Overview
(or an other page you want) - If you don’t have rows/columns, click
Add Row
and on the rowAdd Column
- Click on it and choose
List card
- Click on the
+
and chooseLabel List Item
- Click on it and
Edit YAML
- Paste the code
YAML for Label List Item
below into it - Click
Done
andSave
(top right)
Note:
Then you use a Group
as Things online item
, the state on
and off
is only visible if at least one item was created within the group.
Inputs, corrections and suggestions are very welcome.
Detection of offline Things is based on the template Thing Status Reporting. My first approach was to use it to implement this template. But it turned out more complicated than implementing that part myself.
YAML for Label List Item:
component: oh-label-item
config:
action: group
actionGroupPopupItem: OnlineThings
item: OnlineThings
style:
background: =items.OnlineThings.state == 'OFF'?'red':''
title: Online Things
Language: ECMAScript (ECMAScript 262 Edition 11)
Dependencies: JavaScript Scripting
Changelog
Version 0.1
- initial release
Version 0.2
- do not delete online items in other groups
Resources
uid: prosenb:offline_things_display
label: Offline Things display
description: Queries all Things about offline state and displays the offline ones.
configDescriptions:
- name: PARENT_ITEM
label: Parent item
description: Online items for Things will be created under this item. It must be of type `Group`.
type: TEXT
context: item
required: true
- name: IGNORE_THINGS_ITEM
label: Ignored Things item
description: Create a tag on this item for each Thing to be ignore.
type: TEXT
context: item
required: false
- name: THINGS_ONLINE_ITEM
label: Things online item
description: This items shows if any Thing is offline. It is `on` when all Things are online and `off` otherwise. It must be of type `Switch` or `Group`. If it's `Group`, the `Members Base Type` must be set to `Switch`.
type: TEXT
context: item
required: false
- name: ITEM_LIST_WIDGET
label: Online items list widget
description: The list widget of the items representing the online state of Things.
type: TEXT
required: false
defaultValue: oh-label-item
triggers:
- id: "1"
label: A Thing Changes Status
description: Triggers when any Thing changes status
configuration:
types: ThingStatusInfoChangedEvent
payload: ""
topic: openhab/things/**
source: ""
type: core.GenericEventTrigger
conditions: []
actions:
- inputs: {}
id: "1"
configuration:
type: application/javascript;version=ECMAScript-2021
script: >-
/* global Java, event, items, actions */
(function () {
// Arguments
const parentItemName = '{{PARENT_ITEM}}';
const ignoreThingsItemName = '{{IGNORE_THINGS_ITEM}}';
const thingsOnlineItemName = '{{THINGS_ONLINE_ITEM}}';
const itemListWidget = '{{ITEM_LIST_WIDGET}}';
const parentItem = items.getItem(parentItemName, true);
const ignoreThingsItem = items.getItem(ignoreThingsItemName, true);
const thingsOnlineItem = items.getItem(thingsOnlineItemName, true);
if (parentItem == null) {
console.info("parentItem not found, stop rule.")
return;
}
var notProcessedThingOnlineItems = parentItem.members;
var atLeastOneOffline = false;
things.getThings().forEach(thing => {
const onlineItemName = generateOnlineItemName(thing);
// remove this item from notProcessedThingOnlineItems
notProcessedThingOnlineItems = notProcessedThingOnlineItems.filter(item => item.name !== onlineItemName);
if (ignoreThingsItem != null && ignoreThingsItem.tags.includes(thing.uid)) {
if (items.getItem(onlineItemName, true) != null) {
items.removeItem(onlineItemName);
console.info("OfflineThingsDisplay", "ignored, remove onlineItem: " + onlineItemName);
}
} else if (thing.status == "OFFLINE") {
atLeastOneOffline = true;
var onlineItem = items.getItem(onlineItemName, true);
if (onlineItem == null) {
console.info("OfflineThingsDisplay", "add onlineItem: " + onlineItemName);
addItem(onlineItemName, thing.label);
onlineItem = items.getItem(onlineItemName);
}
if (onlineItem.state == "ON") {
console.info("OfflineThingsDisplay", "offline: " + onlineItemName);
}
onlineItem.sendCommandIfDifferent("OFF");
replaceMetadata(onlineItem, "widgetOrder", "1");
} else { // ONLINE
const onlineItem = items.getItem(onlineItemName, true);
if (onlineItem != null) {
if (onlineItem.state == "OFF") {
console.info("OfflineThingsDisplay", "online: " + onlineItemName);
}
onlineItem.sendCommandIfDifferent("ON");
replaceMetadata(onlineItem, "widgetOrder", "100");
}
}
});
if (thingsOnlineItem != null) {
if (atLeastOneOffline) {
thingsOnlineItem.sendCommandIfDifferent("OFF");
} else {
thingsOnlineItem.sendCommandIfDifferent("ON");
}
}
// remove ThingOnlineItems that related to deleted Things
notProcessedThingOnlineItems.forEach(item => {
if (item.tags.find(tag => tag == "ThingOnlineItem") == null) {
console.debug("Not removed item " + item.name
+ " because it does not have the tag ThingOnlineItem but: " + item.tags);
} else if (item.groupNames.size() > 1) {
console.debug("Not removed item " + item.name
+ " because it is also in other groups: " + item.groupNames);
} else {
items.removeItem(item.name);
console.info("Removed item: " + item.name);
}
});
function addItem(name, label) {
items.addItem({
type: 'Switch',
name: name,
label: label,
groups: [parentItemName],
tags: ['Point', 'ThingOnlineItem'],
metadata: {
listWidget: itemListWidget,
stateDescription: {
config: {
readOnly: true
}
}
}
});
}
function generateOnlineItemName(thing) {
const newName = 'Online_' + thing.uid;
return newName.replaceAll(":", "_").replaceAll("-", "_");
}
function replaceMetadata(item, namespace, value) {
// OPENHAB_JS_VERSION before 4.5.0 are null
if (utils.OPENHAB_JS_VERSION == null) {
item.upsertMetadataValue(namespace, value);
} else {
item.replaceMetadata(namespace, value);
}
}
})()
type: script.ScriptAction