openhab-scripting 5.8.0 → 5.10.0
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/events/abstract_event.rb +3 -0
- data/lib/openhab/core/events/item_event.rb +19 -0
- data/lib/openhab/core/items/item.rb +75 -3
- data/lib/openhab/core/items/item_channel_links.rb +44 -0
- data/lib/openhab/core/items/semantics.rb +5 -2
- data/lib/openhab/core/things/channel.rb +34 -1
- data/lib/openhab/core/things/channel_uid.rb +1 -2
- data/lib/openhab/core/things/item_channel_link.rb +6 -0
- data/lib/openhab/core/things/profile_callback.rb +14 -21
- data/lib/openhab/core/things/proxy.rb +1 -1
- data/lib/openhab/core/things/thing.rb +12 -6
- data/lib/openhab/dsl/items/builder.rb +2 -9
- data/lib/openhab/dsl/rules/automation_rule.rb +2 -0
- data/lib/openhab/dsl/things/builder.rb +43 -4
- data/lib/openhab/dsl/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acf8ae7ed285c32bb11070e6ae64c54b9687dae7883c272be4a9ad30f399ed8c
|
4
|
+
data.tar.gz: 8820ac3849f07734843d2863ff483fbde70bfe56c41981f2d48ec2e8c7bd73a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab2e153c20c4d81b4b4b5b7d3025d1f49812099ea1040eba85b03f6fc8ce4217d84a3204e1c0917ed53c8386220b25da7d1da4bc367b51459ef74d67a52d7d44
|
7
|
+
data.tar.gz: 0bdc096799e02f344f7d24c218af6ed045840c9a87ab890e81a339896801c53c6e18a6dabafd060e2c18023b69da8fdb4df9d3d58fcab3917baba6274fe992eb
|
@@ -16,6 +16,25 @@ module OpenHAB
|
|
16
16
|
def item
|
17
17
|
EntityLookup.lookup_item(item_name)
|
18
18
|
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# @!attribute [r] group
|
22
|
+
#
|
23
|
+
# Returns the group item whose member had triggered this event.
|
24
|
+
#
|
25
|
+
# This is the equivalent of openHAB's `triggeringGroup`, and it is only available
|
26
|
+
# on a member-of-group trigger.
|
27
|
+
#
|
28
|
+
# @return [Item,nil] The group item whose member had triggered this event.
|
29
|
+
# `nil` when the event wasn't triggered by a member-of-group trigger.
|
30
|
+
#
|
31
|
+
# @since openHAB 4.0 for file-based rules
|
32
|
+
# @since openHAB 4.1 for UI rules
|
33
|
+
#
|
34
|
+
def group
|
35
|
+
triggering_group = inputs&.[]("triggeringGroup") || $ctx&.[]("triggeringGroup")
|
36
|
+
Items::Proxy.new(triggering_group) if triggering_group
|
37
|
+
end
|
19
38
|
end
|
20
39
|
end
|
21
40
|
end
|
@@ -251,6 +251,7 @@ module OpenHAB
|
|
251
251
|
!(self.tags.to_a & tags).empty?
|
252
252
|
end
|
253
253
|
|
254
|
+
# @!attribute thing [r]
|
254
255
|
# Return the item's thing if this item is linked with a thing. If an item is linked to more than one thing,
|
255
256
|
# this method only returns the first thing.
|
256
257
|
#
|
@@ -260,6 +261,7 @@ module OpenHAB
|
|
260
261
|
end
|
261
262
|
alias_method :linked_thing, :thing
|
262
263
|
|
264
|
+
# @!attribute things [r]
|
263
265
|
# Returns all of the item's linked things.
|
264
266
|
#
|
265
267
|
# @return [Array<Thing>] An array of things or an empty array
|
@@ -268,11 +270,80 @@ module OpenHAB
|
|
268
270
|
end
|
269
271
|
alias_method :all_linked_things, :things
|
270
272
|
|
273
|
+
#
|
274
|
+
# @!attribute links [r]
|
271
275
|
# Returns all of the item's links (channels and link configurations).
|
272
276
|
#
|
273
|
-
# @return [
|
277
|
+
# @return [ItemChannelLinks] An array of ItemChannelLink or an empty array
|
278
|
+
#
|
279
|
+
# @example Get the configuration of the first link
|
280
|
+
# LivingRoom_Light_Power.links.first.configuration
|
281
|
+
#
|
282
|
+
# @example Remove all managed links
|
283
|
+
# LivingRoom_Light_Power.links.clear
|
284
|
+
#
|
285
|
+
# @see link
|
286
|
+
# @see unlink
|
287
|
+
#
|
274
288
|
def links
|
275
|
-
Things::Links::Provider.registry.get_links(name)
|
289
|
+
ItemChannelLinks.new(self, Things::Links::Provider.registry.get_links(name))
|
290
|
+
end
|
291
|
+
|
292
|
+
#
|
293
|
+
# Links the item to a channel.
|
294
|
+
#
|
295
|
+
# @param [String, Things::Channel, Things::ChannelUID] channel The channel to link to.
|
296
|
+
# @param [Hash] config The configuration for the link.
|
297
|
+
#
|
298
|
+
# @return [Things::ItemChannelLink] The created link.
|
299
|
+
#
|
300
|
+
# @example Link an item to a channel
|
301
|
+
# LivingRoom_Light_Power.link("mqtt:topic:livingroom-light:power")
|
302
|
+
#
|
303
|
+
# @example Link to a Thing's channel
|
304
|
+
# LivingRoom_Light_Power.link(things["mqtt:topic:livingroom-light"].channels["power"])
|
305
|
+
#
|
306
|
+
# @example Specify a link configuration
|
307
|
+
# High_Temperature_Alert.link(
|
308
|
+
# "mqtt:topic:outdoor-thermometer:temperature",
|
309
|
+
# profile: "system:hysteresis",
|
310
|
+
# lower: "29 °C",
|
311
|
+
# upper: "30 °C")
|
312
|
+
#
|
313
|
+
# @see links
|
314
|
+
# @see unlink
|
315
|
+
#
|
316
|
+
def link(channel, config = {})
|
317
|
+
Core::Things::Links::Provider.create_link(self, channel, config).tap do |new_link|
|
318
|
+
provider = Core::Things::Links::Provider.current
|
319
|
+
if !(current_link = provider.get(new_link.uid))
|
320
|
+
provider.add(new_link)
|
321
|
+
elsif current_link.configuration != config
|
322
|
+
provider.update(new_link)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
#
|
328
|
+
# Removes a link to a channel from managed link providers.
|
329
|
+
#
|
330
|
+
# @param [String, Things::Channel, Things::ChannelUID] channel The channel to remove the link to.
|
331
|
+
#
|
332
|
+
# @return [Things::ItemChannelLink, nil] The removed link, if found.
|
333
|
+
# @raise [FrozenError] if the link is not managed by a managed link provider.
|
334
|
+
#
|
335
|
+
# @see link
|
336
|
+
# @see links
|
337
|
+
#
|
338
|
+
def unlink(channel)
|
339
|
+
link_to_delete = Things::Links::Provider.create_link(self, channel, {})
|
340
|
+
provider = Things::Links::Provider.registry.provider_for(link_to_delete.uid)
|
341
|
+
unless provider.is_a?(ManagedProvider)
|
342
|
+
raise FrozenError,
|
343
|
+
"Cannot remove the link #{link_to_delete.uid} from non-managed provider #{provider.inspect}"
|
344
|
+
end
|
345
|
+
|
346
|
+
provider.remove(link_to_delete.uid)
|
276
347
|
end
|
277
348
|
|
278
349
|
# @return [String]
|
@@ -286,7 +357,8 @@ module OpenHAB
|
|
286
357
|
"#{s}>"
|
287
358
|
end
|
288
359
|
|
289
|
-
#
|
360
|
+
# @!attribute provider [r]
|
361
|
+
# @return [org.openhab.core.common.registry.Provider, nil] Returns the provider for this item.
|
290
362
|
def provider
|
291
363
|
Provider.registry.provider_for(self)
|
292
364
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "delegate"
|
4
|
+
|
5
|
+
module OpenHAB
|
6
|
+
module Core
|
7
|
+
module Items
|
8
|
+
#
|
9
|
+
# A wrapper for {Item#links} delegated to Set<{org.openhab.core.thing.link.ItemChannelLink}>.
|
10
|
+
#
|
11
|
+
# Adds methods for clearing item's links to channels.
|
12
|
+
#
|
13
|
+
class ItemChannelLinks < SimpleDelegator
|
14
|
+
#
|
15
|
+
# @param [Item] item The item that the links belong to
|
16
|
+
# @param [Set<ItemChannelLink>] links The set of links to delegate to
|
17
|
+
#
|
18
|
+
# @!visibility private
|
19
|
+
def initialize(item, links)
|
20
|
+
super(links)
|
21
|
+
@item = item
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Removes all links to channels from managed link providers.
|
26
|
+
# @return [self]
|
27
|
+
#
|
28
|
+
def clear
|
29
|
+
Things::Links::Provider.registry.all.each do |link|
|
30
|
+
next unless link.item_name == @item.name
|
31
|
+
|
32
|
+
provider = Things::Links::Provider.registry.provider_for(link.uid)
|
33
|
+
if provider.is_a?(ManagedProvider)
|
34
|
+
provider.remove(link.uid)
|
35
|
+
else
|
36
|
+
logger.warn("Cannot remove the link #{link.uid} from non-managed provider #{provider.inspect}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
self
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -311,6 +311,11 @@ module OpenHAB
|
|
311
311
|
synonyms = Array.wrap(synonyms).map { |s| s.to_s.strip }
|
312
312
|
|
313
313
|
tags.map do |name, parent|
|
314
|
+
if (existing_tag = lookup(name))
|
315
|
+
logger.warn("Tag already exists: #{existing_tag.inspect}")
|
316
|
+
next
|
317
|
+
end
|
318
|
+
|
314
319
|
unless parent.is_a?(SemanticTag)
|
315
320
|
parent_tag = lookup(parent)
|
316
321
|
raise ArgumentError, "Unknown parent: #{parent}" unless parent_tag
|
@@ -318,8 +323,6 @@ module OpenHAB
|
|
318
323
|
parent = parent_tag
|
319
324
|
end
|
320
325
|
|
321
|
-
next if lookup(name)
|
322
|
-
|
323
326
|
new_tag = org.openhab.core.semantics.SemanticTagImpl.new("#{parent.uid}_#{name}",
|
324
327
|
label,
|
325
328
|
description,
|
@@ -32,9 +32,14 @@ module OpenHAB
|
|
32
32
|
def inspect
|
33
33
|
r = "#<OpenHAB::Core::Things::Channel #{uid}"
|
34
34
|
r += " #{label.inspect}" if label
|
35
|
-
r += "
|
35
|
+
r += " description=#{description.inspect}" if description
|
36
|
+
r += " kind=#{kind.inspect}"
|
37
|
+
r += " channel_type_uid=#{channel_type_uid.inspect}" if channel_type_uid
|
36
38
|
r += " configuration=#{configuration.properties.to_h}" unless configuration.properties.empty?
|
37
39
|
r += " properties=#{properties.to_h}" unless properties.empty?
|
40
|
+
r += " default_tags=#{default_tags.to_a}" unless default_tags.empty?
|
41
|
+
r += " auto_update_policy=#{auto_update_policy}" if auto_update_policy
|
42
|
+
r += " accepted_item_type=#{accepted_item_type}" if accepted_item_type
|
38
43
|
"#{r}>"
|
39
44
|
end
|
40
45
|
|
@@ -42,6 +47,34 @@ module OpenHAB
|
|
42
47
|
def to_s
|
43
48
|
uid.to_s
|
44
49
|
end
|
50
|
+
|
51
|
+
# @deprecated OH3.4 this whole section is not needed in OH4+. Also see Thing#config_eql?
|
52
|
+
if Gem::Version.new(Core::VERSION) < Gem::Version.new("4.0.0")
|
53
|
+
# @!visibility private
|
54
|
+
module ChannelComparable
|
55
|
+
# @!visibility private
|
56
|
+
# This is only needed in OH3 because it is implemented in OH4 core
|
57
|
+
def ==(other)
|
58
|
+
return true if equal?(other)
|
59
|
+
return false unless other.is_a?(Channel)
|
60
|
+
|
61
|
+
%i[class
|
62
|
+
uid
|
63
|
+
label
|
64
|
+
description
|
65
|
+
kind
|
66
|
+
channel_type_uid
|
67
|
+
configuration
|
68
|
+
properties
|
69
|
+
default_tags
|
70
|
+
auto_update_policy
|
71
|
+
accepted_item_type].all? do |attr|
|
72
|
+
send(attr) == other.send(attr)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
org.openhab.core.thing.binding.builder.ChannelBuilder.const_get(:ChannelImpl).prepend(ChannelComparable)
|
77
|
+
end
|
45
78
|
end
|
46
79
|
end
|
47
80
|
end
|
@@ -42,8 +42,7 @@ module OpenHAB
|
|
42
42
|
# @return [Array<Item>] An array of things or an empty array
|
43
43
|
#
|
44
44
|
def items
|
45
|
-
registry
|
46
|
-
registry.get_linked_items(self).map { |i| Items::Proxy.new(i) }
|
45
|
+
Links::Provider.registry.get_linked_items(self).map { |i| Items::Proxy.new(i) }
|
47
46
|
end
|
48
47
|
end
|
49
48
|
end
|
@@ -8,44 +8,37 @@ module OpenHAB
|
|
8
8
|
# and channels.
|
9
9
|
#
|
10
10
|
module ProfileCallback
|
11
|
-
class << self
|
12
|
-
#
|
13
|
-
# Wraps the parent class's method to format non-Types.
|
14
|
-
#
|
15
|
-
# @!macro def_state_parsing_method
|
16
|
-
# @!method $1($2)
|
17
|
-
# @return [void]
|
18
|
-
# @!visibility private
|
19
|
-
def def_state_parsing_method(method, param_name)
|
20
|
-
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
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)
|
23
|
-
super(type) # super(type)
|
24
|
-
end # end
|
25
|
-
RUBY
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
11
|
#
|
30
12
|
# Forward the given command to the respective thing handler.
|
31
13
|
#
|
32
14
|
# @param [Command] command
|
33
15
|
#
|
34
|
-
|
16
|
+
def handle_command(command)
|
17
|
+
@dummy_channel_item ||= DSL::Items::ItemBuilder.item_factory.create_item(link.channel.accepted_item_type,
|
18
|
+
"")
|
19
|
+
command = @dummy_channel_item.format_command(command)
|
20
|
+
super(command)
|
21
|
+
end
|
35
22
|
|
36
23
|
#
|
37
24
|
# Send a command to the framework.
|
38
25
|
#
|
39
26
|
# @param [Command] command
|
40
27
|
#
|
41
|
-
|
28
|
+
def send_command(command)
|
29
|
+
command = link.item.format_command(command)
|
30
|
+
super(command)
|
31
|
+
end
|
42
32
|
|
43
33
|
#
|
44
34
|
# Send a state update to the framework.
|
45
35
|
#
|
46
36
|
# @param [State] state
|
47
37
|
#
|
48
|
-
|
38
|
+
def send_update(state)
|
39
|
+
state = link.item.format_update(state)
|
40
|
+
super(state)
|
41
|
+
end
|
49
42
|
end
|
50
43
|
end
|
51
44
|
end
|
@@ -64,13 +64,17 @@ module OpenHAB
|
|
64
64
|
# Array wrapper class to allow searching a list of channels
|
65
65
|
# by channel id
|
66
66
|
class ChannelsArray < Array
|
67
|
+
def initialize(thing, array)
|
68
|
+
super(array)
|
69
|
+
@thing = thing
|
70
|
+
end
|
71
|
+
|
67
72
|
# Allows indexing by both integer as an array or channel id acting like a hash.
|
68
|
-
# @param [Integer, String] index
|
73
|
+
# @param [Integer, String, ChannelUID] index
|
74
|
+
# Numeric index, string channel id, or a {ChannelUID} to search for.
|
69
75
|
def [](index)
|
70
|
-
if index.
|
71
|
-
|
72
|
-
return find { |channel| channel.uid.id == key }
|
73
|
-
end
|
76
|
+
return @thing.get_channel(index) if index.is_a?(ChannelUID)
|
77
|
+
return @thing.get_channel(index.to_str) if index.respond_to?(:to_str)
|
74
78
|
|
75
79
|
super
|
76
80
|
end
|
@@ -204,7 +208,9 @@ module OpenHAB
|
|
204
208
|
# @return [true,false] true if all attributes are equal, false otherwise
|
205
209
|
#
|
206
210
|
def config_eql?(other)
|
207
|
-
|
211
|
+
# @deprecated OH3.4 - in OH4, channels can be included in the array and do not need to be compared separately
|
212
|
+
channels.to_a == other.channels.to_a &&
|
213
|
+
%i[uid label bridge_uid location configuration].all? { |method| send(method) == other.send(method) }
|
208
214
|
end
|
209
215
|
|
210
216
|
#
|
@@ -156,7 +156,6 @@ module OpenHAB
|
|
156
156
|
item.update(builder.state) unless builder.state.nil?
|
157
157
|
|
158
158
|
# make sure to add the item to the registry before linking it
|
159
|
-
provider = Core::Things::Links::Provider.current
|
160
159
|
channel_uids = builder.channels.to_set do |(channel, config)|
|
161
160
|
# fill in partial channel names from group's thing id
|
162
161
|
if !channel.include?(":") &&
|
@@ -165,17 +164,11 @@ module OpenHAB
|
|
165
164
|
channel = "#{thing}:#{channel}"
|
166
165
|
end
|
167
166
|
|
168
|
-
|
169
|
-
if !(current_link = provider.get(new_link.uid))
|
170
|
-
provider.add(new_link)
|
171
|
-
elsif current_link.configuration != config
|
172
|
-
provider.update(new_link)
|
173
|
-
end
|
174
|
-
|
175
|
-
new_link.linked_uid
|
167
|
+
item.link(channel, config).linked_uid
|
176
168
|
end
|
177
169
|
|
178
170
|
# remove links not in the new item
|
171
|
+
provider = Core::Things::Links::Provider.current
|
179
172
|
provider.all.each do |link|
|
180
173
|
provider.remove(link.uid) if link.item_name == item.name && !channel_uids.include?(link.linked_uid)
|
181
174
|
end
|
@@ -257,7 +257,14 @@ module OpenHAB
|
|
257
257
|
# The ChannelBuilder DSL allows you to customize a channel
|
258
258
|
class ChannelBuilder
|
259
259
|
attr_accessor :label
|
260
|
-
attr_reader :uid,
|
260
|
+
attr_reader :uid,
|
261
|
+
:config,
|
262
|
+
:type,
|
263
|
+
:default_tags,
|
264
|
+
:properties,
|
265
|
+
:description,
|
266
|
+
:auto_update_policy,
|
267
|
+
:accepted_item_type
|
261
268
|
|
262
269
|
#
|
263
270
|
# Constructor for ChannelBuilder
|
@@ -269,10 +276,27 @@ module OpenHAB
|
|
269
276
|
# @param [String] label The channel label.
|
270
277
|
# @param [thing] thing The thing associated with this channel.
|
271
278
|
# This parameter is not needed for the {ThingBuilder#channel} method.
|
279
|
+
# @param [String] description The channel description.
|
272
280
|
# @param [String] group The group name.
|
273
281
|
# @param [Hash] config Channel configuration. The keys can be strings or symbols.
|
282
|
+
# @param [Hash] properties The channel properties.
|
283
|
+
# @param [String,Symbol,Semantics::Tag,Array<String,Symbol,Semantics::Tag>] default_tags
|
284
|
+
# The default tags for this channel.
|
285
|
+
# @param [:default, :recommend, :veto, org.openhab.core.thing.type.AutoUpdatePolicy] auto_update_policy
|
286
|
+
# The channel's auto update policy.
|
287
|
+
# @param [String] accepted_item_type The accepted item type.
|
274
288
|
#
|
275
|
-
def initialize(uid,
|
289
|
+
def initialize(uid,
|
290
|
+
type,
|
291
|
+
label = nil,
|
292
|
+
thing:,
|
293
|
+
description: nil,
|
294
|
+
group: nil,
|
295
|
+
config: nil,
|
296
|
+
properties: nil,
|
297
|
+
default_tags: nil,
|
298
|
+
auto_update_policy: nil,
|
299
|
+
accepted_item_type: nil)
|
276
300
|
@thing = thing
|
277
301
|
|
278
302
|
uid = uid.to_s
|
@@ -292,7 +316,14 @@ module OpenHAB
|
|
292
316
|
end
|
293
317
|
@type = type
|
294
318
|
@label = label
|
295
|
-
@config = config
|
319
|
+
@config = config&.transform_keys(&:to_s)
|
320
|
+
@default_tags = Items::ItemBuilder.normalize_tags(*Array.wrap(default_tags))
|
321
|
+
@properties = properties&.transform_keys(&:to_s)
|
322
|
+
@description = description
|
323
|
+
@accepted_item_type = accepted_item_type
|
324
|
+
return unless auto_update_policy
|
325
|
+
|
326
|
+
@auto_update_policy = org.openhab.core.thing.type.AutoUpdatePolicy.value_of(auto_update_policy.to_s.upcase)
|
296
327
|
end
|
297
328
|
|
298
329
|
# @!visibility private
|
@@ -300,7 +331,15 @@ module OpenHAB
|
|
300
331
|
org.openhab.core.thing.binding.builder.ChannelBuilder.create(uid)
|
301
332
|
.with_kind(kind)
|
302
333
|
.with_type(type)
|
303
|
-
.
|
334
|
+
.tap do |builder|
|
335
|
+
builder.with_label(label) if label
|
336
|
+
builder.with_configuration(Core::Configuration.new(config)) if config && !config.empty?
|
337
|
+
builder.with_default_tags(Set.new(default_tags).to_java) unless default_tags.empty?
|
338
|
+
builder.with_properties(properties) if properties
|
339
|
+
builder.with_description(description) if description
|
340
|
+
builder.with_auto_update_policy(auto_update_policy) if auto_update_policy
|
341
|
+
builder.with_accepted_item_type(accepted_item_type) if accepted_item_type
|
342
|
+
end
|
304
343
|
.build
|
305
344
|
end
|
306
345
|
|
data/lib/openhab/dsl/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openhab-scripting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian O'Connell
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-10-
|
13
|
+
date: 2023-10-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -409,6 +409,7 @@ files:
|
|
409
409
|
- lib/openhab/core/items/group_item.rb
|
410
410
|
- lib/openhab/core/items/image_item.rb
|
411
411
|
- lib/openhab/core/items/item.rb
|
412
|
+
- lib/openhab/core/items/item_channel_links.rb
|
412
413
|
- lib/openhab/core/items/location_item.rb
|
413
414
|
- lib/openhab/core/items/metadata.rb
|
414
415
|
- lib/openhab/core/items/metadata/hash.rb
|