ruby_home 0.1.17 → 0.1.18

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: 2f1ec9a0cf851dfdd6394018bf525c56543316231714b79003bbecf58b0996e1
4
- data.tar.gz: 935e5d614d0c4738511e83ba1dcead41a22ac49aed6da5e66bf2fbef96cb2f01
3
+ metadata.gz: ad5b7e8f3b0b442d25929da1a8af15bdf127cd722102f7ff9399ee1ed085872a
4
+ data.tar.gz: bb1a2e1b6cce59ec430f7a12125f61d5786eb80ffa816c6e92bd3082a9481fee
5
5
  SHA512:
6
- metadata.gz: d18cdd0a7a98ac1109257851c1fcc30e96574e532835bd76945a36905f460385cfbe1b566534d15a9d11a79cac3d4200fb2ff9b2c430eee5ecffebd0e2ca0a9a
7
- data.tar.gz: 99aae206a6330cb6cbdf04158c79219670454d88eaf65ff2cc9cb311d596c9f9004ff13ee2334f10a43d709a33e443d3a561bfa995941379b45c74c270b10636
6
+ metadata.gz: 7671cc93259b8934c88928dc8c956ed40062a668d5c593a6f69f69b6607d74796d9e8522a3b3f13373fc35b59d2e971656b6dce8396e9bcf3abc6ddc7d601a20
7
+ data.tar.gz: bfd2b41ede9bd1ac5f0af0048e39cd1ea98dc3cd302bd19b836a7ea78c92fda2bad7be16791e82bb88bfcad5e25fafbdf1d04a54ada620d92599712c9f1049fd
data/.travis.yml CHANGED
@@ -14,6 +14,7 @@ install:
14
14
  rvm:
15
15
  - 2.4
16
16
  - 2.5
17
+ - 2.6
17
18
  - ruby-head
18
19
  os:
19
20
  - linux
data/README.md CHANGED
@@ -47,8 +47,8 @@ require 'ruby_home'
47
47
  accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
48
48
  fan = RubyHome::ServiceFactory.create(:fan)
49
49
 
50
- fan.characteristic(:on).after_update do |characteristic|
51
- if characteristic.value == true
50
+ fan.on.after_update do |updated_value|
51
+ if updated_value
52
52
  puts "Fan switched on"
53
53
  else
54
54
  puts "Fan switched off"
@@ -58,27 +58,6 @@ end
58
58
  RubyHome.run
