openhab-scripting 3.0.1 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8359f48a32afdddb1863616bf95c24974c31b059506ecb5a07656d2ed7ee1738
4
- data.tar.gz: e1c45eba3ca90174d507becbe2158fc93154d11610d841ad01e6ba705433edb3
3
+ metadata.gz: 90af7470bbd47fa813a1a4a5a9083f178a36225ab6f9cfbd2ff1852cc0eb4c92
4
+ data.tar.gz: 789d9c72ce03d498416bf53c86d6b7f895df8296d849f702b59398e831aad6f1
5
5
  SHA512:
6
- metadata.gz: 7472fd8ed608b6b74a38358e98fd00b1534e2d4e7d88adfe726018afd48c28783324fe3d2388d6a9749a4d8d8c804c4d795bf3ab338849783ee6c4a1f0cb69aa
7
- data.tar.gz: feb348e3b10f8ec03659e4066dffeef8df1d5a7f41ba4d4faf31ac2078d5b63024360dbd0d6acb5fc0348fb9254e84a09409680d74a96a1415c3ecf017f0cca8
6
+ metadata.gz: 9066fe74d2d508e06ce9a62244a19a75470fcffb85bdbcaa2c899b5220a15da351ae4f55be08fb80d3c3222a1a26d16471420049b8621a60d143f16b867d7180
7
+ data.tar.gz: 53d1df31662e7552566d6dd92237b862b32f988e4edf42bc95b44fff3af425e5a038771c2372e2fe71928867c41962907825a24e05fbf3e91ed31f5ff6ee2778
@@ -87,8 +87,10 @@ module OpenHAB
87
87
  # @return [Object] the ruby wrapper for the item
88
88
  #
89
89
  # rubocop: disable Metrics/MethodLength
90
+ # rubocop: disable Metrics/CyclomaticComplexity
90
91
  # Disabled line length and branch size - case dispatch pattern
91
92
  def self.decorate_item(item)
93
+ logger.trace("Decorating #{item.class}")
92
94
  case item
93
95
  when Java::OrgOpenhabCoreItems::GroupItem
94
96
  OpenHAB::DSL::Items::GroupItem.new(item)
@@ -102,11 +104,15 @@ module OpenHAB
102
104
  OpenHAB::DSL::Items::RollershutterItem.new(item)
103
105
  when Java::OrgOpenhabCoreLibraryItems::PlayerItem
104
106
  OpenHAB::DSL::Items::PlayerItem.new(item)
107
+ when Java::OrgOpenhabCoreLibraryItems::ImageItem
108
+ OpenHAB::DSL::Items::ImageItem.new(item)
105
109
  else
110
+ logger.trace("Returning undecorated item #{item.class}")
106
111
  item
107
112
  end
108
113
  end
109
114
  # rubocop: enable Metrics/MethodLength
115
+ # rubocop: enable Metrics/CyclomaticComplexity
110
116
 
111
117
  #
112
118
  # Looks up a Thing in the OpenHAB registry replacing '_' with ':'
@@ -14,6 +14,7 @@ require 'openhab/dsl/group'
14
14
  require 'openhab/dsl/things'
15
15
  require 'openhab/dsl/items/items'
16
16
  require 'openhab/dsl/items/datetime_item'
17
+ require 'openhab/dsl/items/image_item'
17
18
  require 'openhab/dsl/items/number_item'
18
19
  require 'openhab/dsl/items/player_item'
19
20
  require 'openhab/dsl/items/group_item'
@@ -5,6 +5,7 @@ require 'java'
5
5
  require 'time'
6
6
  require 'openhab/dsl/types/datetime'
7
7
  require 'openhab/dsl/items/item_delegate'
8
+ require 'openhab/dsl/items/item_command'
8
9
 
9
10
  module OpenHAB
