openhab-jrubyscripting 5.0.0.rc5 → 5.0.0.rc6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions.rb +6 -6
  3. data/lib/openhab/core/dependency_tracking.rb +34 -0
  4. data/lib/openhab/core/entity_lookup.rb +132 -78
  5. data/lib/openhab/core/events/item_channel_link.rb +2 -2
  6. data/lib/openhab/core/events/item_command_event.rb +1 -1
  7. data/lib/openhab/core/events/item_event.rb +2 -2
  8. data/lib/openhab/core/events/item_state_changed_event.rb +1 -1
  9. data/lib/openhab/core/events/thing.rb +1 -1
  10. data/lib/openhab/core/items/accepted_data_types.rb +2 -2
  11. data/lib/openhab/core/items/contact_item.rb +1 -1
  12. data/lib/openhab/core/items/dimmer_item.rb +2 -2
  13. data/lib/openhab/core/items/generic_item.rb +45 -224
  14. data/lib/openhab/core/items/group_item.rb +5 -3
  15. data/lib/openhab/core/items/image_item.rb +2 -2
  16. data/lib/openhab/core/items/item.rb +219 -0
  17. data/lib/openhab/core/items/metadata/hash.rb +1 -1
  18. data/lib/openhab/core/items/persistence.rb +4 -5
  19. data/lib/openhab/core/items/provider.rb +2 -2
  20. data/lib/openhab/core/items/proxy.rb +68 -7
  21. data/lib/openhab/core/items/registry.rb +6 -6
  22. data/lib/openhab/core/items/semantics/enumerable.rb +6 -6
  23. data/lib/openhab/core/items/semantics.rb +8 -7
  24. data/lib/openhab/core/items.rb +2 -1
  25. data/lib/openhab/core/provider.rb +14 -7
  26. data/lib/openhab/core/rules/registry.rb +2 -2
  27. data/lib/openhab/core/rules.rb +1 -1
  28. data/lib/openhab/core/script_handling.rb +6 -6
  29. data/lib/openhab/core/things/channel.rb +1 -1
  30. data/lib/openhab/core/things/channel_uid.rb +2 -2
  31. data/lib/openhab/core/things/item_channel_link.rb +2 -2
  32. data/lib/openhab/core/things/links/provider.rb +2 -2
  33. data/lib/openhab/core/things/registry.rb +1 -1
  34. data/lib/openhab/core/things/thing.rb +1 -1
  35. data/lib/openhab/core/types/date_time_type.rb +4 -4
  36. data/lib/openhab/core/types/hsb_type.rb +2 -2
  37. data/lib/openhab/core/types/quantity_type.rb +1 -1
  38. data/lib/openhab/core/types.rb +1 -1
  39. data/lib/openhab/core/uid.rb +1 -1
  40. data/lib/openhab/core/value_cache.rb +188 -0
  41. data/lib/openhab/core.rb +57 -15
  42. data/lib/openhab/core_ext/ruby/symbol.rb +7 -0
  43. data/lib/openhab/dsl/items/builder.rb +17 -10
  44. data/lib/openhab/dsl/items/ensure.rb +5 -5
  45. data/lib/openhab/dsl/items/timed_command.rb +4 -4
  46. data/lib/openhab/dsl/rules/automation_rule.rb +53 -39
  47. data/lib/openhab/dsl/rules/builder.rb +128 -79
  48. data/lib/openhab/dsl/rules/guard.rb +5 -5
  49. data/lib/openhab/dsl/rules/name_inference.rb +20 -1
  50. data/lib/openhab/dsl/rules/rule_triggers.rb +3 -3
  51. data/lib/openhab/dsl/rules/terse.rb +1 -0
  52. data/lib/openhab/dsl/rules/triggers/changed.rb +26 -23
  53. data/lib/openhab/dsl/rules/triggers/command.rb +6 -5
  54. data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +2 -2
  55. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +2 -2
  56. data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +6 -6
  57. data/lib/openhab/dsl/rules/triggers/updated.rb +5 -5
  58. data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +11 -12
  59. data/lib/openhab/dsl/things/builder.rb +73 -14
  60. data/lib/openhab/dsl/version.rb +2 -2
  61. data/lib/openhab/dsl.rb +43 -17
  62. data/lib/openhab/log.rb +5 -5
  63. data/lib/openhab/rspec/configuration.rb +5 -5
  64. data/lib/openhab/rspec/example_group.rb +1 -1
  65. data/lib/openhab/rspec/helpers.rb +4 -4
  66. data/lib/openhab/rspec/hooks.rb +19 -1
  67. data/lib/openhab/rspec/karaf.rb +12 -19
  68. data/lib/openhab/rspec/suspend_rules.rb +2 -1
  69. data/lib/openhab/yard/base_helper.rb +46 -0
  70. data/lib/openhab/yard/markdown_directive.rb +125 -0
  71. data/lib/openhab/yard/markdown_helper.rb +99 -0
  72. metadata +10 -3
