Fire trigger at FILTERED "current_end" in iCal-Binding

Good evening, everybody…

Please, I would need some help with the following issue:

I have installed the iCal-Binding on an openHAB4-System and reading my roster from my company’s website through an iCal file. I have implemented two filters, which filter the events as follows:
Whenever the location of an event contains the String “FRA -”, I will be leaving the house.
Whenever the location of an event contains the String “- FRA”, I will be returning home.
With the help of this forum I was able to create a rule which turns off my heaters 1 hour before I have to leave the house.

Now, I am stuck with turning the heaters back on 3 hours before I return home.
I cannot use the channel “current_end” since I cannot apply any filter to this channel. My roster contains other events, e.g. home office etc. So using the channel “current_end” would turn on the heaters every time an event ends, even when I am at home.

I also cannot use the filter-channel “result_0#end” because this gets updated the second the event starts. In other words, when the event (where I return back home) starts, this event is deleted and the “result_1#end” will instantly become “result_0#end”.

So what I am looking for is a way to filter the “current_event_end” for the Location “- FRA”, or in other words: How do I turn on my heaters 3 hours before the current DateTime item containing the String “- FRA” ends?
Right now I am starting my heaters at the beginning of the “return home event”, but they might run for up to 15 hours unnecessarily until I get back home.

Any help is greatly appreciated…

There is no such thing as a DateTime Item with a String so we might need more details about what you mean by this.

If you have a DateTime Item and If you are on OH 4.3 M4 or later you trigger the rule with the “time is item” trigger using the DateTime Item with a negative -10800 offset. That will trigger the rule three hours before the time in that DateTime Item’s state.

If you asking about how to identify a String that contains “- FRA” in a rule, that can be as simple as the following in JS.

if(items.FRAItem.state.includes("- FRA")) // do something

This can be done in Blockly or any of the other languages too though the syntax will be different. From there I imagine you can get the DateTime somethow and set a Timer or use the time is rule trigger trick above.

There really isn’t enough information here to provide a more specific item.

Ok, I will try to provide more information…

So, here’s my .things file:

Bridge icalendar:calendar:dienstplan    "Dienstplan" [ url="https://mycompany.ics", refreshTime=60 ]
Thing  icalendar:eventfilter:outbound "Tomorrow's events" (icalendar:calendar:dienstplan) [ maxEvents=3, datetimeUnit="DAY", datetimeStart=0, datetimeEnd=31, textEventField="LOCATION", textEventValue="FRA -", textValueType="TEXT", datetimeRound=false ]
Thing  icalendar:eventfilter:inbound "Tomorrow's events" (icalendar:calendar:dienstplan) [ maxEvents=3, datetimeUnit="DAY", datetimeStart=0, datetimeEnd=31, textEventField="LOCATION", textEventValue="- FRA", textValueType="TEXT", datetimeRound=false ]

This is my .items:

String   current_event_name         "current event [%s]"                       <calendar> { channel="icalendar:calendar:dienstplan:current_title" }
DateTime dtcurrent_event_until      "current until [%1$tT, %1$tY-%1$tm-%1$td]" <calendar> { channel="icalendar:calendar:dienstplan:current_end" }

DateTime dtnext_event_end           "Next event end"                           <calendar> { channel="icalendar:calendar:dienstplan:next_end" }
String   next_event_name            "next event [%s]"                          <calendar> { channel="icalendar:calendar:dienstplan:next_title" }
DateTime dtnext_event_at            "next at [%1$tT, %1$tY-%1$tm-%1$td]"       <calendar> { channel="icalendar:calendar:dienstplan:next_start" }

DateTime dtlast_update	            "Last update"                              <calendar> { channel="icalendar:calendar:dienstplan:last_update" }

String   next_outbound_title        "first event [%s]"                         <calendar> { channel="icalendar:eventfilter:outbound:result_0#title" }

DateTime dtnext_outbound_begin      "first at [%1$tT, %1$tY-%1$tm-%1$td]"      <calendar> { channel="icalendar:eventfilter:outbound:result_0#begin" }

