]> git.basschouten.com Git - openhab-addons.git/commitdiff
[jrubyscripting] Update README.md (#15624)
authorjimtng <2554958+jimtng@users.noreply.github.com>
Sun, 1 Oct 2023 14:01:13 +0000 (00:01 +1000)
committerGitHub <noreply@github.com>
Sun, 1 Oct 2023 14:01:13 +0000 (16:01 +0200)
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
bundles/org.openhab.automation.jrubyscripting/README.md

index 39686cb12bd631f8c6d1610dda147a15fd2b0489..e6b1145b65edfbf1cb2efa256a5e2184f72d4c22 100644 (file)
@@ -38,6 +38,7 @@ If you're new to Ruby, you may want to check out [Ruby Basics](https://openhab.g
   - [Shared Code](#shared-code)
   - [Transformations](#transformations)
   - [Profile](#profile)
+  - [Sitemaps](#sitemaps)
 - [File Based Rules](#file-based-rules)
   - [Basic Rule Structure](#basic-rule-structure)
   - [Rule Triggers](#rule-triggers)
@@ -61,6 +62,7 @@ If you're new to Ruby, you may want to check out [Ruby Basics](https://openhab.g
   - [Dynamic Generation of Rules](#dynamic-generation-of-rules)
   - [Hooks](#hooks)
 - [Calling Java From JRuby](#calling-java-from-jruby)
+- [Full Documentation](#full-documentation)
 
 Additional [example rules are available](https://openhab.github.io/openhab-jruby/main/file.examples.html), as well as examples of [conversions from DSL and Python rules](https://openhab.github.io/openhab-jruby/main/file.conversions.html).
 
@@ -79,7 +81,7 @@ Additional [example rules are available](https://openhab.github.io/openhab-jruby
 - Abstract away complexities of openHAB
 - Enable all the power of Ruby and openHAB
 - Create a Frictionless experience for building automation
-- The common, yet tricky tasks are abstracted and made easy. e.g. creating a timer that automatically reschedules itself.
+- The common, yet tricky tasks are abstracted and made easy, e.g. creating a timer that automatically reschedules itself.
 - Tested
   - Designed and tested using [Test-Driven Development](https://en.wikipedia.org/wiki/Test-driven_development) with [RSpec](https://rspec.info/)
 - Extensible.
@@ -95,8 +97,7 @@ Additional [example rules are available](https://openhab.github.io/openhab-jruby
 
 ### From the User Interface
 
-1. Go to `Settings -> Add-ons -> Automation` and install the jrubyscripting automation addon
-   following the [openHAB instructions](https://www.openhab.org/docs/configuration/addons.html).
+1. Go to `Settings -> Add-ons -> Automation` and install the jrubyscripting automation addon following the [openHAB instructions](https://www.openhab.org/docs/configuration/addons.html).
    In openHAB 4.0+ the defaults are set so the next step can be skipped.
 1. Go to `Settings -> Other Services -> JRuby Scripting`:
    - **Ruby Gems**: `openhab-scripting=~>5.0`
@@ -104,8 +105,7 @@ Additional [example rules are available](https://openhab.github.io/openhab-jruby
 
 ### Using Files
 
-1. Edit `<OPENHAB_CONF>/services/addons.cfg` and ensure that `jrubyscripting` is included in
-   an uncommented `automation=` list of automations to install.
+1. Edit `<OPENHAB_CONF>/services/addons.cfg` and ensure that `jrubyscripting` is included in an uncommented `automation=` list of automations to install.
    In openHAB 4.0+ the defaults are set so the next step can be skipped.
 1. Configure JRuby openHAB services
 
@@ -146,20 +146,18 @@ org.openhab.automation.jrubyscripting:require=openhab/dsl
 
 ### gem_home
 
-Path to where Ruby Gems will be installed to and loaded from. The directory will be created if necessary.
-You can use `RUBY_ENGINE_VERSION`, `RUBY_ENGINE` and/or `RUBY_VERSION` replacements in this value
-to automatically point to a new directory when the addon is updated with a new version of JRuby.
+Path to where Ruby Gems will be installed to and loaded from.
+The directory will be created if necessary.
+You can use `RUBY_ENGINE_VERSION`, `RUBY_ENGINE` and/or `RUBY_VERSION` replacements in this value to automatically point to a new directory when the addon is updated with a new version of JRuby.
 
 ### gems
 
 A comma separated list of [Ruby Gems](https://rubygems.org/) to install.
 
 The default installs the version of the helper for this version of openHAB.
-When overriding the default, be sure to still include the `openhab-scripting` gem in the
-list of gems to install.
+When overriding the default, be sure to still include the `openhab-scripting` gem in the list of gems to install.
 
-Each gem can have version specifiers which uses
-[pessimistic versioning](https://thoughtbot.com/blog/rubys-pessimistic-operator).
+Each gem can have version specifiers which uses [pessimistic versioning](https://thoughtbot.com/blog/rubys-pessimistic-operator).
 Multiple version specifiers can be added by separating them with a semicolon.
 
 Examples:
@@ -175,8 +173,7 @@ Examples:
 ### check_update
 
 Check RubyGems for updates to the above gems when openHAB starts or JRuby settings are changed.
-Otherwise it will try to fulfil the requirements with locally installed gems, and you can manage them yourself
-with an external Ruby by setting the same GEM_HOME.
+Otherwise it will try to fulfil the requirements with locally installed gems, and you can manage them yourself with an external Ruby by setting the same GEM_HOME.
 
 ### require
 
@@ -185,13 +182,13 @@ The default is to require the helper library.
 
 ### rubylib
 
-Search path for user libraries. Separate each path with a colon (semicolon in Windows).
+Search path for user libraries.
+Separate each path with a colon (semicolon in Windows).
 
 ### dependency_tracking
 
 Dependency tracking allows your scripts to automatically reload when one of its dependencies is updated.
-You may want to disable dependency tracking if you plan on editing or updating a shared library,
-but don't want all your scripts to reload until you can test it.
+You may want to disable dependency tracking if you plan on editing or updating a shared library, but don't want all your scripts to reload until you can test it.
 
 ### local_context
 
@@ -201,7 +198,8 @@ See [this](https://github.com/jruby/jruby/wiki/RedBridge#context-instance-type)
 
 ### local_variables
 
-Defines how variables are shared between Ruby and Java. Valid values are: `transient`, `persistent`, or `global`.
+Defines how variables are shared between Ruby and Java.
+Valid values are: `transient`, `persistent`, or `global`.
 See the [JRuby documentation](https://github.com/jruby/jruby/wiki/RedBridge#local-variable-behavior-options) for options and details.
 
 ## Usage
@@ -210,8 +208,7 @@ See the [JRuby documentation](https://github.com/jruby/jruby/wiki/RedBridge#loca
 
 The quickest way to add rules is through the openHAB Web UI.
 
-Advanced users, or users migrating scripts from existing systems may want to use
-[File Based Scripts](#file-based-scripts) for managing rules using files in the user configuration directory.
+Advanced users, or users migrating scripts from existing systems may want to use [File Based Scripts](#file-based-scripts) for managing rules using files in the user configuration directory.
 
 #### Adding Triggers
 
@@ -262,7 +259,8 @@ See [File Based Rules](#file-based-rules) for examples of creating rules within
 
 When you use "Item event" as trigger (i.e. "[item] received a command", "[item] was updated", "[item] changed"), there is additional context available for the action in a variable called `event`.
 
-This tables gives an overview of the `event` object for most common trigger types. For full details, explore [OpenHAB::Core::Events](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Events.html).
+This tables gives an overview of the `event` object for most common trigger types.
+For full details, explore [OpenHAB::Core::Events](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Events.html).
 
 | Property Name | Type                                                                                         | Trigger Types                          | Description                                          | Rules DSL Equivalent   |
 | ------------- | -------------------------------------------------------------------------------------------- | -------------------------------------- | ---------------------------------------------------- | ---------------------- |
@@ -542,9 +540,7 @@ See [unit block](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL.html#u
 
 ##### Range checking
 
-Types that are comparable, such as [StringType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/StringType.html), [DateTimeType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/DateTimeType.html), [DecimalType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/DecimalType.html), [PercentType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/PercentType.html),
-include Ruby's [Comparable](https://docs.ruby-lang.org/en/master/Comparable.html) module which provides
-the handy [between?](https://docs.ruby-lang.org/en/master/Comparable.html#method-i-between-3F) method.
+Types that are comparable, such as [StringType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/StringType.html), [DateTimeType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/DateTimeType.html), [DecimalType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/DecimalType.html), [PercentType](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Types/PercentType.html), include Ruby's [Comparable](https://docs.ruby-lang.org/en/master/Comparable.html) module which provides the handy [between?](https://docs.ruby-lang.org/en/master/Comparable.html#method-i-between-3F) method.
 
 ```ruby
 String_Item.update("Freddy")
@@ -559,8 +555,8 @@ Temperature_Item.update(16 | "°C")
 Temperature_Item.state.between?(20 | "°C", 24 | "°C") # => false
 ```
 
-Alternatively, a Ruby [range](https://docs.ruby-lang.org/en/master/Range.html) can be used. This can be
-handy for excluding the end of the range with the `...` operator.
+Alternatively, a Ruby [range](https://docs.ruby-lang.org/en/master/Range.html) can be used.
+This can be handy for excluding the end of the range with the `...` operator.
 
 ```ruby
 if (5..10).cover?(Number_Item.state)
@@ -708,6 +704,23 @@ thing.enable
 logger.info "TV enabled: #{thing.enabled?}"
 ```
 
+Get Thing's configurations:
+
+```ruby
+server = things["smtp:mail:local"].configuration["hostname"]
+logger.info "Configured SMTP Server: #{server}"
+
+frontporch_cam_ip = things["ipcamera:dahua:frontporch"].configuration["ipAddress"]
+logger.info "Front Porch Camera's IP Address: #{frontporch_cam_ip}"
+```
+
+Get Thing's property:
+
+```ruby
+model_id = things["fronius:meter:mybridge:mymeter"].properties["modelId"]
+logger.info "Fronius Smart Meter model: #{model_id}"
+```
+
 ### Actions
 
 [openHAB built-in actions](https://www.openhab.org/docs/configuration/actions.html) are available as children of the [Actions](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Actions.html) module.
@@ -740,14 +753,15 @@ Exec.execute_command_line('/path/to/program')
 
 ### Logging
 
-The JRuby Scripting addon has a global `logger` object for logging. To log a message on `INFO` log level:
+The JRuby Scripting addon has a global `logger` object for logging.
+To log a message on `INFO` log level:
 
 ```ruby
 logger.info("The current time is #{Time.now}")
 ```
 
 The default logger name for UI rules is `org.openhab.automation.jrubyscripting.script`.
-For file-based rules, it's based on the rule's ID, such as `org.openhab.automation.jrubyscripting.rule.myrule.rb:15`
+For file-based rules, it's based on the rule's ID, such as `org.openhab.automation.jrubyscripting.rule.myrule.rb:15`.
 
 To use a custom logger name:
 
@@ -780,7 +794,9 @@ sleep 1.5 # sleep for 1.5 seconds
 
 See Ruby docs on [sleep](https://docs.ruby-lang.org/en/master/Kernel.html#method-i-sleep).
 
-`sleep` should be avoided if possible. A [delay](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL/Rules/BuilderDSL.html#delay-instance_method) can be inserted in between two execution blocks to achieve the same result. This delay is implemented with a timer.
+`sleep` should be avoided if possible.
+A [delay](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL/Rules/BuilderDSL.html#delay-instance_method) can be inserted in between two execution blocks to achieve the same result.
+This delay is implemented with a timer.
 This is available only on file-based rules.
 
 ```ruby
@@ -850,7 +866,7 @@ It can be rescheduled to a different duration
 ```ruby
 after(3.minutes) do |timer|
   My_Light.on
-  my_timer.reschedule(1.minute)
+  timer.reschedule(1.minute)
 end
 ```
 
@@ -922,22 +938,22 @@ Just be wary of Ruby-only data types (such as Symbols) that won't be accessible
 Get a previously set object with a default value:
 
 ```ruby
-counter_object = shared_cache.compute_if_absent(:counter) { { "times" => 0 } }
-logger.info("Count: #{counter_object["times"] += 1}")"
+shared_cache.compute_if_absent(:counter) { 0 } # Initialize with 0 if it didn't exist
+logger.info("Count: #{shared_cache[:counter] += 1}")
 ```
 
 Get a previously set object, or assign it (this version is subject to race conditions with other scripts):
 
 ```ruby
-counter_object = shared_cache[:counter] ||= { "times" => 0 }
-logger.info("Count: #{counter_object["times"] += 1}")"
+shared_cache[:counter] ||= 0
+logger.info("Count: #{shared_cache[:counter] += 1}")
 ```
 
-Get a previously set object with a default value, without assigning it (this version has an even longer amount of time between fetchig the value and assigning it):
+Get a previously set object with a default value, without assigning it (this version has an even longer amount of time between fetching the value and assigning it):
 
 ```ruby
-count = shared_count.fetch(:counter) { 0 }
-shared_count[:counter] = count + 1
+count = shared_cache.fetch(:counter) { 0 }
+shared_cache[:counter] = count + 1
 ```
 
 ### Time
@@ -1140,20 +1156,19 @@ Date.today.in_dayset?(:school) # => false
 
 ### Rules, Scripts, and Scenes
 
-[Rules](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Rule.html), Scenes and Scripts can be accessed using the
-[rules](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Registry.html) object. For example, to execute/trigger a rule:
+[Rules](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Rule.html), Scenes and Scripts can be accessed using the [rules](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Registry.html) object.
+For example, to execute/trigger a rule:
 
 ```ruby
 rules[rule_uid].trigger
 ```
 
-Scenes are rules with a `Scene` tag, and Scripts are rules with a `Script` tag. They can be found
-using their uid just like normal rules, i.e. `rules[uid]`. For convenience, a list of all Scenes are
-available through the enumerable [rules.scenes](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Registry.html#scenes-instance_method),
-and a list of all Scripts through [rules.scripts](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Registry.html#scripts-instance_method).
+Scenes are rules with a `Scene` tag, and Scripts are rules with a `Script` tag.
+They can be found using their uid just like normal rules, i.e. `rules[uid]`.
+For convenience, a list of all Scenes are available through the enumerable [rules.scenes](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Registry.html#scenes-instance_method), and a list of all Scripts through [rules.scripts](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Rules/Registry.html#scripts-instance_method).
 
-Example: All scenes tagged `sunrise` will be triggered at sunrise, and all scenes tagged
-`sunset` will be triggered at sunset. Note: these use the [Terse Rule](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL/Rules/Terse.html) syntax.
+Example: All scenes tagged `sunrise` will be triggered at sunrise, and all scenes tagged `sunset` will be triggered at sunset.
+Note: these use the [Terse Rule](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL/Rules/Terse.html) syntax.
 
 ```ruby
 channel("astro:sun:home:rise#event") { rules.scenes.tagged("sunrise").each(&:trigger) }
@@ -1210,9 +1225,32 @@ rules[rule_uid].enable
 rules[rule_uid].disable
 ```
 
+#### Passing Values to Rules
+
+A rule/script may be given additional context/data by the caller.
+This additional data is available within the rule by referring to the names of the context variable.
+This is applicable to both UI rules and file-based rules.
+
+Within the script/rule body (either UI or file rule)
+
+```ruby
+script id: "check_temp" do
+  if CPU_Temperature.state > maxTemperature
+    logger.warn "The CPU is overheating!"
+  end
+end
+```
+
+The above script can be executed, passing it the `maxTemperature` argument from any supported scripting language, e.g.:
+
+```ruby
+rules["check_temp"].trigger(maxTemperature: 80 | "°C")
+```
+
 ### Gems
 
-[Bundler](https://bundler.io/) is integrated, enabling any [Ruby gem](https://rubygems.org/) compatible with JRuby to be used within rules. This permits easy access to the vast ecosystem of libraries within the Ruby community.
+[Bundler](https://bundler.io/) is integrated, enabling any [Ruby gem](https://rubygems.org/) compatible with JRuby to be used within rules.
+This permits easy access to the vast ecosystem of libraries within the Ruby community.
 Gems are available using the [inline bundler syntax](https://bundler.io/guides/bundler_in_a_single_file_ruby_script.html).
 The require statement can be omitted.
 
@@ -1250,14 +1288,26 @@ end
 
 ### Transformations
 
+#### Using openHAB Transformations
+
+Existing openHAB transformations can also be used by calling the [transform](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL.html#transform-class_method) method.
+This enables the use of any transformations from the `/transform` folder or managed through the UI, such as MAP, JSONPATH, Jinja Transformation, etc.
+
+```ruby
+# Convert OPEN/CLOSED to Online/Offline using availability.map
+# OPEN=Online
+# CLOSED=OFFLINE
+logger.info transform(:map, "availability.map", LivingRoom_Switch_Availability.state)
+```
+
+#### Writing Custom Transformations in Ruby
+
 This add-on also provides the necessary infrastructure to use Ruby for writing [transformations](https://www.openhab.org/docs/configuration/transformations.html).
 
 The main value to be transformed is given to the script in a variable called `input`.
 Note that the values are passed to the transformation as Strings even for numeric items and data types.
 
-**Note**: In openHAB 3.4, due to an [issue](https://github.com/jruby/jruby/issues/5876) in the current version of JRuby,
-you will need to begin your script with `input ||= nil` (and `a ||= nil` etc. for additional query variables) so that
-JRuby will recognize the variables as variables--rather than method calls--when it's parsing the script.
+**Note**: In openHAB 3.4, due to an [issue](https://github.com/jruby/jruby/issues/5876) in the current version of JRuby, you will need to begin your script with `input ||= nil` (and `a ||= nil` etc. for additional query variables) so that JRuby will recognize the variables as variables--rather than method calls--when it's parsing the script.
 Otherwise you will get errors like `(NameError) undefined local variable or method 'input' for main:Object`.
 This is not necessary in openHAB 4.0+.
 
@@ -1266,8 +1316,7 @@ This is not necessary in openHAB 4.0+.
 Once the addon is installed, you can create a Ruby file in the `$OPENHAB_CONF/transform` directory, with the extension `.rb`.
 When referencing the file, you need to specify the `RB` transform: `RB(mytransform.rb):%s`.
 
-You can also specify additional variables to be set in the script using a URI-like query syntax: `RB(mytransform.rb?a=1&b=c):%s`
-in order to share a single script with slightly different parameters for different items.
+You can also specify additional variables to be set in the script using a URI-like query syntax: `RB(mytransform.rb?a=1&b=c):%s` in order to share a single script with slightly different parameters for different items.
 
 ##### Example: Display the wind direction in degrees and cardinal direction
 
@@ -1309,7 +1358,8 @@ When 3 lights out of 10 lights are on, this will produce a formatted state of `3
 
 #### Inline Transformations
 
-Inline transformations are supported too. For example, to display the temperature in both °C and °F:
+Inline transformations are supported too.
+For example, to display the temperature in both °C and °F:
 
 ```Xtend
 Number:Temperature Outside_Temperature "Outside Temperature [RB(|  input.to_f.|('°C').then { |t| %(#{t.format('%d °C')} / #{t.to_unit('°F').format('%d °F')}) }   ):%s]"
@@ -1322,6 +1372,31 @@ When the item contains `0 °C`, this will produce a formatted state of `0 °C /
 You can create an openHAB profile in JRuby that can be applied to item channel links.
 For more details, see [#profile](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL.html#profile-class_method).
 
+### Sitemaps
+
+Sitemaps can be created via [sitemaps.build](https://openhab.github.io/openhab-jruby/main/OpenHAB/Core/Sitemaps/Provider.html#build-instance_method).
+
+```ruby
+sitemaps.build do
+  sitemap "default", "My Residence" do
+    frame label: "Control" do
+      text label: "Climate", icon: "if:mdi:home-thermometer-outline" do
+        frame label: "Main Floor" do
+          text item: MainFloor_AmbTemp
+          switch item: MainFloorThermostat_TargetMode, label: "Mode", mappings: %w[off auto cool heat]
+          setpoint item: MainFloorThermostat_SetPoint, label: "Set Point", visibility: "MainFloorThermostat_TargetMode!=off"
+        end
+        frame label: "Basement" do
+          text item: Basement_AmbTemp
+          switch item: BasementThermostat_TargetMode, label: "Mode", mappings: { OFF: "off", COOL: "cool", HEAT: "heat" }
+          setpoint item: BasementThermostat_SetPoint, label: "Set Point", visibility: "BasementThermostat_TargetMode!=off"
+        end
+      end
+    end
+  end
+end
+```
+
 ## File Based Rules
 
 ### Basic Rule Structure
@@ -1360,8 +1435,8 @@ See [#changed](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL/Rules/Bu
 
 ##### Detecting Change Duration
 
-Only execute a rule when an item state changed and stayed the same for a period of time. This method
-can only be done using a file-based rule.
+Only execute a rule when an item state changed and stayed the same for a period of time.
+This method can only be done using a file-based rule.
 
 ```ruby
 rule "Garage Door Alert" do
@@ -1540,13 +1615,13 @@ See [Rule Guards](https://openhab.github.io/openhab-jruby/main/OpenHAB/DSL/Rules
 ### Rule Executions
 
 Execution blocks are executed when a rule is triggered and all the rule conditions are met.
-Multiple execution blocks can be specified. This can be useful especially when using a delay execution
-block inbetween two run or triggered blocks.
+Multiple execution blocks can be specified.
+This can be useful especially when using a delay execution block inbetween two run or triggered blocks.
 
 #### Run Execution Block
 
-A run execution block is the most commonly used execution block. It provides the full [event object](#event-object)
-to the block.
+A run execution block is the most commonly used execution block.
+It provides the full [event object](#event-object) to the block.
 
 ```ruby
 rule "Rule with a run block" do
@@ -1559,8 +1634,8 @@ end
 
 #### Triggered Execution Block
 
-A triggered execution block passes the `TriggeringItem` object directly to the block. It is handy when combined with
-Ruby's pretzel-colon operator to act directly on the object.
+A triggered execution block passes the `TriggeringItem` object directly to the block.
+It is handy when combined with Ruby's pretzel-colon operator to act directly on the object.
 
 ```ruby
 rule "Limit the duration of TV watching" do
@@ -1571,9 +1646,9 @@ end
 
 #### Delay Execution Block
 
-A delay exection block is useful for adding a delay inbetween rule executions or even at the beginning of the
-trigger event without having to manually create a timer. Unlike `sleep`, a delay block does not block
-the current executing thread. It actually sets a timer for you behind the scenes.
+A delay exection block is useful for adding a delay inbetween rule executions or even at the beginning of the trigger event without having to manually create a timer.
+Unlike `sleep`, a delay block does not block the current executing thread.
+It actually sets a timer for you behind the scenes.
 
 ```ruby
 rule "Check for offline things 15 minutes after openHAB had started" do
@@ -1686,7 +1761,7 @@ end
 
 ## Calling Java From JRuby
 
-JRuby can access almost any Java object that's available in the current JVM.
+JRuby can [access almost any Java object](https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby) that's available in the current JVM.
 This is how the library is implemented internally.
 
 ```ruby
@@ -1699,4 +1774,6 @@ formatter = DateTimeFormatter.of_pattern("yyyy MM dd")
 formatter = java.time.format.DateTimeFormatter.of_pattern("yyyy MM dd")
 ```
 
-See [full documentation from JRuby](https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby)
+## Full Documentation
+
+Visit <https://openhab.github.io/openhab-jruby/> for the full documentation of the **openHAB JRuby Helper Library**.