rspec-openhab-scripting 0.0.16-java → 0.0.17-java

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5dd7ea9915aa3edecf86f75d7331bfe77ad3fbbbee4c278fd130895e4bc1e6c
4
- data.tar.gz: 489db2879bf94009c027fcbb87572ae5b3834d31fab17f473cddc2fdecfebdfd
3
+ metadata.gz: a5541ba712d1a3fef9112f736b456309acb491aa0cdf075098abe04712a59940
4
+ data.tar.gz: d75f2b90687529a2bbc63f6d456f639a23360e7636d8ea7c36ed4d2113c7b6d7
5
5
  SHA512:
6
- metadata.gz: 967d33cd26a809179324637df7ebb9243ec901ae6c75aaa97a1615a6f699082bb83050727502c326bcf85732f86521f93ce253877306d8e6cf86b4ed84030708
7
- data.tar.gz: 375c3ebb1c64176b3da00a8489b8b9574e5636d767a2cb981100dc3b6b3128cbf23fc8b7ab9998ed3b7154a9d0754be6f349d3711ef326e7714ec360cac89732
6
+ metadata.gz: f576f81ea3fea76dbb173e8aa7ad3d1439f24e518bcd8574597266fe4bc457e325b6ec2f214e9c15a9c6b4c681d7350f7845fe055962f3b1b68214c0433b6b4d
7
+ data.tar.gz: 394f5a733ed2ddd02bf109f08fb80bbc35f8db5cebb340231a4b9bb17064ba17598ea1dbd90de18e16ff7d6ef52c387db001da6f6a3ae140c44928e71cef48c5
@@ -4,11 +4,12 @@ require "faraday"
4
4
 
5
5
  module OpenHAB
6
6
  class API
7
- def initialize(url)
7
+ def initialize(url, token = nil)
8
8
  @faraday = Faraday.new(url) do |f|
9
9
  f.response :raise_error
10
10
  f.response :json
11
11
  f.path_prefix = "/rest/"
12
+ f.headers = { "X-OPENHAB-TOKEN" => token } if token
12
13
  end
13
14
  end
14
15
 
@@ -36,6 +37,22 @@ module OpenHAB
36
37
  nil
37
38
  end
38
39
 
40
+ def channel_types
41
+ @faraday.get("channel-types").body
42
+ end
43
+
44
+ def thing_types
45
+ @faraday.get("thing-types").body
46
+ end
47
+
48
+ def things
49
+ @faraday.get("things").body
50
+ end
51
+
52
+ def authenticated?
53
+ @faraday.headers.key?("X-OPENHAB-TOKEN")
54
+ end
55
+
39
56
  private
40
57
 
41
58
  def root_data
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module OpenHAB
5
+ module Core
6
+ module Mocks
7
+ class ChannelTypeProvider
8
+ include org.openhab.core.thing.type.ChannelTypeProvider
9
+ include Singleton
10
+
11
+ def initialize
12
+ @types = {}
13
+ end
14
+
15
+ def add(type)
16
+ @types[type.uid] = type
17
+ end
18
+
19
+ def get_channel_types(_locale)
20
+ @types.values
21
+ end
22
+
23
+ def get_channel_type(uid, _locale)
24
+ @types[uid]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module OpenHAB
5
+ module Core
6
+ module Mocks
7
+ class ItemChannelLinkProvider
8
+ include org.openhab.core.thing.link.ItemChannelLinkProvider
9
+ include Singleton
10
+
11
+ def initialize
12
+ @listeners = []
13
+ @links = []
14
+ end
15
+
16
+ def add_provider_change_listener(listener)
17
+ @listeners << listener
18
+ end
19
+
20
+ def remove_provider_change_listener(listener)
21
+ @listeners.delete(listener)
22
+ end
23
+
24
+ def all
25
+ @links
26
+ end
27
+
28
+ def add(link)
29
+ @links << link
30
+ @listeners.each { |l| l.added(self, link) }
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module OpenHAB
5
+ module Core
6
+ module Mocks
7
+ class ThingTypeProvider
8
+ include org.openhab.core.thing.binding.ThingTypeProvider
9
+ include Singleton
10
+
11
+ def initialize
12
+ @types = {}
13
+ end
14
+
15
+ def add(type)
16
+ @types[type.uid] = type
17
+ end
18
+
19
+ def get_thing_types(_locale)
20
+ @types.values
21
+ end
22
+
23
+ def get_thing_type(uid, _locale)
24
+ @types[uid]
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -4,7 +4,11 @@ module OpenHAB
4
4
  module Core