@@ -14,15 +14,18 @@ end
14
14
  module OpenHAB
15
15
  module DSL
16
16
  #
17
- # Creates and manages OpenHAB Rules
17
+ # Creates and manages openHAB Rules
18
18
  #
19
19
  module Rules
20
- # A rules builder allows you to create OpenHAB rules.
20
+ # A rules builder allows you to create openHAB rules.
21
21
  #
22
22
  # Note that all methods on this module are also availabe directly on {OpenHAB::DSL}.
23
23
  #
24
24
  class Builder
25
25
  include Terse
26
+ include Core::EntityLookup
27
+
28
+ self.create_dummy_items = true
26
29
 
27
30
  # @return [org.openhab.core.automation.RuleProvider]
28
31
  attr_reader :provider
@@ -34,21 +37,24 @@ module OpenHAB
34
37
  #
35
38
  # Create a new rule
36
39
  #
40
+ # The rule must have at least one trigger and one execution block.
41
+ # To create a "script" without any triggers, use {#script}.
42
+ #
37
43
  # @param [String] name The rule name
38
- # @yield Block executed in the context of a {Rules::Builder}
39
- # @yieldparam [Rules::Builder] rule
44
+ # @yield Block executed in the context of a {Rules::BuilderDSL}
45
+ # @yieldparam [Rules::BuilderDSL] rule
40
46
  # Optional parameter to access the rule configuration from within execution blocks and guards.
41
- # @return [Rule]
47
+ # @return [Core::Rules::Rule, nil] The rule object, or nil if no rule was created.
42
48
  #
43
- # @see OpenHAB::DSL::Rules::Builder Rule builder for details on rule triggers, guards and execution blocks
49
+ # @see OpenHAB::DSL::Rules::BuilderDSL Rule BuilderDSL for details on rule triggers, guards and execution blocks
44
50
  # @see Rules::Terse Terse Rules
45
51
  #
46
52
  # @example
47
53
  # require "openhab/dsl"
48
54
  #
49
55
  # rule "name" do
50
- # <zero or more triggers>
51
- # <zero or more execution blocks>
56
+ # <one or more triggers>
57
+ # <one or more execution blocks>
52
58
  # <zero or more guards>
53
59
  # end
54
60
  #
@@ -85,7 +91,7 @@ module OpenHAB
85
91
  # @param [String] name A descriptive name
86
92
  # @param [String] id The script's ID
87
93
  # @yield [] Block executed when the script is executed.
88
- # @return [Rule]
94
+ # @return [Core::Rules::Rule]
89
95
  #
90
96
  def script(name = nil, id: nil, script: nil, &block)
91
97
  raise ArgumentError, "Block is required" unless block
@@ -108,7 +114,7 @@ module OpenHAB
108
114
  end
109
115
 
110
116
  #
111
- # Rule configuration for OpenHAB Rules engine
117
+ # Rule configuration for openHAB Rules engine
112
118
  #
113
119
  class BuilderDSL
114
120
  include Core::EntityLookup
@@ -117,6 +123,8 @@ module OpenHAB
117
123
  extend Property
118
124
  extend Forwardable
119
125
 
126
+ self.create_dummy_items = true
127
+
120
128
  delegate %i[triggers trigger_conditions attachments] => :@rule_triggers
121
129
 
122
130
  # @!visibility private
@@ -259,7 +267,7 @@ module OpenHAB
259
267
  #
260
268
  # @example
261
269
  # rule 'Delay sleeps between execution elements' do
262
- # on_start
270
+ # on_load
263
271
  # run { logger.info("Sleeping") }
264
272
  # delay 5.seconds
265
273
  # run { logger.info("Awake") }
@@ -267,7 +275,7 @@ module OpenHAB
267
275
  #
268
276
  # @example Like other execution blocks, multiple can exist in a single rule.
269
277
  # rule 'Multiple delays can exist in a rule' do
270
- # on_start
278
+ # on_load
271
279
  # run { logger.info("Sleeping") }
272
280
  # delay 5.seconds
273
281
  # run { logger.info("Sleeping Again") }
@@ -277,7 +285,7 @@ module OpenHAB
277
285
  #
278
286
  # @example You can use Ruby code in your rule across multiple execution blocks like a run and a delay.
