openhab-scripting 2.16.1 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab.rb +12 -16
  3. data/lib/openhab/core/entity_lookup.rb +168 -0
  4. data/lib/openhab/core/openhab_setup.rb +31 -0
  5. data/lib/openhab/core/osgi.rb +61 -0
  6. data/lib/openhab/dsl/actions.rb +105 -0
  7. data/lib/openhab/dsl/dsl.rb +49 -0
  8. data/lib/openhab/{core/dsl → dsl}/gems.rb +0 -1
  9. data/lib/openhab/dsl/group.rb +100 -0
  10. data/lib/openhab/dsl/items/datetime_item.rb +97 -0
  11. data/lib/openhab/dsl/items/items.rb +46 -0
  12. data/lib/openhab/dsl/items/number_item.rb +352 -0
  13. data/lib/openhab/dsl/items/string_item.rb +120 -0
  14. data/lib/openhab/dsl/monkey_patch/actions/actions.rb +4 -0
  15. data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +32 -0
  16. data/lib/openhab/dsl/monkey_patch/events/events.rb +5 -0
  17. data/lib/openhab/dsl/monkey_patch/events/item_command.rb +23 -0
  18. data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +35 -0
  19. data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +33 -0
  20. data/lib/openhab/dsl/monkey_patch/items/contact_item.rb +61 -0
  21. data/lib/openhab/dsl/monkey_patch/items/dimmer_item.rb +193 -0
  22. data/lib/openhab/dsl/monkey_patch/items/group_item.rb +37 -0
  23. data/lib/openhab/dsl/monkey_patch/items/items.rb +133 -0
  24. data/lib/openhab/dsl/monkey_patch/items/metadata.rb +281 -0
  25. data/lib/openhab/dsl/monkey_patch/items/persistence.rb +70 -0
  26. data/lib/openhab/dsl/monkey_patch/items/switch_item.rb +95 -0
  27. data/lib/openhab/dsl/monkey_patch/ruby/number.rb +39 -0
  28. data/lib/openhab/dsl/monkey_patch/ruby/range.rb +47 -0
  29. data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +8 -0
  30. data/lib/openhab/dsl/monkey_patch/ruby/string.rb +41 -0
  31. data/lib/openhab/dsl/monkey_patch/ruby/time.rb +32 -0
  32. data/lib/openhab/dsl/monkey_patch/types/decimal_type.rb +70 -0
  33. data/lib/openhab/dsl/monkey_patch/types/on_off_type.rb +51 -0
  34. data/lib/openhab/dsl/monkey_patch/types/open_closed_type.rb +36 -0
  35. data/lib/openhab/dsl/monkey_patch/types/percent_type.rb +32 -0
  36. data/lib/openhab/dsl/monkey_patch/types/quantity_type.rb +69 -0
  37. data/lib/openhab/dsl/monkey_patch/types/types.rb +8 -0
  38. data/lib/openhab/dsl/persistence.rb +25 -0
  39. data/lib/openhab/dsl/rules/automation_rule.rb +342 -0
  40. data/lib/openhab/dsl/rules/guard.rb +134 -0
  41. data/lib/openhab/dsl/rules/property.rb +102 -0
  42. data/lib/openhab/dsl/rules/rule.rb +116 -0
  43. data/lib/openhab/dsl/rules/rule_config.rb +151 -0
  44. data/lib/openhab/dsl/rules/triggers/changed.rb +143 -0
  45. data/lib/openhab/dsl/rules/triggers/channel.rb +53 -0
  46. data/lib/openhab/dsl/rules/triggers/command.rb +104 -0
  47. data/lib/openhab/dsl/rules/triggers/cron.rb +177 -0
  48. data/lib/openhab/dsl/rules/triggers/trigger.rb +124 -0
  49. data/lib/openhab/dsl/rules/triggers/updated.rb +98 -0
  50. data/lib/openhab/dsl/states.rb +61 -0
  51. data/lib/openhab/dsl/things.rb +91 -0
  52. data/lib/openhab/dsl/time_of_day.rb +232 -0
  53. data/lib/openhab/dsl/timers.rb +77 -0
  54. data/lib/openhab/dsl/types/datetime.rb +326 -0
  55. data/lib/openhab/dsl/types/quantity.rb +290 -0
  56. data/lib/openhab/dsl/units.rb +39 -0
  57. data/lib/openhab/log/configuration.rb +21 -0
  58. data/lib/openhab/log/logger.rb +172 -0
  59. data/lib/openhab/version.rb +1 -1
  60. metadata +58 -58
  61. data/lib/openhab/configuration.rb +0 -16
  62. data/lib/openhab/core/cron.rb +0 -27
  63. data/lib/openhab/core/debug.rb +0 -34
  64. data/lib/openhab/core/dsl.rb +0 -51
  65. data/lib/openhab/core/dsl/actions.rb +0 -107
  66. data/lib/openhab/core/dsl/entities.rb +0 -140
  67. data/lib/openhab/core/dsl/group.rb +0 -93
  68. data/lib/openhab/core/dsl/items/items.rb +0 -51
  69. data/lib/openhab/core/dsl/items/number_item.rb +0 -323
  70. data/lib/openhab/core/dsl/items/string_item.rb +0 -122
  71. data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +0 -4
  72. data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +0 -22
  73. data/lib/openhab/core/dsl/monkey_patch/events.rb +0 -5
  74. data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +0 -13
  75. data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +0 -25
  76. data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +0 -26
  77. data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +0 -54
  78. data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +0 -182
  79. data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +0 -27
  80. data/lib/openhab/core/dsl/monkey_patch/items/items.rb +0 -132
  81. data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +0 -283
  82. data/lib/openhab/core/dsl/monkey_patch/items/persistence.rb +0 -72
  83. data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +0 -87
  84. data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +0 -41
  85. data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +0 -47
  86. data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +0 -7
  87. data/lib/openhab/core/dsl/monkey_patch/ruby/string.rb +0 -43
  88. data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +0 -60
  89. data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +0 -41
  90. data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +0 -25
  91. data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +0 -23
  92. data/lib/openhab/core/dsl/monkey_patch/types/quantity_type.rb +0 -58
  93. data/lib/openhab/core/dsl/monkey_patch/types/types.rb +0 -8
  94. data/lib/openhab/core/dsl/persistence.rb +0 -27
  95. data/lib/openhab/core/dsl/property.rb +0 -96
  96. data/lib/openhab/core/dsl/rule/automation_rule.rb +0 -348
  97. data/lib/openhab/core/dsl/rule/guard.rb +0 -136
  98. data/lib/openhab/core/dsl/rule/rule.rb +0 -117
  99. data/lib/openhab/core/dsl/rule/rule_config.rb +0 -153
  100. data/lib/openhab/core/dsl/rule/triggers/changed.rb +0 -145
  101. data/lib/openhab/core/dsl/rule/triggers/channel.rb +0 -55
  102. data/lib/openhab/core/dsl/rule/triggers/command.rb +0 -106
  103. data/lib/openhab/core/dsl/rule/triggers/cron.rb +0 -160
  104. data/lib/openhab/core/dsl/rule/triggers/trigger.rb +0 -126
  105. data/lib/openhab/core/dsl/rule/triggers/updated.rb +0 -100
  106. data/lib/openhab/core/dsl/states.rb +0 -63
  107. data/lib/openhab/core/dsl/things.rb +0 -93
  108. data/lib/openhab/core/dsl/time_of_day.rb +0 -231
  109. data/lib/openhab/core/dsl/timers.rb +0 -79
  110. data/lib/openhab/core/dsl/types/quantity.rb +0 -292
  111. data/lib/openhab/core/dsl/units.rb +0 -41
  112. data/lib/openhab/core/log.rb +0 -170
  113. data/lib/openhab/core/patch_load_path.rb +0 -7
  114. data/lib/openhab/core/startup_delay.rb +0 -23
  115. data/lib/openhab/osgi.rb +0 -59
