openhab-jrubyscripting 5.0.0.rc3 → 5.0.0.rc5
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.
- checksums.yaml +4 -4
- data/lib/openhab/core/actions.rb +19 -3
- data/lib/openhab/core/items/metadata/hash.rb +2 -1
- data/lib/openhab/core/items/metadata/namespace_hash.rb +1 -1
- data/lib/openhab/core/items/persistence.rb +18 -8
- data/lib/openhab/core/items/semantics.rb +18 -22
- data/lib/openhab/core/items.rb +1 -1
- data/lib/openhab/core/profile_factory.rb +13 -3
- data/lib/openhab/core/provider.rb +3 -3
- data/lib/openhab/core/rules/module.rb +26 -0
- data/lib/openhab/core/rules/provider.rb +15 -0
- data/lib/openhab/core/script_handling.rb +32 -3
- data/lib/openhab/core/things/profile_callback.rb +1 -1
- data/lib/openhab/core/timer.rb +21 -10
- data/lib/openhab/core/types/point_type.rb +1 -1
- data/lib/openhab/core_ext/between.rb +32 -0
- data/lib/openhab/core_ext/java/duration.rb +1 -0
- data/lib/openhab/core_ext/java/local_date.rb +1 -0
- data/lib/openhab/core_ext/java/local_time.rb +1 -0
- data/lib/openhab/core_ext/java/month.rb +13 -2
- data/lib/openhab/core_ext/java/month_day.rb +2 -0
- data/lib/openhab/core_ext/java/zoned_date_time.rb +4 -4
- data/lib/openhab/core_ext/ruby/date.rb +4 -1
- data/lib/openhab/core_ext/ruby/date_time.rb +1 -0
- data/lib/openhab/core_ext/ruby/time.rb +1 -0
- data/lib/openhab/dsl/items/timed_command.rb +1 -1
- data/lib/openhab/dsl/rules/automation_rule.rb +1 -1
- data/lib/openhab/dsl/rules/builder.rb +1 -1
- data/lib/openhab/dsl/rules/name_inference.rb +1 -1
- data/lib/openhab/dsl/rules/rule_triggers.rb +1 -1
- data/lib/openhab/dsl/rules/triggers/changed.rb +1 -1
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +2 -2
- data/lib/openhab/dsl/version.rb +1 -1
- data/lib/openhab/dsl.rb +2 -0
- data/lib/openhab/log.rb +7 -0
- data/lib/openhab/rspec/helpers.rb +1 -1
- data/lib/openhab/rspec/hooks.rb +3 -4
- data/lib/openhab/rspec/karaf.rb +6 -2
- data/lib/openhab/rspec/mocks/persistence_service.rb +15 -0
- data/lib/openhab/rspec/mocks/thing_handler.rb +2 -2
- data/lib/openhab/yard/html_helper.rb +3 -3
- metadata +8 -7
- data/lib/openhab/dsl/script_handling.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5963df56b31bb66f4d4cf5afa5927719d61740df847c5d5ff0965a188a73c62
|
4
|
+
data.tar.gz: 0011f05f77383e9618844437bc63b55d02e62ed9a402d775a76dbc75d20a8334
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffdb129b03aac2d44365aa42a7f02889f5d8a20f662391b874cb795547b646d6d4f02d014284a73143862ca25f931f42429be012a25b645d02b1e713a02c073b
|
7
|
+
data.tar.gz: ca9804074c3092c6bcff87ed17bffe4543ef95b3ef0c230d4767811a266d368210658f36968d4d42b6ed2f320a8935ab28363a318a6bd0d2a7d393afab67a29a
|
data/lib/openhab/core/actions.rb
CHANGED
@@ -66,11 +66,27 @@ module OpenHAB
|
|
66
66
|
#
|
67
67
|
module Actions
|
68
68
|
OSGi.services("org.openhab.core.model.script.engine.action.ActionService")&.each do |service|
|
69
|
-
|
70
|
-
|
69
|
+
action_class = service.action_class
|
70
|
+
module_name = action_class.simple_name
|
71
|
+
action = if action_class.interface?
|
72
|
+
impl = OSGi.service(action_class)
|
73
|
+
unless impl
|
74
|
+
logger.error("Unable to find an implementation object for action service #{action_class}.")
|
75
|
+
next
|
76
|
+
end
|
77
|
+
const_set(module_name, impl)
|
78
|
+
else
|
79
|
+
(java_import action_class.ruby_class).first
|
80
|
+
end
|
81
|
+
logger.trace("Loaded ACTION: #{action_class}")
|
82
|
+
Object.const_set(module_name, action)
|
71
83
|
end
|
84
|
+
|
72
85
|
# Import common actions
|
73
|
-
%w[Exec HTTP Ping].each
|
86
|
+
%w[Exec HTTP Ping].each do |action|
|
87
|
+
klass = (java_import "org.openhab.core.model.script.actions.#{action}").first
|
88
|
+
Object.const_set(action, klass)
|
89
|
+
end
|
74
90
|
|
75
91
|
module_function
|
76
92
|
|
@@ -380,6 +380,7 @@ module OpenHAB
|
|
380
380
|
|
381
381
|
[value, to_h].inspect
|
382
382
|
end
|
383
|
+
remove_method :to_s
|
383
384
|
alias_method :to_s, :inspect
|
384
385
|
|
385
386
|
#
|
@@ -399,7 +400,7 @@ module OpenHAB
|
|
399
400
|
return preferred_provider unless provider
|
400
401
|
|
401
402
|
unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
|
402
|
-
raise FrozenError, "Cannot modify metadata from provider #{provider.inspect}"
|
403
|
+
raise FrozenError, "Cannot modify metadata from provider #{provider.inspect} for #{uid}."
|
403
404
|
end
|
404
405
|
|
405
406
|
if preferred_provider != provider
|
@@ -40,16 +40,26 @@ module OpenHAB
|
|
40
40
|
module Persistence
|
41
41
|
GenericItem.prepend(self)
|
42
42
|
|
43
|
-
#
|
43
|
+
#
|
44
|
+
# A state class with an added timestamp attribute.
|
45
|
+
#
|
46
|
+
# This wraps {org.openhab.core.persistence.HistoricItem HistoricItem}
|
47
|
+
# to allow implicitly treating the object as its state, and wrapping of
|
48
|
+
# that state into a {QuantityType} as necessary.
|
49
|
+
#
|
44
50
|
class HistoricState < SimpleDelegator
|
45
|
-
attr_reader :timestamp
|
46
|
-
|
47
51
|
alias_method :state, :__getobj__
|
48
52
|
|
49
|
-
def initialize(state,
|
50
|
-
@
|
53
|
+
def initialize(state, historic_item)
|
54
|
+
@historic_item = historic_item
|
51
55
|
super(state)
|
52
56
|
end
|
57
|
+
|
58
|
+
# @!attribute [r] timestamp
|
59
|
+
# @return [ZonedDateTime]
|
60
|
+
def timestamp
|
61
|
+
@historic_item.timestamp
|
62
|
+
end
|
53
63
|
end
|
54
64
|
|
55
65
|
# All persistence methods that could return a QuantityType
|
@@ -245,7 +255,7 @@ module OpenHAB
|
|
245
255
|
def previous_state(service = nil, skip_equal: false)
|
246
256
|
service ||= persistence_service
|
247
257
|
result = Actions::PersistenceExtensions.previous_state(self, skip_equal, service&.to_s)
|
248
|
-
HistoricState.new(quantify(result.state), result
|
258
|
+
HistoricState.new(quantify(result.state), result)
|
249
259
|
end
|
250
260
|
|
251
261
|
PERSISTENCE_METHODS.each do |method|
|
@@ -286,7 +296,7 @@ module OpenHAB
|
|
286
296
|
# @return [Object] QuantityType or the original value
|
287
297
|
#
|
288
298
|
def quantify(value)
|
289
|
-
if value.is_a?(DecimalType) && unit
|
299
|
+
if value.is_a?(DecimalType) && respond_to?(:unit) && unit
|
290
300
|
logger.trace("Unitizing #{value} with unit #{unit}")
|
291
301
|
QuantityType.new(value.to_big_decimal, unit)
|
292
302
|
else
|
@@ -308,7 +318,7 @@ module OpenHAB
|
|
308
318
|
def wrap_result(result, method)
|
309
319
|
if result.is_a?(org.openhab.core.persistence.HistoricItem)
|
310
320
|
return HistoricState.new(quantify(result.state),
|
311
|
-
result
|
321
|
+
result)
|
312
322
|
end
|
313
323
|
return quantify(result) if QUANTITY_METHODS.include?(method)
|
314
324
|
|
@@ -187,11 +187,6 @@ module OpenHAB
|
|
187
187
|
# end
|
188
188
|
#
|
189
189
|
|
190
|
-
# @!visibility private
|
191
|
-
# import the actual semantics action
|
192
|
-
SemanticsAction = org.openhab.core.model.script.actions.Semantics
|
193
|
-
private_constant :SemanticsAction
|
194
|
-
|
195
190
|
# import all the semantics constants
|
196
191
|
[org.openhab.core.semantics.model.point.Points,
|
197
192
|
org.openhab.core.semantics.model.property.Properties,
|
@@ -223,6 +218,7 @@ module OpenHAB
|
|
223
218
|
# Property = org.openhab.core.semantics.Property
|
224
219
|
|
225
220
|
# put ourself into the global namespace, replacing the action
|
221
|
+
Object.send(:remove_const, :Semantics)
|
226
222
|
::Semantics = self # rubocop:disable Naming/ConstantName
|
227
223
|
|
228
224
|
#
|
@@ -234,7 +230,7 @@ module OpenHAB
|
|
234
230
|
# @return [true, false]
|
235
231
|
#
|
236
232
|
def location?
|
237
|
-
|
233
|
+
Actions::Semantics.location?(self)
|
238
234
|
end
|
239
235
|
|
240
236
|
#
|
@@ -246,7 +242,7 @@ module OpenHAB
|
|
246
242
|
# @return [true, false]
|
247
243
|
#
|
248
244
|
def equipment?
|
249
|
-
|
245
|
+
Actions::Semantics.equipment?(self)
|
250
246
|
end
|
251
247
|
|
252
248
|
# Checks if this Item is a {Point}
|
@@ -257,7 +253,7 @@ module OpenHAB
|
|
257
253
|
# @return [true, false]
|
258
254
|
#
|
259
255
|
def point?
|
260
|
-
|
256
|
+
Actions::Semantics.point?(self)
|
261
257
|
end
|
262
258
|
|
263
259
|
#
|
@@ -280,7 +276,7 @@ module OpenHAB
|
|
280
276
|
# @return [GenericItem, nil]
|
281
277
|
#
|
282
278
|
def location
|
283
|
-
|
279
|
+
Actions::Semantics.get_location(self)&.then(&Proxy.method(:new))
|
284
280
|
end
|
285
281
|
|
286
282
|
#
|
@@ -293,7 +289,7 @@ module OpenHAB
|
|
293
289
|
# @return [Class, nil]
|
294
290
|
#
|
295
291
|
def location_type
|
296
|
-
|
292
|
+
Actions::Semantics.get_location_type(self)&.ruby_class
|
297
293
|
end
|
298
294
|
|
299
295
|
#
|
@@ -306,7 +302,7 @@ module OpenHAB
|
|
306
302
|
# @return [GenericItem, nil]
|
307
303
|
#
|
308
304
|
def equipment
|
309
|
-
|
305
|
+
Actions::Semantics.get_equipment(self)&.then(&Proxy.method(:new))
|
310
306
|
end
|
311
307
|
|
312
308
|
#
|
@@ -319,7 +315,7 @@ module OpenHAB
|
|
319
315
|
# @return [Class, nil]
|
320
316
|
#
|
321
317
|
def equipment_type
|
322
|
-
|
318
|
+
Actions::Semantics.get_equipment_type(self)&.ruby_class
|
323
319
|
end
|
324
320
|
|
325
321
|
#
|
@@ -330,7 +326,7 @@ module OpenHAB
|
|
330
326
|
# @return [Class, nil]
|
331
327
|
#
|
332
328
|
def point_type
|
333
|
-
|
329
|
+
Actions::Semantics.get_point_type(self)&.ruby_class
|
334
330
|
end
|
335
331
|
|
336
332
|
#
|
@@ -341,7 +337,7 @@ module OpenHAB
|
|
341
337
|
# @return [Class, nil]
|
342
338
|
#
|
343
339
|
def property_type
|
344
|
-
|
340
|
+
Actions::Semantics.get_property_type(self)&.ruby_class
|
345
341
|
end
|
346
342
|
|
347
343
|
# @!attribute [r] semantic_type
|
@@ -355,7 +351,7 @@ module OpenHAB
|
|
355
351
|
# @return [Class, nil]
|
356
352
|
#
|
357
353
|
def semantic_type
|
358
|
-
|
354
|
+
Actions::Semantics.get_semantic_type(self)&.ruby_class
|
359
355
|
end
|
360
356
|
|
361
357
|
#
|
@@ -409,7 +405,7 @@ module Enumerable
|
|
409
405
|
# Returns a new array of items that are a semantics Location (optionally of the given type)
|
410
406
|
# @return [Array<GenericItem>]
|
411
407
|
def locations(type = nil)
|
412
|
-
if type && (!type.is_a?(Module) || !(type <
|
408
|
+
if type && (!type.is_a?(Module) || !(type < Semantics::Location))
|
413
409
|
raise ArgumentError, "type must be a subclass of Location"
|
414
410
|
end
|
415
411
|
|
@@ -432,7 +428,7 @@ module Enumerable
|
|
432
428
|
# @example Get all TVs in a room
|
433
429
|
# lGreatRoom.equipments(Semantics::Screen)
|
434
430
|
def equipments(type = nil)
|
435
|
-
if type && (!type.is_a?(Module) || !(type <
|
431
|
+
if type && (!type.is_a?(Module) || !(type < Semantics::Equipment))
|
436
432
|
raise ArgumentError, "type must be a subclass of Equipment"
|
437
433
|
end
|
438
434
|
|
@@ -457,19 +453,19 @@ module Enumerable
|
|
457
453
|
end
|
458
454
|
unless point_or_property_types.all? do |tag|
|
459
455
|
tag.is_a?(Module) &&
|
460
|
-
(tag <
|
456
|
+
(tag < Semantics::Point || tag < Semantics::Property)
|
461
457
|
end
|
462
458
|
raise ArgumentError, "point_or_property_types must all be a subclass of Point or Property"
|
463
459
|
end
|
464
|
-
if point_or_property_types.count { |tag| tag <
|
465
|
-
point_or_property_types.count { |tag| tag <
|
460
|
+
if point_or_property_types.count { |tag| tag < Semantics::Point } > 1 ||
|
461
|
+
point_or_property_types.count { |tag| tag < Semantics::Property } > 1
|
466
462
|
raise ArgumentError, "point_or_property_types cannot both be a subclass of Point or Property"
|
467
463
|
end
|
468
464
|
|
469
465
|
select do |point|
|
470
466
|
point.point? && point_or_property_types.all? do |tag|
|
471
|
-
(tag <
|
472
|
-
(tag <
|
467
|
+
(tag < Semantics::Point && point.point_type <= tag) ||
|
468
|
+
(tag < Semantics::Property && point.property_type&.<=(tag))
|
473
469
|
end
|
474
470
|
end
|
475
471
|
end
|
data/lib/openhab/core/items.rb
CHANGED
@@ -100,7 +100,7 @@ module OpenHAB
|
|
100
100
|
constants.map { |c| const_get(c) }
|
101
101
|
.grep(Module)
|
102
102
|
.select { |k| k <= GenericItem && k != GroupItem && k != StringItem }
|
103
|
-
.sort { |a, b| a < b ? 1 : -1 }
|
103
|
+
.sort { |a, b| (a < b) ? 1 : -1 }
|
104
104
|
.each do |klass|
|
105
105
|
klass.field_reader :ACCEPTED_COMMAND_TYPES, :ACCEPTED_DATA_TYPES unless klass == GenericItem
|
106
106
|
|
@@ -98,6 +98,19 @@ module OpenHAB
|
|
98
98
|
|
99
99
|
def initialize
|
100
100
|
@profiles = {}
|
101
|
+
|
102
|
+
@registration = OSGi.register_service(self)
|
103
|
+
ScriptHandling.script_unloaded { unregister }
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Unregister the ProfileFactory OSGi service
|
108
|
+
#
|
109
|
+
# @!visibility private
|
110
|
+
# @return [void]
|
111
|
+
#
|
112
|
+
def unregister
|
113
|
+
@registration.unregister
|
101
114
|
end
|
102
115
|
|
103
116
|
# @!visibility private
|
@@ -113,8 +126,5 @@ module OpenHAB
|
|
113
126
|
@profiles.keys
|
114
127
|
end
|
115
128
|
end
|
116
|
-
|
117
|
-
registration = OSGi.register_service(ProfileFactory.instance)
|
118
|
-
ScriptHandling.script_unloaded { registration.unregister }
|
119
129
|
end
|
120
130
|
end
|
@@ -212,11 +212,11 @@ module OpenHAB
|
|
212
212
|
|
213
213
|
private
|
214
214
|
|
215
|
-
def initialize
|
216
|
-
super
|
215
|
+
def initialize(script_unloaded_before: nil)
|
216
|
+
super()
|
217
217
|
@elements = {}
|
218
218
|
self.class.registry.add_provider(self)
|
219
|
-
ScriptHandling.script_unloaded { unregister }
|
219
|
+
ScriptHandling.script_unloaded(before: script_unloaded_before) { unregister }
|
220
220
|
end
|
221
221
|
end
|
222
222
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenHAB
|
4
|
+
module Core
|
5
|
+
module Rules
|
6
|
+
# @interface
|
7
|
+
java_import org.openhab.core.automation.Module
|
8
|
+
|
9
|
+
# @!visibility private
|
10
|
+
module Module
|
11
|
+
# @return [String]
|
12
|
+
def inspect
|
13
|
+
r = "#<OpenHAB::Core::Rules::#{self.class.simple_name} #{id} (#{type_uid})"
|
14
|
+
r += " #{label.inspect}" if label
|
15
|
+
r += " configuration=#{configuration.properties.to_h}" unless configuration.properties.empty?
|
16
|
+
"#{r}>"
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
def to_s
|
21
|
+
id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -19,6 +19,21 @@ module OpenHAB
|
|
19
19
|
$rules
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
super(script_unloaded_before: lambda do |callbacks|
|
25
|
+
callbacks.index do |cb|
|
26
|
+
case cb.binding.receiver
|
27
|
+
when Items::Provider,
|
28
|
+
Things::Provider,
|
29
|
+
DSL::TimerManager
|
30
|
+
true
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end)
|
36
|
+
end
|
22
37
|
end
|
23
38
|
end
|
24
39
|
end
|
@@ -29,9 +29,11 @@ module OpenHAB
|
|
29
29
|
# end
|
30
30
|
#
|
31
31
|
def script_loaded(&block)
|
32
|
-
|
32
|
+
ScriptHandlingCallbacks.script_loaded_hooks << block
|
33
33
|
end
|
34
34
|
|
35
|
+
#
|
36
|
+
# @!method script_unloaded(&block)
|
35
37
|
#
|
36
38
|
# Add a block of code to be executed when the script is unloaded.
|
37
39
|
#
|
@@ -47,8 +49,10 @@ module OpenHAB
|
|
47
49
|
# logger.info 'Hi, this script has been unloaded'
|
48
50
|
# end
|
49
51
|
#
|
50
|
-
def script_unloaded(&block)
|
51
|
-
|
52
|
+
def script_unloaded(before: nil, &block)
|
53
|
+
# `before` is as yet undocumented, because I'm not set on its interface
|
54
|
+
index = before.call(ScriptHandlingCallbacks.script_unloaded_hooks) if before
|
55
|
+
ScriptHandlingCallbacks.script_unloaded_hooks.insert(index || -1, block)
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
@@ -58,6 +62,13 @@ module OpenHAB
|
|
58
62
|
# @!visibility private
|
59
63
|
module ScriptHandlingCallbacks
|
60
64
|
class << self
|
65
|
+
#
|
66
|
+
# Has the script completed loading?
|
67
|
+
#
|
68
|
+
# @!visibility private
|
69
|
+
# @return [true, false]
|
70
|
+
attr_accessor :script_loaded
|
71
|
+
|
61
72
|
#
|
62
73
|
# Return script_loaded_hooks
|
63
74
|
#
|
@@ -74,6 +85,7 @@ module OpenHAB
|
|
74
85
|
@script_unloaded_hooks ||= []
|
75
86
|
end
|
76
87
|
end
|
88
|
+
self.script_loaded = false
|
77
89
|
|
78
90
|
#
|
79
91
|
# Executed when OpenHAB unloads a script file
|
@@ -85,6 +97,22 @@ module OpenHAB
|
|
85
97
|
rescue => e
|
86
98
|
logger.error("Failed to call script_unloaded hook #{hook}: #{e}")
|
87
99
|
end
|
100
|
+
|
101
|
+
return if ScriptHandlingCallbacks.script_loaded
|
102
|
+
|
103
|
+
# Make sure we terminate the main thread if it's still set up, in case
|
104
|
+
# it's timing out and that's why we're unloading.
|
105
|
+
#
|
106
|
+
# It would seem simpler to just record Thread.current when this file
|
107
|
+
# loads, but if the user is using the autorequire feature of the
|
108
|
+
# jrubyscripting addon, this file will load before the main script.
|
109
|
+
#
|
110
|
+
# Note that Thread.list only includes threads that have had Ruby
|
111
|
+
# execute in them, so we don't need to worry about accidentally killing
|
112
|
+
# a random Java thread.
|
113
|
+
#
|
114
|
+
main_thread = Thread.list.find { |t| t != Thread.current && t.name.include?("-safeCall-") }
|
115
|
+
main_thread&.raise(Interrupt.new)
|
88
116
|
end
|
89
117
|
|
90
118
|
#
|
@@ -97,6 +125,7 @@ module OpenHAB
|
|
97
125
|
rescue => e
|
98
126
|
logger.error("Failed to call script_loaded hook #{hook}: #{e}")
|
99
127
|
end
|
128
|
+
ScriptHandlingCallbacks.script_loaded = true
|
100
129
|
end
|
101
130
|
end
|
102
131
|
end
|
@@ -19,7 +19,7 @@ module OpenHAB
|
|
19
19
|
def def_state_parsing_method(method, param_name)
|
20
20
|
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
21
21
|
def #{method}(type) # def handle_command(type)
|
22
|
-
type = link.item.format_#{param_name == :state ? :update : param_name}(type) # type = link.item.format_command(type)
|
22
|
+
type = link.item.format_#{(param_name == :state) ? :update : param_name}(type) # type = link.item.format_command(type)
|
23
23
|
super(type) # super(type)
|
24
24
|
end # end
|
25
25
|
RUBY
|
data/lib/openhab/core/timer.rb
CHANGED
@@ -8,8 +8,6 @@ module OpenHAB
|
|
8
8
|
# Timer allows you to administer the block of code that
|
9
9
|
# has been scheduled to run later with {OpenHAB::DSL.after after}.
|
10
10
|
#
|
11
|
-
# @!attribute [r] execution_time
|
12
|
-
# @return [ZonedDateTime] the scheduled execution time, or null if the timer was cancelled
|
13
11
|
class Timer
|
14
12
|
extend Forwardable
|
15
13
|
|
@@ -30,7 +28,7 @@ module OpenHAB
|
|
30
28
|
# @return [true,false]
|
31
29
|
|
32
30
|
def_delegator :@timer, :has_terminated, :terminated?
|
33
|
-
def_delegators :@timer, :
|
31
|
+
def_delegators :@timer, :active?, :cancelled?, :running?
|
34
32
|
|
35
33
|
# @return [Object, nil]
|
36
34
|
attr_accessor :id
|
@@ -51,13 +49,19 @@ module OpenHAB
|
|
51
49
|
@id = id
|
52
50
|
@thread_locals = thread_locals
|
53
51
|
@block = block
|
54
|
-
@timer =
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
52
|
+
@timer = if defined?(ScriptExecution)
|
53
|
+
ScriptExecution.create_timer(1.minute.from_now) { execute }
|
54
|
+
else # DEPRECATED: openHAB 3.4.0
|
55
|
+
org.openhab.core.model.script.actions.ScriptExecution.create_timer(
|
56
|
+
# create it far enough in the future so it won't execute until we finish setting it up
|
57
|
+
1.minute.from_now,
|
58
|
+
# when running in rspec, it may have troubles finding this class
|
59
|
+
# for auto-conversion of block to interface, so use .impl
|
60
|
+
org.eclipse.xtext.xbase.lib.Procedures::Procedure0.impl { execute }
|
61
|
+
)
|
62
|
+
end
|
63
|
+
# DEPRECATED: openHAB 3.4.0.M6
|
64
|
+
@timer.class.field_reader :future unless @timer.respond_to?(:future)
|
61
65
|
reschedule(@time)
|
62
66
|
end
|
63
67
|
|
@@ -74,6 +78,13 @@ module OpenHAB
|
|
74
78
|
end
|
75
79
|
alias_method :to_s, :inspect
|
76
80
|
|
81
|
+
# @!attribute [r] execution_time
|
82
|
+
# @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
|
83
|
+
def execution_time
|
84
|
+
# DEPRECATED: openHAB 3.4.0.M6 (just remove the entire method)
|
85
|
+
@timer.future.scheduled_time
|
86
|
+
end
|
87
|
+
|
77
88
|
#
|
78
89
|
# Reschedule timer
|
79
90
|
#
|
@@ -21,7 +21,7 @@ module OpenHAB
|
|
21
21
|
if value.is_a?(DecimalType) || value.is_a?(StringType)
|
22
22
|
value
|
23
23
|
elsif value.is_a?(QuantityType)
|
24
|
-
unit = index == 2 ? DSL.unit(SIUnits::METRE.dimension) || SIUnits::METRE : Units::DEGREE_ANGLE
|
24
|
+
unit = (index == 2) ? DSL.unit(SIUnits::METRE.dimension) || SIUnits::METRE : Units::DEGREE_ANGLE
|
25
25
|
DecimalType.new(value.to_unit(unit).to_big_decimal)
|
26
26
|
elsif value.respond_to?(:to_str)
|
27
27
|
StringType.new(value.to_str)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenHAB
|
4
|
+
module CoreExt
|
5
|
+
# Extensions that apply to both Date and Time classes
|
6
|
+
module Between
|
7
|
+
#
|
8
|
+
# Checks whether the the object falls between the given range.
|
9
|
+
#
|
10
|
+
# @overload between?(min, max)
|
11
|
+
# @param [Object] min The minimum value to check, inclusive
|
12
|
+
# @param [Object] max The maximum value to check, inclusive
|
13
|
+
# @return [true,false]
|
14
|
+
#
|
15
|
+
# @overload between?(range)
|
16
|
+
# @param [Range] range A range to check
|
17
|
+
# @return [true,false]
|
18
|
+
#
|
19
|
+
def between?(min, max = nil)
|
20
|
+
range = if max
|
21
|
+
Range.new(min, max, false)
|
22
|
+
else
|
23
|
+
raise ArgumentError, "Expecting a range when given a single argument" unless min.is_a?(Range)
|
24
|
+
|
25
|
+
min
|
26
|
+
end
|
27
|
+
|
28
|
+
OpenHAB::DSL.between(range).cover?(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -5,12 +5,23 @@ require_relative "time"
|
|
5
5
|
module OpenHAB
|
6
6
|
module CoreExt
|
7
7
|
module Java
|
8
|
-
|
8
|
+
Month = java.time.Month
|
9
9
|
|
10
10
|
# Extensions to Month
|
11
11
|
class Month
|
12
|
+
include Between
|
12
13
|
# @!parse include Time
|
13
14
|
|
15
|
+
# @return [Month]
|
16
|
+
def +(other)
|
17
|
+
plus(other)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Month]
|
21
|
+
def -(other)
|
22
|
+
minus(other)
|
23
|
+
end
|
24
|
+
|
14
25
|
#
|
15
26
|
# Returns the next month
|
16
27
|
#
|
@@ -49,7 +60,7 @@ module OpenHAB
|
|
49
60
|
# during conversion. {ZonedDateTime.now} is assumed if not given.
|
50
61
|
# @return [ZonedDateTime]
|
51
62
|
def to_zoned_date_time(context = nil)
|
52
|
-
to_local_date(context).to_zoned_date_time
|
63
|
+
to_local_date(context).to_zoned_date_time(context)
|
53
64
|
end
|
54
65
|
end
|
55
66
|
end
|
@@ -10,6 +10,7 @@ module OpenHAB
|
|
10
10
|
# Extensions to ZonedDateTime
|
11
11
|
class ZonedDateTime
|
12
12
|
include Time
|
13
|
+
include Between
|
13
14
|
|
14
15
|
class << self # rubocop:disable Lint/EmptyClass
|
15
16
|
# @!attribute [r] now
|
@@ -91,11 +92,10 @@ module OpenHAB
|
|
91
92
|
# compare instants, otherwise it will differ by timezone, which we don't want
|
92
93
|
# (use eql? if you care about that)
|
93
94
|
if other.respond_to?(:to_zoned_date_time)
|
94
|
-
|
95
|
+
to_instant.compare_to(other.to_zoned_date_time(self).to_instant)
|
96
|
+
elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(self))
|
97
|
+
lhs <=> rhs
|
95
98
|
end
|
96
|
-
return nil unless (lhs, rhs = other.coerce(self))
|
97
|
-
|
98
|
-
lhs <=> rhs
|
99
99
|
end
|
100
100
|
|
101
101
|
#
|
@@ -4,6 +4,8 @@ require "date"
|
|
4
4
|
|
5
5
|
# Extensions to Date
|
6
6
|
class Date
|
7
|
+
include OpenHAB::CoreExt::Between
|
8
|
+
|
7
9
|
#
|
8
10
|
# Extends {#+} to allow adding a {java.time.temporal.TemporalAmount TemporalAmount}
|
9
11
|
#
|
@@ -65,7 +67,7 @@ class Date
|
|
65
67
|
|
66
68
|
return self <=> other.to_date(self) if other.is_a?(java.time.MonthDay)
|
67
69
|
|
68
|
-
if other.respond_to?(:coerce) && (lhs, rhs = coerce(self))
|
70
|
+
if other.respond_to?(:coerce) && (lhs, rhs = other.coerce(self))
|
69
71
|
return lhs <=> rhs
|
70
72
|
end
|
71
73
|
|
@@ -87,5 +89,6 @@ class Date
|
|
87
89
|
[other.to_date, self]
|
88
90
|
end
|
89
91
|
|
92
|
+
remove_method :inspect
|
90
93
|
alias_method :inspect, :to_s
|
91
94
|
end
|
@@ -211,7 +211,7 @@ module OpenHAB
|
|
211
211
|
def execute(_mod = nil, inputs = nil)
|
212
212
|
ThreadLocal.thread_local(**@thread_locals) do
|
213
213
|
@timed_command_details.mutex.synchronize do
|
214
|
-
logger.trace "Canceling implicit timer #{@timed_command_details.timer} for "\
|
214
|
+
logger.trace "Canceling implicit timer #{@timed_command_details.timer} for " \
|
215
215
|
"#{@timed_command_details.item.name} because received event #{inputs}"
|
216
216
|
@timed_command_details.timer.cancel
|
217
217
|
DSL.rules.remove(@timed_command_details.rule_uid)
|
@@ -170,7 +170,7 @@ module OpenHAB
|
|
170
170
|
now = Time.now
|
171
171
|
return true if @between.cover? now
|
172
172
|
|
173
|
-
logger.trace("Skipped execution of rule '#{name}' because the current time #{now} "\
|
173
|
+
logger.trace("Skipped execution of rule '#{name}' because the current time #{now} " \
|
174
174
|
"is not between #{@between.begin} and #{@between.end}")
|
175
175
|
else
|
176
176
|
logger.trace("Skipped execution of rule '#{name}' because of guard #{@guard}")
|
@@ -1417,7 +1417,7 @@ module OpenHAB
|
|
1417
1417
|
added_rule = add_rule(provider, rule)
|
1418
1418
|
# add config so that MainUI can show the script
|
1419
1419
|
added_rule.actions.first.configuration.put("type", "application/x-ruby")
|
1420
|
-
added_rule.actions.first.configuration.put("script", script)
|
1420
|
+
added_rule.actions.first.configuration.put("script", script) if script
|
1421
1421
|
|
1422
1422
|
rule.execute(nil, { "event" => Struct.new(:attachment).new(start_attachment) }) if on_start?
|
1423
1423
|
added_rule
|
@@ -110,7 +110,7 @@ module OpenHAB
|
|
110
110
|
|
111
111
|
# formulate a readable rule name from a channel link trigger
|
112
112
|
def infer_rule_name_from_channel_link_trigger(trigger)
|
113
|
-
trigger == :channel_linked ? "Channel linked to item" : "Channel unlinked from item"
|
113
|
+
(trigger == :channel_linked) ? "Channel linked to item" : "Channel unlinked from item"
|
114
114
|
end
|
115
115
|
|
116
116
|
# formulate a readable rule name from a thing added/updated/remove trigger
|
@@ -44,7 +44,7 @@ module OpenHAB
|
|
44
44
|
def append_trigger(type:, config:, attach: nil, conditions: nil)
|
45
45
|
config.transform_keys!(&:to_s)
|
46
46
|
RuleTriggers.trigger(type: type, config: config).tap do |trigger|
|
47
|
-
logger.trace("Appending trigger (#{trigger}) attach (#{attach}) conditions(#{conditions})")
|
47
|
+
logger.trace("Appending trigger (#{trigger.inspect}) attach (#{attach}) conditions(#{conditions})")
|
48
48
|
@triggers << trigger
|
49
49
|
@attachments[trigger.id] = attach if attach
|
50
50
|
@trigger_conditions[trigger.id] = conditions if conditions
|
@@ -60,7 +60,7 @@ module OpenHAB
|
|
60
60
|
#
|
61
61
|
def wait_trigger(item:, duration:, to: nil, from: nil, attach: nil)
|
62
62
|
item_name = item.respond_to?(:name) ? item.name : item.to_s
|
63
|
-
logger.trace("Creating Changed Wait Change Trigger for Item(#{item_name}) Duration(#{duration}) "\
|
63
|
+
logger.trace("Creating Changed Wait Change Trigger for Item(#{item_name}) Duration(#{duration}) " \
|
64
64
|
"To(#{to}) From(#{from}) Attach(#{attach})")
|
65
65
|
conditions = Conditions::Duration.new(to: to, from: from, duration: duration)
|
66
66
|
changed_trigger(item: item, to: nil, from: nil, attach: attach, conditions: conditions)
|
@@ -24,7 +24,7 @@ module OpenHAB
|
|
24
24
|
@conditions = Conditions::Proc.new(to: to, from: from)
|
25
25
|
@duration = duration
|
26
26
|
@timer = nil
|
27
|
-
logger.trace "Created Duration Condition To(#{to}) From(#{from}) "\
|
27
|
+
logger.trace "Created Duration Condition To(#{to}) From(#{from}) " \
|
28
28
|
"Conditions(#{@conditions}) Duration(#{@duration})"
|
29
29
|
end
|
30
30
|
|
@@ -109,7 +109,7 @@ module OpenHAB
|
|
109
109
|
state, = retrieve_states(inputs)
|
110
110
|
if state == @tracking_to
|
111
111
|
logger.trace("Item changed to #{state} for #{self}, rescheduling timer.")
|
112
|
-
@timer.reschedule(
|
112
|
+
@timer.reschedule(@duration)
|
113
113
|
else
|
114
114
|
logger.trace("Item changed to #{state} for #{self}, canceling timer.")
|
115
115
|
@timer.cancel
|
data/lib/openhab/dsl/version.rb
CHANGED
data/lib/openhab/dsl.rb
CHANGED
@@ -299,6 +299,8 @@ module OpenHAB
|
|
299
299
|
# @example Create a time range
|
300
300
|
# between('7am'..'12pm').cover?(LocalTime.now)
|
301
301
|
#
|
302
|
+
# @see CoreExt::Between#between? #between?
|
303
|
+
#
|
302
304
|
def between(range)
|
303
305
|
raise ArgumentError, "Supplied object must be a range" unless range.is_a?(Range)
|
304
306
|
|
data/lib/openhab/log.rb
CHANGED
@@ -235,12 +235,19 @@ module OpenHAB
|
|
235
235
|
alias_method :to_s, :inspect
|
236
236
|
|
237
237
|
# @!attribute [rw] level
|
238
|
+
#
|
239
|
+
# @note When a logger's level is modified, the logging infrastructure has
|
240
|
+
# to reload, and logging may be completely unavailable for a short time.
|
241
|
+
#
|
238
242
|
# @return [:error,:warn,:info,:debug,:trace] The current log level
|
243
|
+
#
|
239
244
|
def level
|
240
245
|
Logger.log_service.get_level(name)[name]&.downcase&.to_sym
|
241
246
|
end
|
242
247
|
|
243
248
|
def level=(level)
|
249
|
+
return if self.level == level
|
250
|
+
|
244
251
|
Logger.log_service.set_level(name, level.to_s)
|
245
252
|
end
|
246
253
|
|
data/lib/openhab/rspec/hooks.rb
CHANGED
@@ -57,9 +57,8 @@ module OpenHAB
|
|
57
57
|
tm.class.field_reader :storage
|
58
58
|
tm.storage.keys.each { |k| tm.storage.remove(k) } # rubocop:disable Style/HashEachMethods not a hash
|
59
59
|
|
60
|
-
profile_factory = Core::ProfileFactory.send(:new)
|
61
|
-
|
62
|
-
allow(Core::ProfileFactory).to receive(:instance).and_return(profile_factory)
|
60
|
+
@profile_factory = Core::ProfileFactory.send(:new)
|
61
|
+
allow(Core::ProfileFactory).to receive(:instance).and_return(@profile_factory)
|
63
62
|
|
64
63
|
stub_const("OpenHAB::Core::Timer", Mocks::Timer) if self.class.mock_timers?
|
65
64
|
|
@@ -72,7 +71,7 @@ module OpenHAB
|
|
72
71
|
config.after do
|
73
72
|
Core::Items::Proxy.reset_cache
|
74
73
|
Core::Things::Proxy.reset_cache
|
75
|
-
@
|
74
|
+
@profile_factory.unregister
|
76
75
|
timers.cancel_all
|
77
76
|
# timers and rules have already been canceled, so we can safely just
|
78
77
|
# wipe this
|
data/lib/openhab/rspec/karaf.rb
CHANGED
@@ -351,8 +351,7 @@ module OpenHAB
|
|
351
351
|
}.freeze
|
352
352
|
private_constant :BLOCKED_COMPONENTS
|
353
353
|
|
354
|
-
START_LEVEL_OVERRIDES = {
|
355
|
-
}.freeze
|
354
|
+
START_LEVEL_OVERRIDES = {}.freeze
|
356
355
|
private_constant :START_LEVEL_OVERRIDES
|
357
356
|
|
358
357
|
def set_up_bundle_listener
|
@@ -429,6 +428,11 @@ module OpenHAB
|
|
429
428
|
|
430
429
|
tm.bundleResolver = Mocks::BundleResolver.instance
|
431
430
|
|
431
|
+
require_relative "mocks/safe_caller"
|
432
|
+
field = tm.class.java_class.declared_field :safeCaller
|
433
|
+
field.accessible = true
|
434
|
+
field.set(tm, Mocks::SafeCaller.instance)
|
435
|
+
|
432
436
|
require_relative "mocks/thing_handler"
|
433
437
|
thf = Mocks::ThingHandlerFactory.instance
|
434
438
|
bundle = org.osgi.framework.FrameworkUtil.get_bundle(org.openhab.core.thing.Thing)
|
@@ -19,6 +19,21 @@ module OpenHAB
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
module HistoricState
|
23
|
+
def timestamp
|
24
|
+
# PersistenceExtensions uses an anonymous class to wrap the current
|
25
|
+
# state if that happens to be an answer. Except it calls
|
26
|
+
# ZonedDateTime.now in Java land, bypassing Timecop.
|
27
|
+
# Detect that and make the call in Ruby
|
28
|
+
#
|
29
|
+
jc = @historic_item.class.java_class
|
30
|
+
return ZonedDateTime.now if jc.anonymous? && jc.enclosing_class == PersistenceExtensions.java_class
|
31
|
+
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
Core::Items::Persistence::HistoricState.prepend(HistoricState)
|
36
|
+
|
22
37
|
attr_reader :id
|
23
38
|
|
24
39
|
def initialize
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# rubocop:disable Naming
|
3
|
+
# rubocop:disable Naming/MethodName, Naming/AccessorMethodName
|
4
4
|
|
5
5
|
require "singleton"
|
6
6
|
|
@@ -73,4 +73,4 @@ module OpenHAB
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
|
-
# rubocop:enable Naming
|
76
|
+
# rubocop:enable Naming/MethodName, Naming/AccessorMethodName
|
@@ -16,8 +16,8 @@ module OpenHAB
|
|
16
16
|
|
17
17
|
# have to completely replace this method. only change is the regex splitting
|
18
18
|
# into parts now allows `.` as part of the identifier
|
19
|
-
# rubocop:disable Style
|
20
|
-
def format_types(typelist, brackets = true)
|
19
|
+
# rubocop:disable Style/NestedTernaryOperator, Style/StringConcatenation, Style/TernaryParentheses
|
20
|
+
def format_types(typelist, brackets = true) # rubocop:disable Style/OptionalBooleanParameter
|
21
21
|
return unless typelist.is_a?(Array)
|
22
22
|
|
23
23
|
list = typelist.map do |type|
|
@@ -27,7 +27,7 @@ module OpenHAB
|
|
27
27
|
end
|
28
28
|
list.empty? ? "" : (brackets ? "(#{list.join(", ")})" : list.join(", "))
|
29
29
|
end
|
30
|
-
# rubocop:enable Style
|
30
|
+
# rubocop:enable Style/NestedTernaryOperator, Style/StringConcatenation, Style/TernaryParentheses
|
31
31
|
|
32
32
|
def link_object(obj, title = nil, *)
|
33
33
|
::YARD::Handlers::JRuby::Base.infer_java_class(obj) if obj.is_a?(String)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openhab-jrubyscripting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.0.
|
4
|
+
version: 5.0.0.rc5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-11-
|
11
|
+
date: 2022-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '8.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '8.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: cuke_linter
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,14 +198,14 @@ dependencies:
|
|
198
198
|
requirements:
|
199
199
|
- - "~>"
|
200
200
|
- !ruby/object:Gem::Version
|
201
|
-
version: '
|
201
|
+
version: '13.0'
|
202
202
|
type: :development
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
|
-
version: '
|
208
|
+
version: '13.0'
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
210
|
name: rspec
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -369,6 +369,7 @@ files:
|
|
369
369
|
- lib/openhab/core/provider.rb
|
370
370
|
- lib/openhab/core/registry.rb
|
371
371
|
- lib/openhab/core/rules.rb
|
372
|
+
- lib/openhab/core/rules/module.rb
|
372
373
|
- lib/openhab/core/rules/provider.rb
|
373
374
|
- lib/openhab/core/rules/registry.rb
|
374
375
|
- lib/openhab/core/rules/rule.rb
|
@@ -408,6 +409,7 @@ files:
|
|
408
409
|
- lib/openhab/core/types/up_down_type.rb
|
409
410
|
- lib/openhab/core/uid.rb
|
410
411
|
- lib/openhab/core_ext.rb
|
412
|
+
- lib/openhab/core_ext/between.rb
|
411
413
|
- lib/openhab/core_ext/java/class.rb
|
412
414
|
- lib/openhab/core_ext/java/duration.rb
|
413
415
|
- lib/openhab/core_ext/java/list.rb
|
@@ -455,7 +457,6 @@ files:
|
|
455
457
|
- lib/openhab/dsl/rules/triggers/updated.rb
|
456
458
|
- lib/openhab/dsl/rules/triggers/watch/watch.rb
|
457
459
|
- lib/openhab/dsl/rules/triggers/watch/watch_handler.rb
|
458
|
-
- lib/openhab/dsl/script_handling.rb
|
459
460
|
- lib/openhab/dsl/things/builder.rb
|
460
461
|
- lib/openhab/dsl/thread_local.rb
|
461
462
|
- lib/openhab/dsl/timer_manager.rb
|