New User: Avalanche of Errors (Getting Smothered)

Hi there!

I’m very new to openHab (like, 5 days) and I’m using it to get around a Kramer Control system that doesn’t have the drivers we need for our TVs. Namely, I just need it to send a command to power the TV on and off. No need for returning a value or anything, just send the command. As I’ve been working, I haven’t been getting the responses I’ve needed, so I opened up the logs and…dear lord. It’s just a stream of errors longer than my commute to the office and I don’t have any idea where to start. The way my architecture is built: I have 3 tvs at IPs 10.47.0.240-241-242, and they have various items attached to them, but the only one that matters are the switches for their power state. They are vizios which operate via smartcast, which accepts JSON-based HTTP requests. I’ve made rules that call these POST commands and input javascript to parse the JSON.

Here’s a doc with all the errors: https://docs.google.com/document/d/1a8mSd90VKcP6Fpp1kgVPUPjkGIJFSfNZuBOb_2WJcZM/edit?usp=drivesdk

If anyone has time to help me out with this, it’d be extremely appreciated. Please let me know if you need anything to clarify the errors, because I can only imagine there are things necessary that I’m not seeing.

I see 2 major issues in the error logs:

  1. The items you created have invalid names (can’t use the dash “-“ symbol)
  2. The openhab binding configuration file seems to be corrupted.

For the first one just rename the items. For the second, can you access Paper UI and try installing a new binding? Any binding should do, just so the file gets “touched” (or new errors generated)…

Thanks so much!

So I went through and did these things and I’m getting some different (but thankfully more specific) errors, which I’ve replaced in the doc. Namely, I’m noticing that it’s not liking my “rules” page, which I’ll paste below:

var autha1 = ""
var autha2 = ""
var authb1 = "Zhgigzcjdr"

import java.net.URI

rule "TV A 1"
when
	Item POWER_TV_A_1 received command
then
	switch(receivedCommand)
	{
		case ON : sendHttpPostRequest(">[https:// IP :7345:JS(powerOn.js){Authorization=OAuth " + autha1 + "}]")
		case OFF : sendHttpPostRequest(">[https:// IP :7345:JS(powerOff.js){Authorization=OAuth " + autha1 + "}]")
	}
end

rule "TV A 2"
when
	Item POWER_TV_A_2 received command
then
	switch(receivedCommand)
	{
		case ON : sendHttpPostRequest(">[https:// IP :7345:JS(powerOn.js){Authorization=OAuth " + autha2 + "}]")
		case OFF : sendHttpPostRequest(">[https:// IP :7345:JS(powerOff.js){Authorization=OAuth " + autha2 + "}]")
	}
end 

rule "TV B 1"
when
	Item POWER_TV_B_1 received command
then
	switch(receivedCommand)
	{
		case ON : sendHttpPostRequest(">[https:// IP :7345:JS(powerOn.js){Authorization=OAuth " + authb1 + "}]")
		case OFF : sendHttpPostRequest(">[https:// IP :7345:JS(powerOff.js){Authorization=OAuth " + authb1 + "}]")
	}
end

The spaces are put after the IP to allow me to post without triggering the spam blocker. I’m not sure exactly where I went wrong, but it’s supposed to do what these commands do:

curl -k -h "Content-Type: application/json" -h "AUTH: CODE_HERE" -X PUT -d "{\"KEYLIST\": [{\"CODESET\": 11,\"CODE\": BOOLEAN,\"ACTION\":\"KEYPRESS\"}]}" https://IP:7345/key_command/

There’s a lot of documentation on various ways to do this, so I could very well be getting confused. The javascript file imports are JSON.Parse() of the data section of the curl commands.

EDIT: Can’t for the life of me figure out why it’s making that bold, apologies for that
EDIT 2: Put in the code fences for ease on the eyes

Check out @rlkoshak 's tutorial on how to use Code Fences - that’ll make your posts much more readable to others.

