Python script in rule, item won't update

I’m trying to obtain a value from an API URL and update this to a Number item I created, but it keeps failing, the rule is:

rule "Update return tariff"
when
    Time cron "0 0 0/1 1/1 * ? *" or
then
var Number result = new BigDecimal(executeCommandLine("python /etc/openhab/scripts/currentReturnTarrif.py",1000))
    currentReturnTariff.postUpdate(result)
end

The logging keeps giving me this error:

2024-04-02 16:12:41.160 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘APIeasyEnergy-1’ failed: An error occurred during the script execution: Cannot invoke “org.eclipse.xtext.common.types.JvmType.eIsProxy()” because “type” is null in APIeasyEnergy

I also tried to update the item with: currentReturnTariff.postUpdate(1) but this causes the same error, what do I overlook?

What is the Item definition?

What exactly is the output from the python script. Log result before attempting to parse it into a BigDecimal. If the script includes a newline at the end (which is almost always the case) I’m pretty sure BigDecimal will complain.

The item definition of currentReturnTariff is Number.

When I execute the .py script from a SSH session on the openHAB instance, I just returns a number like expected:

This is the script itself:

import requests
import urllib3
import datetime

currentT = datetime.datetime.now()

url = 'https://mijn.easyenergy.com/nl/api/tariff/getapxtariffs?startTimestamp='+currentT.strftime('%Y-%m-%d')+'T'+currentT.strftime("%H")+'%3A00%3A00.000Z&endTimestamp='+currentT.strftime('%Y-%m-%d')+'T'+currentT.strftime("%H")+'%3A59%3A00.000Z'
urllib3.disable_warnings()
response = requests.get(url, verify=False)

print(response.json()[0].get("TariffReturn"))

There is nothing else in the logging before the error:

2024-04-02 17:10:10.603 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'test' received command OFF
2024-04-02 17:10:10.605 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'test' changed from ON to OFF
==> /var/log/openhab/openhab.log <==
2024-04-02 17:10:10.701 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'APIeasyEnergy-1' failed: An error occurred during the script execution: Cannot invoke "org.eclipse.xtext.common.types.JvmType.eIsProxy()" because "type" is null in APIeasyEnergy

I appreciate the reply but frankly what the Python script is and what you see on the command line is kind of irrelevant. What needs to be seen is what OH actually gets back.

Importantly, is the rule failing on the executeCommandLine, the creation of the BigDecimal, or the postUpdate? To figure that out you need to separate the call to executeCommandLine from the creation of the BigDecimal and the call to postUpdate.

But looking at it again, you’ve passed no delay in the call to executeCommandLine meaning it doesn’t wait for the script to complete and therefore it doesn’t return anything (i.e. void). Obviously you cannot convert void to a BigDecimal.

This is why it’s crucial to break up lines of code as much as possible when encountering errors and logging out the result of each and every line. That is the only way to get the information needed to solve the problem.

See Actions | openHAB

  • executeCommandLine(String commandLine): Executes a command on the command line without waiting for the command to complete. For example you could run executeCommandLine("path/to/my/script.sh") which then would be executed and the rule would continue processing.
  • executeCommandLine(Duration.ofSeconds(timeout), String commandLine): Executes a command on the command and waits timeout seconds for the command to complete, returning the output from the command as a String. For example you could run var ScriptResponse = executeCommandLine(Duration.ofSeconds(60), "path/to/my/script.sh"); would get executed and wait 1 minute for the output to be responded back and write it into the ScriptResponse variable.

Thanks for the quick replies, I think I understand what you want to say.

First I added the timeout in the execution line, still the same error, then I added 2 log info lines to see how far the rule can get executed, apparently till the python execute line, this is what I did:

rule "Update return tariff"
when
    Time cron "0 0 0/1 1/1 * ? *" or
    Item test changed
then
logInfo("APIeasyEnergy", "Before running Python execute.")
var Number result = new BigDecimal(executeCommandLine(Duration.ofSeconds(10), "python /etc/openhab/scripts/currentReturnTarrif.py",1000))
logInfo("APIeasyEnergy", "After running Python execute is: " + result + " end. ")
    currentReturnTariff.postUpdate(result as DecimalType)
end

And the outcome:

2024-04-02 19:32:48.288 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'test' changed from ON to OFF

==> /var/log/openhab/openhab.log <==

2024-04-02 19:32:48.290 [INFO ] [nhab.core.model.script.APIeasyEnergy] - Before running Python execute.