DateTime dtnext_outbound_end        "first at [%1$tT, %1$tY-%1$tm-%1$td]"      <calendar> { channel="icalendar:eventfilter:outbound:result_0#end" }

String next_inbound_title           "first event [%s]"                         <calendar> { channel="icalendar:eventfilter:inbound:result_0#title" }
DateTime dtnext_inbound_begin       "first at [%1$tT, %1$tY-%1$tm-%1$td]"      <calendar> { channel="icalendar:eventfilter:inbound:result_0#begin" }
DateTime dtnext_inbound_end         "first at [%1$tT, %1$tY-%1$tm-%1$td]"      <calendar> { channel="icalendar:eventfilter:inbound:result_0#end" }

So, “DateTime dtcurrent_event_until” will , if used in a rule, turn on the heaters at the end of any given event, no matter if I am at home or not. So this is not useful for me to use.

“dtnext_inbound_end” will not fire, because the second the event (dtnext_inbound_begin) starts, “dtnext_inbound_end” will be replaced with the next upcoming event.

Would it be possible to do the following math:
1 minute before “dtnext_inbound_begin”, calculate the time difference between “dtnext_inbound_end” and “dtnext_inbound_begin”.
Then set a timer to the previous calculated time-difference minus 180 minutes and after the timer expires, turn on the heaters?

I can’t think of any other way to get this done…

Greetings

Olaf

When do these Items get updated? If it’s updated sometime before the the event starts, you can do the math when it updates. There is no reason to wait.

You don’t need to calculate the difference in times if you have the end time. Just subtract 3 hours from the end time. In JS

var timerTime = time.toZDT(items.dtnext_inbound_end).minusHours(3);
ScriptExecution.createTimer(timerTime, () => { items.HeatersItem.sendCommand(ON) });

But this all depends on when these Items all get populated. You need something to trigger the rule (dtnext_inbound_begin?) and based on that event you have to rely on dtnext_inbound_end being populated before the rule runs. Or maybe you can just trigger it on the end Item. And none of this addresses the “- FRA” stuff. Maybe you can use that Item to trigger the rule and use a condition to only run the rule if the Item has “- FRA” in it.

Hi Rich,

thank you for your reply.
Every item will be updated the second the event “dtnext_inbound_begin” starts. The DateTime information from “dtnext_inbound_end” automatically moves to "dtcurrent_event_until ".
Since I am just a mediocre user and don’t have advanced coding abilities, I am going to stick to the solution that the heaters turn on when “dtnext_inbound_begin” starts. The heaters might run for more than 15 hours until I get back home, but hey, at least it’s cozy warm when I open the door…
Maybe in the future the iCal-Binding will be capable of providing a channel that can be used when an ongoing event (containing certain words) ends.

Thank you, Rich!

This really isn’t hard. The only challenge is I don’t know this Channel so I can’t just code it all for you.

OK, assuming this and OH 4.3 (which will be released in a week or so):

  1. Create a rule that triggers with “time is dtnext_inbound_begin plus 5 seconds”. See https://www.openhab.org/docs/tutorial/rules_basic.html for how to create a rule in the UI. Select “time event” and “at time specificed by item’s state”, select the Item and set the offset to 5s. The 5s gives way more than enough time for all the Items to update after the beginning of the event.
  2. Add a condition to the rule (but only if…). Choose a Script Condition and choose Blockly (I recommend Blockly for non-programmers. if Blockly isn’t an option install the JS Scripting add-on). The script will need to look like this, using current_event_name as the Item (I think).

    This will only allow the rule to run when the state of the current_event_name Items contains “- FRA” in it. If that’s not the right Item, use the one that makes the most sense
  3. Add an action (then). Choose a Script Action and choose Blockly.

    Again, choose dtnext_inbound_end for the Item to get the DateTime from and use what ever Item you use to command the heaters in the “send command” block. If you have more than one Item, add a send command block for each of them.

This isn’t really all that hard.

Ok, Rich,

thank you. I haven’t had the time to check this out, Christmas is approaching. I will try it as soon as all this holiday stress is over and let you know if it worked…

Merry Christmas to all of you!