Exec binding and echo, netcat, a pipe, carriage return and quotation marks

ahh, ok thanks for explaining that.

I did just find a combination that yielded something different:

This in the rule:
"/bin/echo@@-e@@'POWR1@@@@@@\r' | /bin/nc 192.168.1.28 10002", 5000
yields this in the log:
2016-03-21 17:34:40.835 [INFO ] [g.openhab.model.script.ExecLog] - 'POWR1 ' | /bin/nc 192.168.1.28 10002
Looks, similar, BUT it has 3 spaces after the POWR1! probably not a carriage return, but its something

edit: on a lark I tried to put that last command with the @@'s into my item file and got the dreaded:
Binding configuration of type 'exec' of item ‘AV_TV_IP_Power‘ could not be parsed correctly. org.openhab.model.item.binding.BindingConfigParseException: Exec binding legacy format cannot start with '<' or '>'
back to the old drawing board…

If I put this into the .items file for the binding information:
{ exec=">[ON:/bin/echo@@-e@@'POWR1@@@@@@\\r' | /bin/nc 192.168.1.28 10002] >[OFF:/bin/echo@@-e@@'POWR1@@@@@@\\r' | /bin/nc 192.168.1.28 10002]" }
the log doesn’t give the usual error about "Exec binding legacy format cannot start with ‘<’ or ‘>’ but actually gives no errors at all. I added it to my sitemap and still no errors. In the ExecBinding log i defined in logback.xml i get this line:

2016-03-21 17:58:49 INFO o.o.b.e.internal.ExecBinding[:320]- executed commandLine '[/bin/echo, -e, 'POWR1, , , \r' | /bin/nc 192.168.1.28 10002]'

The TV didn’t turn off and on, but I really think i’m close here…

edit: removing the @@'s got rid of the errant commas, still no response from the TV but sooo close. I can taste it

