[jrubyscripting] Update README.md (#14798)

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
This commit is contained in:
jimtng 2023-04-14 16:09:51 +10:00 committed by GitHub
parent e3efe0cc86
commit 9f221e550b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,7 @@
<!-- This file is auto-generated by YARD from https://github.com/openhab/openhab-jruby/blob/main/USAGE.md; please do not edit directly -->
<!-- To regenerate, run `bin/yard display -f markdown -o https://openhab.github.io/openhab-jruby/5.0 file:USAGE.md` -->
# JRuby Scripting <!-- omit from toc -->
# JRuby Scripting
This add-on provides [JRuby](https://www.jruby.org/) scripting language for automation rules.
Also included is [openhab-scripting](https://openhab.github.io/openhab-jruby/), a fairly high-level Ruby gem to support automation in openHAB.
@ -33,8 +33,11 @@ If you're new to Ruby, you may want to check out [Ruby Basics](https://openhab.g
- [Cache](#cache)
- [Time](#time)
- [Ephemeris](#ephemeris)
- [Rules, Scripts, and Scenes](#rules-scripts-and-scenes)
- [Gems](#gems)
- [Shared Code](#shared-code)
- [Transformations](#transformations)
- [Profile](#profile)
- [File Based Rules](#file-based-rules)
- [Basic Rule Structure](#basic-rule-structure)
- [Rule Triggers](#rule-triggers)
@ -54,11 +57,9 @@ If you're new to Ruby, you may want to check out [Ruby Basics](https://openhab.g
- [Triggered Execution Block](#triggered-execution-block)
- [Delay Execution Block](#delay-execution-block)
- [Terse Rules](#terse-rules)
- [Rule Manipulations](#rule-manipulations)
- [Early Exit From a Rule](#early-exit-from-a-rule)
- [Dynamic Generation of Rules](#dynamic-generation-of-rules)
- [Hooks](#hooks)
- [Transformations](#transformations)
- [Calling Java From JRuby](#calling-java-from-jruby)
Additional [example rules are available](https://openhab.github.io/openhab-jruby/5.0/file.examples.html), as well as examples of [conversions from DSL and Python rules](https://openhab.github.io/openhab-jruby/5.0/file.conversions.html).
@ -71,7 +72,7 @@ Additional [example rules are available](https://openhab.github.io/openhab-jruby
- Rich ecosystem of tools, including things like Rubocop to help developers write clean code and RSpec to test the libraries.
- Ruby is really good at letting one express intent and create a DSL to make that expression easier.
### Design points <!-- omit from toc -->
### Design points
- Create an intuitive method of defining rules and automation
- Rule language should "flow" in a way that you can read the rules out loud
@ -87,12 +88,12 @@ Additional [example rules are available](https://openhab.github.io/openhab-jruby
## Installation
### Prerequisites <!-- omit from toc -->
### Prerequisites
1. openHAB 3.4+
1. The JRuby Scripting Language Addon
### From the User Interface <!-- omit from toc -->
### 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).
@ -101,7 +102,7 @@ Additional [example rules are available](https://openhab.github.io/openhab-jruby
- **Ruby Gems**: `openhab-scripting=~>5.0.0`
- **Require Scripts**: `openhab/dsl` (not required, but recommended)
### Using Files <!-- omit from toc -->
### Using Files
1. Edit `<OPENHAB_CONF>/services/addons.cfg` and ensure that `jrubyscripting` is included in
an uncommented `automation=` list of automations to install.
@ -125,16 +126,16 @@ This allows the use of [items](https://openhab.github.io/openhab-jruby/5.0/OpenH
This functionality can be disabled for users who prefer to manage their own gems and `require`s via the add-on configuration options.
Simply change the `gems` and `require` configuration settings.
| Parameter | Description |
| --------------------- | ---------------------------------------------------------------------------------------------------------- |
| Parameter | Description |
| --------------------- | -------------------------------------------------------------------------------------------------------- |
| `gem_home` | The path to store Ruby Gems. <br/><br/>Default: `$OPENHAB_CONF/automation/ruby/.gem/RUBY_ENGINE_VERSION` |
| `gems` | A list of gems to install. <br/><br/>Default: `openhab-scripting=~>5.0.0` |
| `check_update` | Check for updated version of `gems` on start up or settings change. <br/><br/>Default: `true` |
| `require` | List of scripts to be required automatically. <br/><br/>Default: `openhab/dsl` |
| `rubylib` | Search path for user libraries. <br/><br/>Default: `$OPENHAB_CONF/automation/ruby/lib` |
| `dependency_tracking` | Enable dependency tracking. <br/><br/>Default: `true` |
| `local_context` | See notes below. <br/><br/>Default: `singlethread` |
| `local_variables` | See notes below. <br/><br/>Default: `transient` |
| `gems` | A list of gems to install. <br/><br/>Default: `openhab-scripting=~>5.0.0` |
| `check_update` | Check for updated version of `gems` on start up or settings change. <br/><br/>Default: `true` |
| `require` | List of scripts to be required automatically. <br/><br/>Default: `openhab/dsl` |
| `rubylib` | Search path for user libraries. <br/><br/>Default: `$OPENHAB_CONF/automation/ruby/lib` |
| `dependency_tracking` | Enable dependency tracking. <br/><br/>Default: `true` |
| `local_context` | See notes below. <br/><br/>Default: `singlethread` |
| `local_variables` | See notes below. <br/><br/>Default: `transient` |
When using file-based configuration, these parameters must be prefixed with `org.openhab.automation.jrubyscripting:`, for example:
@ -143,13 +144,13 @@ org.openhab.automation.jrubyscripting:gems=openhab-scripting=~>5.0
org.openhab.automation.jrubyscripting:require=openhab/dsl
```
### gem_home <!-- omit from toc -->
### 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.
### gems <!-- omit from toc -->
### gems
A comma separated list of [Ruby Gems](https://rubygems.org/) to install.
@ -171,34 +172,34 @@ Examples:
| `openhab-scripting=~>5.0, faraday=~>2.7;>=2.7.4` | install `openhab-scripting` gem version 5.x and `faraday` gem version 2.7.4 or higher, but less than 3.0 |
| `gem1= >= 2.2.1; <= 2.2.5` | install `gem1` gem version 2.2.1 or above, but less than or equal to version 2.2.5 |
### check_update <!-- omit from toc -->
### 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.
### require <!-- omit from toc -->
### require
A comma separated list of script names to be required by the JRuby Scripting Engine at the beginning of user scripts.
The default is to require the helper library.
### rubylib <!-- omit from toc -->
### rubylib
Search path for user libraries. Separate each path with a colon (semicolon in Windows).
### dependency_tracking <!-- omit from toc -->
### 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.
### local_context <!-- omit from toc -->
### local_context
The local context holds Ruby runtime, name-value pairs for sharing variables between Java and Ruby.
Valid values are: `singleton`, `threadsafe`, `singlethread`, or `concurrent`.
See [this](https://github.com/jruby/jruby/wiki/RedBridge#context-instance-type) for options and details.
### local_variables <!-- omit from toc -->
### local_variables
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.
@ -212,13 +213,13 @@ 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.
#### Adding Triggers <!-- omit from toc -->
#### Adding Triggers
Using the openHAB UI, first create a new rule and set a trigger condition.
![openHAB Rule Configuration](docs/images/rule-config.png)
#### Adding Actions <!-- omit from toc -->
#### Adding Actions
Select "Add Action" and then select "Run Script" with "Ruby".
This will bring up an empty script editor where you can enter your JavaScript.
@ -263,8 +264,8 @@ When you use "Item event" as trigger (i.e. "[item] received a command", "[item]
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/5.0/OpenHAB/Core/Events.html).
| Property Name | Type | Trigger Types | Description | Rules DSL Equivalent |
| ------------- | -------------------------------------------- | -------------------------------------- | ---------------------------------------------------- | ---------------------- |
| Property Name | Type | Trigger Types | Description | Rules DSL Equivalent |
| ------------- | ------------------------------------------------------------------------------------------- | -------------------------------------- | ---------------------------------------------------- | ---------------------- |
| `state` | [State](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/State.html) or `nil` | `[item] changed`, `[item] was updated` | State that triggered event | `triggeringItem.state` |
| `was` | [State](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/State.html) or `nil` | `[item] changed` | Previous state of Item or Group that triggered event | `previousState` |
| `command` | [Command](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/Command.html) | `[item] received a command` | Command that triggered event | `receivedCommand` |
@ -433,7 +434,7 @@ Get a sorted list of Group members matching a condition:
sorted_items_by_battery_level = gBattery.members
.select(&:state?) # only include non NULL / UNDEF members
.select { |item| item.state < 20 } # select only those with low battery
.sort_by(&:state)
.sort_by(&:state)
```
Get a list of values mapped from the members of a group:
@ -463,7 +464,7 @@ My_Item << ON
Note: all possible commands are supported on the corresponding item types, e.g. `on`, `off`, `up`, `down`, `play`, `pause`, `stop`, etc.
For more details, see the individual item classes under [OpenHAB::Core::Items](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Items.html).
##### Sending Commands to an Item Only When Its State is Different <!-- omit from toc -->
##### Sending Commands to an Item Only When Its State is Different
```ruby
My_Item.ensure.on
@ -474,7 +475,7 @@ My_Item.ensure << ON
logger.info("Turning off the light") if My_Item.ensure.off
```
##### Timed Commands <!-- omit from toc -->
##### Timed Commands
A [Timed Command](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Items/TimedCommand.html) is similar to the openHAB Item's [expire parameter](https://www.openhab.org/docs/configuration/items.html#parameter-expire) but it offers more flexibility.
It removes the need to manually create a timer.
@ -523,7 +524,7 @@ if My_Item.state?
end
```
##### Comparing Item's State <!-- omit from toc -->
##### Comparing Item's State
```ruby
String_Item.state == 'test string'
@ -532,14 +533,14 @@ items['Number_Item'].state == 10
# Compare Quantity Types
Temperature_Item.state > 24 | '°C'
Indoor_Temperature.state > Outdoor_Temperature.state
Indoor_Temperature.state > Outdoor_Temperature.state
Indoor_Temperature.state > Outdoor_Temperature.state + 5 | '°C'
Indoor_Temperature.state - Outdoor_Temperature.state > 5 | '°C'
```
See [unit block](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL.html#unit-class_method)
##### Range checking <!-- omit from toc -->
##### Range checking
Types that are comparable, such as [StringType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/StringType.html), [DateTimeType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/DateTimeType.html), [DecimalType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/DecimalType.html), [PercentType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/PercentType.html),
include Ruby's [Comparable](https://docs.ruby-lang.org/en/master/Comparable.html) module which provides
@ -550,7 +551,7 @@ String_Item.update("Freddy")
String_Item.state.between?("E", "G") # => true
Number_Item.update(10)
if Number_Item.state.between?(5, 20)
if Number_Item.state.between?(5, 20)
logger.info "Number_Item falls within the expected range"
end
@ -569,7 +570,7 @@ end
((20|"°C")..(24|"°C")).cover?(Temperature_Item.state)
```
##### Loose Type Comparisons <!-- omit from toc -->
##### Loose Type Comparisons
Some openHAB item types can accept different command types.
For example, a [DimmerItem](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Items/DimmerItem.html) can accept a command with an [OnOffType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/OnOffType.html), [IncreaseDecreaseType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/IncreaseDecreaseType.html) or a [PercentType](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Types/PercentType.html).
@ -798,7 +799,7 @@ end
When a script is unloaded, all created timers are automatically cancelled.
#### Accessing Variables <!-- omit from toc -->
#### Accessing Variables
You can access all variables of the current context in the created timers.
@ -816,7 +817,7 @@ end
my_var = "Hello mutation!" # When the timer runs, it will log "Hello mutation!" instead of "Hello world!"
```
#### Reschedule a Timer <!-- omit from toc -->
#### Reschedule a Timer
A timer can be rescheduled inside the timer body
@ -855,7 +856,7 @@ rule 'cancel timer' do
end
```
#### Manage Multiple Timers <!-- omit from toc -->
#### Manage Multiple Timers
Multiple timers can be managed in the traditional way by storing the timer objects in a Hash:
@ -863,7 +864,7 @@ Multiple timers can be managed in the traditional way by storing the timer objec
@timers ||= {}
if @timers[event.item]
@timers[event.item].reschedule
@timers[event.item].reschedule
else
@timers[event.item] = after 3.minutes do # Use the triggering item as the timer ID
event.item.off
@ -947,7 +948,7 @@ Several options are available for time related code, including but not limited t
- Ruby [Time](https://docs.ruby-lang.org/en/master/Time.html) - represents a specific instant with a date and time
- Ruby [DateTime](https://docs.ruby-lang.org/en/master/DateTime.html) - represents a specific instant with a date and time
#### Durations <!-- omit from toc -->
#### Durations
Ruby [integers](https://docs.ruby-lang.org/en/master/Integer.html) and [floats](https://docs.ruby-lang.org/en/master/Float.html) are extended with several methods to support durations.
These methods create a new [Duration](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/CoreExt/Java/Duration.html) or [Period](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/CoreExt/Java/Period.html) object that is used by the [every](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/BuilderDSL.html#every-instance_method) trigger, [delay](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/BuilderDSL.html#delay-instance_method) block, the for option of [changed](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/BuilderDSL.html#changed-instance_method) triggers, and [timers](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Timer.html).
@ -975,7 +976,7 @@ rule "Timer example" do
end
```
#### Time Comparisons, Conversions, and Arithmetic <!-- omit from toc -->
#### Time Comparisons, Conversions, and Arithmetic
Comparisons, conversions and arithmetic are automatic between Java and Ruby types.
Note that anytime you do a comparison between a type with more specific data, and a type missing specific data, the comparison is done as if the more specific data is at the beginning of its period.
@ -1044,7 +1045,7 @@ end
# Comparing Time against ZonedDateTime with `>`
sunset = things["astro:sun:home"].get_event_time("SUN_SET", nil, nil)
if Time.now > sunset
if Time.now > sunset
logger.info "it is after sunset"
end
@ -1059,7 +1060,7 @@ elapsed_time = Time.now - Motion_Sensor.last_update
elapsed_time = ZonedDateTime.now - Motion_Sensor.last_update
# Using `-` operator with ZonedDateTime
# Comparing two ZonedDateTime using `<`
# Comparing two ZonedDateTime using `<`
Motion_Sensor.last_update < Light_Item.last_update - 10.minutes
# is the same as:
Motion_Sensor.last_update.before?(Light_Item.last_update.minus_minutes(10))
@ -1078,7 +1079,7 @@ Time.at(1669684403).to_zoned_date_time
java.time.Instant.of_epoch_second(1669684403).at_zone(ZoneId.system_default)
```
#### Ranges <!-- omit from toc -->
#### Ranges
Ranges of date time objects work as expected.
Make sure to use `#cover?` instead of `#include?` to do a simple comparison, instead of generating an array and searching it linearly.
@ -1130,6 +1131,78 @@ Date.today.weekend? # => true
Date.today.in_dayset?(:school) # => false
```
### Rules, Scripts, and Scenes
[Rules](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/Core/Rules/Rule.html), Scenes and Scripts can be accessed using the
[rules](https://openhab.github.io/openhab-jruby/5.0/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/5.0/OpenHAB/Core/Rules/Registry.html#scenes-instance_method),
and a list of all Scripts through [rules.scripts](https://openhab.github.io/openhab-jruby/5.0/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/5.0/OpenHAB/DSL/Rules/Terse.html) syntax.
```ruby
channel("astro:sun:home:rise#event") { rules.scenes.tagged("sunrise").each(&:trigger) }
channel("astro:sun:home:set#event") { rules.scenes.tagged("sunset").each(&:trigger) }
```
Or it can be written as one rule with the help of [trigger attachments](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/BuilderDSL.html#Triggers-group).
```ruby
rule "Activate scenes at sunset/sunrise" do
channel "astro:sun:home:rise#event", attach: "sunrise"
channel "astro:sun:home:set#event", attach: "sunset"
run { |event| rules.scenes.tagged(event.attachment).each(&:trigger) }
end
```
Get the UID of a Rule
```ruby
rule_obj = rule 'my rule name' do
received_command My_Item
run do
# rule code here
end
end
rule_uid = rule_obj.uid
```
A rule's UID can also be specified at rule creation
```ruby
rule "my rule name", id: "my_unique_rule_uid" do
# ...
end
# or
rule "my rule name" do
uid "my_unique_rule_uid"
# ...
end
```
Get the UID of a Rule by Name
```ruby
rule_uid = rules.find { |rule| rule.name == 'This is the name of my rule' }.uid
```
Enable or Disable a Rule by UID
```ruby
rules[rule_uid].enable
rules[rule_uid].disable
```
### 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.
@ -1168,6 +1241,81 @@ def my_lib_version
end
```
### Transformations
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.
Otherwise you will get errors like `(NameError) undefined local variable or method 'input' for main:Object`.
This is not necessary in openHAB 4.0+.
#### File Based Transformations
Once the addon is installed, you can create a Ruby file in the `$OPENHAB_CONF/transform` directory, with the extension `.script`.
It's important that the extension is `.script` so that the core `SCRIPT` transform service will recognize it.
When referencing the file, you need to specify the `SCRIPT` transform, with `rb` as the script type: `SCRIPT(rb:mytransform.script):%s`.
You can also specify additional variables to be set in the script using a URI-like query syntax: `SCRIPT(rb:mytransform.script?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
`weather.items`
```Xtend
Number:Angle Exterior_WindDirection "Wind Direction [SCRIPT(rb:compass.script):%s]" <wind>
```
`compass.script`
```ruby
DIRECTIONS = %w[N NE E SE S SW W NW N].freeze
if input.nil? || input == "NULL" || input == "UNDEF"
"-"
else
cardinal = DIRECTIONS[(input.to_f / 45).round]
"#{cardinal} (#{input.to_f.round}°)"
end
```
Given a state of `82 °`, this will produce a formatted state of `E (82°)`.
##### Example: Display the number of lights that are on/off within a group
```Xtend
Group gIndoorLights "Indoor Lights [SCRIPT(rb:group_count.script?group=gIndoorLights):%s]"
Group gOutdoorLights "Outdoor Lights [SCRIPT(rb:group_count.script?group=gOutdoorLights):%s]"
```
`group_count.script`
```ruby
items[group].all_members.then { |all| "#{all.select(&:on?).size}/#{all.size}" }
```
When 3 lights out of 10 lights are on, this will produce a formatted state of `3/10`
#### Inline Transformations
Inline transformations are supported too. For example, to display the temperature in both °C and °F:
```Xtend
Number:Temperature Outside_Temperature "Outside Temperature [SCRIPT(rb:| input.to_f.|('°C').then { |t| %(#{t.format('%d °C')} / #{t.to_unit('°F').format('%d °F')}) } ):%s]"
```
When the item contains `0 °C`, this will produce a formatted state of `0 °C / 32 °F`.
### Profile
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/5.0/OpenHAB/DSL.html#profile-class_method).
## File Based Rules
### Basic Rule Structure
@ -1204,7 +1352,7 @@ end
See [#changed](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/BuilderDSL.html#changed-instance_method)
##### Detecting Change Duration <!-- omit from toc -->
##### 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.
@ -1300,7 +1448,7 @@ end
See [#cron](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/BuilderDSL.html#cron-instance_method)
##### `every` Trigger <!-- omit from toc -->
##### `every` Trigger
```ruby
rule "run every day" do
@ -1444,48 +1592,6 @@ received_command(My_Switch, to: ON) { My_Light.on }
See [Terse Rules](https://openhab.github.io/openhab-jruby/5.0/OpenHAB/DSL/Rules/Terse.html) for full details.
### Rule Manipulations
Get the UID of a Rule
```ruby
rule_obj = rule 'my rule name' do
received_command My_Item
run do
# rule code here
end
end
rule_uid = rule_obj.uid
```
A rule's UID can also be specified at rule creation
```ruby
rule "my rule name", id: "my_unique_rule_uid" do
# ...
end
```
Get the UID of a Rule by Name
```ruby
rule_uid = rules.find { |rule| rule.name == 'This is the name of my rule' }.uid
```
Enable or Disable a Rule by UID
```ruby
rules[rule_uid].enable
rules[rule_uid].disable
```
Run a Rule by UID
```ruby
rules[rule_uid].trigger
```
### Early Exit From a Rule
You can use `next` within a file-based rule, because it's in a block:
@ -1572,39 +1678,6 @@ script_unloaded do
end
```
### Transformations
This add-on also provides the necessary infrastructure to use Ruby for writing [transformations](https://www.openhab.org/docs/configuration/transformations.html).
Once the addon is installed, you can create a Ruby file in the `$OPENHAB_CONF/transform` directory, with the extension `.script`.
It's important that the extension is `.script` so that the core `SCRIPT` transform service will recognize it.
When referencing the file, you need to specify the `SCRIPT` transform, with `rb` as the script type: `SCRIPT(rb:mytransform.script):%s`.
You can also specify additional variables to be set in the script using a URI-like query syntax: `SCRIPT(rb:mytransform.script?a=1b=c):%s` in order to share a single script with slightly different parameters for different items.
**Note**: 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`.
`compass.script`
```ruby
input ||= nil
DIRECTIONS = %w[N NE E SE S SW W NW N].freeze
if input.nil? || input == "NULL" || input == "UNDEF"
"-"
else
cardinal = DIRECTIONS[(input.to_f / 45).round]
"#{cardinal} (#{input.to_i}°)"
end
```
`weather.items`
```Xtend
Number:Angle Exterior_WindDirection "Wind Direction [SCRIPT(rb:compass.script):%s]" <wind>
```
Given a state of `82 °`, this will produce a formatted state of `E (82°)`.
## Calling Java From JRuby
JRuby can access almost any Java object that's available in the current JVM.