5
5
  class OSGI
6
6
  class << self
7
- def register_service(name, service)
7
+ def register_service(name, service = nil)
8
+ if service.nil?
9
+ service = name
10
+ name = service.java_class.interfaces.first&.name || service.java_class.name
11
+ end
8
12
  (@services ||= {})[name] = service
9
13
  end
10
14
 
@@ -68,6 +68,12 @@ module OpenHAB
68
68
  def add_bundle_listener(listener); end
69
69
  end
70
70
 
71
+ class BundleResolver
72
+ include org.openhab.core.util.BundleResolver
73
+
74
+ def resolve_bundle(klass); end
75
+ end
76
+
71
77
  # don't depend on org.openhab.core.test
72
78
  class VolatileStorageService
73
79
  include org.openhab.core.storage.StorageService
@@ -190,7 +196,7 @@ module OpenHAB
190
196
  event_factory.create_event(type, topic, payload, source)
191
197
  rescue Exception => e
192
198
  logger.warn("Creation of event failed, because one of the " \
193
- "registered event factories has thrown an exception: #{e}")
199
+ "registered event factories has thrown an exception: #{e.inspect}")
194
200
  nil
195
201
  end
196
202
 
@@ -201,7 +207,9 @@ module OpenHAB
201
207
  begin
202
208
  event_subscriber.receive(event)
203
209
  rescue Exception => e
204
- logger.warn("Dispatching/filtering event for subscriber '#{event_subscriber.class}' failed: #{e}")
210
+ logger.warn(
211
+ "Dispatching/filtering event for subscriber '#{event_subscriber.class}' failed: #{e.inspect}"
212
+ )
205
213
  end
206
214
  else
207
215
  logger.trace("Skip event subscriber (#{event_subscriber.class}) because of its filter.")
@@ -217,7 +225,7 @@ module OpenHAB
217
225
  include Singleton
218
226
 
219
227
  def submit(runnable)
220
- runnable.run
228
+ runnable.respond_to?(:run) ? runnable.run : runnable.call
221
229
 
222
230
  java.util.concurrent.CompletableFuture.completed_future(nil)
223
231
  end
@@ -233,6 +241,40 @@ module OpenHAB
233
241
  end
234
242
  end
235
243
 
244
+ class SafeCaller
245
+ include org.openhab.core.common.SafeCaller
246
+ include org.openhab.core.common.SafeCallerBuilder
247
+
248
+ def create(target, _interface_type)
249
+ @target = target
250
+ self
251
+ end
252
+
253
+ def build
254
+ @target
255
+ end
256
+
257
+ def with_timeout(_timeout)
258
+ self
259
+ end
260
+
261
+ def with_identifier(_identifier)
262
+ self
263
+ end
264
+
265
+ def on_exception(_handler)
266
+ self
267
+ end
268
+
269
+ def on_timeout(_handler)
270
+ self
271
+ end
272
+
273
+ def with_async
274
+ self
275
+ end
276
+ end
277
+
236
278
  class CallbacksMap < java.util.HashMap
237
279
  def put(_rule_uid, trigger_handler)
238
280
  trigger_handler.executor.shutdown_now
@@ -275,7 +317,7 @@ module OpenHAB
275
317
  # the registries!
276
318
  ss = VolatileStorageService.new
277
319
  mr = org.openhab.core.internal.items.MetadataRegistryImpl.new
