Timeline picker to setup heating, light and so on

Hello, is it possible to configure a timeline for the lighting and one for the heating control?

Yes, you can use as many timelines as you like.
In v2 create a single transferitem for each timeline.
In v3 define a unique id for each timeline.

Hello, I am in the process of configuring the timeline-picker in version "development_v3.x_for_OH3.x (GraalVM). The description (gitlab) says that the API token should be decoded in base64 and then in the files RNTs-tlp3. js, tlp_item_controller.js and tlp_thing_controller.js should be inserted. The path OPENHAB-CONF/html/tlp-jsr/ including all subdirectories should then be copied. However, the RNTs-tlp3.js is not in this path but under automation /js.

Now my question would be what exactly everything has to be copied?

Thank you in advance.

Hi Danny,
On a quick view, the file strucktur on GitLab is correct.
Not right is the table on GitLab. The file RNTs-tlp3.js is the rule in OH so this file must place in automation/jsr. Don’t forget the subfolder conf.

Hello, I started installing the development_v3.x_for_OH3.x (GraalVM). To test, I turn a lamp on and off via the timeline. This also works so far, but I get the following warning in the log every 2 minutes:

[WARN ] [org.openhab.automation.script ] - tlp - W001: no config file exist.

Can someone help me fix the error? I’ve done everything as it says in the instructions (gitlab). Thanks in advance.

I really liked this in oh2.4.

I saw a widget for the main UI, is this correlated with this upcoming version for JavaScript?

@Didschu
This is not an error, it’s a warn message.
You have not created the file 00_RNTs-tlp2_conf.js in the folder automation/js/conf.

@openhabber
Unfortunaly noone else is answering on your question. :thinking: I saw this widget also some time ago. I think it’s not compatible but i haven’t create it. At least the new parameters must be adapted.

@tose
Thank you very much for this component.
I added it the last days into the heating logic of my OH3.2-system and it works great.
:smiling_face_with_three_hearts:

btw: My heating rules have four states: Day/Night/On/Off - so I’m very glad that this is supported :slight_smile:

1 Like

@tose wonderful idea. Works pretty well after some fiddling. The main open point seems to be getting it to work with home.openhab.org.

I have seen the same ‘Bad Request’ response as reported above. Any clue?

Hello all,

I’m trying to get v3 for openHAB 3.x (graalVM) running on 3.2.0.

I already see the html output, but I get the following message when starting.
1_Screenshot 2022-05-09 161453
2_Screenshot 2022-05-09 161517

I am not sure if I have created the API token correctly.
I have for example

oh.timeLine.uDguMpiitAtvhD7gCK...

and then it became with Encode (www.base64decode.org/):

b2gudGltZUxpbmUudURndU1waWl0QXR2aE...

Decode doesn’t seem right to me here, because I only get control characters out of it.

#b냂)+@C�

Maybe someone can help me.

Greetings Holger

You did that right… Encode is the way to go. Did not have those other issues you describe. Have you put RNTs-tlp3.js and conf/.. into $OPENHAB/conf/automation/js/ ?

Hallo,

Here is my directory structure under OPENHAB_CONF. I have another directory /js223 but I can’t copy in there. I think this is correct.

$ OPENHAB_CONF=/etc/openhab

/etc/openhab/automation/js/conf/00_RNTs-tlp3_conf.js
/etc/openhab/automation/js/RNTs-tlp3.js
/etc/openhab/automation/js223

/etc/openhab/html/tlp-jsr/css
/etc/openhab/html/tlp-jsr/fonts
/etc/openhab/html/tlp-jsr/icons
/etc/openhab/html/tlp-jsr/js
/etc/openhab/html/tlp-jsr/index.html

Do I have to set any permissions?

Is the name of the token important? I just named it timeLine.

My directory structure differs as I am using the docker image. I believe yours is ok for a default install.
I also used an arbitrary name for the token. Does not matter.

Sorry and thanks for the help.
I had in the file tlp_thing_controller.js not yet the token encoded.

