openhab-scripting 2.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/workflow.yml +327 -0
- data/.gitignore +17 -0
- data/.java-version +1 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +113 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +245 -0
- data/Guardfile +35 -0
- data/LICENSE +277 -0
- data/README.md +23 -0
- data/Rakefile +406 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/config/userdata/config/org/openhab/restauth.config +3 -0
- data/cucumber.yml +1 -0
- data/docs/_config.yml +135 -0
- data/docs/contributing/index.md +47 -0
- data/docs/examples/conversions.md +123 -0
- data/docs/examples/index.md +61 -0
- data/docs/index.md +19 -0
- data/docs/installation/index.md +26 -0
- data/docs/motivation/index.md +27 -0
- data/docs/usage/execution.md +9 -0
- data/docs/usage/execution/delay.md +48 -0
- data/docs/usage/execution/otherwise.md +30 -0
- data/docs/usage/execution/run.md +70 -0
- data/docs/usage/execution/triggered.md +48 -0
- data/docs/usage/guards.md +51 -0
- data/docs/usage/guards/between.md +30 -0
- data/docs/usage/guards/not_if.md +41 -0
- data/docs/usage/guards/only_if.md +40 -0
- data/docs/usage/index.md +11 -0
- data/docs/usage/items.md +66 -0
- data/docs/usage/items/contact.md +84 -0
- data/docs/usage/items/dimmer.md +147 -0
- data/docs/usage/items/groups.md +76 -0
- data/docs/usage/items/number.md +225 -0
- data/docs/usage/items/string.md +49 -0
- data/docs/usage/items/switch.md +85 -0
- data/docs/usage/misc.md +7 -0
- data/docs/usage/misc/actions.md +108 -0
- data/docs/usage/misc/duration.md +21 -0
- data/docs/usage/misc/gems.md +25 -0
- data/docs/usage/misc/logging.md +21 -0
- data/docs/usage/misc/metadata.md +128 -0
- data/docs/usage/misc/store_states.md +42 -0
- data/docs/usage/misc/time_of_day.md +69 -0
- data/docs/usage/misc/timers.md +67 -0
- data/docs/usage/rule.md +43 -0
- data/docs/usage/things.md +29 -0
- data/docs/usage/triggers.md +8 -0
- data/docs/usage/triggers/changed.md +57 -0
- data/docs/usage/triggers/channel.md +54 -0
- data/docs/usage/triggers/command.md +69 -0
- data/docs/usage/triggers/cron.md +19 -0
- data/docs/usage/triggers/every.md +76 -0
- data/docs/usage/triggers/updated.md +78 -0
- data/lib/openhab.rb +39 -0
- data/lib/openhab/configuration.rb +16 -0
- data/lib/openhab/core/cron.rb +27 -0
- data/lib/openhab/core/debug.rb +34 -0
- data/lib/openhab/core/dsl.rb +47 -0
- data/lib/openhab/core/dsl/actions.rb +107 -0
- data/lib/openhab/core/dsl/entities.rb +103 -0
- data/lib/openhab/core/dsl/gems.rb +29 -0
- data/lib/openhab/core/dsl/group.rb +91 -0
- data/lib/openhab/core/dsl/items/items.rb +39 -0
- data/lib/openhab/core/dsl/items/number_item.rb +217 -0
- data/lib/openhab/core/dsl/items/string_item.rb +102 -0
- data/lib/openhab/core/dsl/monkey_patch/actions/actions.rb +4 -0
- data/lib/openhab/core/dsl/monkey_patch/actions/script_thing_actions.rb +22 -0
- data/lib/openhab/core/dsl/monkey_patch/events.rb +5 -0
- data/lib/openhab/core/dsl/monkey_patch/events/item_command.rb +13 -0
- data/lib/openhab/core/dsl/monkey_patch/events/item_state_changed.rb +25 -0
- data/lib/openhab/core/dsl/monkey_patch/events/thing_status_info.rb +26 -0
- data/lib/openhab/core/dsl/monkey_patch/items/contact_item.rb +54 -0
- data/lib/openhab/core/dsl/monkey_patch/items/dimmer_item.rb +125 -0
- data/lib/openhab/core/dsl/monkey_patch/items/group_item.rb +27 -0
- data/lib/openhab/core/dsl/monkey_patch/items/items.rb +130 -0
- data/lib/openhab/core/dsl/monkey_patch/items/metadata.rb +259 -0
- data/lib/openhab/core/dsl/monkey_patch/items/switch_item.rb +86 -0
- data/lib/openhab/core/dsl/monkey_patch/ruby/number.rb +69 -0
- data/lib/openhab/core/dsl/monkey_patch/ruby/range.rb +46 -0
- data/lib/openhab/core/dsl/monkey_patch/ruby/ruby.rb +5 -0
- data/lib/openhab/core/dsl/monkey_patch/types/decimal_type.rb +24 -0
- data/lib/openhab/core/dsl/monkey_patch/types/on_off_type.rb +41 -0
- data/lib/openhab/core/dsl/monkey_patch/types/open_closed_type.rb +25 -0
- data/lib/openhab/core/dsl/monkey_patch/types/percent_type.rb +23 -0
- data/lib/openhab/core/dsl/monkey_patch/types/types.rb +7 -0
- data/lib/openhab/core/dsl/property.rb +85 -0
- data/lib/openhab/core/dsl/rule/channel.rb +41 -0
- data/lib/openhab/core/dsl/rule/cron.rb +115 -0
- data/lib/openhab/core/dsl/rule/guard.rb +99 -0
- data/lib/openhab/core/dsl/rule/item.rb +207 -0
- data/lib/openhab/core/dsl/rule/rule.rb +374 -0
- data/lib/openhab/core/dsl/rule/triggers.rb +77 -0
- data/lib/openhab/core/dsl/states.rb +63 -0
- data/lib/openhab/core/dsl/things.rb +93 -0
- data/lib/openhab/core/dsl/time_of_day.rb +203 -0
- data/lib/openhab/core/dsl/timers.rb +85 -0
- data/lib/openhab/core/dsl/types/quantity.rb +255 -0
- data/lib/openhab/core/dsl/units.rb +41 -0
- data/lib/openhab/core/duration.rb +69 -0
- data/lib/openhab/core/log.rb +175 -0
- data/lib/openhab/core/patch_load_path.rb +7 -0
- data/lib/openhab/core/startup_delay.rb +22 -0
- data/lib/openhab/osgi.rb +52 -0
- data/lib/openhab/version.rb +9 -0
- data/openhab-scripting.gemspec +30 -0
- data/openhab_rules/warmup.rb +5 -0
- metadata +157 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'java'
|
5
|
+
require 'set'
|
6
|
+
require 'core/dsl/group'
|
7
|
+
require 'core/dsl/items/number_item'
|
8
|
+
require 'core/dsl/items/string_item'
|
9
|
+
|
10
|
+
# Automation lookup and injection of OpenHab entities
|
11
|
+
java_import org.openhab.core.items.GroupItem
|
12
|
+
|
13
|
+
#
|
14
|
+
# Implements const_missing to return OpenHAB items or things if mapping to missing name if they exist
|
15
|
+
#
|
16
|
+
# @param [String] name Capital string that was not set as a constant and to be looked up
|
17
|
+
#
|
18
|
+
# @return [Object] OpenHAB Item or Thing if their name exist in OpenHAB item and thing regestries
|
19
|
+
#
|
20
|
+
def Object.const_missing(name)
|
21
|
+
EntityLookup.lookup_item(name) || EntityLookup.lookup_thing(name) || super
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Manages access to OpenHAB entities
|
26
|
+
#
|
27
|
+
module EntityLookup
|
28
|
+
#
|
29
|
+
# Decorate items with Ruby wrappers
|
30
|
+
#
|
31
|
+
# @param [Array] items Array of items to decorate
|
32
|
+
#
|
33
|
+
# @return [Array] Array of decorated items
|
34
|
+
#
|
35
|
+
def self.decorate_items(*items)
|
36
|
+
items.flatten.map do |item|
|
37
|
+
case item
|
38
|
+
when GroupItem
|
39
|
+
group = item
|
40
|
+
item = OpenHAB::Core::DSL::Groups::Group.new(Set.new(EntityLookup.decorate_items(item.all_members.to_a)))
|
41
|
+
item.group = group
|
42
|
+
item
|
43
|
+
when Java::Org.openhab.core.library.items::NumberItem
|
44
|
+
OpenHAB::Core::DSL::Items::NumberItem.new(item)
|
45
|
+
when Java::Org.openhab.core.library.items::StringItem
|
46
|
+
OpenHAB::Core::DSL::Items::StringItem.new(item)
|
47
|
+
else
|
48
|
+
item
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Loops up a Thing in the OpenHAB registry replacing '_' with ':'
|
55
|
+
#
|
56
|
+
# @param [String] name of Thing to lookup in Thing registry
|
57
|
+
#
|
58
|
+
# @return [Thing] if found, nil otherwise
|
59
|
+
#
|
60
|
+
def self.lookup_thing(name)
|
61
|
+
# Convert from : syntax to underscore
|
62
|
+
name = name.to_s if name.is_a? Symbol
|
63
|
+
|
64
|
+
# Thing UIDs have at least 3 segements
|
65
|
+
return if name.count('_') < 3
|
66
|
+
|
67
|
+
name = name.gsub('_', ':')
|
68
|
+
# rubocop: disable Style/GlobalVars
|
69
|
+
$things.get(Java::OrgOpenhabCoreThing::ThingUID.new(name))
|
70
|
+
# rubocop: enable Style/GlobalVars
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Lookup OpenHAB items in item registry
|
75
|
+
#
|
76
|
+
# @param [String] name of item to lookup
|
77
|
+
#
|
78
|
+
# @return [Item] OpenHAB item if registry contains a matching item, nil othewise
|
79
|
+
#
|
80
|
+
def self.lookup_item(name)
|
81
|
+
name = name.to_s if name.is_a? Symbol
|
82
|
+
# rubocop: disable Style/GlobalVars
|
83
|
+
item = $ir.get(name)
|
84
|
+
# rubocop: enable Style/GlobalVars
|
85
|
+
EntityLookup.decorate_items(item).first
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Automatically looks up OpenHAB items and things in appropriate registries
|
90
|
+
#
|
91
|
+
# @param [method] method Name of item to lookup
|
92
|
+
# @param [<Type>] args method arguments
|
93
|
+
# @param [<Type>] block supplied to missing method
|
94
|
+
#
|
95
|
+
# @return [Object] Item or Thing if found in registry
|
96
|
+
#
|
97
|
+
def method_missing(method, *args, &block)
|
98
|
+
return if method.to_s == 'scriptLoaded'
|
99
|
+
return if method.to_s == 'scriptUnloaded'
|
100
|
+
|
101
|
+
EntityLookup.lookup_item(method) || EntityLookup.lookup_thing(method) || super
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'core/log'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler/inline'
|
7
|
+
|
8
|
+
include Logging
|
9
|
+
logger.debug('Bundler required')
|
10
|
+
rescue LoadError
|
11
|
+
include Logging
|
12
|
+
logger.debug('Bundler not found installing')
|
13
|
+
|
14
|
+
begin
|
15
|
+
require 'rubygems/commands/install_command'
|
16
|
+
cmd = Gem::Commands::InstallCommand.new
|
17
|
+
cmd.handle_options ['--no-document', 'bundler', '-v', '2.1.4']
|
18
|
+
cmd.execute
|
19
|
+
logger.debug('Bundler is installed')
|
20
|
+
require 'bundler/inline'
|
21
|
+
rescue Gem::SystemExitException => e
|
22
|
+
if e.exit_code.zero?
|
23
|
+
logger.debug('Bundler is installed')
|
24
|
+
require 'bundler/inline'
|
25
|
+
else
|
26
|
+
logger.error("Error installing bundler, exit code: #{e}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,91 @@
|
|
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
|
+
Groups.new(EntityLookup.decorate_items($ir.items.select { |item| item.is_a? GroupItem }))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Group class that provides access to OpenHAB group object and delegates other methods to
|
45
|
+
# a set of group items
|
46
|
+
class Group < SimpleDelegator
|
47
|
+
extend Forwardable
|
48
|
+
|
49
|
+
java_import org.openhab.core.items.GroupItem
|
50
|
+
|
51
|
+
# @return [org.openhab.core.items.GroupItem] OpenHAB Java Group Item
|
52
|
+
attr_accessor :group
|
53
|
+
|
54
|
+
# @!macro [attach] def_delegators
|
55
|
+
# @!method $2
|
56
|
+
# Forwards to org.openhab.core.items.GroupItem
|
57
|
+
# @see org::openhab::core::items::GroupItem
|
58
|
+
def_delegator :@group, :name
|
59
|
+
def_delegator :@group, :label
|
60
|
+
|
61
|
+
#
|
62
|
+
# Gets members of this group that are themselves a group
|
63
|
+
#
|
64
|
+
# @return [Set] Set of members that are of type group
|
65
|
+
#
|
66
|
+
def groups
|
67
|
+
group.members.grep(org.openhab.core.items.GroupItem)
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Wraps the group in a struct, this method is intended to be called
|
72
|
+
# as an indicator to the rule method that the user wishes to trigger
|
73
|
+
# based on changes to group items
|
74
|
+
#
|
75
|
+
# @return [GroupItems] Indicator struct used by rules engine to trigger based on item changes
|
76
|
+
#
|
77
|
+
def items
|
78
|
+
GroupItems.new(group: group)
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# @return [String] List of groups seperated by commas
|
83
|
+
#
|
84
|
+
def to_s
|
85
|
+
"[#{map(&:to_s).join(',')}]"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,39 @@
|
|
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
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
java_import org.openhab.core.items.GroupItem
|
29
|
+
# Fetches all non-group items from the item registry
|
30
|
+
# @return [OpenHAB::Core::DSL::Items::Items]
|
31
|
+
def items
|
32
|
+
# rubocop: disable Style/GlobalVars
|
33
|
+
Items.new(EntityLookup.decorate_items($ir.items.reject { |item| item.is_a? GroupItem }))
|
34
|
+
# rubocop: enable Style/GlobalVars
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,217 @@
|
|
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
|
+
class NumberItem < Numeric
|
16
|
+
extend Forwardable
|
17
|
+
|
18
|
+
def_delegator :@number_item, :to_s
|
19
|
+
|
20
|
+
java_import org.openhab.core.library.types.DecimalType
|
21
|
+
java_import org.openhab.core.library.types.QuantityType
|
22
|
+
java_import 'tec.uom.se.format.SimpleUnitFormat'
|
23
|
+
java_import 'tec.uom.se.AbstractUnit'
|
24
|
+
|
25
|
+
#
|
26
|
+
# Create a new NumberItem
|
27
|
+
#
|
28
|
+
# @param [Java::Org::openhab::core::library::items::NumberItem] number_item OpenHAB number item to delegate to
|
29
|
+
#
|
30
|
+
def initialize(number_item)
|
31
|
+
@number_item = number_item
|
32
|
+
super()
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Check if NumberItem is truthy? as per defined by library
|
37
|
+
#
|
38
|
+
# @return [Boolean] True if item is not in state UNDEF or NULL and value is not zero.
|
39
|
+
#
|
40
|
+
def truthy?
|
41
|
+
@number_item.state? && @number_item.state != DecimalType::ZERO
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Coerce objects into a NumberItem
|
46
|
+
#
|
47
|
+
# @param [Object] other object to coerce to a NumberItem if possible
|
48
|
+
#
|
49
|
+
# @return [Object] NumberItem, QuantityTypes, BigDecimal or nil depending on NumberItem configuration and/or supplied object
|
50
|
+
#
|
51
|
+
def coerce(other)
|
52
|
+
logger.trace("Coercing #{self} as a request from #{other.class}")
|
53
|
+
case other
|
54
|
+
when Quantity
|
55
|
+
as_qt = to_qt
|
56
|
+
logger.trace("Converted #{self} to a Quantity #{as_qt}")
|
57
|
+
[other, as_qt]
|
58
|
+
when Numeric
|
59
|
+
if dimension
|
60
|
+
[Quantity.new(other), to_qt]
|
61
|
+
elsif @number_item.state?
|
62
|
+
[BigDecimal(other), @number_item.state.to_big_decimal.to_d]
|
63
|
+
end
|
64
|
+
else
|
65
|
+
logger.trace("#{self} cannot be coereced to #{other.class}")
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Compare NumberItem to supplied object
|
72
|
+
#
|
73
|
+
# @param [Object] other object to compare to
|
74
|
+
#
|
75
|
+
# @return [Integer] -1,0,1 or nil depending on value supplied, nil comparison to supplied object is not possible.
|
76
|
+
#
|
77
|
+
def <=>(other)
|
78
|
+
logger.trace("Comparing #{self} to #{other}")
|
79
|
+
case other
|
80
|
+
when NumberItem
|
81
|
+
if other.dimension
|
82
|
+
logger.trace('Other is dimensioned, converting self and other to QuantityTypes to compare')
|
83
|
+
to_qt <=> other.to_qt
|
84
|
+
else
|
85
|
+
@number_item.state <=> other.state
|
86
|
+
end
|
87
|
+
when Numeric
|
88
|
+
@number_item.state.to_big_decimal.to_d <=> BigDecimal(other)
|
89
|
+
when String
|
90
|
+
@number_item.state <=> QuantityType.new(other) if dimension
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Convert NumberItem to a Quantity
|
96
|
+
#
|
97
|
+
# @param [Object] other String or Unit representing an OpenHAB Unit
|
98
|
+
#
|
99
|
+
# @return [OpenHAB::Core::DSL::Types::Quantity] NumberItem converted to supplied Unit
|
100
|
+
#
|
101
|
+
def |(other)
|
102
|
+
other = SimpleUnitFormat.instance.unitFor(other) if other.is_a? String
|
103
|
+
|
104
|
+
if dimension
|
105
|
+
to_qt | other
|
106
|
+
else
|
107
|
+
Quantity.new(QuantityType.new(to_d.to_java, other))
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Convert NumberItem to a Quantity
|
113
|
+
#
|
114
|
+
# @return [OpenHAB::Core::DSL::Types::Quantity] NumberItem converted to a QuantityUnit
|
115
|
+
#
|
116
|
+
def to_qt
|
117
|
+
if dimension
|
118
|
+
Quantity.new(@number_item.get_state_as(QuantityType))
|
119
|
+
else
|
120
|
+
Quantity.new(QuantityType.new(to_d.to_java, AbstractUnit::ONE))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Converts the NumberItem to an Integer
|
126
|
+
#
|
127
|
+
# @return [Integer] NumberItem as an integer
|
128
|
+
#
|
129
|
+
def to_i
|
130
|
+
to_d&.to_i
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Converts the NumberItem to a float
|
135
|
+
#
|
136
|
+
# @return [Float] NumberItem as a float
|
137
|
+
#
|
138
|
+
def to_f
|
139
|
+
to_d&.to_f
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# Converts the NumberItem to a BigDecimal
|
144
|
+
#
|
145
|
+
# @return [BigDecimal] NumberItem as a BigDecimal
|
146
|
+
#
|
147
|
+
def to_d
|
148
|
+
@number_item.state.to_big_decimal.to_d if @number_item.state.respond_to? :to_big_decimal
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
# Get the Dimension attached to the NumberItem
|
153
|
+
#
|
154
|
+
# @return [Java::org::openhab::core::library::types::QuantityType] dimension
|
155
|
+
#
|
156
|
+
def dimension
|
157
|
+
@number_item.dimension
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Forward missing methods to Openhab Number Item if they are defined
|
162
|
+
#
|
163
|
+
# @param [String] meth method name
|
164
|
+
# @param [Array] args arguments for method
|
165
|
+
# @param [Proc] block <description>
|
166
|
+
#
|
167
|
+
# @return [Object] Value from delegated method in OpenHAB NumberItem
|
168
|
+
#
|
169
|
+
def method_missing(meth, *args, &block)
|
170
|
+
if @number_item.respond_to?(meth)
|
171
|
+
@number_item.__send__(meth, *args, &block)
|
172
|
+
elsif ::Kernel.method_defined?(meth) || ::Kernel.private_method_defined?(meth)
|
173
|
+
::Kernel.instance_method(meth).bind_call(self, *args, &block)
|
174
|
+
else
|
175
|
+
super(meth, *args, &block)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
%w[+ - * /].each do |operation|
|
180
|
+
define_method(operation) do |other|
|
181
|
+
logger.trace("Execution math operation '#{operation}' on #{inspect} with #{other.inspect}")
|
182
|
+
if other.is_a? NumberItem
|
183
|
+
logger.trace('Math operations is between two NumberItems.')
|
184
|
+
if dimension && other.dimension
|
185
|
+
# If both numbers have dimensions, do the math on the quantity types.
|
186
|
+
logger.trace("Both objects have dimensions self='#{dimension}' other='#{other.dimension}'")
|
187
|
+
to_qt.public_send(operation, other.to_qt)
|
188
|
+
elsif dimension && !other.dimension
|
189
|
+
# If this number has dimension and the other does not, do math with this quantity type and the other as a big decimal
|
190
|
+
logger.trace("Self has dimension self='#{dimension}' other lacks dimension='#{other}'")
|
191
|
+
to_qt.public_send(operation, other)
|
192
|
+
elsif other.dimension
|
193
|
+
# If this number has no dimension and the other does, convert this into a dimensionless quantity
|
194
|
+
logger.trace("Self has no dimension self='#{self}' other has dimension='#{other.dimension}'")
|
195
|
+
to_qt.public_send(operation, other)
|
196
|
+
else
|
197
|
+
logger.trace("Both objects lack dimension, self='#{self}' other='#{other}'")
|
198
|
+
# If nothing has a dimension, just use BigDecimals
|
199
|
+
to_d.public_send(operation, other.to_d)
|
200
|
+
end
|
201
|
+
elsif other.is_a? Numeric
|
202
|
+
to_d.public_send(operation, BigDecimal(other))
|
203
|
+
elsif dimension && other.is_a?(String)
|
204
|
+
to_qt.public_send(operation, Quantity.new(other))
|
205
|
+
elsif other.respond_to? :coerce
|
206
|
+
a, b = other.coerce(to_d)
|
207
|
+
a.public_send(operation, b)
|
208
|
+
else
|
209
|
+
raise TypeError, "#{other.class} can't be coerced into a NumberItem"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|