278
- OpenHAB::Core::OSGI.register_service("org.openhab.core.items.MetadataRegistry", mr)
320
+ OpenHAB::Core::OSGI.register_service(mr)
279
321
  mr.managed_provider = mmp = org.openhab.core.internal.items.ManagedMetadataProviderImpl.new(ss)
280
322
  mr.add_provider(mmp)
281
323
  gmp = org.openhab.core.model.item.internal.GenericMetadataProvider.new
@@ -286,16 +328,24 @@ module OpenHAB
286
328
  ir.event_publisher = ep
287
329
  up = org.openhab.core.internal.i18n.I18nProviderImpl.new(cc)
288
330
  ir.unit_provider = up
289
- ir.item_state_converter = org.openhab.core.internal.items.ItemStateConverterImpl.new(up)
331
+ ir.item_state_converter = isc = org.openhab.core.internal.items.ItemStateConverterImpl.new(up)
290
332
  tr = org.openhab.core.thing.internal.ThingRegistryImpl.new
333
+ tr.managed_provider = mtp = org.openhab.core.thing.ManagedThingProvider.new(ss)
334
+ tr.add_provider(mtp)
291
335
  mtr = org.openhab.core.automation.internal.type.ModuleTypeRegistryImpl.new
292
336
  rr = org.openhab.core.automation.internal.RuleRegistryImpl.new
293
337
  rr.module_type_registry = mtr
294
338
  rr.managed_provider = mrp = org.openhab.core.automation.ManagedRuleProvider.new(ss)
295
339
  rr.add_provider(mrp)
296
340
  iclr = org.openhab.core.thing.link.ItemChannelLinkRegistry.new(tr, ir)
341
+ iclr.add_provider(RSpec::OpenHAB::Core::Mocks::ItemChannelLinkProvider.instance)
342
+ OpenHAB::Core::OSGI.register_service(iclr)
297
343
  ctr = org.openhab.core.thing.type.ChannelTypeRegistry.new
344
+ OpenHAB::Core::OSGI.register_service(ctr)
345
+ ctr.add_channel_type_provider(RSpec::OpenHAB::Core::Mocks::ChannelTypeProvider.instance)
298
346
  ttr = org.openhab.core.thing.type.ThingTypeRegistry.new(ctr)
347
+ OpenHAB::Core::OSGI.register_service(ttr)
348
+ ttr.add_thing_type_provider(RSpec::OpenHAB::Core::Mocks::ThingTypeProvider.instance)
299
349
 
300
350
  safe_emf = org.openhab.core.model.core.internal.SafeEMFImpl.new
301
351
  model_repository = org.openhab.core.model.core.internal.ModelRepositoryImpl.new(safe_emf)
@@ -362,9 +412,12 @@ module OpenHAB
362
412
  iu = org.openhab.core.internal.items.ItemUpdater.new(ir)
363
413
  ief = org.openhab.core.items.events.ItemEventFactory.new
364
414
 
365
- sc = org.openhab.core.internal.common.SafeCallerImpl.new({})
366
- aum = org.openhab.core.thing.internal.AutoUpdateManager.new({ "enabled" => "true" }, nil, ep, iclr, mr, tr)
367
- cm = org.openhab.core.thing.internal.CommunicationManager.new(aum, nil, nil, iclr, ir, nil, ep, sc, tr)
415
+ sc = SafeCaller.new
416
+ aum = org.openhab.core.thing.internal.AutoUpdateManager.new(
417
+ { "enabled" => true, "sendOptimisticUpdates" => true }, ctr, ep, iclr, mr, tr
418
+ )
419
+ spf = org.openhab.core.thing.internal.profiles.SystemProfileFactory.new(ctr, nil, BundleResolver.new)
420
+ cm = org.openhab.core.thing.internal.CommunicationManager.new(aum, ctr, spf, iclr, ir, isc, ep, sc, tr)
368
421
 
369
422
  em.add_event_subscriber(iu)
370
423
  em.add_event_subscriber(cm)
@@ -3,6 +3,18 @@
3
3
  module RSpec