279
287
  # rule 'Dim a switch on system startup over 100 seconds' do
280
- # on_start
288
+ # on_load
281
289
  # 100.times do
282
290
  # run { DimmerSwitch.dim }
283
291
  # delay 1.second
@@ -302,7 +310,7 @@ module OpenHAB
302
310
  #
303
311
  # @example
304
312
  # rule 'Turn switch ON or OFF based on value of another switch' do
305
- # on_start
313
+ # on_load
306
314
  # run { TestSwitch << ON }
307
315
  # otherwise { TestSwitch << OFF }
308
316
  # only_if { OtherSwitch.on? }
@@ -425,28 +433,28 @@ module OpenHAB
425
433
  #
426
434
  # @example String of {LocalTime}
427
435
  # rule 'Log an entry if started between 3:30:04 and midnight using strings' do
428
- # on_start
436
+ # on_load
429
437
  # run { logger.info ("Started at #{LocalTime.now}")}
430
438
  # between '3:30:04'..LocalTime::MIDNIGHT
431
439
  # end
432
440
  #
433
441
  # @example {LocalTime}
434
442
  # rule 'Log an entry if started between 3:30:04 and midnight using LocalTime objects' do
435
- # on_start
443
+ # on_load
436
444
  # run { logger.info ("Started at #{LocalTime.now}")}
437
445
  # between LocalTime.of(3, 30, 4)..LocalTime::MIDNIGHT
438
446
  # end
439
447
  #
440
448
  # @example String of {MonthDay}
441
449
  # rule 'Log an entry if started between March 9th and April 10ths' do
442
- # on_start
450
+ # on_load
443
451
  # run { logger.info ("Started at #{Time.now}")}
444
452
  # between '03-09'..'04-10'
445
453
  # end
446
454
  #
447
455
  # @example {MonthDay}
448
456
  # rule 'Log an entry if started between March 9th and April 10ths' do
449
- # on_start
457
+ # on_load
450
458
  # run { logger.info ("Started at #{Time.now}")}
451
459
  # between MonthDay.of(03,09)..'04-06'
452
460
  # end
@@ -533,8 +541,8 @@ module OpenHAB
533
541
  @rule_triggers = RuleTriggers.new
534
542
  @caller = caller_binding.eval "self"
535
543
  @ruby_triggers = []
544
+ @on_load_id = nil
536
545
  enabled(true)
537
- on_start(false)
538
546
  tags([])
539
547
  end
540
548
 
@@ -789,19 +797,19 @@ module OpenHAB
789
797
  # for is a reserved word in ruby, so use local_variable_get :for
790
798
  duration = binding.local_variable_get(:for)
791
799
 
800
+ @ruby_triggers << [:changed, items, { to: to, from: from, duration: duration }]
801
+
792
802
  from = [nil] if from.nil?
793
803
  to = [nil] if to.nil?
794
-
795
- @ruby_triggers << [:changed, items, { to: to, from: from, duration: duration }]
796
804
  items.each do |item|
797
805
  case item
798
806
  when Core::Things::Thing,
799
807
  Core::Things::ThingUID,
800
- Core::Items::GenericItem,
808
+ Core::Items::Item,
801
809
  Core::Items::GroupItem::Members
802
810
  nil
803
811
  else
804
- raise ArgumentError, "items must be a GenericItem, GroupItem::Members, Thing, or ThingUID"
812
+ raise ArgumentError, "items must be an Item, GroupItem::Members, Thing, or ThingUID"
805
813
  end
806
814
 
807
815
  logger.trace("Creating changed trigger for entity(#{item}), to(#{to.inspect}), from(#{from.inspect})")
@@ -818,7 +826,7 @@ module OpenHAB
818
826
  # Create a cron trigger
819
827
  #
820
828
  # @overload cron(expression, attach: nil)
821
- # @param [String, nil] expression [OpenHAB style cron expression](https://www.openhab.org/docs/configuration/rules-dsl.html#time-based-triggers)
829
+ # @param [String, nil] expression [openHAB style cron expression](https://www.openhab.org/docs/configuration/rules-dsl.html#time-based-triggers)
822
830
  # @param [Object] attach object to be attached to the trigger
823
831
  #
824
832
  # @example Using a cron expression
@@ -962,45 +970,116 @@ module OpenHAB
962
970
  end
963
971
 
964
972
  #
965
- # Run this rule when the script is loaded.
973
+ # Creates a trigger that executes when the script is loaded
966
974
  #