10
11
  module DSL
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'net/http'
5
+ require 'java'
6
+ require 'mimemagic'
7
+ require 'openhab/dsl/items/item_command'
8
+ require 'openhab/dsl/items/item_delegate'
9
+
10
+ module OpenHAB
11
+ module DSL
12
+ module Items
13
+ #
14
+ # Delegator to OpenHAB Player Item
15
+ #
16
+ class ImageItem
17
+ extend OpenHAB::DSL::Items::ItemCommand
18
+ extend OpenHAB::DSL::Items::ItemDelegate
19
+
20
+ def_item_delegator :@image_item
21
+
22
+ item_type Java::OrgOpenhabCoreLibraryItems::ImageItem
23
+
24
+ #
25
+ # Creates a new ImageItem
26
+ #
27
+ # @param [Java::OrgOpenhabCoreLibraryItems::ImageItem] image_item
28
+ # The OpenHAB ImageItem to delegate to
29
+ #
30
+ def initialize(image_item)
31
+ logger.trace("Wrapping #{image_item}")
32
+ @image_item = image_item
33
+
34
+ item_missing_delegate { @image_item }
35
+
36
+ super()
37
+ end
38
+
39
+ #
40
+ #
41
+ # Update image with base64 encoded OpenHAB compatable image
42
+ #
43
+ # @param [String] base_64 base_64 encoding of an image
44
+ #
45
+ #
46
+ def update(base_64_encoded_image)
47
+ logger.trace { "Updating #{self} with Base64 image #{base_64_encoded_image}" }
48
+ @image_item.update base_64_encoded_image
49
+ end
50
+
51
+ #
52
+ # Update image from file
53
+ #
54
+ # @param [String] file location
55
+ # @param [String] mime_type of image
56
+ #
57
+ #
58
+ def update_from_file(file, mime_type: nil)
59
+ file_data = IO.binread(file)
60
+ mime_type ||= (MimeMagic.by_path(file) || MimeMagic.by_magic(file_data))&.type
61
+ update_from_bytes(file_data, mime_type: mime_type)
62
+ end
63
+
64
+ #
65
+ # Update image from image at URL
66
+ #
67
+ # @param [String] uri location of image
68
+ #
69
+ #
70
+ def update_from_url(uri)
71
+ logger.debug("Downloading image from #{uri}")
72
+ response = Net::HTTP.get_response(URI(uri))
73
+ mime_type = response['content-type']
74
+ bytes = response.body
75
+ mime_type ||= detect_mime_from_bytes(bytes: bytes)
76
+ update_from_bytes(bytes, mime_type: mime_type)
77
+ end
78
+
79
+ #
80
+ # Update image from image bytes
81
+ #
82
+ # @param [String] mime_type of image
83
+ # @param [Object] bytes image data
84
+ #
85
+ #
86
+ def update_from_bytes(bytes, mime_type: nil)
87
+ mime_type ||= detect_mime_from_bytes(bytes: bytes)
88
+ base_64_image = encode_image(mime_type: mime_type, bytes: bytes)
89
+ update base_64_image
90
+ end
91
+
92
+ #
93
+ # Get the mime type for the image item
94
+ #
95
+ # @return [String] mime type for image, e.g. image/png
96
+ #
97
+ def mime_type
98
+ state&.mime_type
99
+ end
100
+
101
+ #
102
+ # Get the bytes of the image
103
+ #
104
+ # @return [Array] Bytes that comprise the image
105
+ #
106
+ def bytes
107
+ state&.get_bytes
108
+ end
109
+
110
+ private
111
+
112
+ #
113
+ # Encode image information in the format required by OpenHAB
114
+ #
115
+ # @param [String] mime_type for image
116
+ # @param [Object] bytes image data
117
+ #
118
+ # @return [String] OpenHAB image format with image data Base64 encoded
119
+ #
120
+ def encode_image(mime_type:, bytes:)
121
+ "data:#{mime_type};base64,#{Base64.strict_encode64(bytes)}"
122
+ end
123
+
124
+ #
125
+ # Detect the mime type based on bytes
126
+ #
127
+ # @param [Array] bytes representing image data
128
+ #
129
+ # @return [String] mime type if it can be detected, nil otherwise
130
+ #
131
+ def detect_mime_from_bytes(bytes:)
132
+ logger.trace('Detecting mime type from file image contents')
133
+ MimeMagic.by_magic(bytes)&.type
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -43,7 +43,7 @@ module OpenHAB
43
43
  # @return [Java::OrgOpenhabCoreLibraryTypes::PercentType] the position of the rollershutter
