conf/automation/jsr223/ is for jsr223 scripts (depending on which automation addon is enabled). The type of script depends on the file extension, so .rb files will be executed by jruby, .js will be executed by jsscripting, .py. will be executed by jython, etc.
Traditionally these scripts are organised inside a subdirectory that correspond to the actual language, so jruby scripts are usually placed in /conf/automation/jsr223/ruby, jsscripting in conf/automation/jsr223/js and so on. This is purely for organisational purposes, done by convention. So it is advisable to follow the convention.
You can make subdirectories below this to organise your scripts even further. For example I have conf/automation/jsr223/ruby/personal/lights/ for all my light-related scripts.
conf/automation/lib/ruby is by convention used for storing shared code/libraries that you could require from your script. It is also added to Rubyâs $LOAD_PATH (by default). You are not required to use this, you can put it in /any/place/you/like/that/is/accessible as long as you set the RUBYLIB config so that the path gets added to $LOAD_PATH, but itâs easier to stick to the convention.
Lastly, GEM_HOME is set to conf/scripts/lib/ruby also by default - you can change this in the addon config if you so desire.
Itâs very, very nice to be able to write code that writes rules. I found a couple of issues - should they go into the GH issues in the addons repo or do you prefer them here?
Hope this is the right forum to post this. I have a generic rule which dynamically gets a related item to update a date/time. It works unless the dynamic item is NULL. code is below
event_motion_tripped = items[event.item.name + "_Tripped"]
event_motion_lasttrippeddate = items[event.item.name + "_LastTrippedDate"]
case newVariable
when "Tripped"
if (newTripped == 1)
event_motion_tripped.on
event_motion_lasttrippeddate.update(newDateTime)
else
event_motion_tripped.off
end
end
So if event_motion_tripped is NULL, the event_motion_tripped.on throws an error (undefined method `offâ for nil:NilClass (NoMethodError).
The error message says that the objectevent_motion_tripped itself is nil, i.e. it isnât referring to an actual Item. This could happen if there is no such item with the name event.item.name + "_Tripped"
The item exists in my item file, itâs just NULL.
so event_motion_tripped = items[event.item.name + â_Trippedâ] returnd a NIL item, hence the .on throws and error, but if I reference one of the items directly from the script like SplitSystemUnit_Spare_Motion_Tripped.on - that works even if the item is currently NIL.
Try adding logger.info "#{event.item.name}_Tripped" and see what the name really is when you got the error. I am sure it would say something that doesnât exist.
You can always do AValidItem.on regardless of its current state, so even when its state is currently NULL (AValidItem.state == nil && AValidItem.null? == true). As I said above, event_motion_tripped is the Ruby nil object (not to be confused with an Item object having NULL as its state). And itâs nil because items["a non existent item"] will return nil.
Let me start by saying that I really like the compact way of writing rules with JRuby. Thanks for all the hard work put into that!
Iâm in the process of migrating my rules (mostly Jython) to JRuby and I canât figure out how to get the channel name as string, so I can extract part of the channel name with .split(). Since Ruby is new for me as a programming language, I just might miss something very obviousâŠ
For the record: running OH 3.3.0 in a container (on Kubernetes).
I am converting a rule that handles different Hue dimmer switch events to turn lights on/of or select a predefined scene. The sample rule for testing that:
rule 'Hue Dimmer Switch Key triggered' do
channel [
'dim_office:dimmer_switch_event',
# ... etc ...
],
thing: 'hue:0820:0016852dc5a3'
run do |event|
logger.info("Hue Dimmer Trigger event: #{event}")
logger.info("Hue Dimmer Trigger channel: #{event.channel}")
sw = event.channel.split(':')
logger.info("Hue Dimmer Trigger switch: #{sw}")
end
end
How can I convert the Java class ChannelUID to a string in JRuby? Could not find an example in the documentation.
On a side note: I noticed that the error logging used a backtick as opening for the method name and a single quote as closing in the undefined method error message⊠:o)
I believe event.channel.to_s.split(':') should do the trick!
As for the backtick in the error message, thatâs just how rubyâs error messages are written (you can see it in the stack trace location as well). Not sure about the exact reason for it, but Iâve seen it elsewhere as well.
JRuby creates some convenient alias methods for all java classes, e.g to_s => toString(), and also any getSomething() => something, setSomething() => something= etc.
Strategies {
default = everyUpdate
}
Items {
// persist all items added to group gPersist on every change and restore them from the database at startup
gPersist* : strategy = everyChange,restoreOnStartup
}
I changed the Item state a few times through Karaf to make sure it has a previous state before testing the rule.
The rule (simplified for testing):
rule 'Hue Dimmer Switch Key triggered' do
channel [
'dim_office:dimmer_switch_event',
# ... etc ...
],
thing: 'hue:0820:0017682fc1b3',
triggered: ['1000.0', '1002.0']
run do |event|
lightScene = items['Light_Scene_' + event.channel.to_s.split(':')[3].split('_')[1]]
logger.info "#{lightScene.class} #{lightScene.methods}"
logger.info "Hue #{lightScene.name} state is #{lightScene} with trigger #{event.get_event}"
logger.info "Previous state: #{lightScene.previous_state}"
end
end
Gives an error:
[INFO ] [ort.loader.AbstractScriptFileWatcher] - Loading script '/openhab/conf/automation/jsr223/ruby/personal/hue_sw_office.rb'
[INFO ] [fice.hue_dimmer_switch_key_triggered] - Java::OrgOpenhabCoreLibraryItems::StringItem [:casecmp, :valid_encoding?, :acceptedDataTypes, :to_java_bytes, :getAcceptedDataTypes, :squeeze!, [**SNIP**] :previous_state, :delta_since, [**SNIP**] :state=, :]
[INFO ] [fice.hue_dimmer_switch_key_triggered] - Hue Light_Scene_office state is OFF with trigger 1000.0
[ERROR] [obj.OpenHAB.DSL.Rules.AutomationRule] - undefined method `state' for nil:NilClass
Did you mean? state? (NoMethodError)
In rule: Hue Dimmer Switch Key triggered
uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/delegate.rb:83:in `method_missing'
/openhab/conf/automation/jsr223/ruby/personal/hue_sw_office.rb:35:in `block in <main>'
As can be seen from the methods dump, :previous_state should be available for this StringType item. Any suggestions how I can get the previous state?
From a quick glance, I donât see anything wrong with your rule. This may be an error in the library. While we do test many of the persistence methods, for some reason pervious_state isnât one of them.
I can try and reproduce this tonight (US Eastern time) and let you know what I find.
MapDB can only store one state for each Item, which is the current state (its main purpose is to restore states on startup), which means there isnât any previous state, so null is returned. If you need this you have to use a different persistence service.