JRuby Scripting Official Helper Library

Version 5.27.0 is out!

What’s new:

Features

  • Support offset in at and every :day, at: triggers in #278 - this is a new openHAB 4.3 feature (merged after 4.3.0.M1)
  • Support space separator between date and time for DateTimeType.parse in #329

Bug Fixes

  • DateTimeType implements Java’s Comparable in openHAB 4.3 in #328
  • Sitemap updates not propagated to listeners in #327

Full Changelog: v5.26.0…v5.27.0

Example:

Run a rule 30 minutes before the time stored in the My_Daily_Alarm item:

# This only works in openhab 4.3 post M1.
rule "DateTimeItem trigger" do
  every :day, at: My_Daily_Alarm, offset: -30.minutes
  run { Audio.play "alarm_prewarning.mp3" }
end

Note: JRuby supports DateTimeItem trigger in two ways:

  • To use only the time part of the item, use the every :day, at: Item like the example above.
  • To use both the date and time in the item, use the at trigger. Example below:
rule "Birthday trigger" do
  at My_Birthday_This_Year, offset: -1.day
  run { Notification.send "Don't forget to buy Jim a birthday present!" }
end
2 Likes

Version 5.29.0 is out!

What’s new:

  • Improvement in DateTimeType.parse
  • Allow the use of items object within sitemap builder
  • Allow literal states for sitemap visibility rules.
    Example:
    sitemaps.build do
      sitemap "default" do
        switch item: AnItem, visibility: OFF # Previously it had to be string "OFF"
        items.tagged("Switch").each { |item| switch item: }
      end
    end
    
  • Make working with Instant easier.
    You can now write Instant.now - 2.hours just like the operations for ZonedDateTime, Time, etc.
  • Add #yesterday?, #today? , and #tomorrow? to date/time related classes (e.g. ZonedDateTime, Time, Date, Instant, DateTimeType).
  • Add #time_only? and #offset to TimerEvent

Bug fixes:

  • Proper clean up of providers, which affects ruby-built items, things, links, etc. in #330
  • Fix timed command expire in #337

Full Changelog : v5.27.0…v5.29.0

Version 5.31.0 is out!

New features:

  • Allow sending source with commands
  • Add CCT helpers for HSBType.

Example:

# Toggle lights when buttons are pressed
received_command LightButton do
  LightBulb.toggle source: "button"
end

# Set a timer if light wasn't turned on with a physical button
# e.g. via voice command
received_command LightBulb do |event|
  if event.on? && event.source != "button"
    after(30.minutes, id: event.item) { event.item.off }
  else
    timers.cancel(event.item)
  end
end

Full Changelog : v5.29.0…v5.31.0

Version 5.32.0 is out!

Features

  • alias GenericItem#category to GenericItem#icon by @ccutrer in #350
  • Add all state and command descriptions options to items builder by @ccutrer in #351
  • Add NumberItem#range by @ccutrer in #352
  • Add planckian helpers for HSBType by @ccutrer in #353
  • support sitemap colortemperaturepicker by @ccutrer in #357

Bug Fixes

  • special case mired unit dimension inference in items builder by @ccutrer in #349
  • Fix logger error when no toplevel file is found by @jimtng in #348
  • Use Units::MIRED instead of “mired” in HSBType by @jimtng in #360
  • fix mired detection in OH 4.3 by @ccutrer in #359
  • fix race condition when using semantic methods by @ccutrer in #356

Full Changelog: v5.31.0…v5.32.0

HSBType now has planckian helper methods to make working with white CCT lights easier. For more details, see HSBType#planckian? (aliased as #white_cct?), and HSBType#planckian_cct (aliased as #white_cct).

Version 5.33.1 is out!

This version supports running on openHAB 5.0-SNAPSHOT by working around a current JRuby bug reported here. The issue exists on Java21. The library continues to be compatible with and tested against openHAB 3.4.5, and all 4.x latest releases.

Features

Bug Fixes

Full Changelog : v5.32.0…v5.33.1

Version 5.34.0 is out!

Features

  • Support creating a trigger profile for the UI by @jimtng in #373

    It is now possible (and easy!) to create a profile in JRuby for every possible scenario: State and Trigger profiles, which can be used both in UI and file-based items/links.

    Example code in this post

  • Support TimedCommand on GroupItem and Enumerable by @jimtng in #377
    Example:

    [PorchLight, Driveway_Light, Garage_Light].on for: 1.hour
    
  • Allow passing an array of channels to item builder by @ccutrer in #375
    Example:

    items.build do
      dimmer_item DemoDimmer, channels: ["hue:0210:bridge:1:color", "knx:device:bridge:generic:controlDimmer"]
    end
    