So I’m not at a working execbinding item yet, but I have learned some important things:

  1. the Exec binding legacy format cannot start with '<' or '>' error was happening whenever I had /r in the exec item. It was only suppressed with an extra / before it (i.e. //r)

  2. single quotes can be used around the string in exec -e without escape, but double quotes will cause a Exec binding legacy format cannot start with '<' or '>' error

  3. Escaping out double quotes with a backslash (i.e. /") seems to get them to work.

For instance, Here is the entries in the ExecBinding log for both of those options:
2016-03-21 18:11:54 INFO o.o.b.e.internal.ExecBinding[:323]- executed commandLine '/bin/echo -e 'POWR0 \r' | /bin/nc 192.168.1.28 10002' 2016-03-21 18:11:56 INFO o.o.b.e.internal.ExecBinding[:323]- executed commandLine '/bin/echo -e 'POWR1 \r' | /bin/nc 192.168.1.28 10002' 2016-03-21 18:13:33 INFO o.o.b.e.internal.ExecBinding[:323]- executed commandLine '/bin/echo -e "POWR1 \r" | /bin/nc 192.168.1.28 10002' 2016-03-21 18:13:34 INFO o.o.b.e.internal.ExecBinding[:323]- executed commandLine '/bin/echo -e "POWR0 \r" | /bin/nc 192.168.1.28 10002'

Now if I copy and paste either of the power on (POWR1) and power off (POWR0) commands from the log and into the command line, the TV will appropriately respond. But nothing when hitting the button in the sitemap. Though I’ve only been copying what was inside the single quotes…If I copy the command WITH the wrapping single quotes I get a bash: /bin/echo -e POWR0: No such file or directory error

Yes. The exec binding doesn’t give you anything in your logs for what the script/command returned. This is why I always recommend using executeCommandLine with a log statement.

At this point, speaking just for myself, I would punt. Put the command into a shell script and call that from my exec binding or executeCommandLine. I suspect with enough experimentation you can figure out why it works differently and figure out what the magic combination of quotes, escapes, and backtics. But for me, I know it will work if you put it into a shell script and solving these sorts of problems is less interesting to me than the larger home automation problems.

But what am I looking for in the log from the Rule (that I’m not seeing that is)? When I put the working command(s) into Terminal, I do not get any text response or anything. As far as I can tell, that the command is (finally) being read by openhab correctly, in that there are no errors and the exec debug log shows that it’s sending the correct command (the correctness proved by copying and pasting from the debug log into the console and it working). I’m just not sure what else I would be looking for in the log from the rule?

So I was starting to think the same thing, but instead of the shell script, which is still an option, I was looking into the TCP/UDP binding as alternative. Trying to figure out if I could avoid making a .map transformation file for each command when I ran across this, Is it possible that the character set the exec binding is using simply doesn’t understand /r as a carriage return?

In any event, seems like writing shell scripts for each command would be just as tedious as writing .map transformation files for each command (probably MORE tedious). Is it foolhardy to hope I could maybe hijack one of the other TV bindings?

When you run a command using the Exec binding instead of executeCommandLine, you will never see anything in the log whether it worked or not. You script can generate a page of text and the Exec binding will not put that into the logs. The only way to see what your script returns is to use executeCommandLine with a timeout. In other words, the Exec binding provides no feedback whatsoever.

Anything is possible at this point. Have you tried \n instead of \r? Typically you either see \r\n together (usually on Windows) or just \n (everyone else) when it comes to ACSII/UTF-8 encoded files.

Why do you have to do this? Write a script that accepts the name of your command as Input and put the name of the key in your binding config.

The Script: script.sh

#!/bin/sh

/bin/echo '$1 \r' | /bin/nc 192.168.1.28 10002

Your Items:

Switch Power1 {exec=">[ON:script.sh POWR1] >[OFF:script.sh POWR1]"}
Switch Power2 {exec=">[ON:script.sh POWR2] >[OFF:script.sh POWR2]"}

Not sure it would be any less work.

Oh interesting, i didn’t know you could feed a shell script a variable like that, that is pretty easy.

I still feel like a quitter for not figuring out why this exec command doesn’t work…but thanks for sticking with it for as long as you did! (p.s. /n didn’t work:( )

I can’t quite get the script to fire the way you say it should (I’m sorry I’m very new to script writing). I added the -e flag and the 3 trailing spaces after the variable to the command:
/bin/echo -e '$1 /r' | /bin/nc 192.168.1.28 10002
(i know its showing up as only 1 space bewteen $1 and /r but i’m typing 3 and there are def three in the actual script)
I then chown’ed it to openhab:openhab and chmod’ed it with 777. when I execute
./script.sh POWR0
it doesn’t give me an error or anything but the TV (which is currently on) doesn’t turn off. If I copy and paste the POWR0 over the $1 the tv turns off though…

Again, sorry. I’m sure its something little or stupid…

edit: I also tried changing the script to:
/bin/echo -e $1 | /bin/nc 192.168.1.28 10002
and executing it with
./script.sh 'POWR0 /r
and it took a bit to complete but once it finished there was no error and the TV was still on…

Maybe because we are now in a shell script you should use double quotes instead of single quotes. The single quotes may be keeping the shell from interpreting the $1 as a variable.

Double quotes is the more standard way to do that in scripts.

It might be worth setting up wireshark or a tcpdump and seeing exactly what is being sent to your IP address to know for sure.

Yeah I tried that, and single quotes inside double quotes for the second attempt (where the variable covers the command, three trailing spaces AND the carriage return). Neither seemed to work. But I just realized I only tried replacing the variable directly in the command line, not inside the shell script and trying to run the shell script (as in just running the command as a shell script without the variable). I just discovered the concept of positional parameters, so I was trying to google for a bit more color on what’s allowed but my concerns were two-fold:
with this shell script:
/bin/echo -e '$1 /r' | /bin/nc 192.168.1.28 10002
The color of the $1 changed when I removed the quotes around it, which led me to worry that it was being read as a string literal (i think I used that term right). It’s my understanding that I need the -e flag in order for it to interpret \r as a carriage return…
with this shell script:
/bin/echo -e $1 | /bin/nc 192.168.1.28 10002
The issue is that when I execute the script with ./script.sh "POWR0 \r" I’m not sure what the delimiter is between what is read as $1 or $2 (and so on). If its a space, then
I’m not sure it’ll get passed to the script correctly, or if wrapping it in quotes is enough.

Obviously i’ll be researching positional parameters but if you have any input on this I’d be happy to hear it.

hmm not sure what that is, but I’ll look into it.

One thing I’ve noticed over and over but haven’t commented on because I figured it was just a typo but to do the carrage return you must use backslash "" as in “\r”, not forward slash as in “/r”. Your postings seem to go back and forth in the usage. Make sure that it is “\r” in your script.

Take a step back and work on the script bit by bit.

Get rid of the pipe and everything after it and see what the echo is actually echoing.

#!/bin/sh

/bin/echo -e "start  $1   \rend"

When you call script.sh POWR! your output should be something like:

endrt  POWR1

NOTE: The carage return returns the cursor to the beginning of the line so the echo first prints "start POWR1 " then returns the cursor to the beginning and prints “end”.

If you run that script you will see whether or not the script is interpreting the $1 as a variable or as a string literal (you used the term correctly). Once you see something like that, remove the “start” and “end” from the echo statement and readd back in the pipe. If it doesn’t work now the problem isn’t the echo but the nc command.

The delimiter is space so you might need to escape the spaces, though I think the quotes are enough to put it all in $1.

./script.sh "POWR0\ \ \ \r"

And again, by focusing on just getting the echo to work right it will be lot easier to test this out to see what is happening. For example:

#!/bin/sh

echo "Argument 1 = $1"
echo "Argument 2 = $2"

When something doesn’t work, break it down into tiny pieces and work on them one by one until you get it to work rather than trying to get everything working all at once.

Yeah those are just typos. Its weird to use the backslash when typing. thank you though.

This is great advice (and something I constantly seem to forget). Thanks and I’ll report back.

I’m not in front of an actual sh, but I’ve been playing around with an online bash emulator and I’m beginning to think the issue with both the exec commands and this is the three spaces. For instance running executing this script:
/bin/echo -e $1
with:
./script.sh POWR0 \r
returns:
POWR0
As excepted, and putting stuff after the carriage return “overwrites” the initial output as you detailed above. However, there’s no real way for me to be sure that all 3 spaces are included before the carriage return.
SO, I executed:
./script.sh POWR0 .\r
and it returned
POWR0 .
with only one space between the zero and the period! I feel like this condensing of 3 spaces into 1 has happened a few times in random situations (or at least in a pattern I haven’t been able to recognize. It even happened earlier when I was typing in something on this thread).
Putting this in the actual script:
echo -e "$1 .\r"
and executing:
./script.sh POWR0
returns
POWR0 .\r
so maybe that’s the answer (though without the period), but I could’ve SWORN i already tried that. I’ll report back.

EDIT: haha it happened again. In that last Preformatted Text i wrote, the POWR0 .\r I definitely have typed 3 spaces in both instances but the forum prints it as 1 space…

Be wary of using how a web based bash emulator or this forum treats spaces as how it will actually behave. Be default web browsers will treat several spaces in a row as a single space so what you might be seeing is just a side effect of how the web browser renders the page. The proof will be when you run your tests in front of an actual shell.

If the actual shell is also condensing the spaces (which I find hard to believe), use "\ \ \ " for the spaces. That will escape them and keep the echo hopefully from condensing them

of course, just reporting weird findings that might describe some of my issues. I’ll hold all judgments until I try on the Pi

I’ve tried to “escape” out spaces with a slash many times. It doesn’t seem to work that way and everything I find on the web regarding the backslash characters doesn’t seem to list anything for spaces (closest is /0 for null). Any time I tried that in the exec binding item configuration or the rule I would get an error or some other undesirable behavior. Just saying, I don’t think typing a backslash then a space reads into the shell as a space.

Actually the opposite. It may not read as a space in the Exec binding. In the shell if you, for example, need to cd to a folder with a space in the name you use "\ ".For example here is how I would cd to my “Calibre Library” folder on my Linux machine:

cd /mnt/media/Calibre\ Library/

oo of course. Stupid me.

Actually now that you type that I realize that the issue is when the slash’s are combined with the -e flag and inside the quotes. Cause cd /mnt/media/Calibre\ Library/ is how you would move to the Calibre folder, or cd "mnt/media/Calibre Library/

Correct, both work so maybe the quotes make it so you don’t need the three spaces.

I tried this script:

#!/bin/sh

/bin/echo -e "$1   -\r"

which produced

 POWR1   -

There are three spaces between POWR1 and the “-”. So that works. I also put stuff after the \r to see if that was working and it is.

Then I tried to pass in the three spaces with the carriage return as the argument and I see the same behavior (i.e. echo is concatenating the spaces.

Neither "POWR1 -\r" worked nor "POWR1\ \ \ -\r" nor POWR1\ \ \ -\r worked.

So the question becomes, is it only some of these commands that need the three spaces or all of them? If all of them then just use the first script. If only some of them you may need multiple scripts, one for the three spaces and one without.