2024-04-02 19:32:48.291 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'APIeasyEnergy-1' failed: An error occurred during the script execution: Cannot invoke "org.eclipse.xtext.common.types.JvmType.eIsProxy()" because "type" is null in APIeasyEnergy

There is nothing after that error. What would be the best approach to break t down even further?

You’ve missed

To figure that out you need to separate the call to executeCommandLine from the creation of the BigDecimal and the call to postUpdate .

Is the error happening from the python script? executeCommandLine? BigDecimal? :man_shrugging: It’s all on one line.

You have to break it up and log each step of the way.

rule "Update return tariff"
when
    Time cron "0 0 0/1 1/1 * ? *" or
    Item test changed
then
    logInfo("APIeasyEnergy", "Before running Python execute.")
    var execResults = executeCommandLine(Duration.ofSeconds(10), "python /etc/openhab/scripts/currentReturnTarrif.py")
    logInfo("APIeasyEnergy", execResults)
    var result = new BigDecimal(execResults)
    logInfo("APIeasyEnergy", result)
    currentReturnTariff.postUpdate(result)
end

Also, there were two syntax errors in your original code. What was that 1000 at the end of the call to executeCommandLine? BigDecimal is not DecimalType, you cannot cast it to become one.

I know, I wasn’t sure how to do this, apparently, by putting it in a var, learned something new today :slight_smile:

The outcome:

2024-04-02 19:55:36.621 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item ‘test’ changed from OFF to ON

==> /var/log/openhab/openhab.log <==

2024-04-02 19:55:36.717 [INFO ] [nhab.core.model.script.APIeasyEnergy] - Before running Python execute.

2024-04-02 19:55:36.730 [WARN ] [rg.openhab.core.io.net.exec.ExecUtil] - Failed to execute commandLine ‘[python /etc/openhab/scripts/currentReturnTarrif.py]’

2024-04-02 19:55:36.731 [INFO ] [nhab.core.model.script.APIeasyEnergy] - null

2024-04-02 19:55:36.732 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘APIeasyEnergy-1’ failed: An error occurred during the script execution: Cannot invoke “org.eclipse.xtext.common.types.JvmType.eIsProxy()” because “type” is null in APIeasyEnergy

For some reason, the script can’t be executed but it will run from the CLI, could it be something to do with permissions or so?

If you are not experienced in programming and/or are struggling with rules, I cannot recommend strongly enough to use Blockly. It’s really hard to make the sorts of errors that I see here in Blockly and for most the graphical way the blocks plug together is much easier to understand.

OK, so there is something wrong with the execute command line. As the docs indicate under “Scripts with parameters”:

you have to add one argument per script parameter to the function.

This command takes an argument so separate the call to python and the path to the script.

You also may need to put the full path to python.

var execResults = executeCommandLine(Duration.ofSeconds(10), "/usr/bin/python", "/etc/openhab/scripts/currentReturnTarrif.py")

You’ll have to verify that’s the path to Python on your machine.

Certainly. Scripts run from openHAB run as user openhab. When you run it from the command line it’s running under your account.

I’m not familiar with Blocky either, will look into it. I do it this way, and not- for example- via the GUI because I want to learn from it, also from my mistakes. So sometimes I need a little help from here.

This seems to be the right way to execute the command, so it return the value as expected from the script, the only problem left is the new BigDecimal part, that still seems to fail. Is there another way to convert the returned string value from the command to a number type?

2024-04-02 21:45:39.540 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item ‘test’ changed from ON to OFF

==> /var/log/openhab/openhab.log <==

2024-04-02 21:45:39.635 [INFO ] [nhab.core.model.script.APIeasyEnergy] - Before running Python execute.

2024-04-02 21:45:40.014 [INFO ] [nhab.core.model.script.APIeasyEnergy] - 0.07243

2024-04-02 21:45:40.015 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘APIeasyEnergy-1’ failed: An error occurred during the script execution: Cannot invoke “org.eclipse.xtext.common.types.JvmType.eIsProxy()” because “type” is null in APIeasyEnergy

I’m not sure what doing it from the UI changes in that regard. Mistakes are mistakes and mistakes are possible in both places. But when you are first learning, it’s hard enough to deal with the logical errors without throwing in stray commas, unbalanced parens, etc which can completely break a script.

And the UI doesn’t mean you don’t write code. If you really do want to fight syntax errors and the like, you can write code in the UI too.

Over all though, I figure most people will want to spend their time fighting home automation problems, not incorrect white space or similar syntax errors.

