Hi guys, had time to finish my TimeScheduler/Cosntructor. It is just basically a timetable for the automated blind control. The table is stored as JSON insidide an item. The Scheduler Widget (upper) just displays the values as “table”, the constructor injects the new values into the JSON (via an item and javascript rule because it is not directly possible inside a widget), a second rule checks via cron if the times are matching and then act accordingly.
Had this already in HabPanel but did rewrite it fully.
- Due to its highly customized to my items and needs I post it to show users the possibilities of the UI
- I only post the widget code and the rule for the JSON ‘injection’ , other rules etc. do not matter
Resources
Schedule Widget:
uid: TimeSchedule
tags: []
props:
parameters:
- description: A text prop
label: Prop 1
name: prop1
required: false
type: TEXT
- context: item
description: An item to control
label: Item
name: item
required: false
type: TEXT
parameterGroups: []
timestamp: Jan 14, 2021, 1:40:36 PM
component: f7-card
slots:
default:
- component: oh-toggle
config:
variable: mobile
slots: {}
- component: Label
config:
text: "=(vars.mobile === true) ? 'Mobil' : 'Tab/Pc'"
slots: {}
- component: f7-swiper
config:
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
slidesPerView: 1
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: room
rangeStart: 0
rangeStop: 13
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.room
expandable: true
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.room === 0) ? 'Wohnzimmer Fenster' : (loop.room === 1) ? 'Wohnzimmer Tisch' : (loop.room === 2) ? 'Wohnzimmer Couch' : (loop.room === 3) ? 'Badezimmer' : (loop.room === 4) ? 'Michael Nord' : (loop.room === 5) ? 'Michael Fenster 1' : (loop.room === 6) ? 'Michael Fenster 2' : (loop.room === 7) ? 'Maxi Fenster 1' : (loop.room === 8) ? 'Maxi Fenster 2' : (loop.room === 9) ? 'Maxi Fenster 3' : (loop.room === 10) ? 'Küche Fenster' : (loop.room === 11) ? 'Küche Panorama' : (loop.room === 12) ? 'Küche Tür' : (loop.room === 13) ? 'Eltern Fenster' : 'unknown' "
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
slots:
default:
- component: oh-list
config:
title: Funktion
slots:
default:
- component: oh-list-item
config:
title: ""
slots: {}
- component: oh-list-item
config:
title: "=(vars.mobile === true) ? 'S1' : 'Stufe 1'"
style:
font-size: "=(vars.mobile === true) ? '15px' : '20px'"
slots: {}
- component: oh-list-item
config:
title: "=(vars.mobile === true) ? 'S2' : 'Stufe 2'"
style:
font-size: "=(vars.mobile === true) ? '15px' : '20px'"
slots: {}
- component: oh-list-item
config:
title: Öffnen
visible: =!vars.mobile
style:
font-size: "=(vars.mobile === true) ? '15px' : '20px'"
slots: {}
- component: oh-list-item
config:
icon: f7:arrow_up
visible: =vars.mobile
slots: {}
- component: oh-list-item
config:
title: Schließen
visible: =!vars.mobile
style:
font-size: "=(vars.mobile === true) ? '15px' : '20px'"
slots: {}
- component: oh-list-item
config:
icon: f7:arrow_down
visible: =vars.mobile
slots: {}
- component: oh-repeater
config:
sourceType: range
for: day
rangeStart: 1
rangeStop: 7
fragment: true
slots:
default:
- component: f7-col
slots:
default:
- component: oh-list
config:
title: Tage
slots:
default:
- component: oh-list-item
config:
title: "=(vars.mobile === true) ? ((loop.day === 1) ? 'Mo' : (loop.day === 2) ? 'Di' : (loop.day === 3) ? 'Mi' : (loop.day === 4) ? 'Do' : (loop.day === 5) ? 'Fr' : (loop.day === 6) ? 'Sa' : (loop.day === 7) ? 'So' : 'unknown') : ((loop.day === 1) ? 'Montag' : (loop.day === 2) ? 'Dienstag' : (loop.day === 3) ? 'Mittwoch' : (loop.day === 4) ? 'Donnerstag' : (loop.day === 5) ? 'Freitag' : (loop.day === 6) ? 'Samstag' : (loop.day === 7) ? 'Sonntag' : 'unknown')"
style:
font-size: "=(vars.mobile === true) ? '15px' : '20px'"
slots: {}
- component: oh-list-item
config:
title: =JSON.parse(items.SavedSchedule.state)[loop.room.toString()][loop.day.toString()]['LAM1']
style:
font-size: "=(vars.mobile === true) ? '12px' : '18px'"
slots: {}
- component: oh-list-item
config:
title: =JSON.parse(items.SavedSchedule.state)[loop.room.toString()][loop.day.toString()]['LAM2']
style:
font-size: "=(vars.mobile === true) ? '12px' : '18px'"
slots: {}
- component: oh-list-item
config:
title: =JSON.parse(items.SavedSchedule.state)[loop.room.toString()][loop.day.toString()]['AUF']
style:
font-size: "=(vars.mobile === true) ? '12px' : '18px'"
slots: {}
- component: oh-list-item
config:
title: =JSON.parse(items.SavedSchedule.state)[loop.room.toString()][loop.day.toString()]['ZU']
style:
font-size: "=(vars.mobile === true) ? '12px' : '18px'"
slots: {}
Constructor Widget
uid: TimeController
tags: []
props:
parameters:
- description: Switch on Debug Mode
label: Debug Mode
name: debugmode
required: false
type: BOOLEAN
- context: item
description: An item to control
label: Item
name: item
required: false
type: TEXT
parameterGroups: []
timestamp: Jan 16, 2021, 7:29:46 PM
component: f7-card
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: Label
config:
text: "Bitte wähle ein Fenster/Raffstore aus:"
style:
color: rgb(255,59,48)
font-weight: 600
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: oh-list
config:
title: Liste
accordionList: true
style:
margin-top: 5px
slots:
default:
- component: oh-list-item
config:
title: "=(vars.roomS === NULL) ? 'Wählen Sie ein Fenster' : vars.roomS"
accordionItem: true
slots:
accordion:
- component: oh-list
config:
accordionList: true
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: room
rangeStart: 0
rangeStop: 13
fragment: true
slots:
default:
- component: oh-list-item
config:
title: "=(loop.room === 0) ? 'Wohnzimmer Fenster' : (loop.room === 1) ? 'Wohnzimmer Tisch' : (loop.room === 2) ? 'Wohnzimmer Couch' : (loop.room === 3) ? 'Badezimmer' : (loop.room === 4) ? 'Michael Nord' : (loop.room === 5) ? 'Michael Fenster 1' : (loop.room === 6) ? 'Michael Fenster 2' : (loop.room === 7) ? 'Maxi Fenster 1' : (loop.room === 8) ? 'Maxi Fenster 2' : (loop.room === 9) ? 'Maxi Fenster 3' : (loop.room === 10) ? 'Küche Fenster' : (loop.room === 11) ? 'Küche Panorama' : (loop.room === 12) ? 'Küche Tür' : (loop.room === 13) ? 'Eltern Fenster' : 'unknown' "
action: variable
actionVariable: roomS
actionVariableValue: "=(loop.room === 0) ? 'Wohnzimmer Fenster' : (loop.room === 1) ? 'Wohnzimmer Tisch' : (loop.room === 2) ? 'Wohnzimmer Couch' : (loop.room === 3) ? 'Badezimmer' : (loop.room === 4) ? 'Michael Nord' : (loop.room === 5) ? 'Michael Fenster 1' : (loop.room === 6) ? 'Michael Fenster 2' : (loop.room === 7) ? 'Maxi Fenster 1' : (loop.room === 8) ? 'Maxi Fenster 2' : (loop.room === 9) ? 'Maxi Fenster 3' : (loop.room === 10) ? 'Küche Fenster' : (loop.room === 11) ? 'Küche Panorama' : (loop.room === 12) ? 'Küche Tür' : (loop.room === 13) ? 'Eltern Fenster' : 'unknown' "
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: Label
config:
text: "Bitte wähle einen Tag aus:"
style:
color: rgb(255,59,48)
font-weight: 600
margin-top: 15px
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-segmented
config:
strong: false
style:
width: 450px
margin-top: 5px
slots:
default:
- component: oh-button
config:
text: Mo
action: variable
actionVariable: day
actionVariableValue: 1
disabled: =(vars.day === 1)
textColor: "=(vars.day === 1) ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Di
action: variable
actionVariable: day
actionVariableValue: 2
disabled: =(vars.day === 2)
textColor: "=(vars.day === 2) ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Mi
action: variable
actionVariable: day
actionVariableValue: 3
disabled: =(vars.day === 3)
textColor: "=(vars.day === 3) ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Do
action: variable
actionVariable: day
actionVariableValue: 4
disabled: =(vars.day === 4)
textColor: "=(vars.day === 4) ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Fr
action: variable
actionVariable: day
actionVariableValue: 5
disabled: =(vars.day === 5)
textColor: "=(vars.day === 5) ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Sa
action: variable
actionVariable: day
actionVariableValue: 6
disabled: =(vars.day === 6)
textColor: "=(vars.day === 6) ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: So
action: variable
actionVariable: day
actionVariableValue: 7
disabled: =(vars.day === 7)
textColor: "=(vars.day === 7) ? 'green' : 'red'"
style:
font-weight: 400
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: Label
config:
text: "Bitte wähle ein Funktion aus:"
style:
color: rgb(255,59,48)
font-weight: 600
margin-top: 15px
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-segmented
config:
strong: false
style:
width: 450px
margin-top: 5px
slots:
default:
- component: oh-button
config:
text: Stufe 1
action: variable
actionVariable: function
actionVariableValue: LAM1
disabled: =(vars.function === 'LAM1')
textColor: "=(vars.function === 'LAM1') ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Stufe 2
action: variable
actionVariable: function
actionVariableValue: LAM2
disabled: =(vars.function === 'LAM2')
textColor: "=(vars.function === 'LAM2') ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Öffnen
action: variable
actionVariable: function
actionVariableValue: AUF
disabled: =(vars.function === 'AUF')
textColor: "=(vars.function === 'AUF') ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Schließen
action: variable
actionVariable: function
actionVariableValue: ZU
disabled: =(vars.function === 'ZU')
textColor: "=(vars.function === 'ZU') ? 'green' : 'red'"
style:
font-weight: 400
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-segmented
config:
strong: false
style:
width: 450px
margin-top: 5px
slots:
default:
- component: oh-button
config:
text: Uhrzeit ändern
action: variable
actionVariable: variante
actionVariableValue: change
disabled: =(vars.variante === 'change')
textColor: "=(vars.variante === 'change') ? 'green' : 'red'"
style:
font-weight: 400
- component: oh-button
config:
text: Deaktivieren
action: variable
actionVariable: variante
actionVariableValue: deactivate
disabled: =(vars.variante === 'deactivate')
textColor: "=(vars.variante === 'deactivate') ? 'green' : 'red'"
style:
font-weight: 400
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: Label
config:
text: "Bitte wähle eine Zeit aus:"
visible: =!(vars.variante === 'deactivate')
style:
color: rgb(255,59,48)
font-weight: 600
margin-top: 15px
- component: f7-row
config:
visible: =!(vars.variante === 'deactivate')
class:
- justify-content-center
- align-items-center
- text-align-center
style:
margin-top: 5px
slots:
default:
- component: oh-input
config:
type: time
defaultValue: =dayjs().format('HH:mm')
validate: true
step: 900
min: 00:00
max: 23:59
required: true
variable: time
disabled: =(vars.variante === 'deactivate')
slots: {}
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
- text-align-center
style:
margin-top: 20px
slots:
default:
- component: oh-button
config:
raised: true
text: Ändern
action: command
actionItem: ScheduleSaving
actionCommand: "=((vars.roomS === 'Wohnzimmer Fenster') ? '0' : (vars.roomS === 'Wohnzimmer Tisch') ? '1' : (vars.roomS === 'Wohnzimmer Couch') ? '2' : (vars.roomS === 'Badezimmer') ? '3' : (vars.roomS === 'Michael Nord') ? '4' : (vars.roomS === 'Michael Fenster 1') ? '5' : (vars.roomS === 'Michael Fenster 2') ? '6' : (vars.roomS === 'Maxi Fenster 1') ? '7' : (vars.roomS === 'Maxi Fenster 2') ? '8' : (vars.roomS === 'Maxi Fenster 3') ? '9' : (vars.roomS === 'Küche Fenster') ? '10' : (vars.roomS === 'Küche Panorama') ? '11' : (vars.roomS === 'Küche Tür') ? '12' : (vars.roomS === 'Eltern Fenster') ? '13' : 'unknown') + ',' + vars.day + ',' + vars.function + ',' + ((vars.variante === 'change') ? vars.time : 'AUS')"
actionFeedback: ok
disabled: =(vars.roomS === NULL || vars.day === undefined || vars.function === undefined)
- component: f7-row
config:
visible: =props.debugmode
slots:
default:
- component: Label
config:
text: "=vars.day + '.' + vars.function + '||' + ((vars.variante === 'change') ? vars.time : 'AUS')"
- component: Label
config:
text: "=(vars.roomS === NULL) ? 'true' : 'false'"
Javascript Rule for JSON editing
triggers:
- id: "1"
configuration:
itemName: ScheduleSaving
type: core.ItemStateChangeTrigger
conditions: []
actions:
- inputs: {}
id: "2"
configuration:
type: application/javascript
script: >
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
var schedule = itemRegistry.getItem('SavedSchedule').getState();
var id = itemRegistry.getItem('ScheduleSaving').getState().toString().split(',')[0];
var day = itemRegistry.getItem('ScheduleSaving').getState().toString().split(',')[1];
var fun = itemRegistry.getItem('ScheduleSaving').getState().toString().split(',')[2];
var time = itemRegistry.getItem('ScheduleSaving').getState().toString().split(',')[3];
var json_obj = JSON.parse(schedule);
json_obj[id][day][fun] = time;
events.sendCommand('SavedSchedule', JSON.stringify(json_obj));
var feedback = JSON.parse(itemRegistry.getItem('SavedSchedule').getState());
logger.info("Input: " + json_obj[id][day][fun]);
type: script.ScriptAction
@ysc Do you have any clue why editing the ‘scheduler’ is so laggy with 2 oh-repeat (editing widget itself and page on it)? Should multiple oh-repeat be avoided?