String to Integer conversion in OH4 rules

Hello, i have the following code that worked well in OH2

            val String echoResult2 = executeCommandLine("cat@@/etc/openhab2/variables/valve.txt", 5000)   
            sendCommand(VALVE,(Integer::parseInt(echoResult2) as Number))

When i try to have this rule work in OH4

val String echoResult2 = executeCommandLine(Duration.ofSeconds(5),"/bin/bash", "-c", "cat /etc/openhab/variables/valve.txt");
sendCommand(VALVE,(Integer::parseInt(echoResult2) as Number))

I get
2024-01-06 22:06:16.438 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘RestoreSystemItems’ failed: For input string: "1

The valve.txt file has one character “1” and can be successfully printed in a log without quotes.

Can you help me to understand why Integer::parseInt does not like this string and looks like get it with quotes??

I think the executeCommandLine part could be shortened:

executeCommandLine(Duration.ofSeconds(5),"/bin/cat", "/etc/openhab/variables/valve.txt")

How does the error message exaclty look like ?
Is it

For input string: "1


For input string: "1"

I think the quotes are there just put around that what is returned. They are not really there.
If the error message looks like in the first case ( output over two lines ) then a newline is part of the txt file.

Add an other line of code that prints out the variable into the openhab.log file. Then you will be sure about what the content of the variable really is.

It looks like on screenshot. Looks like you are correct and CR is returned back with the String. Let me check and remove CR character

I had the same problem. If you convert the number to string and log out the length of the string you will notice that it does not match with the digits.
I worked around by multiplying by 1 to get rid of any “hidden” characters

I tried a coupe of things.

First, when you save the number into the file with echo command it adds 0x0A (CR) after 1(0x31). And that does not help. While it was working well in OH2

Second, i tried to replace 0x0A with 0x00 and this error shows up showing only 1 in quotes

I could not find easy way to hexedit the file to make its length only 1 byte. Any idea what editor i can use? Please do not propose vi as i’m not really fan of it and do now want to spend time to learn it.

Anyway i’m confused why Integer;;parseInt does not work with well formatted string that consist only of numbers

Thanks Oliver for reply.
I didn’t get what do you mean to multiply by 1.
Can you give example of code?

I did not test this, but in principal this is what I mean:

val String echoResult2 = executeCommandLine(Duration.ofSeconds(5),"/bin/bash", "-c", "cat /etc/openhab/variables/valve.txt");
val echoResult3 = (Integer::parseInt(echoResult2) as Number) * 1

Still does not work

// Restore values from the file
logInfo("Start","Variable initialization from file");
val String echoResult2 = executeCommandLine(Duration.ofSeconds(5),"/bin/bash","-c", "cat /etc/openhab/variables/valve.txt");
val echoResult3 = (Integer::parseInt(echoResult2) as Number) * 1

and result

I guess sendCommand expcts a string.


No, VALVE is of type Number and if i send echoResult2 as it read from the file as String the error is the same

No. sendCommand(item,state) definitely requires a string for state. sendCommand converts the value by itself into the correct type.
Could you please try as suggested and report back what the log says?

hi, i have something similar.

val String echoResult2 = executeCommandLine(Durati...
echoResult2 = echoResult2.trim()


Here we go

Doesn’t work either

Assignment to final variable…
try var instead of val

Ultimately everything you need to solve this has been said on this post so far but I want to summarize and consolidate.

  1. Your call to execute command line is returning a newline after the output. So instead of 1, you are getting 1\n. Obviously, 1\n is not a number and you cannot parse it into one. But you can use trim to remove the newline (I recommend that over multiplying by 1 as suggested by @Oliver2, though that should work too.

    val echoResult2 = executeCommandLine(Duration.ofSeconds(5),“/bin/cat”, “/etc/openhab/variables/valve.txt”).trim()

Also I suspect the carriage return is being added by cat so even if you managed to remove it from the file, you’ll still have to deal with it. So don’t bother, just trim the result in your rule.

  1. The sendCommand() action indeed expects two Strings as arguments, doesn’t matter what type the Item is. Often it can be smart enough to call toString() on what’s passed to it but not always. This is why the docs and it’s always been recommended to use Item.sendCommand(newState) over sendCommand(ItemName, newState) as the Item method can accept more different types and convert as needed.
    But given that it expects a String in the first place, you don’t need to parse it into an Integer in the first place. Just pass the String from executeCommandLine directly to the Item in the update. The error “for input string: 1” is telling you that it expects a String for the second argument but it’s not getting a String because you are parsing it into an Integer.

  2. The line above avoids the assignment to final val by doing the trim on the same line. If you do two lines like @Baschtlwaschtl desmonstrates, you must use var instead of val so you can change the value of the variable.

Hi Rich, as always your comments and structured answers works best Thanks!

So both #1 and #2 from you worked well.
#1 method .trim() used for executeCommandLine worked to remove \n from the string
However echoResult2=echoResult2.trim() didn’t worked. Though i didn’t try wit var
#2 Using Item.sendCommand() worked well without additional type conversions

so in the end the working code looks like

// Restore values from the file
logInfo("Start","Variable initialization from file");
val String echoResult2 = executeCommandLine(Duration.ofSeconds(5),"/bin/bash","-c", "cat /etc/openhab/variables/valve.txt").trim();

And all this is confusing as initial code was working in OH2 without an issue.