openhab-scripting 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/workflow.yml +327 -0
  3. data/.gitignore +17 -0
  4. data/.java-version +1 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/CHANGELOG.md +113 -0
  8. data/Gemfile +28 -0
  9. data/Gemfile.lock +245 -0
  10. data/Guardfile +35 -0
  11. data/LICENSE +277 -0
  12. data/README.md +23 -0
  13. data/Rakefile +406 -0
  14. data/bin/console +15 -0
  15. data/bin/setup +8 -0
  16. data/config/userdata/config/org/openhab/restauth.config +3 -0
  17. data/cucumber.yml +1 -0
  18. data/docs/_config.yml +135 -0
  19. data/docs/contributing/index.md +47 -0
  20. data/docs/examples/conversions.md +123 -0
  21. data/docs/examples/index.md +61 -0
  22. data/docs/index.md +19 -0
  23. data/docs/installation/index.md +26 -0
  24. data/docs/motivation/index.md +27 -0
  25. data/docs/usage/execution.md +9 -0
  26. data/docs/usage/execution/delay.md +48 -0
  27. data/docs/usage/execution/otherwise.md +30 -0
  28. data/docs/usage/execution/run.md +70 -0
  29. data/docs/usage/execution/triggered.md +48 -0
  30. data/docs/usage/guards.md +51 -0
  31. data/docs/usage/guards/between.md +30 -0
  32. data/docs/usage/guards/not_if.md +41 -0
  33. data/docs/usage/guards/only_if.md +40 -0
  34. data/docs/usage/index.md +11 -0
  35. data/docs/usage/items.md +66 -0
  36. data/docs/usage/items/contact.md +84 -0
  37. data/docs/usage/items/dimmer.md +147 -0
  38. data/docs/usage/items/groups.md +76 -0
  39. data/docs/usage/items/number.md +225 -0
  40. data/docs/usage/items/string.md +49 -0
  41. data/docs/usage/items/switch.md +85 -0
  42. data/docs/usage/misc.md +7 -0
  43. data/docs/usage/misc/actions.md +108 -0
  44. data/docs/usage/misc/duration.md +21 -0
  45. data/docs/usage/misc/gems.md +25 -0
  46. data/docs/usage/misc/logging.md +21 -0
  47. data/docs/usage/misc/metadata.md +128 -0
  48. data/docs/usage/misc/store_states.md +42 -0
  49. data/docs/usage/misc/time_of_day.md +69 -0
  50. data/docs/usage/misc/timers.md +67 -0
  51. data/docs/usage/rule.md +43 -0
  52. data/docs/usage/things.md +29 -0
  53. data/docs/usage/triggers.md +8 -0
  54. data/docs/usage/triggers/changed.md +57 -0
  55. data/docs/usage/triggers/channel.md +54 -0
  56. data/docs/usage/triggers/command.md +69 -0
  57. data/docs/usage/triggers/cron.md +19 -0
  58. data/docs/usage/triggers/every.md +76 -0
  59. data/docs/usage/triggers/updated.md +78 -0
  60. data/lib/openhab.rb +39 -0
  61. data/lib/openhab/configuration.rb +16 -0
  62. data/lib/openhab/core/cron.rb +27 -0
  63. data/lib/openhab/core/debug.rb +34 -0
  64. data/lib/openhab/core/dsl.rb +47 -0
  65. data/lib/openhab/core/dsl/actions.rb +107 -0
  66. data/lib/openhab/core/dsl/entities.rb +103 -0
  67. data/lib/openhab/core/dsl/gems.rb +29 -0
  68. data/lib/openhab/core/dsl/group.rb +91 -0
  69. data/lib/openhab/core/dsl/items/items.rb +39 -0
  70. data/lib/openhab/core/dsl/items/number_item.rb +217 -0
  71. data/lib/openhab/core/dsl/items/string_item.rb +102 -0
  72. data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +4 -0
  73. data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +22 -0
  74. data/lib/openhab/core/dsl/monkey_patch/events.rb +5 -0
  75. data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +13 -0
  76. data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +25 -0
  77. data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +26 -0
  78. data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +54 -0
  79. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +125 -0
  80. data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +27 -0
  81. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +130 -0
  82. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +259 -0
  83. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +86 -0
  84. data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +69 -0
  85. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +46 -0
  86. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +5 -0
  87. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +24 -0
  88. data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +41 -0
  89. data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +25 -0
  90. data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +23 -0
  91. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +7 -0
  92. data/lib/openhab/core/dsl/property.rb +85 -0
  93. data/lib/openhab/core/dsl/rule/channel.rb +41 -0
  94. data/lib/openhab/core/dsl/rule/cron.rb +115 -0
  95. data/lib/openhab/core/dsl/rule/guard.rb +99 -0
  96. data/lib/openhab/core/dsl/rule/item.rb +207 -0
  97. data/lib/openhab/core/dsl/rule/rule.rb +374 -0
  98. data/lib/openhab/core/dsl/rule/triggers.rb +77 -0
  99. data/lib/openhab/core/dsl/states.rb +63 -0
  100. data/lib/openhab/core/dsl/things.rb +93 -0
  101. data/lib/openhab/core/dsl/time_of_day.rb +203 -0
  102. data/lib/openhab/core/dsl/timers.rb +85 -0
  103. data/lib/openhab/core/dsl/types/quantity.rb +255 -0
  104. data/lib/openhab/core/dsl/units.rb +41 -0
  105. data/lib/openhab/core/duration.rb +69 -0
  106. data/lib/openhab/core/log.rb +175 -0
  107. data/lib/openhab/core/patch_load_path.rb +7 -0
  108. data/lib/openhab/core/startup_delay.rb +22 -0
  109. data/lib/openhab/osgi.rb +52 -0
  110. data/lib/openhab/version.rb +9 -0
  111. data/openhab-scripting.gemspec +30 -0
  112. data/openhab_rules/warmup.rb +5 -0
  113. metadata +157 -0