#Bug Fixes

  • Adapt DateTimeType internal switch from ZonedDateTime to Instant in openHAB 4.3 by @jimtng in #369
  • Fix #toggle on dimmer items by @ccutrer in #378

Full Changelog: v5.33.1…v5.34.0

Version 5.35.1 was released on 2025-02-25

NOTE: This is the last version that supports openHAB 3.4.x and 4.0.x!

Changes since 5.34.0:

Features

  • Support setting Thing property using hash-like syntax []= by @jimtng in #391

Bug Fixes

  • Fix GroupItem::Members#inspect double >> by @jimtng in #398
  • Add a space between semantic name and its parent in #inspect by @jimtng in #399
  • Fix QuantityType#eql? raising exception on incompatible QuantityType unit by @jimtng in #400
  • Fix problem in getting the provider for entities of ManagedProvider by @jimtng in #402
  • Fix disabled rule remains disabled by @jimtng in #388
  • Use system timezone when converting from LocalDate/LocalTime to instant by @jimtng in #386

Full Changelog : v5.34.0…v5.35.1

Version 5.36.0 is out!

NOTE: This version dropped support for openHAB 3.4.x and openHAB 4.0.x. Changes in the gem versioning are not required for existing openHAB 3/4.0 installations. The gem dependencies will automatically resolve and only upgrade the helper library up to the latest supported version 5.35.1

openHAB 4.1.x, 4.2.x, 4.3.x, and 5.0 are fully supported going forward.

This is an exciting release because we’re able to drop the old Ruby 2.6 compatibility used in openHAB 3.4.x and move the codebase up to Ruby 3.1 syntax and libraries. A lot of legacy openHAB 3.4 and 4.0 specific code have also been removed.

Features

  • Pass self to Item#modify block by @jimtng in #404

  • Add helpful #inspect (and docs) for CommandDescription and StateDescription by @ccutrer in #407

  • Add console scripts for Karaf console by @jimtng in #405

  • Drop openHAB 3.4 support by @ccutrer in #98

  • Drop openHAB 4.0 Support by @ccutrer in #411

  • Support Date/Time operations against Time QuantityType by @jimtng in #396

    Example:

    Number:Time MinimumDelay { unit="min" }
    
    MinimumDelay.update("3 min")
    
    # Adding a Time/ZonedDateTime and a QuantityType
    logger.info(Time.parse("7pm") + MinimumDelay.state) # => 2025-03-16 19:00:03 +1000
    
    # Adding LocalTime and QuantityType
    logger.info(LocalTime.parse("7pm") + MinimumDelay.state) # => 19:03
    
    # comparison between QuantityType and Duration
    logger.info(MinimumDelay.state > 1.hour) # => false 
    
  • Add RawType#bytesize by @ccutrer in #416

  • Update javadocs links to Java 21 by @jimtng in #395

  • Improve errors when an item no longer exists by @ccutrer in #354

Bug Fixes

  • Use #ruby_first to solve Java21’s List#first incompatibility by @jimtng in #383

Full Changelog: v5.35.1…v5.36.0

1 Like

Version 5.36.1 is out!

This fixes a critical gem dependency issue that’s caused by 5.36.0 as reported here

If you experienced an error after upgrading to 5.36.0, please delete your .gems directory, usually located in CONF/automation/ruby/.gems and restart jrubyscripting addon or openhab itself. If you were still on earlier version, you don’t need to delete your gems directory.

Please re-install any custom gems if you had previously installed them manually. Gems installed through the inline bundler will automatically reinstall when your inline bundler re-executes.

Version 5.36.2 is out!

Bug Fixes

  • Fix issue with kwargs methods being treated as ruby2_keywords sometimes by @ccutrer in #423

Full Changelog : v5.36.1…v5.36.2

Version 5.37.0 is out

Features

  • Persistence: support riemann_sum methods by @jimtng in #362

More info:
https://github.com/openhab/openhab-core/pull/4461
https://github.com/openhab/openhab-core/issues/4439
Riemann Sums: Left, Right, Trapezoid, Midpoint, Simpson’s

Full Changelog: v5.36.2…v5.37.0

Version 5.38.0 is out

Features

  • Add a default file so Gemfile doesn’t need a custom require by @jimtng in #428
    This is for the upcoming support of using Gemfile and bundler for gem management.
  • Support ItemStateUpdatedEvent#last_state_update and ItemStateChangedEvent#last_state_change by @jimtng in #401
  • Add GenericItem#was, #was?, #was_xxx? predicates, document Item#last_state, #last_state_change, and #last_state_update methods by @jimtng in #397
  • Support passing timer objects to other scripts via shared_cache by @jimtng in #431
  • Semantic Tags: add subclasses: parameter to allow exact match and exclude all subclasses of the given tags by @jimtng in #433
  • Support wildcard item and improve wildcard thing triggers by @jimtng in #413