hey @tose
I thought about trying this again in OH3 now and applied the branch “develop_v3.x_for_OH3.x(GraalVM)”

I edited the 3 config files and applied the base64 encoded token (you might adjust your readme). After that I adjusted my existing sitemap to the following:

sitemap zeitsteuerung label="Zeitsteuerung der Poolpumpe" {
    Frame label="Mo-So" {
        Webview icon="none" url="/static/tlp-jsr/index.html?id=MoSo&mode=1,2,3,4,5,6,7&states=0,1&lang=de&deactivation=true" height=14
    }
}

I edited the “automation/js/conf/00_RNTs-tlp3_conf.js” to the following:

var tlp_ids = {
  'MoSo': 'MBF_PAR_FILT_MANUAL_STATE'
}

But if I check the sitemap it complains about a missing id which I could create now. This is confusing because If I read the readme and check against the files I would assume everything should be set by defining the id in the url and in this config file.

What is the correct way to do it?

I also do not know what to do with this statement: “the path in automation is changed !”

EDIT: Same warning and error as mentioned before. The file exists!

2022-07-10 19:30:00.499 [WARN ] [.automation.script.file.RNTs-tlp3.js] - tlp - W001: no config file exist
2022-07-10 19:30:00.505 [WARN ] [.automation.script.file.RNTs-tlp3.js] - tlp - E002: error in inner loop {}

EDIT2: curl -X GET --header "Accept: application/json" "http://127.0.0.1:8080/rest/things/tlpicker:tlp:home" -u 'token:'
→ {"error":{"message":"Thing tlpicker:tlp:home does not exist!","http-code":404}}

EDIT3: Adjusting the path in RNTs-tlp3.js to tlp_ids = require('/etc/openhab/automation/js/conf/00_RNTs-tlp3_conf.js')seems to fix the loading issue of the file (there seems to be something wrong about loading files inside /automation/js subfolders? Do you use a customize script / binding / installation of openhab / openhab-js?)

But the list seems to be empty anyways:

      tlp_ids = require('/etc/openhab/automation/js/conf/00_RNTs-tlp3_conf.js')
      console.warn("IDs: ", tlp_ids)

→ [.automation.script.file.RNTs-tlp3.js] - IDs: {}

Ref1: [jsscripting] JS script engine no longer watches node_modules for scripts by jpg0 ¡ Pull Request #11830 ¡ openhab/openhab-addons ¡ GitHub
Ref2: [jsscripting] Allow loading files relative from root folder automation/js ¡ Issue #12016 ¡ openhab/openhab-addons ¡ GitHub

But there is still no thing being created. Reading tlpThing you get the error mentioned above

2022-07-10 20:50:00.817 [WARN ] [.automation.script.file.RNTs-tlp3.js] - {
  "error": {
    "message": "Thing tlpicker:tlp:home does not exist!",
    "http-code": 404
  }
}

Hi Sefer,

There are two ways to declare items for switching. The first in the sitemapfile as url parameter, the second in file 00__RNTs-tlp3_config.js. The definition in file is only for switch items. When you call the timeline for the first time, you still have to confirm the creation of the id.

The folder structure has changed.

You can use this statement (the origin line on GitLab is wrong and must updated):

tlp_ids = require('../../js/conf/00_RNTs-tlp3_conf.js')

Please post the console from your browser after an click on ‘yes - create id’.

Alright, I see. So I choose an ID of my liking and don’t have to add “linkedItems=VirtualItem” to the url anymore because it checks this one against the ID in the config file (which should match the id in the URL).

But the confirmation of the ID seems unnecessary if it is in the config (might implement a check against that). I can live with that anyways :slight_smile:

Got it. Was confused. I applied every file anyways (for me nothing changed because it was a fresh start). You might want to make that clear in the readme.

Thank you very much. Indeed, the error is gone. I only tested .../ too instead of .../.../