59
59
  ```
60
60
 
61
- Create a garage door opener.
62
-
63
- ```ruby
64
- require 'ruby_home'
65
-
66
- accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
67
- door = RubyHome::ServiceFactory.create(:garage_door_opener)
68
-
69
- door.characteristic(:target_door_state).after_update do |characteristic|
70
- if characteristic.value == 0 # open
71
- sleep 1
72
- door.characteristic(:current_door_state).value = 0
73
- elsif characteristic.value == 1 #closed
74
- sleep 1
75
- door.characteristic(:current_door_state).value = 1
76
- end
77
- end
78
-
79
- RubyHome.run
80
- ```
81
-
82
61
  ## Customization
83
62
 
84
63
  RubyHome tries to provide sane defaults for all services. Customization of any of the options is possible.
@@ -105,8 +84,8 @@ fan = RubyHome::ServiceFactory.create(:fan,
105
84
  serial_number: '123-UK-A12345'
106
85
  )
107
86
 
108
- fan.characteristic(:on).after_update do |characteristic|
109
- if characteristic.value == true
87
+ fan.on.after_update do |updated_value|
88
+ if updated_value
110
89
  puts "Fan switched on"
111
90
  else
112
91
  puts "Fan switched off"
@@ -128,7 +107,6 @@ require 'open-uri'
128
107
  require 'ruby_home'
129
108
 
130
109
  fan = RubyHome::ServiceFactory.create(:fan)
131
- on_characteristic = fan.characteristic(:on)
132
110
 
133
111
  Thread.new do
134
112
  def fetch_fan_status
@@ -141,8 +119,83 @@ Thread.new do
141
119
 
142
120
  current_fan_status = fetch_fan_status
143
121
 
144
- unless on_characteristic.value == current_fan_status
145
- on_characteristic.value = current_fan_status
122
+ unless fan.on == current_fan_status
123
+ fan.on = current_fan_status
124
+ end
125
+ end
126
+ end
127
+
128
+ RubyHome.run
129
+ ```
130
+
131
+ ## More examples
132
+
133
+ ### Create a garage door opener.
134
+
135
+ ```ruby
136
+ require 'ruby_home'
137
+
138
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
139
+ door = RubyHome::ServiceFactory.create(:garage_door_opener)
140
+
141
+ door.target_door_state.after_update do |updated_value|
142
+ if updated_value == 0 # open
143
+ sleep 1
144
+ door.current_door_state = 0
145
+ elsif updated_value == 1 #closed
146
+ sleep 1
147
+ door.current_door_state = 1
148
+ end
149
+ end
150
+
151
+ RubyHome.run
152
+ ```
153
+
154
+ ### Create a thermostat.
155
+
156
+ ```ruby
157
+ require 'ruby_home'
158
+
159
+ accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
160
+ thermostat = RubyHome::ServiceFactory.create(:thermostat,
161
+ current_heating_cooling_state: 0, # off
162
+ target_heating_cooling_state: 0, # off
163
+ current_temperature: 18,
164
+ target_temperature: 18,
165
+ temperature_display_units: 0
166
+ )
167
+
168
+ thermostat.target_temperature.after_update do |updated_value|
169
+ if thermostat.current_temperature < updated_value
170
+ thermostat.target_heating_cooling_state = 1 # heat
171
+ elsif thermostat.current_temperature > updated_value
172
+ thermostat.target_heating_cooling_state = 2 # cool
173
+ end
174
+ end
175
+
176
+ thermostat.target_heating_cooling_state.after_update do |updated_value|
177
+ if updated_value == 1
178
+ thermostat.current_heating_cooling_state = 1 # heat
179
+ elsif updated_value == 2
180
+ thermostat.current_heating_cooling_state = 2 # cool
181
+ else
182
+ thermostat.current_heating_cooling_state = 0 # off
183
+ end
184
+ end
185
+
186
+ Thread.new do
187
+ loop do
188
+ sleep 5 # seconds
189
+
190
+ puts "current_temperature: #{thermostat.current_temperature.value.to_i}"
191
+ puts "target_temperature: #{thermostat.target_temperature.value.to_i}"
192
+
193
+ if thermostat.target_temperature.to_i > thermostat.current_temperature.to_i
194
+ thermostat.current_temperature += 1
195
+ elsif thermostat.target_temperature.to_i < thermostat.current_temperature.to_i
196
+ thermostat.current_temperature -= 1
197
+ else
198
+ thermostat.target_heating_cooling_state = 3 # auto
146
199
  end
147
200
  end
148
201
  end
data/bin/ruby_home CHANGED
@@ -5,8 +5,8 @@ require_relative '../lib/ruby_home'
5
5
  accessory_information = RubyHome::ServiceFactory.create(:accessory_information)
6
6
  fan = RubyHome::ServiceFactory.create(:fan)
7
7
 
8
- fan.characteristic(:on).after_update do |characteristic|
9
- if characteristic.value == true
8
+ fan.on.after_update do |updated_value|
9
+ if updated_value
10
10
  puts "Fan switched on"
11
11
  else
12
12
  puts "Fan switched off"
@@ -13,7 +13,7 @@ module RubyHome
13
13
  end
14
14
 
15
15
  def initialize
16
- @services = []
16
+ @services = ServiceCollection.new
17
17
  @id = next_available_accessory_id
18
18
  @@all << self
19
19
  end
@@ -21,7 +21,7 @@ module RubyHome
21
21
  attr_reader :services, :id
22
22
 
23
23
  def characteristics
24
- services.flat_map(&:characteristics)
24
+ services.characteristics
25
25
  end
26
26
 
27
27
  def next_available_instance_id
@@ -35,19 +35,13 @@ module RubyHome
35
35
  end
36
36
 
37
37
  def contains_instance_id?(instance_id)
38
- instance_ids.include?(instance_id)
38
+ services.any? do |service|
39
+ service.contains_instance_id?(instance_id)
40
+ end
39
41
  end
40
42
 
41
43
  private
42
44
 
43
- def instance_ids
44
- instances.map(&:instance_id)
45
- end
46
-
47
- def instances
48
- services + characteristics
49
- end
50
-
51
45
  def largest_instance_id
52
46
  IdentifierCache.where(accessory_id: id).map(&:instance_id).max
53
47
  end
@@ -7,10 +7,8 @@ module RubyHome
7
7
  @accessories = accessories
8
8
  end
9
9
 
10
- def each
11
- @accessories.map do |accessory|
12
- yield accessory
13
- end
10
+ def each(&block)
11
+ accessories.each(&block)
14
12
  end
15
13
 
16
14
  def <<(accessory)
@@ -27,12 +25,12 @@ module RubyHome
27
25
 
28
26
  private
29
27
 
30
- def services
31
- accessories.flat_map(&:services)
32
- end
28
+ def services
29
+ accessories.flat_map(&:services)
30
+ end
33
31
 
34
- def characteristics
35
- services.flat_map(&:characteristics)
36
- end
32
+ def characteristics
33
+ services.flat_map(&:characteristics)
34
+ end
37
35
  end
38
36
  end
@@ -1,3 +1,5 @@
1
+ require_relative 'characteristic_collection'
2
+
1
3
  module RubyHome
2
4
  class DuplicateCharacteristicError < StandardError; end
3
5
 
@@ -52,20 +54,33 @@ module RubyHome
52
54
  @instance_id = new_id
53
55
  end
54
56
 
55
- delegate :accessory, to: :service
56
- delegate :id, to: :accessory, prefix: true
57
+ def accessory
58
+ service.accessory
59
+ end
60
+
61
+ def accessory_id
62
+ accessory.id
63
+ end
57
64
 
58
65
  def service_iid
59
66
  service.instance_id
60
67
  end
61
68
 
69
+ def method_missing(method_name, *args, &block)
70
+ value.send(method_name, *args, &block)
71
+ end
72
+
73
+ def respond_to_missing?(method_name, *args)
74
+ value.respond_to?(method_name, *args) || super
75
+ end
76
+
62
77
  def value
63
78
  value_object.value
64
79
  end
65
80
 
66
81
  def value=(new_value)
67
82
  value_object.value = new_value
68
- broadcast(:after_update, self)
83
+ broadcast(:after_update, new_value)
69
84
  end
70
85
  end
71
86
  end
@@ -0,0 +1,48 @@
1
+ module RubyHome
2
+ class CharacteristicCollection
3
+ include Enumerable
4
+
5
+ def initialize(*characteristics)
6
+ @characteristics = characteristics
7
+ end
8
+
9
+ def each(&block)
10
+ characteristics.each(&block)
11
+ end
12
+
13
+ def <<(characteristic)
14
+ define_service_getter(characteristic)
15
+ define_service_setter(characteristic)
16
+
17
+ @characteristics << characteristic
18
+ end
19
+
20
+ alias all to_a
21
+
22
+ def contains_instance_id?(instance_id)
23
+ map(&:instance_id).include?(instance_id)
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :characteristics
29
+
30
+ def define_service_getter(characteristic)
31
+ service = characteristic.service
32
+
33
+ unless service.respond_to?(characteristic.name)
34
+ service.define_singleton_method(characteristic.name) { characteristic }
35
+ end
36
+ end
37
+
38
+ def define_service_setter(characteristic)
39
+ service = characteristic.service
40
+
41
+ unless service.respond_to?("#{characteristic.name}=")
42
+ service.define_singleton_method("#{characteristic.name}=") do |args|
43
+ characteristic.value = args
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -44,7 +44,9 @@ module RubyHome
44
44
 
45
45
  attr_reader :service, :characteristic_name, :subtype
46
46
 
47
- delegate :accessory, to: :service
47
+ def accessory
48
+ service.accessory
49
+ end
48
50
 
49
51
  def template
50
52
  @template ||= CharacteristicTemplate.find_by(name: characteristic_name)
@@ -5,6 +5,7 @@ module RubyHome
5
5
  @port = port
6
6
  @host = host
7
7
  @selector = NIO::Selector.new
8
+ @status = :running
8
9
  end
9
10
 
10
11
  attr_reader :port, :host
@@ -17,10 +18,18 @@ module RubyHome
17
18
  monitor.value = proc { accept }
18
19
 
19
20
  loop do
20
- @selector.select { |monitor| monitor.value.call(monitor) }
21
+ if @status == :running
22
+ @selector.select { |monitor| monitor.value.call(monitor) }
23
+ else
24
+ @selector.close
25
+ end
21
26
  end
22
27
  end
23
28
 
29
+ def shutdown
30
+ @status = :shutdown
31
+ end
32
+
24
33
  private
25
34
 
26
35
  SESSIONS = {}
@@ -73,15 +73,15 @@ module RubyHome
73
73
  end
74
74
 
75
75
  def decryption_time?
76
- controller_to_accessory_key.present?
76
+ !!controller_to_accessory_key
77
77
  end
78
78
 
79
79
  def accessory_to_controller_key?
80
- accessory_to_controller_key.present?
80
+ !!accessory_to_controller_key
81
81
  end
82
82
 
83
83
  def controller_to_accessory_key?
84
- controller_to_accessory_key.present?
84
+ !!controller_to_accessory_key
85
85
  end
86
86
  end
87
87
  end
@@ -1,9 +1,11 @@
1
+ require 'facets/string/modulize'
2
+
1
3
  module RubyHome
2
4
  class BaseValue
3
5
  def self.value_for_template(template)
4
6
  return IdentifyValue if template.name == :identify
5
7
 
6
- "::RubyHome::#{template.format.classify}Value".safe_constantize || NullValue
8
+ Object.const_get("::RubyHome::#{template.format.modulize}Value") || NullValue
7
9
  end
8
10
 
9
11
  def initialize(characteristic_template=nil, initial_value=nil)
@@ -13,8 +13,6 @@ module RubyHome
13
13
 
14
14
  def rack_builder
15
15
  ::Rack::Builder.new do
16
- use ::Rack::CommonLogger
17
-
18
16
  map('/accessories') { run AccessoriesController }
19
17
  map('/characteristics') { run CharacteristicsController }
20
18
  map('/identify') { run IdentifyController }
@@ -1,3 +1,5 @@
1
+ require 'logger'
2
+
1
3
  module RubyHome
2
4
  module HTTP
3
5
  class ApplicationController < Sinatra::Base
@@ -1,3 +1,5 @@
1
+ require 'facets/hash/symbolize_keys'
2
+
1
3
  module RubyHome
2
4
  module HTTP
3
5
  module ObjectSerializer
@@ -14,7 +14,7 @@ module RubyHome
14
14
  end
15
15
 
16
16
  def trim_leading_zeros(input)
17
- input.remove(/^0*/)
17
+ input.gsub(/^0*/, '')
18
18
  end
19
19
  end
20
20
  end
@@ -1,3 +1,5 @@
1
+ require 'facets/cattr'
2
+
1
3
  module RubyHome
2
4
  module Persistable
3
5
  def self.included(base)
@@ -1,3 +1,5 @@
1
+ require_relative 'service_collection'
2
+
1
3
  module RubyHome
2
4
  class DuplicateServiceError < StandardError; end
3
5
 
@@ -9,7 +11,7 @@ module RubyHome
9
11
  @name = name
10
12
  @description = description
11
13
  @uuid = uuid
12
- @characteristics = []
14
+ @characteristics = CharacteristicCollection.new
13
15
  end
14
16
 
15
17
  attr_reader(
@@ -29,7 +31,13 @@ module RubyHome
29
31
  @instance_id = new_id
30
32
  end
31
33
 
32
- delegate :id, to: :accessory, prefix: true
34
+ def contains_instance_id?(instance_id)
35
+ self.instance_id == instance_id || characteristics.contains_instance_id?(instance_id)
36
+ end
37
+
38
+ def accessory_id
39
+ accessory.id
40
+ end
33
41
 
34
42
  def characteristic(characteristic_name)
35
43
  characteristics.find do |characteristic|
@@ -0,0 +1,25 @@
1
+ module RubyHome
2
+ class ServiceCollection
3
+ include Enumerable
4
+
5
+ def initialize(*services)
6
+ @services = services
7
+ end
8
+
9
+ def each(&block)
10
+ services.each(&block)
11
+ end
12
+
13
+ def <<(service)
14
+ @services << service
15
+ end
16
+
17
+ def characteristics
18
+ flat_map(&:characteristics).flat_map(&:all)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :services
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module RubyHome
2
- VERSION = '0.1.17'
2
+ VERSION = '0.1.18'
3
3
  end
data/lib/ruby_home.rb CHANGED
@@ -1,7 +1,6 @@
1
- require 'active_support'
2
- require 'active_support/core_ext/hash'
3
1
  require 'bindata'
4
2
  require 'dnssd'
3
+ require 'facets/hash/slice'
5
4
  require 'hkdf'
6
5
  require 'nio'
7
6
  require 'oj'
@@ -38,6 +37,8 @@ module RubyHome
38
37
  end
39
38
 
40
39
  def shutdown
40
+ hap_server.shutdown
41
+
41
42
  threads.each(&:exit)
42
43
  end
43
44
 
data/rubyhome.gemspec CHANGED
@@ -25,16 +25,17 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = ['ruby_home']
26
26
  spec.require_paths = ['lib']
27
27
 
28
- spec.add_dependency 'activesupport', '~> 5.0'
29
28
  spec.add_dependency 'bindata', '~> 2.4', '>= 2.4.3'
30
29
  spec.add_dependency 'dnssd', '~> 3.0'
30
+ spec.add_dependency 'facets', '~> 3.1'
31
31
  spec.add_dependency 'hkdf', '~> 0.3.0'
32
32
  spec.add_dependency 'nio4r', '~> 2.3', '>= 2.3.1'
33
- spec.add_dependency 'oj', '3.7.4'
33
+ spec.add_dependency 'oj', '3.7.6'
34
34
  spec.add_dependency 'rbnacl', '~> 6.0'
35
35
  spec.add_dependency 'ruby_home-srp', '~> 1.2'
36
- spec.add_dependency 'sinatra', '2.0.4'
36
+ spec.add_dependency 'sinatra', '2.0.5'
37
37
  spec.add_dependency 'wisper', '~> 2.0'
38
+
38
39
  spec.add_development_dependency 'bundler', '~> 1.16'
39
40
  spec.add_development_dependency 'byebug', '~> 10.0'
40
41
  spec.add_development_dependency 'plist', '~> 3.4'
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_home
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.17
4
+ version: 0.1.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Entwistle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-17 00:00:00.000000000 Z
11
+ date: 2019-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '5.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '5.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bindata
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -58,6 +44,20 @@ dependencies:
58
44
  - - "~>"
59
45
  - !ruby/object:Gem::Version
60
46
  version: '3.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: facets
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.1'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: hkdf
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -98,14 +98,14 @@ dependencies:
98
98
  requirements:
99
99
  - - '='
100
100
  - !ruby/object:Gem::Version
101
- version: 3.7.4
101
+ version: 3.7.6
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - '='
107
107
  - !ruby/object:Gem::Version
108
- version: 3.7.4
108
+ version: 3.7.6
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: rbnacl
111
111
  requirement: !ruby/object:Gem::Requirement
@@ -140,14 +140,14 @@ dependencies:
140
140
  requirements:
141
141
  - - '='
142
142
  - !ruby/object:Gem::Version
143
- version: 2.0.4
143
+ version: 2.0.5
144
144
  type: :runtime
145
145
  prerelease: false
146
146
  version_requirements: !ruby/object:Gem::Requirement
147
147
  requirements:
148
148
  - - '='
149
149
  - !ruby/object:Gem::Version
150
- version: 2.0.4
150
+ version: 2.0.5
151
151
  - !ruby/object:Gem::Dependency
152
152
  name: wisper
153
153
  requirement: !ruby/object:Gem::Requirement
@@ -271,7 +271,11 @@ files:
271
271
  - bin/ruby_home
272
272
  - bin/setup
273
273
  - lib/ruby_home.rb
274
+ - lib/ruby_home/accessory.rb
275
+ - lib/ruby_home/accessory_collection.rb
274
276
  - lib/ruby_home/accessory_info.rb
277
+ - lib/ruby_home/characteristic.rb
278
+ - lib/ruby_home/characteristic_collection.rb
275
279
  - lib/ruby_home/config/characteristics.yml
276
280
  - lib/ruby_home/config/services.yml
277
281
  - lib/ruby_home/device_id.rb
@@ -282,20 +286,16 @@ files:
282
286
  - lib/ruby_home/factories/templates/characteristic_template.rb
283
287
  - lib/ruby_home/factories/templates/service_template.rb
284
288
  - lib/ruby_home/greeter.rb
285
- - lib/ruby_home/hap/accessory.rb
286
- - lib/ruby_home/hap/accessory_collection.rb
287
- - lib/ruby_home/hap/characteristic.rb
288
289
  - lib/ruby_home/hap/crypto/chacha20poly1305.rb
289
290
  - lib/ruby_home/hap/crypto/hkdf.rb
290
291
  - lib/ruby_home/hap/crypto/session_key.rb
292
+ - lib/ruby_home/hap/decrypter.rb
293
+ - lib/ruby_home/hap/encrypter.rb
291
294
  - lib/ruby_home/hap/ev_response.rb
292
295
  - lib/ruby_home/hap/hap_request.rb
293
296
  - lib/ruby_home/hap/hap_response.rb
294
297
  - lib/ruby_home/hap/server.rb
295
- - lib/ruby_home/hap/service.rb
296
298
  - lib/ruby_home/hap/session.rb
297
- - lib/ruby_home/hap/session/decrypter.rb
298
- - lib/ruby_home/hap/session/encrypter.rb
299
299
  - lib/ruby_home/hap/tlv.rb
300
300
  - lib/ruby_home/hap/values/base_value.rb
301
301
  - lib/ruby_home/hap/values/bool_value.rb
@@ -327,6 +327,8 @@ files:
327
327
  - lib/ruby_home/identifier_cache.rb
328
328
  - lib/ruby_home/password.rb
329
329
  - lib/ruby_home/persistable.rb
330
+ - lib/ruby_home/service.rb
331
+ - lib/ruby_home/service_collection.rb
330
332
  - lib/ruby_home/version.rb
331
333
  - rubyhome.gemspec
332
334
  - sbin/characteristic_generator.rb
@@ -350,8 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
350
352
  - !ruby/object:Gem::Version
351
353
  version: '0'
352
354
  requirements: []
353
- rubyforge_project:
354
- rubygems_version: 2.7.6
355
+ rubygems_version: 3.0.1
355
356
  signing_key:
356
357
  specification_version: 4
357
358
  summary: Ruby HomeKit support