Full Changelog : v5.37.0…v5.38.0

Examples:

Share timer object with other scripts (including JS)

# script1.rb:
timer = after(10.hours) { logger.warn "Timer created in script1.rb fired" }
shared_cache[:script1_timer] = timer

# inside a different JRuby UI rule or script:
# This is an openHAB timer object, not a JRuby timer object
# the reschedule method expects a ZonedDateTime
shared_cache[:script1_timer]&.reschedule(10.seconds.from_now)

# inside another JS script:
cache.shared.get("script1_timer")?.cancel()

Note that JRuby manages all the timers it created and when the script is unloaded/reloaded, all timers that were created in that script will be cancelled to avoid “runaway timers”.

openHAB does the same thing for timers in the shared cache. It will cancel it once all scripts referencing the cache have been unloaded.

If you do not want JRuby to cancel the timer upon script un/reloading, you can call Timer#unmanage.

Semantic Subclasses

# This will include CeilingFan and ExhaustFan
items.equipments(Semantics::Fan) 

# This includes _only_ Fan, not the subclasses
items.equipments(Semantics::Fan, subclasses: false) 

Wildcard Event Triggers

This could possibly replace having to use Group triggers if you have consistent item naming.

rule "My Rule" do
  changed "LivingRoom_*_Light"
  run do |event|
    logger.info "#{event.item.label} changed to #{event.state}"
  end
end
rule "MQTT Item Status" do
  changed "mqtt:*" # Triggers on any MQTT Thing status changes
  run do |event|
    logger.info "Thing #{event.thing.uid} changed to #{event.thing.status}"
  end
end

openHAB 5 new item properties

In openHAB 5 we have new properties for Items:

Property Description
was The prior state before it changed to the current state. nil if it was NULL or UNDEF
last_state_update The time (ZonedDateTime) when the latest state update occurred
last_state_change The time (ZonedDateTime) when the latest state change occurred
was? true if the prior state was not NULL or UNDEF
was_undef? true if the prior state was UNDEF
was_null? true if the prior state was NULL
was_on? true if the prior state was ON
was_off? true if the prior state was OFF
was_open? true if the prior state was OPEN
was_closed? true if the prior state was CLOSED
was_up? true if the prior state was UP
was_down? true if the prior state was DOWN
was_playing? true if the prior state was PLAY
was_paused? true if the prior state was PAUSE
was_rewinding? true if the prior state was REWIND
was_fast_forwarding? true if the prior state was FASTFORWARD

These are in addition to the existing state, state?, null?, undef?, on?, off?, etc. which are used to check the current item state.

These was predicates are also available in the ItemStateChangedEvent, (this part isn’t new, it has been available since the beginning), and now we can check the timestamp of the change with last_state_change, e.g.

rule "Item change rule" do
  changed MyPlayerItem
  run do |event|
    if event.was_playing?
      logger.info "MyPlayerItem was playing something, it's now #{event.state}"
    end
  end
end
rule "Calculate delta" do
  changed MyHumidityItem
  run do |event|
    next unless event.was? # Make sure we have a previous state to calculate

    delta = event.state - event.was
    next if delta < 10 # Don't bother for small changes

    logger.info "The humidity has changed by #{delta}"
    logger.info "It changed to #{event.was} at #{event.last_state_change}"
  end
end
rule "avoid quick on/off" do
  received_command LightSwitch
  run do |event|
    # do not pass on the command if the light was recently changed
    next if event.command != LightBulb.state && LightBulb.last_state_change > 2.seconds.ago

    LightBulb.command(event.command) # Pass on the command
  end
end
1 Like

Version 5.39.0 is out!

Changes since 5.38.0:

Features

  • Autoload builders (items, things, sitemaps, rules) and item metadata by @jimtng in #429
    This provides a slightly faster initial loading time and a reduced memory footprint — particularly for UI based scripts, though most file-based scripts also gain from these improvements.
  • Enhance flexibility of #points by @ccutrer in #459
  • Support passing Ranges to between persistence methods by @ccutrer in #463

Bug Fixes

  • console irb: Require irb ~> 1.14 to allow the version shipped with JRuby 10 by @jimtng in #439
  • Fix JRuby 10.0 compatibility: use itr instead of it for iterator by @ccutrer in #444
  • Fix various “instance vars on non-persistent Java type” warnings on JRuby 10 by @ccutrer in #450
  • Resolve $terminal from $console by @jimtng in #436
  • handle nil last_state for was_xx? predicate by @jimtng in #435
  • Fix console winsize by @ccutrer in #462

Full Changelog : v5.38.0…v5.39.0