I am using this in HABPanel as an iframe-widget, too. Works great more or less (but not with the mobile apps, hard to navigate and a bit is cut off from the iframe). Wasn’t able to fit it yet. But this is none of your problems because even now the apps are still not optimized…

On OH3 UI it also works as an webframe-card

component: oh-webframe-card
config:
  src: /static/tlp-jsr/index.html?id=MoSo&linkedItems=VirtualPumpenmodus_TLP&mode=1,2,3,4,5,6,7&states=OFF,ON&lang=de&deactivation=true
  title: Timeline
  height: 1000px

Current console log after fixing the path:

roboto.css:1          GET http://192.168.2.20:8080/basicui/fonts/Roboto-Regular.woff2 net::ERR_ABORTED 404 (Not Found)
roboto.css:1          GET http://192.168.2.20:8080/basicui/fonts/Roboto-Medium.woff2 net::ERR_ABORTED 404 (Not Found)
vue.js:8542 Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
vue.js:8553 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
roboto.css:1          GET http://192.168.2.20:8080/basicui/fonts/Roboto-Medium.woff net::ERR_ABORTED 404 (Not Found)
roboto.css:1          GET http://192.168.2.20:8080/basicui/fonts/Roboto-Regular.woff net::ERR_ABORTED 404 (Not Found)
vue.js:8542 Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
vue.js:8553 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
roboto.css:1          GET http://192.168.2.20:8080/basicui/fonts/Roboto-Medium.ttf net::ERR_ABORTED 404 (Not Found)
roboto.css:1          GET http://192.168.2.20:8080/basicui/fonts/Roboto-Regular.ttf net::ERR_ABORTED 404 (Not Found)
tlp_thing_controller.js:29 TypeError: Failed to fetch
    at tlp_thing_controller.js:26:11
    at new Promise (<anonymous>)
    at tlpThing.get (tlp_thing_controller.js:12:12)
    at tlp_thing_controller.js:137:16
    at new Promise (<anonymous>)
    at tlpThing.get_id (tlp_thing_controller.js:134:12)
    at Vue._initTimelineView (switchPointSet_jsr.js:234:20)
    at Vue.created (switchPointSet_jsr.js:97:10)
    at callHook (vue.js:2921:21)
    at Vue._init (vue.js:4617:5)
tlp_thing_controller.js:29 TypeError: Failed to fetch
    at tlp_thing_controller.js:26:11
    at new Promise (<anonymous>)
    at tlpThing.get (tlp_thing_controller.js:12:12)
    at VueComponent._initAdminSetupView (tlpAdminSetup.js:105:18)
    at VueComponent.created (tlpAdminSetup.js:87:10)
    at callHook (vue.js:2921:21)
    at Vue._init (vue.js:4617:5)
    at new VueComponent (vue.js:4785:12)
    at createComponentInstanceForVnode (vue.js:4304:10)
    at init (vue.js:4125:45)
switchPointSet_jsr.js:293 TypeError: Cannot read properties of null (reading 'location')
    at Vue._getParamsFromURL (switchPointSet_jsr.js:144:50)
    at switchPointSet_jsr.js:238:20
vue.js:8542 Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
vue.js:8553 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
vue.js:8542 Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
vue.js:8553 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html

I adjusted the widget from @fabian_b for the OH3 GraalVM version. I left out “&event” because it causes the warning to keep or remove the timeline on each refresh
oh and Dark mode doesn’t work as of commit 250ad0a2801f55550229fa6d2ad943d9bcfa2fb7

