JRuby OpenHAB Rules System

So, I finally got Ruby LSP and Rubocop working. How? Well… I dipped the Windows way and went the Linux way. :wink:

The only question I have: Where do I place the .rubocop.yml file? According to https://docs.rubocop.org/rubocop/configuration.html#config-file-locations it can be placed anywhere inside the project. What is meant by project in this case? My rules are in /etc/openhab/automation/jsr223
and some helper libs in
/etc/openhab/automation/ruby/lib

Does it mean I can place the file inside /etc/openhab/automation and it gets used? How do I know it is getting used?

Put .rubocop.yml in automation/ruby and move your rules there too, out of jsr223.

1 Like

Sorry there ist still an error:

16:18:59.097 [ERROR] [automation.jrubyscripting.rule.test:6] - no method ‘sendHttpPostRequest’ for arguments (org.jruby.RubyString,org.jruby.RubyString,org.jruby.RubyHash,org.jruby.RubyHash,org.jruby.RubyFixnum) on Java::OrgOpenhabCoreModelScriptActions::HTTP (NameError)
/etc/openhab/automation/jsr223/ruby/test.rb:15:in `block in ’

I tried also with

content = "data=#{data.to_json}"

Same error occured.

Seems like a problem with the headers?

My bad again!

The line should be this:

HTTP.send_http_post_request("http://192.168.XXX.YYY/api/power/config", content_type, content, headers: headers, timeout: 5.seconds)

i.e. I should’ve used content as the argument, not data! Sorry I missed that.

You should still try it as content = data.to_json first.

1 Like

Fantastic! I’m impressed by your knowledge and the way you give explanaitions!
Your support here was one major reason I started to change my rules to ruby. :slight_smile:

For others facing the same problems:

To successful excute the POST request I had to change the content type to:

content_type = "application/x-www-form-urlencoded"

Now I’m able to control my Hoymiles HMT-2250 converters with the web API that is offered by openDTU.

1 Like

I’m glad you’re enjoying Ruby so far!

the HTTP.send_http_post_request is a helper method provided by openhab core. This means it’s available from other languages, e.g. rulesdsl, jsscripting etc. However, it’s pretty spartan.

There are other ways of doing HTTP requests in Ruby that may be more convenient / powerful. For example, all Ruby flavours, including JRuby, are bundled with Net::HTTP module by default.

Here’s how you would use it for your use case:

require "net/http"
require "json"

converter_id = "123456789"
data = { serial: converter_id, power: 0 }
content = { data: data.to_json }

uri = URI("http://192.168.XXX.YYY/api/power/config")
uri.user = "USERNAME"
uri.password = "PASSWORD"

Net::HTTP.post_form(uri, content)

In this form:

  • You don’t need to manually construct the Authorization header nor deal with base64 encoding. It’s done for you.
  • You don’t need to specify content-type manually. It will be set to Content-Type: application/x-www-form-urlencoded in the above code

IMO, this is much easier and simpler than using HTTP.send_http_post_request

There are other HTTP libraries (gems) that you can use in Ruby, if Net::HTTP isn’t to your liking: Faraday, httparty, etc. however, they require you to install the corresponding gem. Installing additional gems is very easy to do too.

Also, if the data, url, user/pass are always the same, you could move them out of the rule and create them as constants

e.g.

require "net/http"
require "json"

CONVERTER_ID = "123456789"
CONTENT = {
  data: { serial: CONVERTER_ID, power: 0 }.to_json
}

POWER_CONFIG_URI = URI("http://192.168.XXX.YYY/api/power/config")
POWER_CONFIG_URI.user = "USERNAME"
POWER_CONFIG_URI.password = "PASSWORD"

rule "Testrule" do
  received_command TestSwitch
  run do
    Net::HTTP.post_form(POWER_CONFIG_URI, CONTENT)
  end
end
1 Like

I like it very much. So easy and so many possibilities compared to building DSL-Rules.

I also like the way to use Net::HTTP now. Easier and simpler to read as you said.

Thank you very much for your afffort.

Hey hey,

according to JRuby Scripting - Automation | openHAB one can use the following trigger mechanism:

rule "cancel all timers" do
  received_command Cancel_All_Timers, to: ON # Send a command to this item to cancel all timers

but when I try to copy this like that

rule "Jalousien: Kinderzimmer mit Knopf hochfahren" do
  received_command Schalter_Wohnzimmer, to: "1004"
  run do
(...)

I receive this error

Error during evaluation of script '/etc/openhab/automation/ruby/jalousien.rb': Error during evaluation of Ruby in /etc/openhab/automation/ruby/.gem/9.4.5.0/gems/openhab-scripting-5.17.0/lib/openhab/dsl/rules/builder.rb at line 1464: (ArgumentError) unknown keyword: :to

Any idea?

It looks like that example is wrong. The docs for that method are correct. The parameter is named command, not to.

Thanks, that makes absolutely more sense!

Just wanted to thank again for the Rubocop support. It is such a game changer when writing rules, wow!

1 Like