967
- # Execute the rule on OpenHAB start up and whenever the script is
968
- # reloaded. This is useful to perform initialization routines,
969
- # especially when combined with other triggers.
975
+ # Execute the rule whenever the script is first loaded, including on openHAB start up,
976
+ # and on subsequent reloads on file modifications.
977
+ # This is useful to perform initialization routines, especially when combined with other triggers.
970
978
  #
971
- # @param [true, false] run_on_start Run this rule on start, defaults to True
972
- # @param [Object] attach object to be attached to the trigger
979
+ # @param [Object] attach Object to be attached to the trigger
973
980
  # @return [void]
974
981
  #
975
982
  # @example
976
- # rule "startup rule" do
977
- # on_start
983
+ # rule "script startup rule" do
984
+ # on_load
978
985
  # run do
979
986
  # <calculate some item state>
980
987
  # end
981
988
  # end
982
989
  #
983
990
  # @example
984
- # rule 'Ensure all security lights are on' do
985
- # on_start
991
+ # rule "Ensure all security lights are on" do
992
+ # on_load
986
993
  # run { Security_Lights.on }
987
994
  # end
988
995
  #
989
- # rubocop:disable Style/OptionalBooleanParameter
990
- def on_start(run_on_start = true, attach: nil)
991
- @on_start = Struct.new(:enabled, :attach).new(run_on_start, attach)
996
+ def on_load(attach: nil)
997
+ # prevent overwriting @on_load_id
998
+ raise ArgumentError, "on_load can only be used once within a rule" if @on_load_id
999
+
1000
+ @on_load_id = SecureRandom.uuid
1001
+ attachments[@on_load_id] = attach
1002
+ end
1003
+
1004
+ #
1005
+ # Creates a trigger that executes when openHAB reaches a certain start level
1006
+ #
1007
+ # This will only trigger once during openHAB start up. It won't trigger on script reloads.
1008
+ #
1009
+ # @param [Integer,:rules,:ruleengine,:ui,:things,:complete] at_level
1010
+ # Zero or more start levels. Note that Startlevels less than 40 are not available as triggers
1011
+ # because the rule engine needs to start up first before it can execute any rules
1012
+ #
1013
+ # | Symbol | Start Level |
1014
+ # | ------------- | ----------- |
1015
+ # | `:osgi` | 10 |
1016
+ # | `:model` | 20 |
1017
+ # | `:state` | 30 |
1018
+ # | `:rules` | 40 |
1019
+ # | `:ruleengine` | 50 |
1020
+ # | `:ui` | 70 |
1021
+ # | `:things` | 80 |
1022
+ # | `:complete` | 100 |
1023
+ # @param [Array<Integer,:rules,:ruleengine,:ui,:things,:complete>] at_levels Fluent alias for `at_level`
1024
+ # @param [Object] attach Object to be attached to the trigger
1025
+ # @return [void]
1026
+ #
1027
+ # @example
1028
+ # rule "Trigger at openHAB system start" do
1029
+ # on_start # trigger at the default startlevel 100
1030
+ # run { logger.info "openHAB start up complete." }
1031
+ # end
1032
+ #
1033
+ # @example Trigger at a specific start level
1034
+ # rule "Trigger after things are loaded" do
1035
+ # on_start at_level: :things
1036
+ # run { logger.info "Things are ready!" }
1037
+ # end
1038
+ #
1039
+ # @example Trigger at multiple levels
1040
+ # rule "Multiple start up triggers" do
1041
+ # on_start at_levels: %i[ui things complete]
1042
+ # run do |event|
1043
+ # logger.info "openHAB startlevel has reached level #{event.startlevel}"
1044
+ # end
1045
+ # end
1046
+ #
1047
+ # @see https://www.openhab.org/docs/configuration/rules-dsl.html#system-based-triggers System based triggers
1048
+ #
1049
+ def on_start(at_level: nil, at_levels: nil, attach: nil)
1050
+ levels = Array.wrap(at_level) | Array.wrap(at_levels)
1051
+ levels = [100] if levels.empty?
1052
+
1053
+ levels.map! do |level|
1054
+ next level unless level.is_a?(Symbol)
1055
+
1056
+ begin
1057
+ klass = org.openhab.core.service.StartLevelService.java_class
1058
+ klass.declared_field("STARTLEVEL_#{level.upcase}").get_int(klass)
1059
+ rescue java.lang.NoSuchFieldException
1060
+ raise ArgumentError, "Invalid symbol for at_level: :#{level}"
1061
+ end
1062
+ end
1063
+
1064
+ @ruby_triggers << [:on_start, levels]
1065
+ levels.each do |level|
1066
+ logger.warn "Rule engine doesn't start until start level 40" if level < 40
1067
+ config = { startlevel: level }
1068
+ logger.trace("Creating a SystemStartlevelTrigger with startlevel=#{level}")
1069
+ Triggers::Trigger.new(rule_triggers: @rule_triggers)
1070
+ .append_trigger(type: "core.SystemStartlevelTrigger", config: config, attach: attach)
1071
+ end
992
1072
  end
