Script not running?

  • Platform information:
    • Hardware: Rpi 5
    • OS: Linux/6.6.31+rpt-rpi-2712 (aarch64)
    • Java Runtime Environment: 17.0.12
    • openHAB version:4.2.1
  • Issue of the topic: I have created a script: application/vnd.openhab.dsl.rule
  • Please post configurations (if applicable):
rule "Battery Status Check"
when
    Time cron "* * * * * ?"
then
        val mailActions = getActions("mail","mail:smtp:sender_smtp")
        LogInfo("Ny test")
        var String msg = ""
        var triggertDevices = battery_levels.members
        triggertDevices.forEach [ i |
                if (i.state !== NULL) {
                        if ((i.state as Number)  <= 0.75)
                        {
                                msg = msg + i.name + ': ' + i.state.toString + '%\n'
                                logInfo("low_bat-send_mail.rules","Lavt batteriniveau på " + i.name + ": " + i.state.toString + "%")
                        }
                }
            ]

        if (msg != "") {
                val success = mailActions.sendMail("mail@xxxxxx.dk", "Batteri advarsel - openHAB: -" + i.name , msg)
        }
end

Problem is that nothing is shown in the events.log - should LogInfo not write the test string there ??

It will be written in openhab.log, not events.log. Also, you capitalized LogInfo in the first call. Are there no errors qbout the rule in openhab.log?

This kinda hints that you created this in the UI?

Yes I did - under Settings → Scripts → and then I created a “Rule DSL”

Ahh sorry - yes I see loads of errors in the openhab.log. This script worked in openhab 3.2.0 - where i placed it manually in /etc/openhab2/rules - is it wrong to use the UI to add the script ?

What you pasted above is meant to be saved as a file, for a file-based rule.

UI based rules are different. You define the triggers through the UI and the type in the body of the rule. The body is just what’s inside the “then … end” block, without the “then” and “end” lines.

Ahh ok - thank you. I will try and convert it to the UI based approach.

as mentioned above create a rule (not a script) under settings rules with trigger time event.
If you use Blockly you got everything at hand (e.g. logging under openhab - logging and output) without the problem of syntax errors. And you can see the code too (button bottom right) if you prefer to write code. But almost everything can be realized in Blocky too.

If you are going to look at different scripting languages, try Ruby

low_battery_items = battery_levels.members.filter(&:state?).select { |i| i.state < 0.75 }
if low_battery_items.any?
  message = low_battery_items.map { |i| "#{i}: #{(i.state * 100).round}%" }.join("\n")
  message = "Batteri advarsel - openHAB:\n#{message}"
  logger.info(message)
  things["mail:smtp:sender_smtp"].send_mail("mail@xxxxxx.dk", message)
end

I tried the Ruby example - but nothing happens - and no logging at all. All of my bats are below 50%
I also tried this DSL script:

val mailActions = getActions("mail","mail:smtp:sender_smtp")
val String msg = ""
var triggertDevices = battery_levels.members
triggertDevices.forEach [ i |
  if (i.state !== NULL) {
    logInfo("low_bat-send_mail.rules",i.state.toString)
    if ((i.state as Number)  <= 0.75)
      {
        msg = msg + i.name + ': ' + i.state.toString + '%\n'
        logInfo("low_bat-send_mail.rules","Lavt batteriniveau på " + i.name + ": " + i.state.toString + "%")
      }
    }
  ]

if (msg != "") {
  val success = mailActions.sendMail("mail@xxxxxx.dk", "Batteri advarsel - openHAB: -" , msg)
}

I get this in openhab.log: “Script execution of rule with UID ‘a8c93fb732’ failed” - and “Assignment to final variable; line 9, column 292, length 3”

For the Ruby script to work you need to install the jrubyscripting addon, and set up your rules + trigger in the UI.

You can of course have it as a file-based rule, but you’ll have to add the trigger around it like this:

every(:second) do
  # Paste that rule above in here
end

msg was declared as val so it’s not modifiable.

I Have installed the Ruby scripting addon - but when I try to run the script from the Ruby code window nothing happens.

If i declare msg as var then I get this instead:

  1. Cannot refer to the non-final variable msg inside a lambda expression; line 9, column 292, length 3
  2. Cannot refer to the non-final variable msg inside a lambda expression; line 9, column 298, length 3

Also tried Blocky… but I will have to learn that first. cannot seem to get the item of a created loop inside that loop - dont know how to do that.

Could you post a screenshot please?

@Larsen - How would I send an email with blocky and an smtp item ? I cannot find that anywhere only cloud - which I do not wanna use.

There’s a blockly library for mail (Mail Actions) that you can install under add-ons.

https://community.openhab.org/t/mail-actions/138423

Another possibility would be to use the inline-script-block (under run&process) that can hold any Javascript-code.
I never tried sending mails with openhab as I use telegram for any kind of notification which works great with openhab.

Ahh yes - well I have now build this:

But I get this error in openhab.log when I run it ??

“2024-09-08 18:20:58.280 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘send_mail_on_low_bat_blocky’ failed: org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (getItem) on org.openhab.core.internal.items.ItemRegistryImpl@1d09e97e failed due to: Cannot convert ‘[object Object]’(language: JavaScript, type: g) to Java type ‘java.lang.String’: Invalid or lossy primitive coercion.”

What happened when you clicked “Run Now” on that jruby script? Did you see anything in the logs?

try the


in both if-clauses and tell me what you get.

I think the problem is here:

if battery.state <  "0.75"

You cannot compare two strings in this way. They need to be converted to numbers like this:

if battery.numericState <  0.75

See documentation how this can be achieved with blockly.

Just as a side note, the first if-loop is irrelevant as a numericState which is < 0.75 is always not null.
Not sure if this is intended but your script will in worst case send as many separate emails as you have battery items. And each null item will send the message of the last non-null item again.
Take a look, you just need one single if-loop whithin forEach-loop.
Another recommendation could be to add a filter expression to your forEach loop so that you are only dealing with items < 0.75 in your loop.