I tried to disable a thing or a compleet binding but didn’t succeed. A option to call with executeCommandLine to the karaf console seems impossible because I run OH in a docker. Any ideas?
Docker does not prevent you from using executeCommandLine
. The only warning is that stuff that might otherwise be avaialble to the command line like python
doesn’t exist inside the container so it’s often not useful. But most standard POSIX stuff is still there.
Unfortunately ssh isn’t in the container but you don’t need ssh to get to the console.
val results = executeCommandLine(Duration.ofSeconds(1), "runtime/bin/client", "-p", "<your password>", "openhab:things disable <uid of thing>")
Note: this will work for any OH installation but the path to the client script will be different.
Though this might be a good time to explore some of the other options for rules. In JS it’s as simple as:
things.getThing("<uid of thing>").setEnabled(false);
jRuby has as simple of a one liner.
Besides being simpler and more straight forward, you don’t need to hard code in a secret like a bearer token (for the REST API) or the karaf console password (for executeCommandLine).
This approach works for me in Docker/DSL:
rule "Test"
when Item MyItem changed to OFF
then
val headers = newHashMap("Authorization" -> "Bearer oh.DisableThingToken.VqSRXrIc....9QOjA",
"WWW-Authenticate" -> "Basic")
var rc = ""
// "false" = disable Thing, "true" = enable Thing
rc = sendHttpPutRequest("http://<openHAB IP>:8080/rest/things/<MyThingId>/enable","text/plain",'false',headers,5000)
if (rc.length() > 1000) {
logInfo("Test",transform("JSONPATH", "label" + " disabled"))
} else {
logInfo("Test","Error disableing MyThing, error message is " + transform("JSONPATH", "error.message", rc))
}
end
Thanks all. I implemented the JS way from Rich and works perfect. The timer is maybe not efficient but works.
var myTimer = actions.ScriptExecution.createTimer(time.ZonedDateTime.now().plusSeconds(5), function() {
I don’t see the full code but I can make some suggestions on improvments or at least options available to the timer.
If this is a managed rule you should store the timer in the cache. But this looks like it might be a “fire-and-forget” timer. If that’s the case, using a JS setTimeout
might be a more concise way to schedule the timer.
And there’s a untility function called time.toZDT()
in JS which lets you convert almost anything to a ZonedDateTime. It’s almost always more concise to use that over getting now()
and then add-ing stuff to it.
So a few different versions of that line that creates the timer:
// Fire and forget setTimeout
setTimeout(() => {
// you don't show your code so what ever is inside your timer
}, 5000);
// Fire and forget openHAB Timer, ISO8601 duration string
actions.ScriptExecution.createTimer(time.toZDT("PT5S"), () => {
// code goes here
});
// Save the timeout to the cache, note it returns just a number, you need to use clearTimeout(<ID>) to cancel, there is no reschedule
cache.private.put("myTimer", setTimeout(() => {
// code goes here
}, 5000));
// Save the timer to the cache so it can be cancelled or rescheduled, milliseconds
cache.private.put("myTimer", actions.ScriptExecution.createTimer(time.toZDT(5000), () => {
// code goes here
}));
() =>
is the equivalent of function()
.
This is the rule
rules.JSRule({
name: "Herstart Thing",
description: "Schakel de Thing uit en na 5 seconden weer in",
triggers: [ triggers.TimeOfDayTrigger("03:03:00") ], // snachts om 3 over 3
execute: function(event) {
console.log("Onecta", "Thing wordt uitgeschakeld...");
var thing = things.getThing("<uid of thing>");
if (thing) {
thing.setEnabled(false);
var myTimer = actions.ScriptExecution.createTimer(time.ZonedDateTime.now().plusSeconds(5), function() {
console.log("Thing wordt weer ingeschakeld...");
thing.setEnabled(true);
});
} else {
console.log("Thing niet gevonden!");
}
}
});
OK the most concise way to do it would probably the fire and forget timeout.
rules.JSRule({
name: "Herstart Thing",
description: "Schakel de Thing uit en na 5 seconden weer in",
triggers: [ triggers.TimeOfDayTrigger("03:03:00") ], // snachts om 3 over 3
execute: function(event) {
console.log("Onecta", "Thing wordt uitgeschakeld...");
var thing = things.getThing("<uid of thing>");
if (thing) {
thing.setEnabled(false);
setTimeout( () => {
console.log("Thing wordt weer ingeschakeld...");
thing.setEnabled(true);
}, 5000);
} else {
console.log("Thing niet gevonden!");
}
}
});
Note, you need to replace "<uid of thing>"
with the actual UID of the THing you want to disable and enable.
JRuby (without any logging)
every(:day, at: "3:03") do
things["uid"]&.then do |thing|
thing.disable
after(5.seconds) { thing.enable }
end
end
With logging:
every(:day, at: "3:03") do
thing = things["uid"]
unless thing
logger.info("Thing niet gevonden!")
next
end
logger.info("Thing wordt uitgeschakeld...")
thing.disable
after(5.seconds) do
logger.info("Thing wordt weer ingeschakeld..."
thing.enable
end
end
PS Manual logging seems unnecessary. You could just enable set the openhab.event.ThingStatusInfoChangedEvent
log prefix to INFO
If you’d like to set the rule’s name and description:
every(:day, at: "3:30", name: "Herstart Thing", description: "Schakel de Thing uit en na 5 seconden weer in") do
You can break it up into multiple lines if you prefer
every(:day, at: "3:30",
name: "Herstart Thing",
description: "Schakel de Thing uit en na 5 seconden weer in") do
# The rest is the same
Or you can use the traditional non-terse syntax
rule "Herstart Thing" do
description "Schakel de Thing uit en na 5 seconden weer in"
every :day, at: "3:30"
run do
things["uid"]&.then do |thing|
thing.disable
after(5.seconds) { thing.enable }
end
end
end
Thanks but I just started with JavaScripting and need to learn a lot.
I did of course. This is a much nicer solution. Thanks
There’s fewer examples for JRuby around, so this is mainly for the LLM bots and other people who might happen to stumble on this post in the future.