993
- # rubocop:enable Style/OptionalBooleanParameter
994
1073
 
995
1074
  #
996
- # Create a trigger for when an item or group receives a command
1075
+ # Creates a trigger for when an item or group receives a command.
997
1076
  #
998
1077
  # The command/commands parameters are replicated for DSL fluency.
999
1078
  #
1000
1079
  # The `event` passed to run blocks will be an
1001
1080
  # {Core::Events::ItemCommandEvent}.
1002
1081
  #
1003
- # @param [GenericItem, GroupItem::Members] items Items to create trigger for
1082
+ # @param [Item, GroupItem::Members] items Items to create trigger for
1004
1083
  # @param [Core::TypesCommand, Array<Command>, Range, Proc] command commands to match for trigger
1005
1084
  # @param [Array<Command>, Range, Proc] commands Fluent alias for `command`
1006
1085
  # @param [Object] attach object to be attached to the trigger
@@ -1072,11 +1151,11 @@ module OpenHAB
1072
1151
 
1073
1152
  items.each do |item|
1074
1153
  case item
1075
- when Core::Items::GenericItem,
1154
+ when Core::Items::Item,
1076
1155
  Core::Items::GroupItem::Members
1077
1156
  nil
1078
1157
  else
1079
- raise ArgumentError, "items must be a GenericItem or GroupItem::Members"
1158
+ raise ArgumentError, "items must be an Item or GroupItem::Members"
1080
1159
  end
1081
1160
  commands.each do |cmd|
1082
1161
  logger.trace "Creating received command trigger for items #{item.inspect} and commands #{cmd.inspect}"
@@ -1194,7 +1273,7 @@ module OpenHAB
1194
1273
  # {Core::Events::ThingStatusInfoEvent} depending on if the triggering
1195
1274
  # element was an item or a thing.
1196
1275
  #
1197
- # @param [GenericItem, GroupItem::Members, Thing] items
1276
+ # @param [Item, GroupItem::Members, Thing] items
1198
1277
  # Objects to create trigger for.
1199
1278
  # @param [State, Array<State>, Range, Proc, Symbol, String] to
1200
1279
  # Only execute rule if the state matches `to` state(s). If the
@@ -1271,11 +1350,11 @@ module OpenHAB
1271
1350
  case item
1272
1351
  when Core::Things::Thing,
1273
1352
  Core::Things::ThingUID,
1274
- Core::Items::GenericItem,
1353
+ Core::Items::Item,
1275
1354
  Core::Items::GroupItem::Members
1276
1355
  nil
1277
1356
  else
1278
- raise ArgumentError, "items must be a GenericItem, GroupItem::Members, Thing, or ThingUID"
1357
+ raise ArgumentError, "items must be an Item, GroupItem::Members, Thing, or ThingUID"
1279
1358
  end
1280
1359
 
1281
1360
  logger.trace("Creating updated trigger for item(#{item}) to(#{to})")
@@ -1317,7 +1396,7 @@ module OpenHAB
1317
1396
  # @param [Object] attach object to be attached to the trigger
1318
1397
  # @return [void]
1319
1398
  #
1320
- # @example Watch `items` directory inside of the OpenHAB configuration path and log any changes.
1399
+ # @example Watch `items` directory inside of the openHAB configuration path and log any changes.
1321
1400
  # rule 'watch directory' do
1322
1401
  # watch OpenHAB::Core.config_folder / 'items'
1323
1402
  # run { |event| logger.info("#{event.path.basename} - #{event.type}") }
@@ -1358,36 +1437,6 @@ module OpenHAB
1358
1437
 
1359
1438
  # @!endgroup
1360
1439
 
1361
- #
1362
- # Checks if this rule should run on start
1363
- #
1364
- # @return [true, false] True if rule should run on start, false otherwise.
1365
- #
1366
- def on_start?
1367
- @on_start.enabled
1368
- end
1369
-
1370
- #
1371
- # Get the optional start attachment
1372
- #
1373
- # @return [Object] optional user provided attachment to the on_start method
1374
- #
1375
- # @!visibility private
1376
- def start_attachment
1377
- @on_start.attach
1378
- end
1379
-
1380
- # @!visibility private
1381
- #
1382
- # Run the supplied block inside the object instance of the object that created the rule
1383
- #
1384
- # @yield [] Block executed in context of the object creating the rule
1385
- #
1386
- #
1387
- def my(&block)
1388
- @caller.instance_eval(&block)
1389
- end
1390
-
1391
1440
  #
