openhab-jrubyscripting 5.0.0.rc3 → 5.0.0.rc5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|