uid: widget_timelinepicker
tags: []
props:
  parameters:
    - description: Titel of your widget
      label: Title
      name: title
      required: false
      type: TEXT
    - description: Unique identifier for your timeline
      label: ID
      name: timeline_id
      required: true
      type: TEXT
    - description: Configuration Mode (Default is params, ui)
      label: Configuration
      name: conf
      required: false
      type: TEXT
    - description: Days to be managed in your timeline (1,2,3,4,5,6,7 = Each day, 15 = Mon-Fri, 17 = Full Week, 67 = Sat-Sun)
      label: Day Configuration
      name: mode
      required: true
      type: TEXT
    - description: States available for your item (Comma-separated list of maximum six states, i.e. 0,15,INCREASE,DECREASE,OFF,ON, ...)
      label: Switch States
      name: states
      required: true
      type: TEXT
    - context: item
      description: Item(s) which you want to control with the timeline
      label: Linked Item(s)
      name: linked_Items
      required: true
      multiple: true
      type: TEXT
    - description: Language for your widget (Default english)
      label: Language selection
      name: language
      required: false
      type: TEXT
      options:
        - value: "en"
          label: "English"
        - value: "fr"
          label: "French"
        - value: "de"
          label: "German"
        - value: "it"
          label: "Italian"
        - value: "nl"
          label: "Dutch"
        - value: "pt"
          label: "Portuguese"
      limitToOptions: true
    - description: Allows deactivation of timeline in the UI
      label: Deactivation button
      name: deactivation
      required: false
      type: TEXT
      options:
        - value: "true"
          label: "Button active"
        - value: "false"
          label: "Button inactive"
      limitToOptions: true
    - description: Zoom mode to enable control slider for mobiles and tablets
      label: Zoom mode
      name: zoom
      required: false
      type: TEXT
      options:
        - value: "auto"
          label: "Automatic zoom"
        - value: "force"
          label: "Force zoom control"
        - value: "no"
          label: "Disable zoom control"
      limitToOptions: true
    - description: Colorset for the timeline (Default 1, 2, 3, hex values without hash (i.e. 555E7B,B7D968,B576AD))
      label: Colorset
      name: colorset
      required: false
      type: TEXT
    - description: Darkmode for the timeline
      label: Dark mode
      name: dark
      required: false
      type: TEXT
      options:
        - value: "true"
          label: "Enable dark mode"
        - value: "false"
          label: "Disable dark mode"
      limitToOptions: true
  parameterGroups: []
timestamp: Jul 12, 2022, 7:28:50 PM
component: oh-webframe-card
config:
  src: ="/static/tlp-jsr/index.html?id=" + props.timeline_id + "&linkedItems=" + props.linked_Items + "&mode=" + props.mode + "&states=" + props.states + "&lang=" + ((props.language)?props.language:"en") + "&colorset=" + ((props.colorset)?props.colorset:"1") + ((props.deactivation === "true")?"&deactivation":"") + "&zoom=" + ((props.zoom)?props.zoom:"auto") + "&conf=" + ((props.conf)?props.conf:"params") + ((props.dark === "true")?"&dark":"")
  height: 600px
  title: = props.title

EDIT: My approach for a manual mode. I guess there is a better way to do it or code it, but I wanted it done :slight_smile:

VirtualPumpenmodus_States: Managed = OFF, Manual = ON
VirtualPumpenmodus_TLP: OFF, ON
VirtualPumpenmodus_Manuell: OFF, ON

Virtual switches:

Switch VirtualPumpenmodus_States "Pumpenmodus [MAP(virtual_pumpenmodus.map):%s]"
Switch VirtualPumpenmodus_TLP "Pumpenmodus Timeline Picker"
Switch VirtualPumpenmodus_Manuell "Wenn manuell, Pumpe ist"

The rule checks every switch. Since I didn’t test a restart of openhab yet and what happens to these virtual items, I decided to switch everything to off (which means a Managed run setup anyways) if the state is NULL

Then I go and look for the triggering item and decide what to do. If the trigger comes from VirtualPumpenmodus_States to status OFF (managed) I compare the state of VirtualPumpenmodus_TLP to the real world item and switch it accordingly. If States switches to ON (manual) I compare to selected state of VirtualPumpenmodus_Manuell with the real world item and make a switch if neccessary.

The trigger from VirtualPumpenmodus_TLP or VirtualPumpenmodus_Manuell just gets handled based on the States state to (if allowed) switch the real world item