44
44
  #
45
45
  def position
46
- state.as(PercentType)
46
+ state&.as(PercentType)
47
47
  end
48
48
 
49
49
  #
@@ -54,6 +54,8 @@ module OpenHAB
54
54
  # @return [Integer] -1, 0 or 1 depending on the result of the comparison
55
55
  #
56
56
  def <=>(other)
57
+ return nil unless state?
58
+
57
59
  case other
58
60
  when PercentType, Java::OrgOpenhabCoreLibraryTypes::DecimalType then position.compare_to(other)
59
61
  when Numeric then position.int_value <=> other
@@ -73,8 +75,8 @@ module OpenHAB
73
75
  raise ArgumentError, "Cannot coerce to #{other.class}" unless other.is_a? Numeric
74
76
 
75
77
  case other
76
- when Integer then [other, position.int_value]
77
- when Float then [other, position.float_value]
78
+ when Integer then [other, position&.int_value]
79
+ when Float then [other, position&.float_value]
78
80
  end
79
81
  end
80
82
 
@@ -84,7 +86,7 @@ module OpenHAB
84
86
  %i[+ - * / %].each do |operator|
85
87
  define_method(operator) do |other|
86
88
  right, left = coerce(other)
87
- left.send(operator, right)
89
+ left&.send(operator, right)
88
90
  end
89
91
  end
90
92
  end
@@ -36,6 +36,8 @@ module OpenHAB
36
36
  # result from super if not supplied an OpenClosedType
37
37
  #
38
38
  def ==(other)
39
+ other = other.get_state_as(OpenClosedType) if other.respond_to?(:get_state_as)
40
+
39
41
  if other.is_a? OpenClosedType
40
42
  state? && state == other
41
43
  else
@@ -56,6 +56,8 @@ module OpenHAB
56
56
  # otherwise result from super
57
57
  #
58
58
  def ==(other)
59
+ other = other.get_state_as(OnOffType) if other.respond_to?(:get_state_as)
60
+
59
61
  if other.is_a? OnOffType
60
62
  state? && state == other
61
63
  else
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'openhab/dsl/types/quantity'
4
+ require 'openhab/dsl/types/datetime'
5
+ require 'openhab/dsl/items/datetime_item'
4
6
 
5
7
  module OpenHAB
6
8
  module DSL
@@ -21,7 +23,8 @@ module OpenHAB
21
23
  #
22
24
  def ==(other)
23
25
  case other
24
- when OpenHAB::DSL::Types::Quantity, QuantityType, Java::OrgOpenhabCoreLibraryTypes::StringType
26
+ when OpenHAB::DSL::Types::Quantity, QuantityType, Java::OrgOpenhabCoreLibraryTypes::StringType,
27
+ OpenHAB::DSL::Types::DateTime, OpenHAB::DSL::Items::DateTimeItem
25
28
  other == self
26
29
  else
27
30
  super
@@ -44,6 +44,21 @@ module OpenHAB
44
44
  end
45
45
  # rubocop:enable Style/CaseLikeIf
46
46
  end
47
+
48
+ #
49
+ # Test for equality
50
+ #
51
+ # @param [Object] other Other object to compare against
52
+ #
53
+ # @return [Boolean] true if self and other can be considered equal, false otherwise
54
+ #
55
+ def ==(other)
56
+ if other.respond_to?(:get_state_as)
57
+ self == other.get_state_as(OnOffType)
58
+ else
59
+ super
60
+ end
61
+ end
47
62
  end
