I’ll just start with an opinion here: I think the expire binding is too limited for the things I want to do with it. Because of this, I have an idea on a binding I want to create and the contribution page suggested to post here first, so this is that brainstorming post.
I want to be able to have some timed switches where I can tell it to shut off after X amount of time, where I can pass the X value to the binding/item to trigger it. I also want to be able to see when this event will trigger next time or be able to see the countdown (or both, who knows). I have seen a few people post their custom rule code for others to use but they all seem to use the Timer class in Java which IMO is outdated and lacking.
Just as a heads up, I’ve never contributed so I’m not entirely sure this idea is doable the way I’m thinking right now, but here it goes.
Make a new binding that’s probably going to be similar to the expire binding. No idea on a good name yet. It will use a ScheduledThreadPoolExecutor and will hold on to the Future object returned to be used to do things like show when the event will trigger as well as be able to do things like cancel the event. The idea is to have a single thing scheduled at a time per item, so if a new value is created, the old Future is cancelled and replaced with the new Future and thus a new event being scheduled.
I’m not exactly sure how persistence works in OpenHAB but another thing I’d like to be able to do is have the ability or option to persist these values so that they get auto-rescheduled on reboot since they will no longer be queued in memory.
Thoughts? Has something like this already been done and I haven’t found it? Am I reinventing the wheel? Is this a terrible idea? Please let me know.
Kai has made it clear that the Expire binding never should have been a binding in the first place. This feature should have been implemented as part of the core from the beginning. So another binding that does the same thing only more seems like the wrong path. It should be something that is implemented as part of the core.
Let’s assume this is built as a 2. version binding (please don’t even consider building a new 1.x version binding at this point). This means that we need to create Things and the Things will have Channels. This is good news as the Timer can exist as a single Thing and it will have Channels for triggering it, passing it the amount of time to run, seeing how long it left on it, etc.
I can see the following Channels, which would mirror what the Exec 2 binding does:
Switch Run: Channel linked to a Switch Item. Send command ON will cause the Timer to become scheduled using the value stored in the Timeout Channel. Send command OFF will cause the Timer to cancel. Checking the state of this Channel will tell you whether there is a Timer scheduled or not.
Number Timeout: Channel linked to a Number Item where you can define how long the timer is to be set for. It probably should be a Number:Time (or whatever the appropriate Unit of Measure is for duration). An open question is whether sending a command to this Channel triggers the timer to start
Number Time Remaining: Channel linked to a Number Item that indicates how long until a Timer goes off. As above, it probably should be a Number:Time.
Event: A trigger channel that activates when the Timer goes off. You would have a Rule triggered by this Channel which contains the code to execute.
There are some issues with the above approach, really, but like I said at the start. This isn’t something that should be a binding so it’s really kind of academic at this point.
This is something that has been discussed and I hope that support for Timers/Expire gets moved into the core for OH 3. Since the move from ESH I don’t know if the issue that David started to discuss this has made it over. But the ideas from that discussion have been included in his Next generation design: A Paper UI replacement proposal.
I have forked openHAB core and have added all bundles and interfaces I need so I’m not contributing to openHAB core at the moment.
(Which is hard anyway rn, because Markus is on holiday and Kai need to get fit again first)
But my home is using the rule engine for general timing tasks (alarms etc). And item metadata for tasks like “react on item state change and do something X minutes later”.
While I can agree that this should be core functionality in OH2, for the most part I’m trying to solve my problem while also being able to help other people if possible. I personally don’t want to keep adding rules every time I want a timer which is why I thought of doing a binding. So my approach would still be do this at least for myself even if it maybe doesn’t make it into an official binding. That being said, is there a fundamental opposition to this existing at all?
@rlkoshak Thanks for breaking it down into the channels you figure would be useful and pointing to the exec 2. I haven’t really looked much into what makes a binding be a binding and different from a rule so this gives me a good place to start digging.
But even with a binding you can’t get around that. There is no way to pass code to an Item or a Thing to run later. All you can do is schedule an event to occur that triggers a Rule where the code lives.
Rules are going to be required. Period. There is no other option. There is nothing you can add to OH to avoid them. The stuff that happens when a timer goes off can only be implemented in a Rule (and still fit within the OH architecture).
Honestly, without trying to sound mean, it really seems like you do not really know enough yet about how OH works and it’s architecture to actually implement something like this as a binding or as a feature in the core successfully. I strongly suggest spending some time with the Concepts section of the docs and making sure you understand each of the concepts in detail.
OH is an event driven system. Events occur which cause behaviors to happen. The behaviors are defined in Rules. A Timer going off is an event. If you actually want something to happen when the Timer goes off beyond “set the Item to this state” you need a Rule.
To be frank, besides having some sort of aesthetic aversion to Timers it really isn’t clear to me what the problem you are trying to solve actually is.
Yes, I barely know anything about this and decide to ask here first before digging too much in case anything was gonna stop me in my tracks.
The current expire binding doesn’t require a rule to work. My current use case is to create a lot of timed switches that will turn off after a certain amount of time. This is all close to the realm of what expire binding does but I want more.
I want to have an accurate countdown/timestamp of when the event will occur and if it will happen.
I want to be able to cancel/stop the event.
I want to be able to pass the time as a parameter rather than creating 1 item/thing per time.
I want to avoid creating a custom rule each time (which works for my use case of turning on switches and lights in a scheduled manner).
I want to be able to resume the scheduled “jobs” in case of a restart/power loss scenario. This is more of a stretch goal but I think this is doable.
The documentation page is shit (there is no other word for this) to get started developing openHAB bundles.
There are more concepts than bindings, you can extend ALL of those.
The openHAB addons2 repository has “addons” in its name for a purpose, there are more then bindings in it.
A binding is purely for communicating with external devices.
You want a “MetadataProvider” service instead. An item can have individual meta data. The expire binding is doing this actually, just in the old fashioned OH1 way of attaching arbitrary un-organised data to an item. Search the core repository for “MetadataProvider” to see examples. Don’t have time to explain that.
From jsr223 it is possible, because you have access to all java classes. But the OP want to create a java based solution anyway, so he would write a real java bundle to add support for an “expire2” based on item metadata.
That is true. I’m operating under the assumption that if OP is unhappy with Timers as they exist right now are “outdated and lacking” that a call to the REST API using sendHttp*Request Action calls would similarly be unacceptable. But I probably shouldn’t make that assumption.
Timers, as in the Java class, is actually outdated and lacking in functionality. If you go to the Javadoc page for Timer it mentions it there as well.
Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer / TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn’t require subclassing TimerTask (just implement Runnable ). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer .
Using the ScheduledThreadPoolExecutor returns a ScheduledFuture object which provides a simple way to have visibility and control over the scheduled “tasks”.
I’m pretty sure @rlkoshak is talking about rule timers. They are realized with a core internal scheduler. And exactly that is what you would build up with a java bundle that allows a timer-item association.
Well, it’s a good thing that OH doesn’t use java.util.Timer. In the OH Rule context, a Timer is not the same thing as java.util.Timer.
OH timers are a way to schedule a lambda to execute at some later date. OH uses Quartz for scheduling classes (the core internal scheduler that David mentions). And I do know they work pretty differently from java.util.Timer.
In OH Rules there is an Action (in OH Rules an Action is a method call not attached to an Object, at least as far as is apparent in the Rules code) that takes a Joda DateTime Object that represents the date/time the Timer should go off and an Xtend lambda that contains the code that gets executed when the Timer goes off. The createTimer action then uses the Quartz library to schedule the lambda to execute at the given time.
When you create the lambda that gets passed to createTimer (usually it’s defined inline) the lambda inherits the full context at that point, so it gets any variables that are defined inside the lambda up to that point.
Like I tried to imply before. You would be well served to gain a bit more experience with OH and how all the pieces of OH work together before proposing implementing a binding or change such as what is proposed. You want to avoid:
duplicating something that already exists
building something that violates the OH architecture
running into a roadblock that cannot be passed because of some technical limitation of how OH works.
Note my reference to Xtend above. Rules are written in one of three ways. There is the Rules Domain Specific Language which is a custom programming language built on Xtext with a lot of similarities with Xtend. Rules are not Java.
In all three, one can call createTimer to schedule a function to execute at some future date/time. In none of them is java.util.Timer involved.
Interesting. I was aware that OH used a variaton of Xtend and I have written a few simple rules for my own stuff.
I’ve seen a few other solutions that were very suboptimal and they all used Timer and from the quick glimpses I thought it was the Java timer class. I’ll dig into those pieces of code I had seen again and see how they do it, and I might just be able to modify the code they have built to include time-to-execute as something that is exposed.
Also as far as getting familiar with OH, I do know that I’ll need to do this but one of the first bullet points in the Contribution Guidelines is to discuss ideas in the forum. If it is preferable to try and learn as much about OH before discussing an idea then I would say that should be higher up in the Contribution Guidelines.
I think it depends on the nature of the contribution.
If you found an error or something that isn’t clear in the docs or the like I don’t think a discussion is even needed.
If you are looking to add a small feature or fix a bug in a binding then a discussion like this is probably your first step.
But, IMHO, if you are looking to replace or provide and alternative to one of the core and most used features in OH Rules, you should have a pretty good grasp about how that feature you are replacing is implemented, works, and is generally used first. What you originally proposed would be a massive change for users and one that will impact everyone who uses OH.
I was not looking to provide an alternative to OH Timer, since I had no idea the Timer class people kept referencing was not the Java one. I want to provide a more robust alternative for at least myself of the expire binding, which is not core. The tl:dr is that what’s out there right now doesn’t do what I want, and if other people do also want what I want them I’m willing to share. If I would’ve gone ahead and started coding, I would’ve avoided the Timer class from the start because I had a misconception, so this thread has been useful to me already. That said, there’s still the possibility that I find that the OH Timer class doesn’t have everything I need and still end up using a ScheduledThreadPoolExecutor, because in the end this new knowledge changes my approach at solving the problem and not what features I want my thing to have.
Not sure if this is directed at me but I never said this was going to be core development, nor do I have any intention of contributing to the OH core at this moment.