4
4
  module OpenHAB
5
5
  module Items
6
+ class ThingHandler
7
+ include org.openhab.core.thing.binding.ThingHandler
8
+
9
+ attr_reader :thing
10
+
11
+ def initialize(thing)
12
+ @thing = thing
13
+ end
14
+
15
+ def handle_command(channel, command); end
16
+ end
17
+
6
18
  class << self
7
19
  def populate_items_from_api(api)
8
20
  all_items = api.items
@@ -39,6 +51,15 @@ module RSpec
39
51
  item.category = item_json["category"] if item_json["category"]
40
52
 
41
53
  $ir.add(item)
54
+
55
+ next unless item.meta["channel"]&.value
56
+
57
+ channel_uid = org.openhab.core.thing.ChannelUID.new(item.meta["channel"].value)
58
+ channel = $things.get_channel(channel_uid)
59
+ next unless channel
60
+
61
+ link = org.openhab.core.thing.link.ItemChannelLink.new(item.name, channel_uid)
62
+ Core::Mocks::ItemChannelLinkProvider.instance.add(link)
42
63
  end
43
64
  all_items.each do |item_json| # rubocop:disable Style/CombinableLoops
44
65
  item_json["groupNames"].each do |group_name|
@@ -48,6 +69,170 @@ module RSpec
48
69
  end
49
70
  end
50
71
  end
