Help needed: HTTP binding, JSON and basic authentification for CCU825 controller

Dear all,

I tried to bind the following:
CCU825_State.url=https://ccu.sh:8080/data.cgx?cmd=%7b“Command”:“GetStateAndEvents”%7d{BAuthorization=Basic bG9naW46cGFzcw=}

In logs:

18:24:19.939 [ERROR] [ab.core.service.AbstractActiveService] - Error while executing background thread HTTP Refresh Service
java.lang.IllegalArgumentException: Invalid uri 'https://ccu.sh:8080/data.cgx?cmd=%7b“Command”:“GetStateAndEvents”%7d': Invalid query
        at org.apache.commons.httpclient.HttpMethodBase.<init>(HttpMethodBase.java:222) ~[195:org.apache.servicemix.bundles.commons-httpclient:3.1.0.7]
        at org.apache.commons.httpclient.methods.GetMethod.<init>(GetMethod.java:89) ~[195:org.apache.servicemix.bundles.commons-httpclient:3.1.0.7]
        at org.openhab.io.net.http.HttpUtil.createHttpMethod(HttpUtil.java:314) ~[196:org.openhab.core.compat1x:2.4.0]
        at org.openhab.io.net.http.HttpUtil.executeUrl(HttpUtil.java:167) ~[196:org.openhab.core.compat1x:2.4.0]
        at org.openhab.io.net.http.HttpUtil.executeUrl(HttpUtil.java:130) ~[196:org.openhab.core.compat1x:2.4.0]
        at org.openhab.binding.http.internal.HttpBinding.getCacheData(HttpBinding.java:423) ~[?:?]
        at org.openhab.binding.http.internal.HttpBinding.execute(HttpBinding.java:169) ~[?:?]
        at org.openhab.core.binding.AbstractActiveBinding$BindingActiveService.execute(AbstractActiveBinding.java:144) ~[196:org.openhab.core.compat1x:2.4.0]
        at org.openhab.core.service.AbstractActiveService$RefreshThread.run(AbstractActiveService.java:166) [196:org.openhab.core.compat1x:2.4.0]

You’re still using illegal characters in your URL.

This provides some help, including links to the RFCs (formal specifications).

Dear all,

I reworked my code. Now I got:
In Items:
Number CCUPowerVoltage <energy> String CCU_JSON
In Rules
rule "CCU825_StateRead" when Time cron "0 0/5 * 1/1 * ? *" then CCU825_JSON=sendHttpPutRequest("https://ccu.sh:443/data.cgx?cmd=%7bBAuthorization=Basic%20BASE64LOGINPASS%7d","text/plain","%7B%22Command%22%3A%20%22GetStateAndEvents%22%7D") end

In log I am getting the following every 5 mins:

12:05:00.353 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'CCU825_StateRead': An error occurred during the script execution: Couldn't invoke 'assignValueTo' for feature JvmVoid: (eProxyURI: default.rules#|::0.2.0.2.0.0::0::/1)

It does not change if I use 8080 or 443 ports. I also changed “text/plain” with “application/json”- no difference. What does this error message means? Does the sendHttpPutRequest() works?

How is CCU825_JSON declared? Is it a global variable? It needs to be declared as var String CCU825_JSON.

It is just mentioned in the items file as I wrote. I added “var” to the rules file before “CCU825_JSON” and currently log has changed to:

17:15:00.442 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule "CCU825_StateRead": json string can not be null or empty

This probably means that request returns nothing. Correct? Is it possible to make sure that request was accepted by server ccu.sh?

But you didn’t mention it in your .items file. You have CCUPowerVoltage and CCU_JSON in your .items file, not CCU825_JSON.

The error is what is being returned from ccu.sh. Looking at your call in the Rule shows you need to escape the double quotes in the content you pass in the PUT.

"{\“Command\”%3A%20\"GetStateAndEvents\"}”

NOTE, please follow How to use code fences

Now it looks like:

rule "CCU825_StateRead"
    when
	Time cron "0 0/5 * 1/1 * ? *"`
    then
	var CCU825_JSON=sendHttpPutRequest("https://ccu.sh:443/data.cgx?cmd=%7bBAuthorization=Basic%20Base64LoginAndPass=%7d","text/plain","%7B%5CCommand%5C%3A%5C%22GetStateAndEvents%5C%22%7D")
	CCUPowerVoltage=transform("JSONPATH", "$.Power", CCU825_JSON)
end

But in logs I got:

18:15:00.442 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'CCU825_StateRead': json string can not be null or empty

Don’t use URL encoding on the contents. Use the string just like I have above.

rule "CCU825_StateRead"
    when
	Time cron "0 0/5 * 1/1 * ? *"
    then
	var CCU825_JSON=sendHttpPutRequest("https://ccu.sh:8080/data.cgx?cmd=%7bBAuthorization=Basic%20Base64LoginAndPass%7d","application/json","{\“Command\”%3A%20\"GetStateAndEvents\"}”)
	CCUPowerVoltage=transform("JSONPATH", "$.Power", CCU825_JSON)
end

In logs:

18:27:01.941 [WARN ] [del.core.internal.ModelRepositoryImpl] - Configuration model 'default.rules' has errors, therefore ignoring it: [5,167]: Invalid escape sequence (valid ones are  \b  \t  \n  \f  \r  \"  \'  \\ )
[6,29]: missing ')' at 'JSONPATH'
[6,48]: String literal is not properly closed

That’s weird. When I quote it in the forum it strips off the escapes but only on the last two quotes.

Anyway, try it without using URL encoding for the colon.

Remember, this is data we are passing in the body of the HTTP request. URL encoding is only for use when passing data in the URL.

Also, you have a mix of proper " " and fancy “ ”. The fancy ones are not allowed.

rule "CCU825_StateRead"
    when
	Time cron "0 0/5 * 1/1 * ? *"
    then
	var CCU825_JSON=sendHttpPutRequest("https://ccu.sh:443/data.cgx?cmd=%7bBAuthorization=Basic%20Base64LoginPass%7d","application/json","{\"Command\":\"GetStateAndEvents\"}")
	CCUPowerVoltage=transform("JSONPATH", "$.Power", CCU825_JSON)
end

If I use port 443 I see the following in logs:

19:45:00.346 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'CCU825_StateRead': json string can not be null or empty

In case of 8080:

19:35:01.008 [ERROR] [e.smarthome.model.script.actions.HTTP] - Fatal transport error: java.util.concurrent.TimeoutException: Total timeout 1000 ms elapsed
19:35:01.009 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'CCU825_StateRead': An error occurred during the script execution: Cannot assign a value in null context.

Why don’t you log out what get’s returned.

Also, you can’t just set an Item using =. You must call postUpdate or sendCommand.

I don’t know how to log out get’s output. I know how to look through openhab console logs using log:display.

I tried the code:

rule "CCU825_StateRead"
    when
       Time cron "0 0/2 * 1/1 * ? *"
    then
       var CCU825_JSON=sendHttpGetRequest("https://ccu.sh/data.cgx%7BAuthorization=Basic%20LOGINPASS%7D?cmd%3D%7B%22Command%22%3A%22GetStateAndEvents%22%7D")
       logInfo("State Read", "CCU825_JSON: " + CCU825_JSON)
       if (CCU825_JSON !== null ) { CCUPowerVoltage.sendCommand(transform("JSONPATH", "$.Power", CCU825_JSON)) }
end

and getting logs:

17:46:00.206 [INFO ] [pse.smarthome.model.script.State Read] - CCU825_JSON:
17:46:00.207 [ERROR] [untime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'CCU825_StateRead': json string can not be null or empty

So the request returns null. It seems that IF does not work because error comes from transform().
I saw PHP examples of the similar functionality for CCU825, they work with simple URL including request string. Separately headers are formed for authorisation. But here I have to put auth string into URL. Working PHP code:

function http_auth_get($url,$username,$password){
	$cred = sprintf('Authorization: Basic %s',
	base64_encode("$username:$password"));
	$opts = array('http'=>array('method'=>'GET','header'=>$cred));
	$ctx = stream_context_create($opts);
	$handle = fopen ( $url, 'r', false,$ctx);
 
	return stream_get_contents($handle);
}
 
$json = http_auth_get('https://ccu.sh/data.cgx?cmd={"Command":"GetStateAndEvents"}',$jsonUser,$jsonPass);

I tried to form POST request URL with the same result.
What the heck is this does not work?

One difference I Seder if the php coffee is paying a username and password using basic auth and your Rule is not.

My rule uses base64 coding for login:pass pair. Did you mean that the form I use the basic auth is not correct?

I also easily did connection to the site using 2 lines of Python code. So my belief is that OpenHAB requires further development to provide useful functionality.

Typically basic auth takes the form of

Https://username:password@url

as soon as my login contains “@” simbol it should be base64 coded and sent in header. Correct? It does not work.