Import and use HttpUtil directly in rule

Hello,
I want to do a HTTP POST request from a rule.
The well documented way is to use the sendHttpPostRequest() action.
The problem is, that I want to catch exceptions from it and sendHttpPostRequest() does not propagate the exceptions up.

So I found that it internally uses HttpUtil.executeUrl("POST", ... so I should be able to use it directly.
However it seems that I am not able to import HttpUtil class for some reason.
I have found https://github.com/openhab/openhab-core/blob/master/bundles/org.openhab.core.compat1x/src/main/java/org/openhab/io/net/http/HttpUtil.java with package name org.openhab.io.net.http.

But I am still getting: The name 'HttpUtil' cannot be resolved to an item or type;

My rule:

import org.openhab.io.net.http.HttpUtil

val String host = "http://192.168.25.124"
val int timeout = 1000

rule "BedroomTv-Power"
when
	Time cron "* * * ? * * *"
then
	var status = "";
	try {
		var result = HttpUtil.executeUrl("POST", host + "/sony/system", "application/json", '{"method": "getPowerStatus","id": 50,"params": [],"version": "1.0"}', timeout);
		status = transform("JSONPATH", "$.result[0].status", result);
	} catch (Exception e) {
	}
	if (status == "active") {
		danik_bedroomTV__power.postUpdate("ON");
	} else {
		danik_bedroomTV__power.postUpdate("OFF");
	}
end

Any ideas how should I import it? Or make a HTTP post and silent-fail all exceptions?
Many thanks :wink:

  • sendHttpPostRequest(String url) : Sends a POST-HTTP request and returns the result as a String
  • sendHttpPostRequest(String url, String contentType, String content) : Sends a POST-HTTP request with the given content and returns the result as a String

I know. But if anything bad happens there is no way to catch the exception - it goes directly to logs. I am trying to suppress any errors.

I am trying to go around this line: https://github.com/eclipse/smarthome/blob/master/bundles/model/org.eclipse.smarthome.model.script/src/org/eclipse/smarthome/model/script/actions/HTTP.java#L178

OAuth2 using just OH Rules and myopenhab.org shows how to do http calls with the native Java classes. I don’t think all of the OH classes are available in the Rules.

1 Like

Okay, the Exception part I have probably read over.

A workaround could be a bash script. There you have all possibilities.

You want really every Second check your BedroomTV ?

Sure, why not? :wink:
The API of the TV is fast (response under 10 ms) and network is hard-wired so bandwidth is not an issue.
Btw: I also running Icinga instance that is checking all home devices every second :smiling_imp:

I will try to use the pure Java http method, but its kind of paint that we cant include the HttpUtil…

Then it would be better to send a message from Icinga to openHAB if the status is changed, than pulling a message each Second from openHAB via rule.

Please keep in mind, that openHAB has (per default) only two threads for the scheduler, so if using more than one rule with such frequent triggers, it’s very likely to make openHAB working unreliable.
openHAB is event driven, it’s possible, but not recommended to pull messages through rules.

Interesting idea.
Is there any recommended solution for offloading these pooling tasks from OpenHab?
Icinga is great for monitoring but I’m not sure if its the best solution for this task.

Thanks everybody - I got it working.
Result:

import java.net.URL
import java.net.HttpURLConnection
import java.io.BufferedInputStream
import java.io.BufferedReader
import java.io.InputStreamReader
import org.eclipse.xtext.xbase.lib.Functions

val String host = "http://192.168.25.124"
val int timeout = 1000

val Functions$Function2<String, String, String> httpPost = [ url, json |
  val endpointUrl = new URL(url)
  val HttpURLConnection connection = endpointUrl.openConnection() as HttpURLConnection
  connection.setConnectTimeout(500)

  connection.requestMethod = "POST"
  connection.setRequestProperty('content-type', 'application/json')
  connection.setRequestProperty('cache-control', 'no-cache')
  connection.doOutput = true
  connection.setDoInput = true

  connection.outputStream.write(json.getBytes("UTF-8"))

  if (connection.responseCode != 200) {
    logInfo("BedroomTv", "Response code: " + connection.responseCode)
  }

  val StringBuffer sb = new StringBuffer()
  val BufferedReader br = new BufferedReader(new InputStreamReader(new BufferedInputStream(connection.getInputStream())))
  var String inputLine = ""
  while ((inputLine = br.readLine()) !== null) {
    sb.append(inputLine)
  }
  return sb.toString
]

rule "BedroomTv-Power"
when
	Time cron "* * * ? * * *"
then
	var status = "";
	try {
		var result = httpPost.apply(host + "/sony/system", '{"method": "getPowerStatus","id": 50,"params": [],"version": "1.0"}');
		status = transform("JSONPATH", "$.result[0].status", result);
	} catch (Exception e) {
	}
	if (status == "active") {
		danik_bedroomTV__power.postUpdate("ON");
	} else {
		danik_bedroomTV__power.postUpdate("OFF");
	}
end

The overall system load does not seems to be affected by this (on the Raspi side - not sure about the TV), but I am not sure how it will work if I add few more checks like this…

I am doing this only as temporary solution until https://github.com/openhab/openhab2-addons/pull/1249 gets finished and merged.

Did you see that this conversation is stalled since Febuary-01?

The discussion about the Sony binding seems to live here Sony Devices Binding - so I am still full of hopes :wink:

Ah :slight_smile: I cross my fingers :wink:

1 Like