@@ -0,0 +1,19 @@
1
+ ---
2
+ layout: default
3
+ title: Cron
4
+ nav_order: 2
5
+ has_children: false
6
+ parent: Triggers
7
+ grand_parent: Usage
8
+ ---
9
+
10
+
11
+ # Cron
12
+ Utilizes [OpenHAB style cron expressions](https://www.openhab.org/docs/configuration/rules-dsl.html#time-based-triggers) to trigger rules. This property can be utilized when you need to represent complex expressions not possible with the simpler [every](#Every) syntax.
13
+
14
+ ```ruby
15
+ rule 'Using Cron Syntax' do
16
+ cron '43 46 13 ? * ?'
17
+ run { logger.info "Cron rule executed" }
18
+ end
19
+ ```
@@ -0,0 +1,76 @@
1
+ ---
2
+ layout: default
3
+ title: Every
4
+ nav_order: 1
5
+ has_children: false
6
+ parent: Triggers
7
+ grand_parent: Usage
8
+ ---
9
+
10
+ # Every
11
+
12
+ | Value | Description | Example |
13
+ | ----------------- | ---------------------------------------- | ---------- |
14
+ | :second | Execute rule every second | :second |
15
+ | :minute | Execute rule very minute | :minute |
16
+ | :hour | Execute rule every hour | :hour |
17
+ | :day | Execute rule every day | :day |
18
+ | :week | Execute rule every week | :week |
19
+ | :month | Execute rule every month | :month |
20
+ | :year | Execute rule one a year | :year |
21
+ | :monday | Execute rule every Monday at midnight | :monday |
22
+ | :tuesday | Execute rule every Tuesday at midnight | :tuesday |
23
+ | :wednesday | Execute rule every Wednesday at midnight | :wednesday |
24
+ | :thursday | Execute rule every Thursday at midnight | :thursday |
25
+ | :friday | Execute rule every Friday at midnight | :friday |
26
+ | :saturday | Execute rule every Saturday at midnight | :saturday |
27
+ | :sunday | Execute rule every Sunday at midnight | :sunday |
28
+ | [Integer].seconds | Execute a rule every X seconds | 5.seconds |
29
+ | [Integer].minutes | Execute rule every X minutes | 3.minutes |
30
+ | [Integer].hours | Execute rule every X minutes | 10.hours |
31
+
32
+ | Option | Description | Example |
33
+ | ------ | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
34
+ | :at | Limit the execution to specific times of day. The value can either be a String or a TimeOfDay object | at: '16:45' or at: TimeOfDay.new(h: 16, m: 45) |
35
+
36
+
37
+ # Examples
38
+
39
+ ```ruby
40
+ rule 'Log the rule name every minute' do
41
+ description 'This rule will create a log every minute'
42
+ every :minute
43
+ run { logger.info "Rule '#{name}' executed" }
44
+ end
45
+ ```
46
+
47
+
48
+ ```ruby
49
+ rule 'Log an entry at 11:21' do
50
+ every :day, at: '11:21'
51
+ run { logger.info("Rule #{name} run at #{TimeOfDay.now}") }
52
+ end
53
+
54
+ # The above rule could also be expressed using TimeOfDay class as below
55
+
56
+ rule 'Log an entry at 11:21' do
57
+ every :day, at: TimeOfDay.new(h: 11, m: 21)
58
+ run { logger.info("Rule #{name} run at #{TimeOfDay.now}") }
59
+ end
60
+ ```
61
+
62
+
63
+ ```ruby
64
+ rule 'Log an entry Wednesdays at 11:21' do
65
+ every :wednesday, at: '11:21'
66
+ run { logger.info("Rule #{name} run at #{TimeOfDay.now}") }
67
+ end
68
+ ```
69
+
70
+
71
+ ```ruby
72
+ rule 'Every 5 seconds' do
73
+ every 5.seconds
74
+ run { logger.info "Rule #{name} executed" }
75
+ end
76
+ ```
@@ -0,0 +1,78 @@
1
+ ---
2
+ layout: default
3
+ title: Updated
4
+ nav_order: 4
5
+ has_children: false
6
+ parent: Triggers
7
+ grand_parent: Usage
8
+ ---
9
+
10
+ # Updated
11
+
12
+
13
+
14
+ | Options | Description | Example |
15
+ | ------- | -------------------------------------------------- | ----------------------- |
16
+ | to | Only execute rule if update state matches to state | `to: 7` or `to: [7,14]` |
17
+
18
+ Changed accepts Items, Things or Groups.
19
+
20
+ The to value restricts the rule from running to only if the updated state matches. If the updated element being used as a trigger is a thing than the to and from values will accept symbols and strings, where the symbol matches the [supported status](https://www.openhab.org/docs/concepts/things.html).
21
+
22
+ The examples below assume the following background:
23
+
24
+ | type | name | group | state |
25
+ | ------ | ---------------- | ---------- | ----- |
26
+ | Number | Alarm_Mode | AlarmModes | 7 |
27
+ | Number | Alarm_Mode_Other | AlarmModes | 7 |
28
+
29
+
30
+ ```ruby
31
+ rule 'Execute rule when item is updated to any value' do
32
+ updated Alarm_Mode
33
+ run { logger.info("Alarm Mode Updated") }
34
+ end
35
+ ```
36
+
37
+ ```ruby
38
+ rule 'Execute rule when item is updated to specific number' do
39
+ updated Alarm_Mode, to: 7
40
+ run { logger.info("Alarm Mode Updated") }
41
+ end
42
+ ```
43
+
44
+ ```ruby
45
+ rule 'Execute rule when item is updated to one of many specific states' do
46
+ updated Alarm_Mode, to: [7,14]
47
+ run { logger.info("Alarm Mode Updated")}
48
+ end
49
+ ```
50
+
51
+ ```ruby
52
+ rule 'Execute rule when group is updated to any state' do
53
+ updated AlarmModes
54
+ triggered { |item| logger.info("Group #{item.id} updated")}
55
+ end
56
+ ```
57
+
58
+ ```ruby
59
+ rule 'Execute rule when member of group is changed to any state' do
60
+ updated AlarmModes.items
61
+ triggered { |item| logger.info("Group item #{item.id} updated")}
62
+ end
63
+ ```
64
+
65
+ ```ruby
66
+ rule 'Execute rule when member of group is changed to one of many states' do
67
+ updated AlarmModes.items, to: [7,14]
68
+ triggered { |item| logger.info("Group item #{item.id} updated")}
69
+ end
70
+ ```
71
+
72
+ Works with things as well:
73
+ ```ruby
74
+ rule 'Execute rule when thing is updated' do
75
+ updated things['astro:sun:home'], :to => :uninitialized
76
+ run { |event| logger.info("Thing #{event.uid} status <trigger> to #{event.status}") }
77
+ end
78
+ ```
data/lib/openhab.rb ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # First patch the $LOAD_PATH to include lib dir
4
+ require 'openhab/core/patch_load_path'
5
+
6
+ require 'openhab/core/startup_delay'
7
+ require 'openhab/core/log'
8
+ require 'openhab/core/debug'
9
+ require 'openhab/core/dsl'
10
+
11
+ require 'openhab/version'
12
+
13
+ #
14
+ # Module used to extend base object with OpenHAB Library functionality
15
+ #
16
+ module OpenHAB
17
+ include Logging
18
+ #
19
+ # Extends calling object with DSL and helper methods
20
+ #
21
+ # @param [Object] base Object to decorate with DSL and helper methods
22
+ #
23
+ #
24
+ def self.extended(base)
25
+ base.extend Logging
26
+ base.extend Debug
27
+ base.extend EntityLookup
28
+ base.extend OpenHAB::Core::DSL
29
+ base.extend OpenHAB::Core::DSL::Tod
30
+
31
+ base.send :include, OpenHAB::Core::DSL::Tod
32
+ base.send :include, OpenHAB::Core::DSL::Items
33
+ base.send :include, OpenHAB::Core::DSL::Types
34
+ logger.info "OpenHAB JRuby Scripting Library Version #{OpenHAB::VERSION} Loaded"
35
+ end
36
+ end
37
+
38
+ # Extend caller with OpenHAB methods
39
+ extend OpenHAB
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This module holds global configuration values
4
+ module Configuration
5
+ # -*- coding: utf-8 -*-
6
+ LOG_PREFIX = 'jsr223.jruby'
7
+
8
+ #
9
+ # Gets the log prefix
10
+ #
11
+ # @return [String] Prefix for all log entries
12
+ #
13
+ def self.log_prefix
14
+ LOG_PREFIX
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ #
6
+ # Module for Cron related methods
7
+ #
8
+ module Cron
9
+ #
10
+ # Retruns a default map for cron expressions that fires every second
11
+ # This map is usually updated via merge by other methods to refine cron type triggers.
12
+ #
13
+ # @return [Map] Map with symbols for :seconds, :minute, :hour, :dom, :month, :dow configured to fire every second
14
+ #
15
+ def cron_expression_map
16
+ {
17
+ second: '*',
18
+ minute: '*',
19
+ hour: '*',
20
+ dom: '?',
21
+ month: '*',
22
+ dow: '?'
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pp'
4
+ require 'core/log'
5
+ require 'core/dsl/things'
6
+
7
+ #
8
+ # Module to support debugging information about the Ruby or OpenHAB environment
9
+ #
10
+ module Debug
11
+ include Logging
12
+ include OpenHAB::Core::DSL::Things
13
+
14
+ #
15
+ # Print the loadpath, instance and global variables
16
+ #
17
+ def debug_variables
18
+ pp "Instance #{instance_variables}"
19
+ pp "Global #{global_variables}"
20
+ pp "Load Path #{$LOAD_PATH}"
21
+ # pp "Constants #{Module.constants}"
22
+ end
23
+
24
+ #
25
+ # Print information about the OpenHAB instance
26
+ #
27
+ def debug_openhab
28
+ logger.debug { "Things - Count #{things.size}" }
29
+ things.each do |thing|
30
+ logger.debug { "Thing:(#{thing.label}) UID:(#{thing.uid}) Channels(#{thing.channels.map(&:uid).join(', ')})" }
31
+ end
32
+ # logger.debug { $things.getAll.join(", ") }
33
+ end
34
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ require 'core/log'
5
+ require 'core/dsl/monkey_patch/events'
6
+ require 'core/dsl/monkey_patch/ruby/ruby'
7
+ require 'core/dsl/monkey_patch/items/items'
8
+ require 'core/dsl/monkey_patch/types/types'
9
+ require 'core/dsl/monkey_patch/actions/actions'
10
+ require 'core/dsl/rule/rule'
11
+ require 'core/dsl/actions'
12
+ require 'core/dsl/timers'
13
+ require 'core/dsl/group'
14
+ require 'core/dsl/things'
15
+ require 'core/dsl/items/items'
16
+ require 'core/dsl/items/number_item'
17
+ require 'core/dsl/time_of_day'
18
+ require 'core/dsl/gems'
19
+ require 'core/dsl/units'
20
+ require 'core/dsl/types/quantity'
21
+ require 'core/dsl/states'
22
+
23
+ module OpenHAB
24
+ #
25
+ # Holds core functions for OpenHAB Helper Library
26
+ #
27
+ module Core
28
+ #
29
+ # Module to be extended to access the OpenHAB Ruby DSL
30
+ #
31
+ module DSL
32
+ # Extend the calling module/class with the DSL
33
+ def self.extended(base)
34
+ base.send :include, OpenHAB::Core::DSL::Rule
35
+ base.send :include, OpenHAB::Core::DSL::Items
36
+ base.send :include, OpenHAB::Core::DSL::Types
37
+ base.send :include, OpenHAB::Core::DSL::Groups
38
+ base.send :include, OpenHAB::Core::DSL::Units
39
+ base.send :include, OpenHAB::Core::DSL::Actions
40
+ base.send :include, OpenHAB::Core::DSL::Timers
41
+ base.send :include, OpenHAB::Core::DSL::States
42
+ base.send :include, OpenHAB::Core::DSL::Tod
43
+ base.send :include, Things
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+ require 'openhab/osgi'
5
+
6
+ module OpenHAB
7
+ module Core
8
+ module DSL
9
+ #
10
+ # Module to import and steramlime access to OpenHAB actions
11
+ #
12
+ module Actions
13
+ java_import org.openhab.core.library.types.PercentType
14
+ include Logging
15
+
16
+ OpenHAB::OSGI.services('org.openhab.core.model.script.engine.action.ActionService')&.each do |service|
17
+ java_import service.actionClass.to_s
18
+ logger.trace("Loaded ACTION: #{service.actionClass}")
19
+ end
20
+ # Import common actions
21
+ %w[Exec HTTP Ping].each { |action| java_import "org.openhab.core.model.script.actions.#{action}" }
22
+
23
+ #
24
+ # Return an OpenHAB Action object for the given scope and thing
25
+ #
26
+ # @param scope [String] The action scope
27
+ # @param thing_uid [String] Thing UID
28
+ #
29
+ # @return [Object] OpenHAB action
30
+ #
31
+ def actions(scope, thing_uid)
32
+ # rubocop: disable Style/GlobalVars
33
+ $actions.get(scope, thing_uid)
34
+ # rubocop: enable Style/GlobalVars
35
+ end
36
+
37
+ #
38
+ # Gets the list of action objects associated with a specific ThingUID
39
+ #
40
+ # @param [Java::org::openhab::core::thing::ThingUID] thing_uid to get associated actions for
41
+ #
42
+ # @return [Array] of action objects associated with thing_uid, may be empty
43
+ #
44
+ def actions_for_thing(thing_uid)
45
+ thing_uid = thing_uid.to_s
46
+ # rubocop: disable Style/GlobalVars
47
+ action_keys = $actions.action_keys
48
+ # rubocop: enable Style/GlobalVars
49
+ logger.trace( "Registered actions: '#{action_keys}' for thing '#{thing_uid}'")
50
+ action_keys.map { |action_key| action_key.split('-', 2) }
51
+ .select { |action_pair| action_pair.last == thing_uid }
52
+ .map(&:first)
53
+ .map { |scope| actions(scope, thing_uid) }
54
+ end
55
+
56
+ #
57
+ # Send notification to an email or broadcast
58
+ #
59
+ # @param msg [String] The notification message to send
60
+ # @param email [String] The email address to send to. If nil, the message will be broadcasted
61
+ #
62
+ # @return [void]
63
+ #
64
+ def notify(msg, email: nil)
65
+ unless defined? NotificationAction
66
+ raise NoMethodError, 'NotificationAction is not available. Please install the OpenHAB cloud addon'
67
+ end
68
+
69
+ if email
70
+ NotificationAction.sendNotification email, msg
71
+ else
72
+ NotificationAction.sendBroadcastNotification msg
73
+ end
74
+ end
75
+
76
+ #
77
+ # Say text via OpenHAB Text-To-Speech service, Voice.say()
78
+ #
79
+ # @param text [String] The text to say
80
+ # @param voice [String] Specify a particular voice to use
81
+ # @param sink [String] Specify a particular sink to output the speech
82
+ # @param volume [PercentType] Specify the volume for the speech
83
+ #
84
+ # @return [void]
85
+ #
86
+ def say(text, voice: nil, sink: nil, volume: nil)
87
+ volume = PercentType.new(volume&.to_i) unless volume.is_a?(PercentType) || volume.nil?
88
+ Voice.say text, voice, sink, volume
89
+ end
90
+
91
+ #
92
+ # Play an audio file via OpenHAB sound service, Audio.playSound()
93
+ #
94
+ # @param filename [String] The sound file to play
95
+ # @param sink [String] Specify a particular sink to output the speech
96
+ # @param volume [PercentType] Specify the volume for the speech
97
+ #
98
+ # @return [void]
99
+ #
100
+ def play_sound(filename, sink: nil, volume: nil)
101
+ volume = PercentType.new(volume&.to_i) unless volume.is_a?(PercentType) || volume.nil?
102
+ Audio.playSound sink, filename, volume
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end