The thing that doesn’t belong in the ruleset is the JS() transformation. Those can be done in the items and sitemap files, but not in the rules syntax (as far as I know, someone may correct me on that). Your best bet is to either write out the entire javascript string, or put them in global variables at the front of the rules file and concatenate them to your http request string as needed.

I am seeing smart quotes that look like 9 and 6. These can cause issues and is why you need to use code fences as suggested.

Thanks so much!

So after taking your advice, this is now what I have:

import java.net.URI

var autha1 = ""
var autha2 = ""
var authb1 = "Zhgigzcjdr"

var powerOn = '{"KEYLIST":[{"CODESET":11,"CODE":1,"ACTION":"KEYPRESS"}]}'
var powerOff = '{"KEYLIST":[{"CODESET":11,"CODE":0,"ACTION":"KEYPRESS"}]}'

rule "TV A 1"
when
	Item POWER_TV_A_1 received command 
then
	switch(receivedCommand)
	{
		case ON : sendHttpPostRequest(">[https://10.47.0.240:7345){Authorization=OAuth " + autha1 + "}]")
		case OFF : sendHttpPostRequest(">[https://10.47.0.240:7345{Authorization=OAuth " + autha1 + "}]")
	}
end

rule "TV A 2"
when
	Item POWER_TV_A_2 received command
then
	switch(receivedCommand)
	{
		case ON : sendHttpPostRequest(">[https://10.47.0.241:7345{Authorization=OAuth " + autha2 + "}]")
		case OFF : sendHttpPostRequest(">[https://10.47.0.241:7345{Authorization=OAuth " + autha2 + "}]")
	}
end

rule "TV B 1"
when
	Item POWER_TV_B_1 received command 
then
	switch(receivedCommand)
	{
		case ON : sendHttpPostRequest(">[https://10.47.0.242:7345{Authorization=OAuth " + authb1 + "}]")
		case OFF : sendHttpPostRequest(">[https://10.47.0.242:7345{Authorization=OAuth " + authb1 + "}]")
	}
end
	

I’m not sure where the powerOn and powerOff variables would fit into these strings, I’ve been reading up on Xtend http requests, but I’m not finding the examples I’m looking for. I ended up simply pulling the JSON out of the separate files and leaving them as strings, as I realized I don’t need a JSON object here.

However, I’ve also found people using items in this manner, which I took a stab at and came up with this:

Switch Power_TV_B_1 "TV 201b 1 Power" (PartitionB, gPower, TV_3) {http=">[ON:PUT:https://10.47.0.242:7345/key_command/{Content-Type=application/json&Auth=Zhgigzcjdr}:JS(powerOn.js)] >[OFF:PUT:https://10.47.0.242:7345/key_command/{Content-Type=application/json&Auth=Zhgigzcjdr}:JS(powerOff.js)]"}

In your opinion, which of these should I be using? Is there anything else I’m doing wrong?

So I’ve done some more digging, and I’ve found something called executeCommandLine() which appears to be available in Xtend. I can’t seem to find any documentation on the command (I’m having that issue with most of Xtend now that I mention it) but I took a jab at it and made this:

executeCommandLine("c/system/curl -h \"Content-Type: application/json\" -h \"AUTH: Zhgigzcjdr\" -X PUT -d \"{\"KEYLIST\": [{\"CODESET\": 11,\"CODE\": BOOLEAN,\"ACTION\":\"KEYPRESS\"}]}\" https://10.47.0.242:7345/key_command/")

I’m fairly certain this is wrong somehow but, like I said, I’m having a hell of a time finding good documentation. Would this also be a valid way of doing what I need?

Hey there! So I’ve been doing some more work and I’ve isolated down to using executeCommandLine with curl, but I’m having trouble validating the output. Namely if it’s doing anything at all.

Here’s what I’ve made:

power.rules:

import org.openhab.core.*
import org.openhab.model.*

var ipb1 = "10.47.0.242"

var port = "7345"

var authb1 = "Zhgigzcjdr"