1392
1441
  # @return [String]
1393
1442
  #
@@ -1396,7 +1445,7 @@ module OpenHAB
1396
1445
  #<OpenHAB::DSL::Rules::Builder: #{uid}
1397
1446
  triggers=#{triggers.inspect},
1398
1447
  run blocks=#{run.inspect},
1399
- on_start=#{on_start?},
1448
+ on_load=#{!@on_load_id.nil?},
1400
1449
  Trigger Conditions=#{trigger_conditions.inspect},
1401
1450
  Trigger UIDs=#{triggers.map(&:id).inspect},
1402
1451
  Attachments=#{attachments.inspect}
@@ -1419,7 +1468,7 @@ module OpenHAB
1419
1468
  added_rule.actions.first.configuration.put("type", "application/x-ruby")
1420
1469
  added_rule.actions.first.configuration.put("script", script) if script
1421
1470
 
1422
- rule.execute(nil, { "event" => Struct.new(:attachment).new(start_attachment) }) if on_start?
1471
+ rule.execute(nil, { "module" => @on_load_id }) if @on_load_id
1423
1472
  added_rule
1424
1473
  end
1425
1474
 
@@ -1456,7 +1505,7 @@ module OpenHAB
1456
1505
  # @return [true,false] True if rule has triggers, false otherwise
1457
1506
  #
1458
1507
  def triggers?
1459
- on_start? || !triggers.empty?
1508
+ @on_load_id || !triggers.empty?
1460
1509
  end
1461
1510
 
1462
1511
  #
@@ -34,7 +34,7 @@ module OpenHAB
34
34
  #
35
35
  # Checks if a guard should run
36
36
  #
37
- # @param [OpenHAB Trigger Event] event OpenHAB Trigger Event
37
+ # @param [Object] event openHAB Trigger Event
38
38
  #
39
39
  # @return [true,false] True if guard is satisfied, false otherwise
40
40
  #
@@ -51,7 +51,7 @@ module OpenHAB
51
51
  #
52
52
  # @param [Array] conditions to check
53
53
  # @param [Symbol] check_type type of check to perform (:only_if or :not_if)
54
- # @param [Event] event OpenHAB event to see if it satisfies the guard
54
+ # @param [Event] event openHAB event to see if it satisfies the guard
55
55
  #
56
56
  # @return [true,false] True if guard is satisfied, false otherwise
57
57
  #
@@ -70,7 +70,7 @@ module OpenHAB
70
70
  # Execute the guard check
71
71
  #
72
72
  # @param [Symbol] check_type :only_if or :not_if to check
73
- # @param [OpenHAB Event] event event to check if meets guard
73
+ # @param [Object] event event to check if meets guard
74
74
  # @param [Array<Item>] items to check if satisfy criteria
75
75
  # @param [Array] procs to check if satisfy criteria
76
76
  #
@@ -87,7 +87,7 @@ module OpenHAB
87
87
  #
88
88
  # Check not_if guard
89
89
  #
90
- # @param [OpenHAB Event] event to check if meets guard
90
+ # @param [Object] event to check if meets guard
91
91
  # @param [Array<Item>] items to check if satisfy criteria
92
92
  # @param [Array] procs to check if satisfy criteria
93
93
  #
@@ -100,7 +100,7 @@ module OpenHAB
100
100
  #
101
101
  # Check only_if guard
102
102
  #
103
- # @param [OpenHAB Event] event to check if meets guard
103
+ # @param [Object] event to check if meets guard
104
104
  # @param [Array<Item>] items to check if satisfy criteria
105
105
  # @param [Array] procs to check if satisfy criteria
106
106
  #
@@ -18,6 +18,7 @@ module OpenHAB
18
18
  "core.ItemCommandTrigger",
19
19
  "core.ItemStateChangeTrigger",
20
20
  "core.ItemStateUpdateTrigger",
21
+ "core.SystemStartlevelTrigger",
21
22
  Triggers::Cron::CRON_TRIGGER_MODULE_ID
22
23
  ].freeze
23
24
  private_constant :KNOWN_TRIGGER_TYPES
@@ -61,6 +62,8 @@ module OpenHAB
61
62
  infer_rule_name_from_channel_link_trigger(trigger)
62
63
  when :thing_added, :thing_removed, :thing_updated
63
64
  infer_rule_name_from_thing_trigger(trigger)
65
+ when :on_start
66
+ infer_rule_name_from_on_start_trigger(items)
64
67
  end