48
63
  end
49
64
  end
@@ -33,6 +33,21 @@ module OpenHAB
33
33
  super
34
34
  end
35
35
  end
36
+
37
+ #
38
+ # Test for equality
39
+ #
40
+ # @param [Object] other Other object to compare against
41
+ #
42
+ # @return [Boolean] true if self and other can be considered equal, false otherwise
43
+ #
44
+ def ==(other)
45
+ if other.respond_to?(:get_state_as)
46
+ self == other.get_state_as(OpenClosedType)
47
+ else
48
+ super
49
+ end
50
+ end
36
51
  end
37
52
  end
38
53
  end
@@ -30,6 +30,21 @@ module OpenHAB
30
30
  super
31
31
  end
32
32
  end
33
+
34
+ #
35
+ # Test for equality
36
+ #
37
+ # @param [Object] other Other object to compare against
38
+ #
39
+ # @return [Boolean] true if self and other can be considered equal, false otherwise
40
+ #
41
+ def ==(other)
42
+ if other.respond_to?(:get_state_as)
43
+ self == other.get_state_as(UpDownType)
44
+ else
45
+ super
46
+ end
47
+ end
33
48
  end
34
49
  end
35
50
  end
@@ -29,6 +29,7 @@ module OpenHAB
29
29
  set_name(config.name)
30
30
  set_description(config.description)
31
31
  set_triggers(config.triggers)
32
+ @run_context = config.caller
32
33
  @run_queue = config.run
33
34
  @guard = config.guard
34
35
  between = config.between&.yield_self { between(config.between) }
@@ -288,7 +289,7 @@ module OpenHAB
288
289
  #
289
290
  def process_otherwise_task(event, task)
290
291
  logger.trace { "Executing rule '#{name}' otherwise block with event(#{event})" }
291
- task.block.call(event)
292
+ @run_context.instance_exec(event, &task.block)
292
293
  end
293
294
 
294
295
  #
@@ -316,7 +317,7 @@ module OpenHAB
316
317
  return unless event&.item
317
318
 
318
319
  logger.trace { "Executing rule '#{name}' trigger block with item (#{event.item})" }
319
- task.block.call(event.item)
320
+ @run_context.instance_exec(event.item, &task.block)
320
321
  end
321
322
 
322
323
  #
@@ -328,7 +329,7 @@ module OpenHAB
328
329
  #
329
330
  def process_run_task(event, task)
330
331
  logger.trace { "Executing rule '#{name}' run block with event(#{event})" }
331
- task.block.call(event)
332
+ @run_context.instance_exec(event, &task.block)
332
333
  end
333
334
 
334
335
  #
@@ -23,10 +23,11 @@ module OpenHAB
23
23
  def rule(rule_name, &block)
24
24
  @rule_name = rule_name
25
25
  config = RuleConfig.new(rule_name, block.binding)
26
- config.instance_eval(&block)
26
+ config.instance_exec(config, &block)
27
27
  config.guard = Guard::Guard.new(only_if: config.only_if, not_if: config.not_if)
28
28
  logger.trace { config.inspect }
29
29
  process_rule_config(config)
30
+ config
30
31
  rescue StandardError => e
31
32
  re_raise_with_backtrace(e)
32
33
  end
@@ -40,6 +40,9 @@ module OpenHAB
40
40
  # @return [Array] Of trigger guards
41
41
  attr_accessor :guard
42
42
 
43
+ # @return [Object] object that invoked rule method
44
+ attr_accessor :caller
45
+
43
46
  #
44
47
  # Struct holding a run block
45
48
  #
@@ -75,13 +75,13 @@ module OpenHAB
75
75
  # @return [Integer] -1, 0 or 1 depending on the outcome
76
76
  #
77
77
  def <=>(other)
78
+ if other.respond_to?(:zoned_date_time)
79
+ return zoned_date_time.to_instant.compare_to(other.zoned_date_time.to_instant)
80
+ end
81
+
78
82
  case other
