Hi mates,
I’m happy that you gave the concept a try
I’ve just evolved the above a tiny bit even more …
Some of you may have seen my oh-repeater
stuff for timestamps here:
To not spread related content via multiple threads, I’d like to share it here:
Dynamic warning timeouts
In the thread linked above, I’ve created a list which hilights outstanding heartbeats from wireles sensors:
The initial attempt used a fixed timeout (1h) for warnings and another (1day) for errors.
This leads to some false negativ presentation:
While most wireless sensors report something every some seconds/minutes, I do have some sensors too which need quite very long periods of deep sleep to reach an acceptable battery lifetime:
- Xiaomi Lumi Zigbee temp/hum/pressure sensors
- Shelly Flood water sensors
- Shelly Door Window sensors
See them in the above picture shown with orange or red badges…
To overcome this limitation, I’ve extended my uiSemantics
namespace by additional keys for warning/failure timeouts:
"metadata": {
"uiSemantics": {
"config": {
"warn": -1440,
"fail": -2160,
"icon": "f7:waveform_path_ecg",
"preposition": " im ",
"equipment": "Wassermelder",
"location": "Technikraum"
}
Notice the warn/fail keys here. There I’ve added the specific timeout in minutes for that item.
Sure, you’ll certainly ask for the negative values there - right?
Answer: in the dayjs() calculation in the widget I was using negative offsets. So putting negatives here already saved me some rewrite in my widgets.
As in the OP, I don’t populate the key’s by hand. It’s again in a supporting script:
var enrichMetadata = function(item, icon) {
logger.info("Item tested: "+item)
var prepositionFor = ["Küche", "Werkstatt", "Waschküche", "Bibliothek", "Garage"]
var uiSemanticsKeys = { "equipment" : "" , "location" : "", "prepositon" : "" , "icon" : "" , "warn" : -30, "fail" : -45}
var isPointOf = getValue(item, "semantics", "isPointOf");
logger.info("Item isPointOf: "+ isPointOf );
var equipmentItem = isPointOf === undefined ? ir.getItem(item) : ir.getItem( isPointOf ) ;
var locationItem=ir.getItem(getValue(equipmentItem.name, "semantics", "hasLocation"));
uiSemanticsKeys.equipment = equipmentItem.label;
uiSemanticsKeys.location = locationItem.label;
uiSemanticsKeys.preposition = (prepositionFor.indexOf( uiSemanticsKeys.location) > -1 ) ? " in der " : " im ";
uiSemanticsKeys.icon = icon;
var warnTimeoutFor = {"LUMITH" : -720 , "SHELLYDW" : -240 , "SHELLYFLOOD" : -1440 };
for (var s in warnTimeoutFor) {
if (item.toUpperCase().indexOf(s) > -1 ) {
uiSemanticsKeys.warn = warnTimeoutFor[s];
break;
}
}
uiSemanticsKeys.fail= uiSemanticsKeys.warn * 1.5;
if ( getValue(item, UI_NAMESPACE, "location" ) !== null ) {
logger.info( "Item: "+ item +" UPDATE Metadata in "+ UI_NAMESPACE + ": " + uiSemanticsKeys.equipment + uiSemanticsKeys.preposition + uiSemanticsKeys.location );
MetadataRegistry.update(new Metadata(new MetadataKey( UI_NAMESPACE, item), null , uiSemanticsKeys ));
} else {
logger.info( "Item: "+ item +" ADD Metadata in "+ UI_NAMESPACE + ": " + uiSemanticsKeys.equipment + uiSemanticsKeys.preposition + uiSemanticsKeys.location );
MetadataRegistry.add(new Metadata(new MetadataKey( UI_NAMESPACE, item), null , uiSemanticsKeys ));
}
return null;
}
The scripts makes some assumption on the item name to filter the long-sleeping deivices (items). I did this because I didn’t found a way to determine, what thing type an item is linked to from within a rule.
IF SOMEONE HAS GOT AN IDEA ON THIS, please let me know
Once we have the additional timeout set in our metadata, we can change the oh-repeater loop to use the specific timeouts instead of the fixed for filtering and coloring:
- component: oh-repeater
config:
for: i
sourceType: itemsInGroup
groupItem: =props.mainItem
fetchMetadata: semantics,widgetOrder,uiSemantics
filter: '( loop.i.state < dayjs().add(loop.i.metadata.uiSemantics.config.warn,"m").format() ) ? true : vars.detailsOn '
style:
highlightColor: blue
slots:
default:
- component: oh-list-item
config:
icon: ="f7:"+props.icon
iconColor: '=dayjs(items[loop.i.name].state).isAfter(dayjs().add(loop.i.metadata.uiSemantics.config.warn,"m")) ? "green" : dayjs(items[loop.i.name].state).isAfter(dayjs().add(loop.i.metadata.uiSemantics.config.fail,"m")) ? "orange" : "red"'
footer: =loop.i.metadata.uiSemantics.config.preposition + loop.i.metadata.uiSemantics.config.location
title: =loop.i.metadata.uiSemantics.config.equipment
item: =loop.i.name
badge: =dayjs(items[loop.i.name].state).fromNow()
badgeColor: '=dayjs(items[loop.i.name].state).isAfter(dayjs().add(loop.i.metadata.uiSemantics.config.warn,"m")) ? "green" : dayjs(items[loop.i.name].state).isAfter(dayjs().add(loop.i.metadata.uiSemantics.config.fail,"m")) ? "orange" : "red"'
This brings us:
Notice the Shelly Flood “Wassermelder im Technikraum”. This guy was marked orange formerly. BUT: Since it is absolutely fine, if it sleeps for a whole day if no water alarm is to be issued, the widget should not complain about it…
Have fun …