65
68
  end
66
69
 
@@ -122,6 +125,22 @@ module OpenHAB
122
125
  }[trigger]
123
126
  end
124
127
 
128
+ # formulate a readable rule name from an on_start trigger
129
+ def infer_rule_name_from_on_start_trigger(levels)
130
+ levels = levels.map { |level| "#{level} (#{start_level_description(level)})" }
131
+ levels = format_array(levels)
132
+ "System Start Level reached #{levels}"
133
+ end
134
+
135
+ def start_level_description(level)
136
+ klass = org.openhab.core.service.StartLevelService.java_class
137
+ start_level_type = klass.declared_field("STARTLEVEL_OSGI").type
138
+ klass.declared_fields
139
+ .select { |field| field.type == start_level_type && field.name.start_with?("STARTLEVEL_") }
140
+ .find { |field| field.get_int(klass) == level }
141
+ .name.split("_", 2).last.downcase
142
+ end
143
+
125
144
  # format an array of words that will be the beginning of a sentence
126
145
  def format_beginning_of_sentence_array(array)
127
146
  result = format_array(array)
@@ -146,7 +165,7 @@ module OpenHAB
146
165
  return array[0] if array.length == 1
147
166
  return "#{array[0]} or #{array[1]}" if array.length == 2
148
167
 
149
- "any of #{array.join(", ")}"
168
+ "#{array[0..-2].join(", ")}, or #{array[-1]}"
150
169
  end
151
170
  end
152
171
  end
@@ -10,7 +10,7 @@ module OpenHAB
10
10
  module DSL
11
11
  module Rules
12
12
  #
13
- # Rule configuration for OpenHAB Rules engine
13
+ # Rule configuration for openHAB Rules engine
14
14
  #
15
15
  # @!visibility private
16
16
  class RuleTriggers
@@ -39,7 +39,7 @@ module OpenHAB
39
39
  # @param [Map] config map describing trigger configuration
40
40
  # @param [Object] attach object to be attached to the trigger
41
41
  #
42
- # @return [Trigger] OpenHAB trigger
42
+ # @return [org.openhab.core.automation.Trigger] openHAB trigger
43
43
  #
44
44
  def append_trigger(type:, config:, attach: nil, conditions: nil)
45
45
  config.transform_keys!(&:to_s)
@@ -57,7 +57,7 @@ module OpenHAB
57
57
  # @param [String] type of trigger
58
58
  # @param [Map] config map
59
59
  #
60
- # @return [OpenHAB Trigger] configured by type and supplied config
60
+ # @return [org.openhab.core.automation.Trigger] configured by type and supplied config
61
61
  #
62
62
  def self.trigger(type:, config:)
63
63
  logger.trace("Creating trigger of type '#{type}' config: #{config}")
@@ -56,6 +56,7 @@ module OpenHAB
56
56
  def_terse_rule(:thing_updated)
57
57
  def_terse_rule(:thing_removed)
58
58
  def_terse_rule(:updated)
59
+ def_terse_rule(:on_start)
59
60
  end
60
61
  end
61
62
  end
@@ -16,13 +16,13 @@ module OpenHAB
16
16
  #
17
17
  # Create the trigger
18
18
  #
19
- # @param [Object] item item to create trigger for
20
- # @param [Item State] from state to restrict trigger to
21
- # @param [Item State] to state to restrict trigger to
22
- # @param [Duration, nil] duration ruration to delay trigger until to state is met
19
+ # @param [Core::Items::Item, Core::Items::GroupItem::Members] item item to create trigger for
20
+ # @param [Core::Types::State, Array<Core::Types::State>, Range, Proc] from state to restrict trigger to
21
+ # @param [Core::Types::State, Array<Core::Types::State>, Range, Proc] to state to restrict trigger to
22
+ # @param [Duration, nil] duration duration to delay trigger until to state is met
23
23
  # @param [Object] attach object to be attached to the trigger
24
24
  #
25
- # @return [Trigger] OpenHAB triggers
25
+ # @return [org.openhab.core.automation.Trigger] openHAB triggers
26
26
  #
27
27
  def trigger(item:, from:, to:, duration:, attach:)
28
28
  if duration
@@ -50,13 +50,15 @@ module OpenHAB
50
50
  #
51
51
  # Create a TriggerDelay for for an item or group that is changed for a specific duration
52
52
  #
53
- # @param [Object] item to create trigger delay for
53
+ # @param [Core::Items::Item, Core::Items::GroupItem::Members] item to create trigger delay for
54
54
  # @param [Duration] duration to delay trigger for until condition is met
