Disable / enable a thing from DSL or?

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).

1 Like

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().

1 Like

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
1 Like

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.