Rule:

rule "Pumpenschaltung"
when
    Item VirtualPumpenmodus_States received command or
    Item VirtualPumpenmodus_TLP received command or
    Item VirtualPumpenmodus_Manuell received command
then
    if (VirtualPumpenmodus_States.state == NULL) {
        VirtualPumpenmodus_States.sendCommand(OFF)
        logInfo("Pumpensteuerung", "VirtualPumpenmodus_States was NULL, changed")
    } else if (VirtualPumpenmodus_TLP.state == NULL) {
        VirtualPumpenmodus_TLP.sendCommand(OFF)
        logInfo("Pumpensteuerung", "VirtualPumpenmodus_TLP was NULL, changed")
    } else if (VirtualPumpenmodus_Manuell.state == NULL) {
        VirtualPumpenmodus_Manuell.sendCommand(OFF)
        logInfo("Pumpensteuerung", "VirtualPumpenmodus_Manuell was NULL, changed")
    }

    switch(triggeringItemName) {
        case "VirtualPumpenmodus_States": {
            if (receivedCommand == OFF) {
                switch(VirtualPumpenmodus_TLP.state.toString) {
                    case "OFF": {
                        if (MBF_PAR_FILT_MANUAL_STATE.state != 0) {
                            MBF_PAR_FILT_MANUAL_STATE.sendCommand(0)
                        }
                    }
                    case "ON": {
                        if (MBF_PAR_FILT_MANUAL_STATE.state != 1) {
                            MBF_PAR_FILT_MANUAL_STATE.sendCommand(1)
                        }
                    }
                }
            }
            if (receivedCommand == ON) {
                switch(VirtualPumpenmodus_Manuell.state.toString) {
                    case "OFF": {
                        if (MBF_PAR_FILT_MANUAL_STATE.state != 0) {
                            MBF_PAR_FILT_MANUAL_STATE.sendCommand(0)
                        }
                    }
                    case "ON": {
                        if (MBF_PAR_FILT_MANUAL_STATE.state != 1) {
                            MBF_PAR_FILT_MANUAL_STATE.sendCommand(1)
                        }
                    }
                }
            }
        }

        case "VirtualPumpenmodus_TLP": {
            if (VirtualPumpenmodus_States.state == OFF) {
                if (receivedCommand == OFF) {
                    MBF_PAR_FILT_MANUAL_STATE.sendCommand(0)
                }
                if (receivedCommand == ON) {
                    MBF_PAR_FILT_MANUAL_STATE.sendCommand(1)
                }
            }
        }

        case "VirtualPumpenmodus_Manuell": {
            if (VirtualPumpenmodus_States.state == ON) {
                if (receivedCommand == OFF) {
                    MBF_PAR_FILT_MANUAL_STATE.sendCommand(0)
                }
                if (receivedCommand == ON) {
                    MBF_PAR_FILT_MANUAL_STATE.sendCommand(1)
                }
            }
        }
    }
end

Hi, timeline picker is a great tool, many thanks.
I have used it for a while on OH 2 and am now upgrading to OH 3 on a fresh install on a Pi.
It took me four frustrating hours to get timeline picker working, I was getting “error in transfer string”.
in the end the solution was simple, I didn’t have jsonpath transformation installed. Would be good if this was included as a step in the installation instructions.

I look forward to timeline picker working flawlessly in the future as it has in the past.

Again many thanks

1 Like

Hi Frederick,
it’s nice that the timeline picker is working well.
Only the requierements are written in the doc :wink:

MapDB and JSONpath transformation (JSONpath only for the DSL-rules version).

1 Like

Hi, this is exactly what i missed for my heating control. Thank you.

With small change in swtichPointSet.js is working also from openHab cloud.

if(window.location.host == ‘home.myopenhab.org’){
this.ip = ‘https://home.myopenhab.org/rest/items/’;
} else {
this.ip = ‘http://’ + openHAB_ip + ‘/rest/items/’;
}