72
+
73
+ def populate_things_from_api(api)
74
+ populate_channel_types_from_api(api)
75
+ populate_thing_types_from_api(api)
76
+
77
+ thing_type_registry = ::OpenHAB::Core::OSGI.service("org.openhab.core.thing.type.ThingTypeRegistry")
78
+
79
+ api.things.each do |thing_json|
80
+ uid = org.openhab.core.thing.ThingUID.new(thing_json["UID"])
81
+ type_uid = org.openhab.core.thing.ThingTypeUID.new(thing_json["thingTypeUID"])
82
+ bridge_uid = org.openhab.core.thing.ThingUID.new(thing_json["bridgeUID"]) if thing_json["bridgeUID"]
83
+
84
+ type = thing_type_registry.get_thing_type(type_uid)
85
+ klass = if type.is_a?(org.openhab.core.thing.type.BridgeType)
86
+ org.openhab.core.thing.binding.builder.BridgeBuilder
87
+ else
88
+ org.openhab.core.thing.binding.builder.ThingBuilder
89
+ end
90
+ builder = klass.create(type_uid, uid)
91
+ builder.with_bridge(bridge_uid) if bridge_uid
92
+
93
+ thing_json.each do |(k, v)|
94
+ case k
95
+ when "UID", "thingTypeUID", "bridgeUID", "statusInfo", "editable"
96
+ nil
97
+ when "channels"
98
+ builder.with_channels(v.map { |c| build_channel(c) })
99
+ when "configuration"
100
+ builder.with_configuration(org.openhab.core.config.core.Configuration.new(v))
101
+ else
102
+ builder.send(:"with_#{k}", v)
103
+ end
104
+ end
105
+
106
+ thing = builder.build
107
+ # pretend everything is online so that AutoUpdateManager won't reject updates
108
+ # to items linked to offline channels
109
+ thing.status_info = org.openhab.core.thing.binding.builder.ThingStatusInfoBuilder
110
+ .create(org.openhab.core.thing.ThingStatus::ONLINE).build
111
+ handler = ThingHandler.new(thing)
112
+ thing.handler = handler
113
+ $things.add(thing)
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def populate_channel_types_from_api(api)
120
+ api.channel_types.each do |ct_json|
121
+ uid = org.openhab.core.thing.type.ChannelTypeUID.new(ct_json["UID"])
122
+ builder = case ct_json["kind"]
123
+ when "STATE"
124
+ org.openhab.core.thing.type.ChannelTypeBuilder.state(uid, ct_json["label"], ct_json["itemType"])
125
+ when "TRIGGER"
126
+ org.openhab.core.thing.type.ChannelTypeBuilder.trigger(uid, ct_json["label"])
127
+ else
128
+ raise ArgumentError, "Unrecognized channel type kind #{ct_json["kind"]} for #{uid}"
129
+ end
130
+
131
+ ct_json.each do |(k, v)|
132
+ case k
133
+ when "parameters", "parameterGroups", "label", "kind", "UID", "itemType"
134
+ nil
135
+ when "commandDescription"
136
+ builder.with_command_description(build_command_description(v))
137
+ when "stateDescription"
138
+ builder.with_state_description_fragment(build_state_description_fragment(v))
139
+ when "advanced"
140
+ builder.is_advanced(v)
141
+ else
142
+ builder.send(:"with_#{k}", v)
143
+ end
144
+ end
145
+
146
+ ct = builder.build
147
+ Core::Mocks::ChannelTypeProvider.instance.add(ct)
148
+ end
149
+ end
150
+
151
+ def build_command_description(json)
152
+ org.openhab.core.types.CommandDescriptionBuilder.create
153
+ .with_command_options(json["commandOptions"].map do |o|
154
+ org.openhab.core.types.CommandOption.new(o["command"], o["label"])
155
+ end)
156
+ .build
157
+ end
158
+
159
+ def build_state_description_fragment(json)
160
+ org.openhab.core.types.StateDescriptionFragmentBuilder.create
161
+ .with_minimum(json["minimum"]&.to_d)
162
+ .with_maximum(json["maximum"]&.to_d)
163
+ .with_step(json["step"&.to_d])
164
+ .with_pattern(json["pattern"])
165
+ .with_read_only(json["readOnly"])
166
+ .with_options(json["options"].map { |o| org.openhab.core.types.StateOption.new(o["value"], o["label"]) })
167
+ .build
168
+ end
169
+
170
+ def populate_thing_types_from_api(api)
171
+ api.thing_types.each do |tt_json|
172
+ uid = org.openhab.core.thing.ThingTypeUID.new(tt_json["UID"])
173
+ builder = org.openhab.core.thing.type.ThingTypeBuilder.instance(uid, tt_json["label"])
174
+ tt_json.each do |(k, v)|
175
+ case k
176
+ when "UID", "label", "bridge"
177
+ nil
178
+ when "listed"
179
+ builder.is_listed(v)
180
+ when "channels"
181
+ builder.with_channels(v.map { |c| build_channel_definition(c) })
182
+ when "channelGroups"
183
+ builder.with_channel_groups(v.map { |cg| build_channel_group_definition(cg) })
184
+ else
185
+ builder.send(:"with#{k[0].upcase}#{k[1..]}", v)
186
+ end
187
+ end
188
+
189
+ tt = tt_json["bridge"] ? builder.build_bridge : builder.build
190
+ Core::Mocks::ThingTypeProvider.instance.add(tt)
191
+ end
192
+ end
193
+
194
+ def build_channel_definition(json)
195
+ org.openhab.core.thing.type.ChannelDefinition.new(
196
+ json["uid"],
197
+ org.openhab.core.thing.type.ChannelTypeUID.new(json["typeUID"]),
198
+ json["description"],
199
+ json["properties"],
200
+ nil
201
+ )
202
+ end
203
+
204
+ def build_channel_group_definition(json)
205
+ org.openhab.core.thing.type.ChannelGroupDefinition.new(
206
+ json["uid"],
207
+ org.openhab.core.thing.type.ChannelGroupTypeUID.new(json["typeUID"]),
208
+ json["label"],
209
+ json["description"]
210
+ )
211
+ end
212
+
213
+ def build_channel(json)
214
+ uid = org.openhab.core.thing.ChannelUID.new(json["uid"])
215
+ builder = org.openhab.core.thing.binding.builder.ChannelBuilder.create(uid)
216
+
217
+ json.each do |(k, v)|
218
+ case k
219
+ when "uid", "id", "linkedItems", "itemType"
220
+ nil
221
+ when "channelTypeUID"
222
+ builder.with_type(org.openhab.core.thing.type.ChannelTypeUID.new((v)))
223
+ when "configuration"
224
+ builder.with_configuration(org.openhab.core.config.core.Configuration.new(v))
225
+ when "kind"
226
+ builder.with_kind(org.openhab.core.thing.type.ChannelKind.const_get(v, false))
227
+ when "defaultTags"
228
+ builder.with_default_tags(v.to_set)
229
+ else
230
+ builder.send("with_#{k}", v)
231
+ end
232
+ end
233
+
234
+ builder.build
235
+ end
51
236
  end
