Yes, it is possible; I have set up a similar system. It is not a trivial task, because it cannot be done just within a widget. You need a widget which uses a dedicated item to trigger and send information to a rule.
Then you can modify metadata, including the expire metadata within that rule. With the expire metadata, there’s the extra slight complication of making the information itself easily editable because it takes the form of 1h30h0s
which isn’t very user friendly.
I’ve not cleaned this up for general use yet, but here are the pieces I use.
String Item named Rule_ExpireModify
Widget code:
uid: widget_expire_all
tags:
- settings
props:
parameters: []
parameterGroups: []
component: oh-list-card
config:
key: =Math.random() + items.Rule_ExpireModify.state
title: Expire Timers
slots:
default:
- component: oh-repeater
config:
fetchMetadata: expire
filter: loop.expireItem.metadata
for: expireItem
fragment: true
itemTags: ","
sourceType: itemsWithTags
slots:
default:
- component: oh-list-item
config:
title: =loop.expireItem.label.replace(' Timer','')
slots:
after:
- component: f7-row
slots:
default:
- component: oh-repeater
config:
for: timeSeg
fragment: true
in:
- index: 1
title: H
- index: 2
title: M
- index: 3
title: S
sourceType: array
slots:
default:
- component: Label
config:
style:
padding:
- 5px 0 1px 15px
text: "=loop.timeSeg.title + ': '"
- component: Label
config:
style:
padding:
- 5px 0 1px 0
text: =loop.expireItem.metadata.expire.value.split(',')[0].match('([0-9]*)h([0-9]*)m([0-9]*)s')[loop.timeSeg.index]
visible: =!vars[loop.expireItem.name + "vis"]
- component: oh-input
config:
defaultValue: =loop.expireItem.metadata.expire.value.split(',')[0].match('([0-9]*)h([0-9]*)m([0-9]*)s')[loop.timeSeg.index]
inputmode: numeric
outline: true
style:
padding:
- 0 5px 0 5px
width: 20px
type: text
variable: =loop.expireItem.name + loop.timeSeg.title
visible: =!!vars[loop.expireItem.name + "vis"]
- component: Label
config:
text: Bug Workaround
visible: false
- component: oh-link
config:
action: command
actionCommand: =loop.expireItem.name + ',' + (vars[loop.expireItem.name + 'H'] || loop.expireItem.metadata.expire.value.split(',')[0].match('([0-9]*)h([0-9]*)m([0-9]*)s')[1]) + ',' + (vars[loop.expireItem.name + 'M'] || loop.expireItem.metadata.expire.value.split(',')[0].match('([0-9]*)h([0-9]*)m([0-9]*)s')[2]) + ',' + (vars[loop.expireItem.name + 'S'] || loop.expireItem.metadata.expire.value.split(',')[0].match('([0-9]*)h([0-9]*)m([0-9]*)s')[3])
actionItem: Rule_ExpireModify
clearVariable: =loop.expireItem.name + "vis"
iconF7: checkmark_circle_fill
style:
padding:
- 3px 0 1px 15px
visible: =!!vars[loop.expireItem.name + "vis"]
- component: oh-link
config:
action: variable
actionVariable: =loop.expireItem.name + "vis"
actionVariableValue: =!vars[loop.expireItem.name + "vis"]
iconF7: "=(vars[loop.expireItem.name + 'vis']) ? 'xmark_circle_fill' : 'pencil'"
style:
padding:
- 3px 0 1px 15px
Rule:
configuration: {}
triggers:
- id: "1"
configuration:
itemName: Rule_ExpireModify
type: core.ItemStateChangeTrigger
conditions:
- inputs: {}
id: "2"
configuration:
itemName: Rule_ExpireModify
state: None
operator: "!="
type: core.ItemStateCondition
actions:
- inputs: {}
id: "3"
configuration:
type: application/javascript;version=ECMAScript-2021
script: >-
/*
This rule enacts changes to an item's expire metadata as set by the portal timers widget
*/
//Set Logger
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.ModifyExpire');
//Access MetadataRegistry
var FrameworkUtil = Java.type("org.osgi.framework.FrameworkUtil");
this.ScriptHandler = Java.type("org.openhab.core.automation.module.script.rulesupport.shared.ScriptedHandler");
var _bundle = FrameworkUtil.getBundle(ScriptHandler.class);
var bundle_context = _bundle.getBundleContext()
var classname = "org.openhab.core.items.MetadataRegistry"
var MetadataRegistry_Ref = bundle_context.getServiceReference(classname);
var MetadataRegistry = bundle_context.getService(MetadataRegistry_Ref);
var Metadata = Java.type("org.openhab.core.items.Metadata");
var MetadataKey = Java.type("org.openhab.core.items.MetadataKey");
//Collect all info from expire modify item state and existing metadata
var modifyInfo = items.getItem(event.itemName).state.split(',');
var timerName = modifyInfo[0];
var newHours = parseInt(modifyInfo[1]);
var newMinutes = parseInt(modifyInfo[2]);
var newSeconds = parseInt(modifyInfo[3]);
var metadata = MetadataRegistry.get(new MetadataKey("expire",timerName));
//Validate new time values and existing metadata
if (newHours < 0 || 23 < newHours) {
logger.warn('Hours outside of range: expire metadata not set')
} else if (newMinutes < 0 || 59 < newMinutes) {
logger.warn('Minutes outside of range: expire metadata not set')
} else if (newSeconds < 0 || 59 < newSeconds) {
logger.warn('Seconds outside of range: expire metadata not set')
} else if (metadata === null) {
logger.warn(['No expire metadata in',event.itemName,': Please configure metadata first.'].join(' '));
} else {
//Write metadata
var oldExpire = metadata.value;
var newExpire = [newHours,'h',newMinutes,'m',newSeconds,'s,',oldExpire.split(',')[1]].join('')
MetadataRegistry.update(new Metadata(new MetadataKey('expire', timerName), newExpire, metadata.configuration));
logger.info(['Expire changed from ',oldExpire,'to',newExpire,'for',timerName].join(' '));
}
//Cleanup
items.getItem(event.itemName).postUpdate('None');
type: script.ScriptAction