55
- # @param [Item State] to OpenHAB Item State item or group needs to change to
56
- # @param [Item State] from OpenHAB Item State item or group needs to be coming from
55
+ # @param [Core::Types::State, Array<Core::Types::State>, Range, Proc] to
56
+ # State item or group needs to change to
57
+ # @param [Core::Types::State, Array<Core::Types::State>, Range, Proc] from
58
+ # State item or group needs to be coming from
57
59
  # @param [Object] attach object to be attached to the trigger
58
60
  #
59
- # @return [Trigger] OpenHAB trigger
61
+ # @return [org.openhab.core.automation.Trigger]
60
62
  #
61
63
  def wait_trigger(item:, duration:, to: nil, from: nil, attach: nil)
62
64
  item_name = item.respond_to?(:name) ? item.name : item.to_s
@@ -68,11 +70,11 @@ module OpenHAB
68
70
 
69
71
  #
70
72
  # Creates a trigger with a range condition on either 'from' or 'to' field
71
- # @param [Object] item to create changed trigger on
72
- # @param [Object] from state to restrict trigger to
73
- # @param [Object] to state restrict trigger to
73
+ # @param [Core::Items::Item, Core::Items::GroupItem::Members] item to create changed trigger on
74
+ # @param [Range] from state to restrict trigger to
75
+ # @param [Range] to state restrict trigger to
74
76
  # @param [Object] attach object to be attached to the trigger
75
- # @return [Trigger] OpenHAB trigger
77
+ # @return [org.openhab.core.automation.Trigger]
76
78
  #
77
79
  def range_trigger(item:, from:, to:, attach:)
78
80
  from, to = Conditions::Proc.range_procs(from, to)
@@ -81,11 +83,11 @@ module OpenHAB
81
83
 
82
84
  #
83
85
  # Creates a trigger with a proc condition on either 'from' or 'to' field
84
- # @param [Object] item to create changed trigger on
85
- # @param [Object] from state to restrict trigger to
86
- # @param [Object] to state restrict trigger to
86
+ # @param [Core::Items::Item, Core::Items::GroupItem::Members] item to create changed trigger on
87
+ # @param [Proc] from state to restrict trigger to
88
+ # @param [Proc] to state restrict trigger to
87
89
  # @param [Object] attach object to be attached to the trigger
88
- # @return [Trigger] OpenHAB trigger
90
+ # @return [org.openhab.core.automation.Trigger]
89
91
  #
90
92
  def proc_trigger(item:, from:, to:, attach:)
91
93
  # swap from/to w/ nil if from/to is a proc
@@ -100,10 +102,11 @@ module OpenHAB
100
102
  #
101
103
  # Create a changed trigger
102
104
  #
103
- # @param [Object] item to create changed trigger on
104
- # @param [Object] from state to restrict trigger to
105
- # @param [Object] to state restrict trigger to
105
+ # @param [Core::Items::Item, Core::Items::GroupItem::Members] item to create changed trigger on
106
+ # @param [Core::Items::State, Array<Core::Items::State>] from state to restrict trigger to
107
+ # @param [Core::Items::State, Array<Core::Items::State>] to state restrict trigger to
106
108
  # @param [Object] attach object to be attached to the trigger
109
+ # @return [org.openhab.core.automation.Trigger]
107
110
  #
108
111
  def changed_trigger(item:, from:, to:, attach: nil, conditions: nil)
109
112
  type, config = case item
@@ -121,7 +124,7 @@ module OpenHAB
121
124
  #
122
125
  # Create a changed trigger for a thing
123
126
  #
124
- # @param [Thing] thing to detected changed states on
127
+ # @param [Core::Things::Thing] thing to detected changed states on
125
128
  # @param [String] from state to restrict trigger to
126
129
  # @param [String] to state to restrict trigger to
127
130
  #
@@ -152,7 +155,7 @@ module OpenHAB
152
155
  #
153
156
  # Create a changed trigger for group items
154
157
  #
155
- # @param [Group] group to detected changed states on
158
+ # @param [GroupItem] group to detected changed states on
156
159
  # @param [String] from state to restrict trigger to
157
160
  # @param [String] to to restrict trigger to
158
161
  #
@@ -160,7 +163,7 @@ module OpenHAB
160
163
  # second element is a Hash configuring trigger
161
164
  #
162
165
  def group(group:, from:, to:)
163
- config = { "groupName" => group.group.name }
166
+ config = { "groupName" => group.name }
164
167
  config["state"] = to.to_s if to
165
168
  config["previousState"] = from.to_s if from
166
169
  [GROUP_STATE_CHANGE, config]