openhab-jrubyscripting 5.0.0.rc1
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 +7 -0
- data/lib/openhab/core/actions.rb +163 -0
- data/lib/openhab/core/entity_lookup.rb +144 -0
- data/lib/openhab/core/events/abstract_event.rb +17 -0
- data/lib/openhab/core/events/item_channel_link.rb +36 -0
- data/lib/openhab/core/events/item_command_event.rb +78 -0
- data/lib/openhab/core/events/item_event.rb +22 -0
- data/lib/openhab/core/events/item_state_changed_event.rb +52 -0
- data/lib/openhab/core/events/item_state_event.rb +51 -0
- data/lib/openhab/core/events/thing.rb +29 -0
- data/lib/openhab/core/events/thing_status_info_event.rb +53 -0
- data/lib/openhab/core/events.rb +10 -0
- data/lib/openhab/core/items/accepted_data_types.rb +29 -0
- data/lib/openhab/core/items/color_item.rb +52 -0
- data/lib/openhab/core/items/contact_item.rb +52 -0
- data/lib/openhab/core/items/date_time_item.rb +58 -0
- data/lib/openhab/core/items/dimmer_item.rb +148 -0
- data/lib/openhab/core/items/generic_item.rb +344 -0
- data/lib/openhab/core/items/group_item.rb +174 -0
- data/lib/openhab/core/items/image_item.rb +109 -0
- data/lib/openhab/core/items/location_item.rb +34 -0
- data/lib/openhab/core/items/metadata/hash.rb +390 -0
- data/lib/openhab/core/items/metadata/namespace_hash.rb +469 -0
- data/lib/openhab/core/items/metadata.rb +11 -0
- data/lib/openhab/core/items/number_item.rb +62 -0
- data/lib/openhab/core/items/numeric_item.rb +22 -0
- data/lib/openhab/core/items/persistence.rb +327 -0
- data/lib/openhab/core/items/player_item.rb +66 -0
- data/lib/openhab/core/items/proxy.rb +59 -0
- data/lib/openhab/core/items/registry.rb +66 -0
- data/lib/openhab/core/items/rollershutter_item.rb +68 -0
- data/lib/openhab/core/items/semantics/enumerable.rb +152 -0
- data/lib/openhab/core/items/semantics.rb +476 -0
- data/lib/openhab/core/items/state_storage.rb +53 -0
- data/lib/openhab/core/items/string_item.rb +28 -0
- data/lib/openhab/core/items/switch_item.rb +78 -0
- data/lib/openhab/core/items.rb +114 -0
- data/lib/openhab/core/lazy_array.rb +52 -0
- data/lib/openhab/core/profile_factory.rb +118 -0
- data/lib/openhab/core/script_handling.rb +55 -0
- data/lib/openhab/core/things/channel.rb +48 -0
- data/lib/openhab/core/things/channel_uid.rb +51 -0
- data/lib/openhab/core/things/item_channel_link.rb +33 -0
- data/lib/openhab/core/things/profile_callback.rb +52 -0
- data/lib/openhab/core/things/proxy.rb +69 -0
- data/lib/openhab/core/things/registry.rb +46 -0
- data/lib/openhab/core/things/thing.rb +194 -0
- data/lib/openhab/core/things.rb +22 -0
- data/lib/openhab/core/timer.rb +128 -0
- data/lib/openhab/core/types/comparable_type.rb +23 -0
- data/lib/openhab/core/types/date_time_type.rb +259 -0
- data/lib/openhab/core/types/decimal_type.rb +192 -0
- data/lib/openhab/core/types/hsb_type.rb +183 -0
- data/lib/openhab/core/types/increase_decrease_type.rb +34 -0
- data/lib/openhab/core/types/next_previous_type.rb +34 -0
- data/lib/openhab/core/types/numeric_type.rb +52 -0
- data/lib/openhab/core/types/on_off_type.rb +46 -0
- data/lib/openhab/core/types/open_closed_type.rb +41 -0
- data/lib/openhab/core/types/percent_type.rb +95 -0
- data/lib/openhab/core/types/play_pause_type.rb +38 -0
- data/lib/openhab/core/types/point_type.rb +117 -0
- data/lib/openhab/core/types/quantity_type.rb +327 -0
- data/lib/openhab/core/types/raw_type.rb +26 -0
- data/lib/openhab/core/types/refresh_type.rb +27 -0
- data/lib/openhab/core/types/rewind_fastforward_type.rb +38 -0
- data/lib/openhab/core/types/stop_move_type.rb +34 -0
- data/lib/openhab/core/types/string_type.rb +76 -0
- data/lib/openhab/core/types/type.rb +117 -0
- data/lib/openhab/core/types/un_def_type.rb +38 -0
- data/lib/openhab/core/types/up_down_type.rb +50 -0
- data/lib/openhab/core/types.rb +69 -0
- data/lib/openhab/core/uid.rb +36 -0
- data/lib/openhab/core.rb +85 -0
- data/lib/openhab/core_ext/java/duration.rb +115 -0
- data/lib/openhab/core_ext/java/local_date.rb +93 -0
- data/lib/openhab/core_ext/java/local_time.rb +106 -0
- data/lib/openhab/core_ext/java/month.rb +59 -0
- data/lib/openhab/core_ext/java/month_day.rb +105 -0
- data/lib/openhab/core_ext/java/period.rb +103 -0
- data/lib/openhab/core_ext/java/temporal_amount.rb +34 -0
- data/lib/openhab/core_ext/java/time.rb +58 -0
- data/lib/openhab/core_ext/java/unit.rb +15 -0
- data/lib/openhab/core_ext/java/zoned_date_time.rb +116 -0
- data/lib/openhab/core_ext/ruby/array.rb +21 -0
- data/lib/openhab/core_ext/ruby/class.rb +15 -0
- data/lib/openhab/core_ext/ruby/date.rb +89 -0
- data/lib/openhab/core_ext/ruby/numeric.rb +190 -0
- data/lib/openhab/core_ext/ruby/range.rb +70 -0
- data/lib/openhab/core_ext/ruby/time.rb +104 -0
- data/lib/openhab/core_ext.rb +18 -0
- data/lib/openhab/dsl/events/watch_event.rb +18 -0
- data/lib/openhab/dsl/events.rb +9 -0
- data/lib/openhab/dsl/gems.rb +3 -0
- data/lib/openhab/dsl/items/builder.rb +618 -0
- data/lib/openhab/dsl/items/ensure.rb +93 -0
- data/lib/openhab/dsl/items/timed_command.rb +236 -0
- data/lib/openhab/dsl/rules/automation_rule.rb +308 -0
- data/lib/openhab/dsl/rules/builder.rb +1373 -0
- data/lib/openhab/dsl/rules/guard.rb +115 -0
- data/lib/openhab/dsl/rules/name_inference.rb +160 -0
- data/lib/openhab/dsl/rules/property.rb +76 -0
- data/lib/openhab/dsl/rules/rule_triggers.rb +96 -0
- data/lib/openhab/dsl/rules/terse.rb +63 -0
- data/lib/openhab/dsl/rules/triggers/changed.rb +169 -0
- data/lib/openhab/dsl/rules/triggers/channel.rb +57 -0
- data/lib/openhab/dsl/rules/triggers/command.rb +107 -0
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +161 -0
- data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +164 -0
- data/lib/openhab/dsl/rules/triggers/cron/cron.rb +195 -0
- data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +127 -0
- data/lib/openhab/dsl/rules/triggers/trigger.rb +56 -0
- data/lib/openhab/dsl/rules/triggers/updated.rb +130 -0
- data/lib/openhab/dsl/rules/triggers/watch/watch.rb +55 -0
- data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +155 -0
- data/lib/openhab/dsl/rules/triggers.rb +12 -0
- data/lib/openhab/dsl/rules.rb +29 -0
- data/lib/openhab/dsl/script_handling.rb +55 -0
- data/lib/openhab/dsl/things/builder.rb +263 -0
- data/lib/openhab/dsl/thread_local.rb +48 -0
- data/lib/openhab/dsl/timer_manager.rb +191 -0
- data/lib/openhab/dsl/version.rb +9 -0
- data/lib/openhab/dsl.rb +686 -0
- data/lib/openhab/log.rb +348 -0
- data/lib/openhab/osgi.rb +70 -0
- data/lib/openhab/rspec/configuration.rb +56 -0
- data/lib/openhab/rspec/example_group.rb +90 -0
- data/lib/openhab/rspec/helpers.rb +439 -0
- data/lib/openhab/rspec/hooks.rb +93 -0
- data/lib/openhab/rspec/jruby.rb +46 -0
- data/lib/openhab/rspec/karaf.rb +811 -0
- data/lib/openhab/rspec/mocks/bundle_install_support.rb +25 -0
- data/lib/openhab/rspec/mocks/bundle_resolver.rb +30 -0
- data/lib/openhab/rspec/mocks/event_admin.rb +146 -0
- data/lib/openhab/rspec/mocks/metadata_provider.rb +75 -0
- data/lib/openhab/rspec/mocks/persistence_service.rb +140 -0
- data/lib/openhab/rspec/mocks/safe_caller.rb +40 -0
- data/lib/openhab/rspec/mocks/synchronous_executor.rb +56 -0
- data/lib/openhab/rspec/mocks/thing_handler.rb +76 -0
- data/lib/openhab/rspec/mocks/timer.rb +95 -0
- data/lib/openhab/rspec/openhab/core/actions.rb +26 -0
- data/lib/openhab/rspec/openhab/core/items/proxy.rb +27 -0
- data/lib/openhab/rspec/openhab/core/things/proxy.rb +27 -0
- data/lib/openhab/rspec/shell.rb +31 -0
- data/lib/openhab/rspec/suspend_rules.rb +60 -0
- data/lib/openhab/rspec.rb +17 -0
- data/lib/openhab/yard/cli/stats.rb +23 -0
- data/lib/openhab/yard/code_objects/group_object.rb +17 -0
- data/lib/openhab/yard/code_objects/java/base.rb +31 -0
- data/lib/openhab/yard/code_objects/java/class_object.rb +11 -0
- data/lib/openhab/yard/code_objects/java/field_object.rb +15 -0
- data/lib/openhab/yard/code_objects/java/interface_object.rb +15 -0
- data/lib/openhab/yard/code_objects/java/package_object.rb +11 -0
- data/lib/openhab/yard/code_objects/java/proxy.rb +23 -0
- data/lib/openhab/yard/handlers/jruby/base.rb +49 -0
- data/lib/openhab/yard/handlers/jruby/class_handler.rb +18 -0
- data/lib/openhab/yard/handlers/jruby/constant_handler.rb +18 -0
- data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +27 -0
- data/lib/openhab/yard/handlers/jruby/mixin_handler.rb +23 -0
- data/lib/openhab/yard/html_helper.rb +44 -0
- data/lib/openhab/yard/tags/constant_directive.rb +20 -0
- data/lib/openhab/yard/tags/group_directive.rb +24 -0
- data/lib/openhab/yard/tags/library.rb +3 -0
- data/lib/openhab/yard.rb +32 -0
- metadata +504 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "delegate"
|
|
4
|
+
|
|
5
|
+
module OpenHAB
|
|
6
|
+
module RSpec
|
|
7
|
+
# @!visibility private
|
|
8
|
+
module Mocks
|
|
9
|
+
class BundleInstallSupport < SimpleDelegator
|
|
10
|
+
include org.apache.karaf.features.internal.service.BundleInstallSupport
|
|
11
|
+
|
|
12
|
+
def initialize(parent, karaf_wrapper)
|
|
13
|
+
super(parent)
|
|
14
|
+
@karaf_wrapper = karaf_wrapper
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def set_bundle_start_level(bundle, _start_level)
|
|
18
|
+
return if @karaf_wrapper.send(:blocked_bundle?, bundle)
|
|
19
|
+
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "singleton"
|
|
4
|
+
|
|
5
|
+
module OpenHAB
|
|
6
|
+
module RSpec
|
|
7
|
+
module Mocks
|
|
8
|
+
class BundleResolver
|
|
9
|
+
include org.openhab.core.util.BundleResolver
|
|
10
|
+
include Singleton
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@classes = {}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def register_class(klass, bundle)
|
|
17
|
+
# ensure we have an individual java class already
|
|
18
|
+
@classes[klass.become_java!] = bundle
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def resolve_bundle(clazz)
|
|
22
|
+
bundle = @classes[clazz]
|
|
23
|
+
return bundle if bundle
|
|
24
|
+
|
|
25
|
+
org.osgi.framework.FrameworkUtil.get_bundle(clazz)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "singleton"
|
|
4
|
+
|
|
5
|
+
module OpenHAB
|
|
6
|
+
module RSpec
|
|
7
|
+
module Mocks
|
|
8
|
+
# reimplement to not use a thread
|
|
9
|
+
class OSGiEventManager
|
|
10
|
+
attr_reader :logger
|
|
11
|
+
|
|
12
|
+
def initialize(typed_event_factories, typed_event_subscribers)
|
|
13
|
+
@typed_event_factories = typed_event_factories
|
|
14
|
+
@typed_event_subscribers = typed_event_subscribers
|
|
15
|
+
@logger = org.slf4j.LoggerFactory.get_logger("rspec.openhab.core.mocks.event_handler")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def handle_event(osgi_event)
|
|
19
|
+
type = osgi_event.get_property("type")
|
|
20
|
+
payload = osgi_event.get_property("payload")
|
|
21
|
+
topic = osgi_event.get_property("topic")
|
|
22
|
+
source = osgi_event.get_property("source")
|
|
23
|
+
|
|
24
|
+
if type.is_a?(String) && payload.is_a?(String) && topic.is_a?(String)
|
|
25
|
+
handle_event_internal(type, payload, topic, source) unless type.empty? || payload.empty? || topic.empty?
|
|
26
|
+
else
|
|
27
|
+
logger.error("The handled OSGi event is invalid. " \
|
|
28
|
+
"Expect properties as string named 'type', 'payload', and 'topic'. " \
|
|
29
|
+
"Received event properties are: #{osgi_event.property_names.inspect}")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def handle_event_internal(type, payload, topic, source)
|
|
36
|
+
event_factory = @typed_event_factories[type]
|
|
37
|
+
unless event_factory
|
|
38
|
+
logger.debug("Could not find an Event Factory for the event type '#{type}'.")
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
event_subscribers = event_subscribers(type)
|
|
43
|
+
return if event_subscribers.empty?
|
|
44
|
+
|
|
45
|
+
event = create_event(event_factory, type, payload, topic, source)
|
|
46
|
+
return unless event
|
|
47
|
+
|
|
48
|
+
dispatch_event(event_subscribers, event)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def event_subscribers(event_type)
|
|
52
|
+
event_type_subscribers = @typed_event_subscribers[event_type]
|
|
53
|
+
all_event_type_subscribers = @typed_event_subscribers["ALL"]
|
|
54
|
+
|
|
55
|
+
subscribers = java.util.HashSet.new
|
|
56
|
+
subscribers.add_all(event_type_subscribers) if event_type_subscribers
|
|
57
|
+
subscribers.add_all(all_event_type_subscribers) if all_event_type_subscribers
|
|
58
|
+
subscribers
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def create_event(event_factory, type, payload, topic, source)
|
|
62
|
+
event_factory.create_event(type, topic, payload, source)
|
|
63
|
+
rescue Exception => e
|
|
64
|
+
logger.warn("Creation of event failed, because one of the " \
|
|
65
|
+
"registered event factories has thrown an exception: #{e.inspect}")
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def dispatch_event(event_subscribers, event)
|
|
70
|
+
event_subscribers.each do |event_subscriber|
|
|
71
|
+
filter = event_subscriber.event_filter
|
|
72
|
+
if filter.nil? || filter.apply(event)
|
|
73
|
+
begin
|
|
74
|
+
event_subscriber.receive(event)
|
|
75
|
+
rescue Exception => e
|
|
76
|
+
logger.warn(
|
|
77
|
+
"Dispatching/filtering event for subscriber '#{event_subscriber.class}' failed: #{e.inspect}"
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
else
|
|
81
|
+
logger.trace("Skip event subscriber (#{event_subscriber.class}) because of its filter.")
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class EventAdmin < org.osgi.util.tracker.ServiceTracker
|
|
88
|
+
include org.osgi.service.event.EventAdmin
|
|
89
|
+
|
|
90
|
+
def initialize(bundle_context)
|
|
91
|
+
super(bundle_context, "org.osgi.service.event.EventHandler", nil)
|
|
92
|
+
|
|
93
|
+
@handlers_matching_all_events = []
|
|
94
|
+
@handlers_matching_topics = Hash.new { |h, k| h[k] = [] }
|
|
95
|
+
open
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def addingService(reference) # rubocop:disable Naming/MethodName
|
|
99
|
+
topics = Array(reference.get_property(org.osgi.service.event.EventConstants::EVENT_TOPIC))
|
|
100
|
+
topics = nil if topics.empty? || topics.include?("*")
|
|
101
|
+
|
|
102
|
+
service = OSGi.send(:bundle_context).get_service(reference)
|
|
103
|
+
|
|
104
|
+
if reference.get_property("component.name") == "org.openhab.core.internal.events.OSGiEventManager"
|
|
105
|
+
# OSGiEventManager will create a ThreadedEventHandler on OSGi activation;
|
|
106
|
+
# we're skipping that, and directly sending to a non-threaded event handler.
|
|
107
|
+
service.class.field_reader :typedEventFactories, :typedEventSubscribers
|
|
108
|
+
service = OSGiEventManager.new(service.typedEventFactories, service.typedEventSubscribers)
|
|
109
|
+
end
|
|
110
|
+
if topics.nil?
|
|
111
|
+
@handlers_matching_all_events << service
|
|
112
|
+
else
|
|
113
|
+
topics.each do |topic|
|
|
114
|
+
@handlers_matching_topics[topic] << service
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
service
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def postEvent(event) # rubocop:disable Naming/MethodName
|
|
121
|
+
sendEvent(event)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def sendEvent(event) # rubocop:disable Naming/MethodName
|
|
125
|
+
# prevent re-entrancy
|
|
126
|
+
if (pending_events = Thread.current[:event_admin_pending_events])
|
|
127
|
+
pending_events << event
|
|
128
|
+
return
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
pending_events = Thread.current[:event_admin_pending_events] = []
|
|
132
|
+
handle_event(event)
|
|
133
|
+
handle_event(pending_events.shift) until pending_events.empty?
|
|
134
|
+
Thread.current[:event_admin_pending_events] = nil
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def handle_event(event)
|
|
140
|
+
@handlers_matching_all_events.each { |h| h.handle_event(event) }
|
|
141
|
+
@handlers_matching_topics[event.topic].each { |h| h.handle_event(event) }
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenHAB
|
|
4
|
+
module RSpec
|
|
5
|
+
module Mocks
|
|
6
|
+
class MetadataProvider
|
|
7
|
+
org.openhab.core.common.registry.Identifiable
|
|
8
|
+
include org.openhab.core.items.ManagedMetadataProvider
|
|
9
|
+
|
|
10
|
+
def initialize(parent)
|
|
11
|
+
@metadata = {}
|
|
12
|
+
@listeners = []
|
|
13
|
+
@parent = parent
|
|
14
|
+
@removed_from_parent = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def addProviderChangeListener(listener) # rubocop:disable Naming/MethodName required by java interface
|
|
18
|
+
@listeners << listener
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def removeProviderChangeListener(listener) # rubocop:disable Naming/MethodName required by java interface
|
|
22
|
+
old = @listeners.delete(listener)
|
|
23
|
+
return unless old
|
|
24
|
+
|
|
25
|
+
@listeners.each { |l| l.removed(self, old) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add(metadata)
|
|
29
|
+
@metadata[metadata.uid] = metadata
|
|
30
|
+
@listeners.each { |l| l.added(self, metadata) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update(metadata)
|
|
34
|
+
old_element = @metadata[metadata.uid]
|
|
35
|
+
raise ArgumentError if old_element.nil?
|
|
36
|
+
|
|
37
|
+
@metadata[metadata.uid] = metadata
|
|
38
|
+
@listeners.each { |l| l.updated(self, old_element, metadata) }
|
|
39
|
+
metadata
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def remove(key)
|
|
43
|
+
m = @parent.remove(key)
|
|
44
|
+
@removed_from_parent << m if m
|
|
45
|
+
m = @metadata.delete(key)
|
|
46
|
+
@listeners.each { |l| l.removed(self, m) } if m
|
|
47
|
+
m
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def restore_parent
|
|
51
|
+
@removed_from_parent.each do |m|
|
|
52
|
+
@parent.add(m)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def get(key)
|
|
57
|
+
@metadata[key]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def getAll # rubocop:disable Naming/MethodName required by java interface
|
|
61
|
+
@metadata.values
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def removeItemMetadata(item_name) # rubocop:disable Naming/MethodName required by java interface
|
|
65
|
+
@metadata.delete_if do |k, v|
|
|
66
|
+
next unless k.item_name == item_name
|
|
67
|
+
|
|
68
|
+
@listeners.each { |l| l.removed(self, v) }
|
|
69
|
+
true
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenHAB
|
|
4
|
+
module RSpec
|
|
5
|
+
module Mocks
|
|
6
|
+
class PersistenceService
|
|
7
|
+
include org.openhab.core.persistence.ModifiablePersistenceService
|
|
8
|
+
include Singleton
|
|
9
|
+
|
|
10
|
+
class HistoricItem
|
|
11
|
+
include org.openhab.core.persistence.HistoricItem
|
|
12
|
+
|
|
13
|
+
attr_reader :timestamp, :state, :name
|
|
14
|
+
|
|
15
|
+
def initialize(timestamp, state, name)
|
|
16
|
+
@timestamp = timestamp
|
|
17
|
+
@state = state
|
|
18
|
+
@name = name
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :id
|
|
23
|
+
|
|
24
|
+
def initialize
|
|
25
|
+
@id = "default"
|
|
26
|
+
reset
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def reset
|
|
30
|
+
@data = Hash.new { |h, k| h[k] = [] }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def store(item, date = nil, state = nil)
|
|
34
|
+
date = nil if date.is_a?(String) # alias overload
|
|
35
|
+
state ||= item.state
|
|
36
|
+
date ||= ZonedDateTime.now
|
|
37
|
+
|
|
38
|
+
new_item = HistoricItem.new(date, state, item.name)
|
|
39
|
+
|
|
40
|
+
item_history = @data[item.name]
|
|
41
|
+
|
|
42
|
+
insert_index = item_history.bsearch_index do |i|
|
|
43
|
+
i.timestamp.compare_to(date).positive?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
return item_history << new_item unless insert_index
|
|
47
|
+
|
|
48
|
+
return item_history[insert_index].state = state if item_history[insert_index].timestamp == date
|
|
49
|
+
|
|
50
|
+
item_history.insert(insert_index, new_item)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def remove(filter)
|
|
54
|
+
query_internal(filter) do |item_history, index|
|
|
55
|
+
historic_item = item_history.delete_at(index)
|
|
56
|
+
@data.delete(historic_item.name) if item_history.empty?
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def query(filter)
|
|
61
|
+
result = []
|
|
62
|
+
|
|
63
|
+
query_internal(filter) do |item_history, index|
|
|
64
|
+
result << item_history[index]
|
|
65
|
+
|
|
66
|
+
return result if filter.page_number.zero? && result.length == filter.page_size && filter.item_name
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
result.sort_by!(&:timestamp) unless filter.item_name
|
|
70
|
+
|
|
71
|
+
result = result.slice(filter.page_number * filter.page_size, filter.page_size) unless filter.page_number.zero?
|
|
72
|
+
|
|
73
|
+
result
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def get_item_info # rubocop:disable Naming/AccessorMethodName must match Java interface
|
|
77
|
+
@data.map do |(n, entries)|
|
|
78
|
+
[n, entries.length, entries.first.timestamp, entries.last.timestamp]
|
|
79
|
+
end.to_set
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def get_default_strategies # rubocop:disable Naming/AccessorMethodName must match Java interface
|
|
83
|
+
[org.openhab.core.persistence.strategy.PersistenceStrategy::Globals::CHANGE]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def query_internal(filter, &block)
|
|
89
|
+
if filter.item_name
|
|
90
|
+
return unless @data.key?(filter.item_name)
|
|
91
|
+
|
|
92
|
+
query_item_internal(@data[filter.item_name], filter, &block)
|
|
93
|
+
else
|
|
94
|
+
@data.each_value do |item_history|
|
|
95
|
+
query_item_internal(item_history, filter, &block)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def query_item_internal(item_history, filter)
|
|
101
|
+
first_index = 0
|
|
102
|
+
last_index = item_history.length
|
|
103
|
+
|
|
104
|
+
if filter.begin_date
|
|
105
|
+
first_index = item_history.bsearch_index do |i|
|
|
106
|
+
i.timestamp.compare_to(filter.begin_date).positive?
|
|
107
|
+
end
|
|
108
|
+
return if first_index.nil?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
if filter.end_date
|
|
112
|
+
last_index = item_history.bsearch_index do |i|
|
|
113
|
+
i.timestamp.compare_to(filter.end_date).positive?
|
|
114
|
+
end
|
|
115
|
+
return if last_index.zero?
|
|
116
|
+
|
|
117
|
+
last_index ||= item_history.length
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
range = first_index...last_index
|
|
121
|
+
|
|
122
|
+
operator = filter.operator.symbol
|
|
123
|
+
operator = "==" if operator == "="
|
|
124
|
+
|
|
125
|
+
block = lambda do |i|
|
|
126
|
+
next if filter.state && !item_history[i].state.send(operator, filter.state)
|
|
127
|
+
|
|
128
|
+
yield(item_history, i)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
if filter.ordering == filter.class::Ordering::DESCENDING
|
|
132
|
+
range.reverse_each(&block)
|
|
133
|
+
else
|
|
134
|
+
range.each(&block)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "singleton"
|
|
4
|
+
|
|
5
|
+
module OpenHAB
|
|
6
|
+
module RSpec
|
|
7
|
+
module Mocks
|
|
8
|
+
class SafeCaller
|
|
9
|
+
include Singleton
|
|
10
|
+
include org.openhab.core.common.SafeCaller
|
|
11
|
+
|
|
12
|
+
class Builder
|
|
13
|
+
include org.openhab.core.common.SafeCallerBuilder
|
|
14
|
+
|
|
15
|
+
def initialize(target)
|
|
16
|
+
@target = target
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def build
|
|
20
|
+
@target
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def chain(*)
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias_method :withTimeout, :chain
|
|
28
|
+
alias_method :withIdentifier, :chain
|
|
29
|
+
alias_method :onException, :chain
|
|
30
|
+
alias_method :onTimeout, :chain
|
|
31
|
+
alias_method :withAsync, :chain
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def create(target, _klass)
|
|
35
|
+
Builder.new(target)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "singleton"
|
|
4
|
+
|
|
5
|
+
module OpenHAB
|
|
6
|
+
module RSpec
|
|
7
|
+
module Mocks
|
|
8
|
+
class CallbacksMap < java.util.HashMap
|
|
9
|
+
def put(_rule_uid, trigger_handler)
|
|
10
|
+
if trigger_handler.executor
|
|
11
|
+
trigger_handler.executor.shutdown_now
|
|
12
|
+
trigger_handler.executor = SynchronousExecutor.instance
|
|
13
|
+
end
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class SynchronousExecutor < java.util.concurrent.ScheduledThreadPoolExecutor
|
|
19
|
+
class << self
|
|
20
|
+
def instance
|
|
21
|
+
@instance ||= new(1)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def submit(runnable)
|
|
26
|
+
runnable.respond_to?(:run) ? runnable.run : runnable.call
|
|
27
|
+
|
|
28
|
+
java.util.concurrent.CompletableFuture.completed_future(nil)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def execute(runnable)
|
|
32
|
+
runnable.run
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def shutdown; end
|
|
36
|
+
|
|
37
|
+
def shutdown_now
|
|
38
|
+
[]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class SynchronousExecutorMap
|
|
43
|
+
include java.util.Map
|
|
44
|
+
include Singleton
|
|
45
|
+
|
|
46
|
+
def get(_key)
|
|
47
|
+
SynchronousExecutor.instance
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def key_set
|
|
51
|
+
java.util.HashSet.new
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Naming have to follow java interface names
|
|
4
|
+
|
|
5
|
+
require "singleton"
|
|
6
|
+
|
|
7
|
+
module OpenHAB
|
|
8
|
+
module RSpec
|
|
9
|
+
module Mocks
|
|
10
|
+
class ThingHandler
|
|
11
|
+
include org.openhab.core.thing.binding.BridgeHandler
|
|
12
|
+
|
|
13
|
+
attr_reader :thing, :callback
|
|
14
|
+
|
|
15
|
+
def initialize(thing = nil)
|
|
16
|
+
# have to handle the interface method
|
|
17
|
+
if thing.nil?
|
|
18
|
+
status_info = org.openhab.core.thing.binding.builder.ThingStatusInfoBuilder
|
|
19
|
+
.create(org.openhab.core.thing.ThingStatus::ONLINE).build
|
|
20
|
+
@callback.status_updated(self.thing, status_info)
|
|
21
|
+
return
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# ruby initializer here
|
|
25
|
+
@thing = thing
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def thing_updated(thing)
|
|
29
|
+
@thing = thing
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def handle_command(channel, command); end
|
|
33
|
+
|
|
34
|
+
def set_callback(callback)
|
|
35
|
+
@callback = callback
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def child_handler_initialized(child_handler, child_thing); end
|
|
39
|
+
def child_handler_disposed(child_handler, child_thing); end
|
|
40
|
+
|
|
41
|
+
def channel_linked(_channel_uid); end
|
|
42
|
+
def channel_unlinked(_channel_uid); end
|
|
43
|
+
|
|
44
|
+
def dispose; end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class ThingHandlerFactory < org.openhab.core.thing.binding.BaseThingHandlerFactory
|
|
48
|
+
include Singleton
|
|
49
|
+
|
|
50
|
+
class ComponentContext
|
|
51
|
+
include org.osgi.service.component.ComponentContext
|
|
52
|
+
include Singleton
|
|
53
|
+
|
|
54
|
+
def getBundleContext
|
|
55
|
+
org.osgi.framework.FrameworkUtil.get_bundle(org.openhab.core.thing.Thing).bundle_context
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
private_constant :ComponentContext
|
|
59
|
+
|
|
60
|
+
def initialize
|
|
61
|
+
super
|
|
62
|
+
activate(ComponentContext.instance)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def supportsThingType(_type)
|
|
66
|
+
true
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def createHandler(thing)
|
|
70
|
+
ThingHandler.new(thing)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
# rubocop:enable Naming
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "timecop"
|
|
4
|
+
|
|
5
|
+
module OpenHAB
|
|
6
|
+
module RSpec
|
|
7
|
+
module Mocks
|
|
8
|
+
class Timer < Core::Timer
|
|
9
|
+
# @!visibility private
|
|
10
|
+
module MockedZonedDateTime
|
|
11
|
+
def now
|
|
12
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
|
13
|
+
return super unless mocked_time_stack_item
|
|
14
|
+
|
|
15
|
+
mocked_time_stack_item.time.to_zoned_date_time
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
ZonedDateTime.singleton_class.prepend(MockedZonedDateTime)
|
|
19
|
+
|
|
20
|
+
# extend Timecop to support Java time classes
|
|
21
|
+
# @!visibility private
|
|
22
|
+
module TimeCopStackItem
|
|
23
|
+
def parse_time(*args)
|
|
24
|
+
if args.length == 1
|
|
25
|
+
arg = args.first
|
|
26
|
+
if arg.is_a?(Time) ||
|
|
27
|
+
(defined?(DateTime) && arg.is_a?(DateTime)) ||
|
|
28
|
+
(defined?(Date) && arg.is_a?(Date))
|
|
29
|
+
return super
|
|
30
|
+
elsif arg.respond_to?(:to_zoned_date_time)
|
|
31
|
+
return arg.to_zoned_date_time.to_time
|
|
32
|
+
elsif arg.is_a?(java.time.temporal.TemporalAmount)
|
|
33
|
+
return (ZonedDateTime.now + arg).to_time
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
Timecop::TimeStackItem.prepend(TimeCopStackItem)
|
|
41
|
+
|
|
42
|
+
attr_reader :execution_time, :id, :block
|
|
43
|
+
|
|
44
|
+
def initialize(time, id:, thread_locals:, block:) # rubocop:disable Lint/MissingSuper
|
|
45
|
+
@time = time
|
|
46
|
+
@id = id
|
|
47
|
+
@block = block
|
|
48
|
+
@thread_locals = thread_locals
|
|
49
|
+
reschedule(time)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def reschedule(time = nil)
|
|
53
|
+
@execution_time = new_execution_time(time || @time)
|
|
54
|
+
@executed = false
|
|
55
|
+
|
|
56
|
+
DSL::TimerManager.instance.add(self)
|
|
57
|
+
|
|
58
|
+
self
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def execute
|
|
62
|
+
raise "Timer already cancelled" if cancelled?
|
|
63
|
+
raise "Timer already executed" if terminated?
|
|
64
|
+
|
|
65
|
+
super
|
|
66
|
+
@executed = true
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def cancel
|
|
70
|
+
return false if terminated? || cancelled?
|
|
71
|
+
|
|
72
|
+
DSL::TimerManager.instance.delete(self)
|
|
73
|
+
@execution_time = nil
|
|
74
|
+
true
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def cancelled?
|
|
78
|
+
@execution_time.nil?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def terminated?
|
|
82
|
+
@executed || cancelled?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def running?
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def active?
|
|
90
|
+
!terminated?
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|