var powerOn = "{\\\"KEYLIST\\\":[{\\\"CODESET\\\":11,\\\"CODE\\\":1,\\\"ACTION\\\":\\\"KEYPRESS\\\"}]}"
var powerOff = "{\\\"KEYLIST\\\":[{\\\"CODESET\\\":11,\\\"CODE\\\":0,\\\"ACTION\\\":\\\"KEYPRESS\\\"}]}"

rule "TV B 1"
when
	Item Power_TV_B_1 received command 
then
	logError("power.rules","This ran but failed!")
	switch(receivedCommand)
	{
		case ON : executeCommandLine("c:\\windows\\system\\curl@@-k@@-H@@\"Content-Type: application/json\"@@-H@@\"AUTH: " + authb1 + "\"@@-X@@PUT@@-d@@\"" + powerOn + "\"@@http://" + ipb1 + ":" + port + "/key_command/")
		case OFF : executeCommandLine("c:\\windows\\system\\curl@@-k@@-H@@\"Content-Type: application/json\"@@-H@@\"AUTH: " + authb1 + "\"@@-X@@PUT@@-d@@\"" + powerOff + "\"@@http://" + ipb1 + ":" + port + "/key_command/")
	}
end

Now in my logs it says that I’m getting validation errors when loading power.rules, but it’s “using it anyways.” (Real comforting…) I’ve been trying to test it with smarthome:send Power_TV_B_1 ON but it’s not helping me very much. We’ve also tried mock servers and can’t quite verify what’s going on.

Any ideas as to where I’m going wrong? Thanks!

I think your validation isses are the imports. If your using OH2, then you shouldn’t need them (already there). Setup VS Code and it will provide this info for you.

To turn on debugging for executeCommandLine, type this into Karaf (turn it off by changing DEBUG to OFF or WARN)…

log:set DEBUG org.eclipse.smarthome.io.net.exec

Does the curl command work from a command line?

That fixed my validation issues! Thanks!

I did turn on that logger setting and it seems that I’m getting this error primarily:

08:12:05.785 [ERROR] [clipse.smarthome.io.net.exec.ExecUtil] - couldn't execute commandLine 'c:\windows\system\curl@@-k@@-H@@"Content-Type: application/json"@@-H@@"AUTH: Zhgigzcjdr"@@-X@@PUT@@-d@@"{\"KEYLIST\":[{\"CODESET\":11,\"CODE\":1,\"ACTION\":\"KEYPRESS\"}]}"@@http://10.47.0.242:7345/key_command/' java.io.IOException: Cannot run program "c:\windows\system\curl": CreateProcess error=2, The system cannot find the file specified

Which is odd since thought I fixed that error…and now that I take a look it’s actually system 32 that I stuck it in.
Oops.

Running it now w/ system 32 I’m not getting that error, but also nothing is happening on the TV side. I have confirmed that these commands work via commandline, and if I could get what the TV is returning from this, I could probably figure out how to fix it. Do you know a good way to grab the return from a specific IP:port? Usually when I run it via commandline I get a bit of JSON back.

Try this…

var ipb1 = "10.47.0.242"
var port = "7345"
var authb1 = "Zhgigzcjdr"
var powerOn = "{\\\"KEYLIST\\\":[{\\\"CODESET\\\":11,\\\"CODE\\\":1,\\\"ACTION\\\":\\\"KEYPRESS\\\"}]}"
var powerOff = "{\\\"KEYLIST\\\":[{\\\"CODESET\\\":11,\\\"CODE\\\":0,\\\"ACTION\\\":\\\"KEYPRESS\\\"}]}"

rule "TV B 1"
when
	Item Power_TV_B_1 received command 
then
    var String result
    switch(receivedCommand) {
        case ON : result = executeCommandLine("c:\\windows\\system32\\curl.exe -k -H \"Content-Type: application/json\" -H \"AUTH: " + authb1 + "\" -X PUT -d \"" + powerOn + "\" http://" + ipb1 + ":" + port + "/key_command/",5000)
        case OFF : result = executeCommandLine("c:\\windows\\system32\\curl.exe -k -H \"Content-Type: application/json\" -H \"AUTH: " + authb1 + "\" -X PUT -d \"" + powerOff + "\" http://" + ipb1 + ":" + port + "/key_command/",5000)
    }
    logInfo("power.rules","result=[{}]",result)