The log clearly shows there’s a newline output by the Python script. You need to trim() that off. String (Java SE 17 & JDK 17)

I feel like I learn more when do it text/code based over GUI, of course you can make mistakes everywhere. On the bright side, I already have around 50 working rules :slight_smile:
When I started with openHAB (6 years ago) I decided that I wanted to create everything text based, so all the items and things are also created that way.

in these years I already had enough time spent on fighting the home automation problems, now I have time left for stuff like this, so today I learned a lot of new things.

Saw it after you mentioned it, I added the trim() (also a new to me) and the line is gone, but the error remains the same:

2024-04-02 22:21:17.076 [INFO ] [hab.core.model.script.APIeasyEnergy1] - Before running Python execute.

2024-04-02 22:21:17.466 [INFO ] [hab.core.model.script.APIeasyEnergy2] - 0.07274

2024-04-02 22:21:17.467 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘APIeasyEnergy-1’ failed: An error occurred during the script execution: Cannot invoke “org.eclipse.xtext.common.types.JvmType.eIsProxy()” because “type” is null in APIeasyEnergy

first without trim, second time with trim:

So, after some fidgeting around and some more reading on some other topics, I found the way to convert it and update the item, this is working now:

rule "Update return tariff"
when
    Time cron "0 0 0/1 1/1 * ? *" or
    Item test changed
then
    logInfo("APIeasyEnergy1", "Before running Python execute.")
    var execResults = executeCommandLine(Duration.ofSeconds(10), "/usr/bin/python", "/etc/openhab/scripts/currentReturnTarrif.py").trim()
    logInfo("APIeasyEnergy2", execResults)
    currentReturnTariff.postUpdate(execResults, new BigDecimal)
    logInfo("APIeasyEnergy3", "Item currentReturnTariff is updated to: " + currentReturnTariff.state as Number)
end

Thanks for the help!

If you want to play with coding, check out jsscripting and jruby.

This line makes no sense. new BigDecimal isn’t doing anything. I’m a little surprised that it’s not throwing an error. I guess Java is smart enough to ignore extraneous arguments?

This line is wholly dependent on timing. Posting an update to an Item occurs asynchronously. There is no guarantee that `currentReturnTarriff has actually completed changing it’s state when this logInfo line runs. You might be logging out the old value still.

And I’ll second @JimT’s suggestion. If you really want to learn programming, then Rules DSL is probably about your worst choice to use as a language in openHAB right now.

Finally, just to make it perfectly clear, just because a rule is defined through the UI doesn’t mean there’s no code. Here’s how one of mine appears in the UI.

The biggest difference, from a learning to code perspective, is that I can access that code from anywhere I can access OH. I’m not trying to convince you to change, but to make clear to future readers of the thread that using the UI doesn’t automatically free one from learning to code.

Yea you’re right, also without the argument it is working. Just out of curiosity, I thought executeCommand values are always a string type, how can it update the number item without changing the type then?

That’s also true, will change the line to " the current value of item is: xxxx".

Maybe I didn’t choice the right word with GUI with it, I meant I wanted to use text based rules instead of the graph design rule maker in OH.
I also can always access my rules because of VPN and SMB connection, when connected I can read/write/edit code from VS, which I use as code editor :slight_smile:

Thanks for the suggestion, will definitely look into that!

You can always postUpdate or command an Item with a String. If it’s valid, OH will parse it and convert it as it needs to. So if you post update “12345” to. a Number Item, OH will parse that to the number 12345 for you.

I’m not sure that log statement provides much value then. You can’t know whether the current value is the state of the Item before the rule ran or after and based on timing it might be either. If you want to keep that log statement, change it to "Updated currentReturnTariff to " + execResults. That at least will deterministically show what the rule actually did.

You can use any of the text based rules languages in the UI is my main point. Creating rules in the UI does not automatically mean using Blockly.

I can’t do that from my phone though. Being able to quickly bring up a rule and make a quick change has saved me more than once from being overrun by alerts when a rule ran amok while I was out of the house.

Again, I’m not trying to convince you or anyone to change how they work. I am just very sensitve to depecting UI based configs in ways that are not correct or that indicate they are less capable or usable than they really are. Perhaps not you, but there are many users who become convinced they shouldn’t use the UI who frankly have no business using text based configs. When these user don’t just silently give up in despair, they tend to consume an oversized amount of time from the helpers here on the forum.

I will say though that since OH 4 it’s become much better in that regard. I think some of the FUD about UI configs has dissipated.