79
- when DateTime, DateTimeType, DateTimeItem
80
- zoned_date_time.to_instant.compare_to(other.zoned_date_time.to_instant)
81
- when TimeOfDay::TimeOfDay, TimeOfDay::TimeOfDayRangeElement
82
- to_tod <=> other
83
- when String
84
- self <=> DateTime.parse(DATE_ONLY_REGEX =~ other ? "#{other}'T'00:00:00#{zone}" : other)
83
+ when TimeOfDay::TimeOfDay, TimeOfDay::TimeOfDayRangeElement then to_tod <=> other
84
+ when String then self <=> DateTime.parse(DATE_ONLY_REGEX =~ other ? "#{other}'T'00:00:00#{zone}" : other)
85
85
  else
86
86
  self <=> DateTime.from(other)
87
87
  end
@@ -22,9 +22,21 @@ module OpenHAB
22
22
  #
23
23
  # Regex for matching internal calls in a stack trace
24
24
  #
25
- INTERNAL_CALL_REGEX = %r{(openhab-scripting-.*/lib)|(org/jruby/)}.freeze
25
+ INTERNAL_CALL_REGEX = %r{(openhab-scripting-.*/lib)|org[./]jruby}.freeze
26
26
  private_constant :INTERNAL_CALL_REGEX
27
27
 
28
+ #
29
+ # Regex for matching internal calls in a java stack trace
30
+ #
31
+ EXCLUDED_JAVA_PACKAGES = /jdk\.internal\.reflect|java\.lang\.reflect|org\.openhab|java\.lang\.Thread\.run/.freeze
32
+ private_constant :EXCLUDED_JAVA_PACKAGES
33
+
34
+ #
35
+ # Regex for matching internal calls in a java stack trace
36
+ #
37
+ JAVA_INTERNAL_CALL_REGEX = Regexp.union(INTERNAL_CALL_REGEX, EXCLUDED_JAVA_PACKAGES).freeze
38
+ private_constant :JAVA_INTERNAL_CALL_REGEX
39
+
28
40
  #
29
41
  # Create a new logger
30
42
  #
@@ -60,8 +72,13 @@ module OpenHAB
60
72
  def clean_backtrace(error)
61
73
  return error if debug_enabled?
62
74
 
63
- backtrace = error.backtrace_locations.reject { |line| INTERNAL_CALL_REGEX.match? line.to_s }
64
- error.set_backtrace(backtrace.map(&:to_s))
75
+ if error.respond_to? :backtrace_locations
76
+ backtrace = error.backtrace_locations.map(&:to_s).reject { |line| INTERNAL_CALL_REGEX.match? line }
77
+ error.set_backtrace(backtrace)
78
+ elsif error.respond_to? :stack_trace
79
+ backtrace = error.stack_trace.reject { |line| JAVA_INTERNAL_CALL_REGEX.match? line.to_s }
80
+ error.set_stack_trace(backtrace)
81
+ end
65
82
  error
66
83
  end
67
84
 
@@ -5,5 +5,5 @@
5
5
  #
6
6
  module OpenHAB
7
7
  # @return [String] Version of OpenHAB helper libraries
8
- VERSION = '3.0.1'
8
+ VERSION = '3.2.1'
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-03 00:00:00.000000000 Z
11
+ date: 2021-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mimemagic
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.3'
27
41
  description: JRuby Helper Libraries for OpenHAB Scripting
28
42
  email:
29
43
  - broconne@gmail.com
@@ -41,6 +55,7 @@ files:
41
55
  - lib/openhab/dsl/group.rb
42
56
  - lib/openhab/dsl/items/datetime_item.rb
43
57
  - lib/openhab/dsl/items/group_item.rb
58
+ - lib/openhab/dsl/items/image_item.rb
44
59
  - lib/openhab/dsl/items/item_command.rb
45
60
  - lib/openhab/dsl/items/item_delegate.rb
46
61
  - lib/openhab/dsl/items/items.rb