52
237
  end
53
238
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module OpenHAB
5
- VERSION = "0.0.16"
5
+ VERSION = "0.0.17"
6
6
  end
7
7
  end
@@ -5,7 +5,8 @@
5
5
  $LOAD_PATH.unshift(File.expand_path("../vendor/gems/jar-dependencies-1.0.0/lib", __dir__))
6
6
 
7
7
  require "rspec/openhab/api"
8
- api = OpenHAB::API.new("http://#{ENV.fetch("OPENHAB_HOST", "localhost")}:#{ENV.fetch("OPENHAB_HTTP_PORT", "8080")}/")
8
+ api = OpenHAB::API.new("http://#{ENV.fetch("OPENHAB_HOST", "localhost")}:#{ENV.fetch("OPENHAB_HTTP_PORT", "8080")}/",
9
+ ENV.fetch("OPENHAB_TOKEN", nil))
9
10
 
10
11
  module OpenHAB
11
12
  module Core
@@ -66,7 +67,10 @@ require "rspec/openhab/core/logger"
66
67
  # during testing, we don't want "regular" output from rules
67
68
  OpenHAB::Log.logger("org.openhab.automation.jruby.runtime").level = :warn
68
69
  OpenHAB::Log.logger("org.openhab.automation.jruby.logger").level = :warn
70
+ require "rspec/openhab/core/mocks/channel_type_provider"
71
+ require "rspec/openhab/core/mocks/item_channel_link_provider"
69
72
  require "rspec/openhab/core/mocks/persistence_service"
73
+ require "rspec/openhab/core/mocks/thing_type_provider"
70
74
  require "openhab/dsl/imports"
71
75
  OpenHAB::DSL::Imports.api = api
72
76
  OpenHAB::DSL::Imports.import_presets
@@ -93,6 +97,7 @@ RSpec.configure do |config|
93
97
  end
94
98
 
95
99
  RSpec::OpenHAB::SuspendRules.suspend_rules do
100
+ RSpec::OpenHAB::Items.populate_things_from_api(api) if api.authenticated?
96
101
  RSpec::OpenHAB::Items.populate_items_from_api(api)
97
102
  end
98
103
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.17
5
5
  platform: java
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-18 00:00:00.000000000 Z
11
+ date: 2022-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -192,7 +192,10 @@ files:
192
192
  - lib/rspec/openhab/core/item_proxy.rb
193
193
  - lib/rspec/openhab/core/load_path.rb
194
194
  - lib/rspec/openhab/core/logger.rb
195
+ - lib/rspec/openhab/core/mocks/channel_type_provider.rb
196
+ - lib/rspec/openhab/core/mocks/item_channel_link_provider.rb
195
197
  - lib/rspec/openhab/core/mocks/persistence_service.rb
198
+ - lib/rspec/openhab/core/mocks/thing_type_provider.rb
196
199
  - lib/rspec/openhab/core/openhab_setup.rb
197
200
  - lib/rspec/openhab/core/osgi.rb
198
201
  - lib/rspec/openhab/core/script_handling.rb
@@ -237,7 +240,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
237
240
  requirements:
238
241
  - - ">="
239
242
  - !ruby/object:Gem::Version
240
- version: '2.5'
243
+ version: '2.6'
241
244
  required_rubygems_version: !ruby/object:Gem::Requirement
242
245
  requirements:
243
246
  - - ">="