end
1 Like

Thanks for the suggestion!

I’ve been trying to run it all day, but I’m currently stuck since we moved over to a Raspberry PI, and I can’t seem to save my rules in HABmin, so if any of you know a better way to place in my code to the PI aside from HABmin, or if you know what I can do to resolve HABmin not letting me save my code, let me know. So far I can’t find anything online about HABmin acting this way, so any pointers would be much appreciated.

If you’re curious; the exact issue is that when I paste my code in Source then hit save, nothing happens. When I add in a new rule, it posts a new line, but it won’t let me rename any of the rules like it does normally. Then when I refresh to check to see that they are still there, they are gone. OpenHABian is as up to date as it can be, the configuration went through perfectly.

I’m about at the end of my rope here so anything you folks can do to help would be amazing. Thanks!

I recommend (again :wink:) to setup VS Code. TMK, openHABian has samba shares enabled by default. If not, they can be enabled. The nuse VS Code to create and edit your rules.

Oh, sorry must have skipped over it in my rush.

Anyways I tried to install the VS Code on the PI but I couldn’t quite get Samba to run, so I ended up using vim to write directly to the Pi. Interestingly enough it actually has a half-way decent code-parsing interface with vim, although it doesn’t like string literals very much. Nevertheless, your code is running great! All I need to do now is figure out why the TV doesn’t like my command BUT it is sending properly! Thanks so much for all your help!

EDIT: Tho I am noticing that I’m not getting anything with the results printout via Karaf, could it be that it’s returning JSON?

VS Code shouldn’t be installed on the Pi, but your computer. And Samba is already setup on openHABian.

I’m not sure what you mean by this. Are you not seeing logging? It will go into the openhab.log. You can tail it from Karaf.

I figured it out!

When going back and verifying the code, I realized that I had neglected to give executeCommandLine() a timeout parameter, meaning it had 0 milliseconds to return a value. Guess I didn’t scroll right far enough when reading over your code. Would have been solved by copy-pasting in your code, but I’m new to Linux and so my handle on vim is lacking.

As for Samba and VS Code, I did see that they come pre-installed with the OpenHABian image, but like I said my Linux knowledge is lacking and I couldn’t find where I actually used them, but I managed to do without it, so it’ll be something to look into next time I come back to OpenHAB.

However, I did end up not using a curl command through executeCommandLine() as it was just not having it. So I ended up making a shell script and passing arguments to it via executeCommandLine(). It’s amazing how much simpler things get when you break it down to lower level languages.

It ended up looking something like this:

var ipb1 = "10.47.0.242"
var authb1 = "Zhgigzcjdr"
var powerOn = "{\\\"KEYLIST\\\":[{\\\"CODESET\\\":11,\\\"CODE\\\":1,\\\"ACTION\\\":\\\"KEYPRESS\\\"}]}"
var powerOff = "{\\\"KEYLIST\\\":[{\\\"CODESET\\\":11,\\\"CODE\\\":0,\\\"ACTION\\\":\\\"KEYPRESS\\\"}]}"

rule "TV B 1"
when
	Item Power_TV_B_1 received command 
then
    var String result
    switch(receivedCommand) {
        case ON : result = executeCommandLine("usr/openhabian/powerCall.sh@@" + ipb1 + "@@" + authb1 + "@@" + powerOn,5000)
        case OFF : result = executeCommandLine("usr/openhabian/powerCall.sh@@" + ipb1 + "@@" + authb1 + "@@" + powerOff,5000)
    }
    logInfo("power.rules","Result : ",result)
end

…with powerCall.sh being a simple curl call with some file-write commands using commandline-passed parameters.