@@ -1,51 +0,0 @@
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
- require 'core/dsl/persistence'
23
-
24
- module OpenHAB
25
- #
26
- # Holds core functions for OpenHAB Helper Library
27
- #
28
- module Core
29
- #
30
- # Module to be extended to access the OpenHAB Ruby DSL
31
- #
32
- module DSL
33
- # Extend the calling module/class with the DSL
34
- # rubocop: disable Metrics/MethodLength
35
- def self.extended(base)
36
- base.send :include, OpenHAB::Core::DSL::Rule
37
- base.send :include, OpenHAB::Core::DSL::Items
38
- base.send :include, OpenHAB::Core::DSL::Types
39
- base.send :include, OpenHAB::Core::DSL::Groups
40
- base.send :include, OpenHAB::Core::DSL::Units
41
- base.send :include, OpenHAB::Core::DSL::Actions
42
- base.send :include, OpenHAB::Core::DSL::Timers
43
- base.send :include, OpenHAB::Core::DSL::States
44
- base.send :include, OpenHAB::Core::DSL::Tod
45
- base.send :include, OpenHAB::Core::DSL::Persistence
46
- base.send :include, Things
47
- end
48
- # rubocop: enable Metrics/MethodLength
49
- end
50
- end
51
- end
@@ -1,107 +0,0 @@
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
@@ -1,140 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'pp'
4
- require 'java'
5
- require 'set'
6
- require 'core/dsl/group'
7
- require 'core/log'
8
- require 'core/dsl/items/number_item'
9
- require 'core/dsl/items/string_item'
10
-
11
- # Automation lookup and injection of OpenHab entities
12
- java_import org.openhab.core.items.GroupItem
13
-
14
- #
15
- # Implements const_missing to return OpenHAB items or things if mapping to missing name if they exist
16
- #
17
- # @param [String] name Capital string that was not set as a constant and to be looked up
18
- #
19
- # @return [Object] OpenHAB Item or Thing if their name exist in OpenHAB item and thing regestries
20
- #
21
- def Object.const_missing(name)
22
- EntityLookup.lookup_item(name) || EntityLookup.lookup_thing(name) || super
23
- end
24
-
25
- #
26
- # Manages access to OpenHAB entities
27
- #
28
- module EntityLookup
29
- include Logging
30
- #
31
- # Decorate items with Ruby wrappers
32
- #
33
- # @param [Array] items Array of items to decorate
34
- #
35
- # @return [Array] Array of decorated items
36
- #
37
- # rubocop: disable Metrics/MethodLength
38
- # Disabled line length - case dispatch pattern
39
- def self.decorate_items(*items)
40
- items.flatten.map do |item|
41
- case item
42
- when GroupItem
43
- decorate_group(item)
44
- when Java::Org.openhab.core.library.items::NumberItem
45
- OpenHAB::Core::DSL::Items::NumberItem.new(item)
46
- when Java::Org.openhab.core.library.items::StringItem
47
- OpenHAB::Core::DSL::Items::StringItem.new(item)
48
- else
49
- item
50
- end
51
- end
52
- end
53
- # rubocop: enable Metrics/MethodLength
54
-
55
- #
56
- # Loops up a Thing in the OpenHAB registry replacing '_' with ':'
57
- #
58
- # @param [String] name of Thing to lookup in Thing registry
59
- #
60
- # @return [Thing] if found, nil otherwise
61
- #
62
- def self.lookup_thing(name)
63
- logger.trace("Looking up thing(#{name})")
64
- # Convert from : syntax to underscore
65
- name = name.to_s if name.is_a? Symbol
66
-
67
- # Thing UIDs have at least 3 segements
68
- return if name.count('_') < 3
69
-
70
- name = name.gsub('_', ':')
71
- # rubocop: disable Style/GlobalVars
72
- $things.get(Java::OrgOpenhabCoreThing::ThingUID.new(name))
73
- # rubocop: enable Style/GlobalVars
74
- end
75
-
76
- #
77
- # Lookup OpenHAB items in item registry
78
- #
79
- # @param [String] name of item to lookup
80
- #
81
- # @return [Item] OpenHAB item if registry contains a matching item, nil othewise
82
- #
83
- def self.lookup_item(name)
84
- logger.trace("Looking up item(#{name})")
85
- name = name.to_s if name.is_a? Symbol
86
- # rubocop: disable Style/GlobalVars
87
- item = $ir.get(name)
88
- # rubocop: enable Style/GlobalVars
89
- EntityLookup.decorate_items(item).first
90
- end
91
-
92
- #
93
- # Automatically looks up OpenHAB items and things in appropriate registries
94
- #
95
- # @param [method] method Name of item to lookup
96
- # @param [<Type>] args method arguments
97
- # @param [<Type>] block supplied to missing method
98
- #
99
- # @return [Object] Item or Thing if found in registry
100
- #
101
- def method_missing(method, *args, &block)
102
- return if method.to_s == 'scriptLoaded'
103
- return if method.to_s == 'scriptUnloaded'
104
-
105
- logger.trace("method missing, performing OpenHab Lookup for: #{method}")
106
- EntityLookup.lookup_item(method) || EntityLookup.lookup_thing(method) || super
107
- end
108
-
109
- #
110
- # Checks if this method responds to the missing method
111
- #
112
- # @param [String] method_name Name of the method to check
113
- # @param [Boolean] _include_private boolean if private methods should be checked
114
- #
115
- # @return [Boolean] true if this object will respond to the supplied method, false otherwise
116
- #
117
- def respond_to_missing?(method_name, _include_private = false)
118
- logger.trace("Checking if OpenHAB entites exist for #{method_name}")
119
- method_name = method_name.to_s if method_name.is_a? Symbol
120
-
121
- method_name == 'scriptLoaded' ||
122
- method_name == 'scriptUnloaded' ||
123
- EntityLookup.lookup_item(method_name) ||
124
- EntityLookup.lookup_thing(method_name) ||
125
- super
126
- end
127
-
128
- #
129
- # Decorate a group from an item base
130
- #
131
- # @param [OpenHAB item] item item to convert to a group item
132
- #
133
- # @return [OpenHAB::Core::DSL::Groups::Group] Group created from supplied item
134
- #
135
- def self.decorate_group(item)
136
- group = OpenHAB::Core::DSL::Groups::Group.new(Set.new(EntityLookup.decorate_items(item.all_members.to_a)))
137
- group.group = item
138
- group
139
- end
140
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'delegate'
4
- require 'forwardable'
5
- require 'openhab/core/dsl/entities'
6
-
7
- module OpenHAB
8
- module Core
9
- module DSL
10
- #
11
- # Provides access to OpenHAB Groups
12
- #
13
- module Groups
14
- #
15
- # Indicator struct interpreted by rules to trigger based on items contained in a group
16
- #
17
- GroupItems = Struct.new(:group, keyword_init: true)
18
-
19
- #
20
- # Provide access to groups as a set
21
- #
22
- class Groups < SimpleDelegator
23
- #
24
- # Get a OpenHAB Group by name
25
- # @param [String] name of the group to retrieve
26
- #
27
- # @return [Set] of OpenHAB Groups
28
- #
29
- def[](name)
30
- group = EntityLookup.lookup_item(name)
31
- group.is_a?(Group) ? group : nil
32
- end
33
- end
34
-
35
- #
36
- # Retreive all OpenHAB groups
37
- #
38
- # @return [Set] of OpenHAB Groups
39
- #
40
- def groups
41
- # rubocop: disable Style/GlobalVars
42
- Groups.new(EntityLookup.decorate_items($ir.items.select { |item| item.is_a? GroupItem }))
43
- # rubocop: enable Style/GlobalVars
44
- end
45
-
46
- # Group class that provides access to OpenHAB group object and delegates other methods to
47
- # a set of group items
48
- class Group < SimpleDelegator
49
- extend Forwardable
50
-
51
- java_import org.openhab.core.items.GroupItem
52
-
53
- # @return [org.openhab.core.items.GroupItem] OpenHAB Java Group Item
54
- attr_accessor :group
55
-
56
- # @!macro [attach] def_delegators
57
- # @!method $2
58
- # Forwards to org.openhab.core.items.GroupItem
59
- # @see org::openhab::core::items::GroupItem
60
- def_delegator :@group, :name
61
- def_delegator :@group, :label
62
-
63
- #
64
- # Gets members of this group that are themselves a group
65
- #
66
- # @return [Set] Set of members that are of type group
67
- #
68
- def groups
69
- group.members.grep(org.openhab.core.items.GroupItem)
70
- end
71
-
72
- #
73
- # Wraps the group in a struct, this method is intended to be called
74
- # as an indicator to the rule method that the user wishes to trigger
75
- # based on changes to group items
76
- #
77
- # @return [GroupItems] Indicator struct used by rules engine to trigger based on item changes
78
- #
79
- def items
80
- GroupItems.new(group: group)
81
- end
82
-
83
- #
84
- # @return [String] List of groups seperated by commas
85
- #
86
- def to_s
87
- "[#{map(&:to_s).join(',')}]"
88
- end
89
- end
90
- end
91
- end
92
- end
93
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'java'
4
- require 'openhab/core/dsl/entities'
5
-
6
- module OpenHAB
7
- module Core
8
- module DSL
9
- #
10
- # Manages OpenHAB items
11
- #
12
- module Items
13
- #
14
- # Delegates to underlying set of all OpenHAB Items, provides convenience methods
15
- #
16
- class Items < SimpleDelegator
17
- # Fetches the named item from the the ItemRegistry
18
- # @param [String] name
19
- # @return Item from registry, nil if item missing or requested item is a Group Type
20
- def[](name)
21
- # rubocop: disable Style/GlobalVars
22
- item = $ir.getItem(name)
23
- # rubocop: enable Style/GlobalVars
24
- item.is_a?(GroupItem) ? nil : item
25
- rescue Java::OrgOpenhabCoreItems::ItemNotFoundException
26
- nil
27
- end
28
-
29
- # Returns true if the given item name exists
30
- # @param name [String] Item name to check
31
- # @return [Boolean] true if the item exists, false otherwise
32
- def include?(name)
33
- # rubocop: disable Style/GlobalVars
34
- !$ir.getItems(name).empty?
35
- # rubocop: enable Style/GlobalVars
36
- end
37
- alias key? include?
38
- end
39
-
40
- java_import org.openhab.core.items.GroupItem
41
- # Fetches all non-group items from the item registry
42
- # @return [OpenHAB::Core::DSL::Items::Items]
43
- def items
44
- # rubocop: disable Style/GlobalVars
45
- Items.new(EntityLookup.decorate_items($ir.items.reject { |item| item.is_a? GroupItem }))
46
- # rubocop: enable Style/GlobalVars
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,323 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bigdecimal'
4
- require 'forwardable'
5
- require 'java'
6
- require 'openhab/core/dsl/types/quantity'
7
-
8
- module OpenHAB
9
- module Core
10
- module DSL
11
- module Items
12
- #
13
- # Delegation to OpenHAB Number Item
14
- #
15
- # rubocop: disable Metrics/ClassLength
16
- # Disabled because this class has a single responsibility, there does not appear a logical
17
- # way of breaking it up into multiple classes
18
- class NumberItem < Numeric
19
- extend Forwardable
20
-
21
- def_delegator :@number_item, :to_s
22
-
23
- java_import org.openhab.core.library.types.DecimalType
24
- java_import org.openhab.core.library.types.QuantityType
25
- java_import 'tec.uom.se.format.SimpleUnitFormat'
26
- java_import 'tec.uom.se.AbstractUnit'
27
-
28
- #
29
- # Create a new NumberItem
30
- #
31
- # @param [Java::Org::openhab::core::library::items::NumberItem] number_item OpenHAB number item to delegate to
32
- #
33
- def initialize(number_item)
34
- @number_item = number_item
35
- super()
36
- end
37
-
38
- #
39
- # Check if NumberItem is truthy? as per defined by library
40
- #
41
- # @return [Boolean] True if item is not in state UNDEF or NULL and value is not zero.
42
- #
43
- def truthy?
44
- @number_item.state? && @number_item.state != DecimalType::ZERO
45
- end
46
-
47
- #
48
- # Coerce objects into a NumberItem
49
- #
50
- # @param [Object] other object to coerce to a NumberItem if possible
51
- #
52
- # @return [Object] NumberItem, QuantityTypes, BigDecimal or nil depending on NumberItem configuration
53
- # and/or supplied object
54
- #
55
- def coerce(other)
56
- logger.trace("Coercing #{self} as a request from #{other.class}")
57
- case other
58
- when Quantity then coerce_from_quantity(other)
59
- when Numeric then coerce_from_numeric(other)
60
- else
61
- logger.trace("#{self} cannot be coerced to #{other.class}")
62
- nil
63
- end
64
- end
65
-
66
- #
67
- # Compare NumberItem to supplied object
68
- #
69
- # @param [Object] other object to compare to
70
- #
71
- # @return [Integer] -1,0,1 or nil depending on value supplied,
72
- # nil comparison to supplied object is not possible.
73
- #
74
- # rubocop: disable Metrics/AbcSize
75
- def <=>(other)
76
- logger.trace("NumberItem #{self} <=> #{other} (#{other.class})")
77
- case other
78
- when NumberItem then number_item_compare(other)
79
- when Numeric then @number_item.state.to_big_decimal.to_d <=> other.to_d
80
- when String then @number_item.state <=> QuantityType.new(other) if dimension
81
- else
82
- other = other.state if other.respond_to? :state
83
- @number_item.state <=> other
84
- end
85
- end
86
- # rubocop: enable Metrics/AbcSize
87
-
88
- #
89
- # Convert NumberItem to a Quantity
90
- #
91
- # @param [Object] other String or Unit representing an OpenHAB Unit
92
- #
93
- # @return [OpenHAB::Core::DSL::Types::Quantity] NumberItem converted to supplied Unit
94
- #
95
- def |(other)
96
- other = SimpleUnitFormat.instance.unitFor(other) if other.is_a? String
97
-
98
- if dimension
99
- to_qt | other
100
- else
101
- Quantity.new(QuantityType.new(to_d.to_java, other))
102
- end
103
- end
104
-
105
- #
106
- # Convert NumberItem to a Quantity
107
- #
108
- # @return [OpenHAB::Core::DSL::Types::Quantity] NumberItem converted to a QuantityUnit
109
- #
110
- def to_qt
111
- if dimension
112
- Quantity.new(@number_item.get_state_as(QuantityType))
113
- else
114
- Quantity.new(QuantityType.new(to_d.to_java, AbstractUnit::ONE))
115
- end
116
- end
117
-
118
- #
119
- # Converts the NumberItem to an Integer
120
- #
121
- # @return [Integer] NumberItem as an integer
122
- #
123
- def to_i
124
- to_d&.to_i
125
- end
126
-
127
- #
128
- # Converts the NumberItem to a float
129
- #
130
- # @return [Float] NumberItem as a float
131
- #
132
- def to_f
133
- to_d&.to_f
134
- end
135
-
136
- #
137
- # Converts the NumberItem to a BigDecimal
138
- #
139
- # @return [BigDecimal] NumberItem as a BigDecimal
140
- #
141
- def to_d
142
- @number_item.state.to_big_decimal.to_d if @number_item.state.respond_to? :to_big_decimal
143
- end
144
-
145
- #
146
- # Get the Dimension attached to the NumberItem
147
- #
148
- # @return [Java::org::openhab::core::library::types::QuantityType] dimension
149
- #
150
- def dimension
151
- @number_item.dimension
152
- end
153
-
154
- #
155
- # Forward missing methods to Openhab Number Item if they are defined
156
- #
157
- # @param [String] meth method name
158
- # @param [Array] args arguments for method
159
- # @param [Proc] block <description>
160
- #
161
- # @return [Object] Value from delegated method in OpenHAB NumberItem
162
- #
163
- def method_missing(meth, *args, &block)
164
- logger.trace("Method missing, performing dynamic lookup for: #{meth}")
165
- if @number_item.respond_to?(meth)
166
- @number_item.__send__(meth, *args, &block)
167
- elsif ::Kernel.method_defined?(meth) || ::Kernel.private_method_defined?(meth)
168
- ::Kernel.instance_method(meth).bind_call(self, *args, &block)
169
- else
170
- super(meth, *args, &block)
171
- end
172
- end
173
-
174
- #
175
- # Checks if this method responds to the missing method
176
- #
177
- # @param [String] method_name Name of the method to check
178
- # @param [Boolean] _include_private boolean if private methods should be checked
179
- #
180
- # @return [Boolean] true if this object will respond to the supplied method, false otherwise
181
- #
182
- def respond_to_missing?(method_name, _include_private = false)
183
- @number_item.respond_to?(method_name) ||
184
- ::Kernel.method_defined?(method_name) ||
185
- ::Kernel.private_method_defined?(method_name)
186
- end
187
-
188
- %w[+ - * /].each do |operation|
189
- define_method(operation) do |other|
190
- logger.trace("Execution math operation '#{operation}' on #{inspect} with #{other.inspect}")
191
- left_operand, right_operand = operands_for_operation(other)
192
- left_operand.public_send(operation, right_operand)
193
- end
194
- end
195
-
196
- private
197
-
198
- #
199
- # Get the operands for any operation
200
- #
201
- # @param [Object] other object to convert to a compatible operand
202
- #
203
- # @return [Array[Object,Object]] of operands where the first value is the left operand
204
- # and the second value is the right operand
205
- #
206
- def operands_for_operation(other)
207
- case other
208
- when NumberItem then number_item_operands(other)
209
- when Numeric then [to_d, other.to_d]
210
- when String then string_operands(other)
211
- else
212
- return other.coerce(to_d) if other.respond_to? :coerce
213
-
214
- raise ArgumentError, "#{other.class} can't be coerced into a NumberItem"
215
- end
216
- end
217
-
218
- #
219
- # Get operands for an operation when the right operand is provided as a string
220
- #
221
- # @param [String] other right operand
222
- #
223
- # @return [Array[QuantityType,QuantiyType]] of operands where the first value is the left operand
224
- # and the second value is the right operand
225
- #
226
- def string_operands(other)
227
- return [to_qt, Quantity.new(other)] if dimension
228
-
229
- raise ArgumentError, 'Strings are only valid operands if NumberItem is dimensions=ed.'
230
- end
231
-
232
- #
233
- # Get operands for an operation when the right operand is provided is another number item
234
- #
235
- # @param [NumberItem] other right operand
236
- #
237
- # @return [Array<QuantityType,QuantityType>,Array<BigDecimal,BigDecimal>] of operands depending on
238
- # if the left or right operand has a dimensions
239
- #
240
- def number_item_operands(other)
241
- if dimension || other.dimension
242
- dimensioned_operands(other)
243
- else
244
- logger.trace("Both objects lack dimension, self='#{self}' other='#{other}'")
245
- # If nothing has a dimension, just use BigDecimals
246
- [to_d, other.to_d]
247
- end
248
- end
249
-
250
- #
251
- # Get operands for an operation when the left or right operand has a dimension
252
- #
253
- # @param [NumberItem] other right operand
254
- #
255
- # @return [Array<QuantityType,QuantityType>] of operands
256
- #
257
- def dimensioned_operands(other)
258
- logger.trace("Dimensions self='#{dimension}' other='#{other.dimension}'")
259
- if dimension
260
- if other.dimension
261
- # If both numbers have dimensions, do the math on the quantity types.
262
- [to_qt, other.to_qt]
263
- else
264
- # If this number has dimension and the other does not,
265
- # do math with this quantity type and the other as a big decimal
266
- [to_qt, other]
267
- end
268
- else
269
- # If this number has no dimension and the other does, convert this into a dimensionless quantity
270
- [to_qt, other]
271
- end
272
- end
273
-
274
- #
275
- # Compare two number items, taking into account any dimensions
276
- #
277
- # @param [NumberItem] other number item
278
- #
279
- # @return [-1,0,1] depending on if other object is less than, equal to or greater than self
280
- #
281
- def number_item_compare(other)
282
- if other.dimension
283
- logger.trace('Other is dimensioned, converting self and other to QuantityTypes to compare')
284
- to_qt <=> other.to_qt
285
- else
286
- @number_item.state <=> other.state
287
- end
288
- end
289
-
290
- #
291
- # Coerce from a numberic object depnding on dimension and state
292
- #
293
- # @param [Numeric] other numeric object to convert
294
- #
295
- # @return [Array<QuantityType,QuantityType>,Array<BigDecimal,BigDecimal>,nil] depending on
296
- # if this object has a dimension or state
297
- #
298
- def coerce_from_numeric(other)
299
- if dimension
300
- [Quantity.new(other), to_qt]
301
- elsif @number_item.state?
302
- [other.to_d, @number_item.state.to_big_decimal.to_d]
303
- end
304
- end
305
-
306
- #
307
- # Coerce when other is a quantity
308
- #
309
- # @param [QuantityType] other
310
- #
311
- # @return [Array<QuanityType,QuantityType] other and self as a quantity type
312
- #
313
- def coerce_from_quantity(other)
314
- as_qt = to_qt
315
- logger.trace("Converted #{self} to a Quantity #{as_qt}")
316
- [other, as_qt]
317
- end
318
- end
319
- end
320
- end
321
- end
322
- end
323
- # rubocop: enable Metrics/ClassLength