ruby_home 0.2.1 → 0.2.6

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.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +41 -0
  3. data/.gitignore +2 -2
  4. data/.rubocop.yml +2 -9
  5. data/.standard.yml +3 -0
  6. data/CHANGELOG.md +18 -0
  7. data/Gemfile +2 -2
  8. data/README.md +40 -77
  9. data/Rakefile +4 -4
  10. data/examples/air_purifier.rb +66 -0
  11. data/examples/air_quality_sensor.rb +119 -0
  12. data/examples/battery_service.rb +58 -0
  13. data/examples/carbon_dioxide_sensor.rb +78 -0
  14. data/examples/carbon_monoxide_sensor.rb +78 -0
  15. data/examples/contact_sensor.rb +66 -0
  16. data/examples/door.rb +48 -0
  17. data/examples/fan.rb +30 -0
  18. data/examples/fan_v2.rb +68 -0
  19. data/examples/garage_door_opener.rb +71 -0
  20. data/examples/heater_cooler.rb +92 -0
  21. data/examples/humidifier_dehumidifier.rb +88 -0
  22. data/examples/humidity_sensor.rb +62 -0
  23. data/examples/leak_sensor.rb +66 -0
  24. data/examples/light_sensor.rb +64 -0
  25. data/examples/lightbulb.rb +31 -0
  26. data/examples/lock_mechanism.rb +34 -0
  27. data/examples/motion_sensor.rb +66 -0
  28. data/examples/occupancy_sensor.rb +66 -0
  29. data/examples/outlet.rb +29 -0
  30. data/examples/security_system.rb +53 -0
  31. data/examples/smoke_sensor.rb +66 -0
  32. data/examples/switch.rb +16 -0
  33. data/examples/television.rb +73 -0
  34. data/examples/temperature_sensor.rb +62 -0
  35. data/examples/thermostat.rb +113 -0
  36. data/examples/window.rb +48 -0
  37. data/examples/window_covering.rb +72 -0
  38. data/lib/ruby_home.rb +21 -22
  39. data/lib/ruby_home/accessory.rb +1 -1
  40. data/lib/ruby_home/accessory_collection.rb +6 -6
  41. data/lib/ruby_home/accessory_info.rb +18 -18
  42. data/lib/ruby_home/characteristic.rb +13 -7
  43. data/lib/ruby_home/characteristic_collection.rb +13 -13
  44. data/lib/ruby_home/config/categories.yml +39 -0
  45. data/lib/ruby_home/config/characteristics.yml +190 -319
  46. data/lib/ruby_home/config/manual_characteristics.yml +278 -0
  47. data/lib/ruby_home/config/manual_services.yml +45 -0
  48. data/lib/ruby_home/config/services.yml +338 -304
  49. data/lib/ruby_home/configuration.rb +21 -2
  50. data/lib/ruby_home/device_id.rb +3 -3
  51. data/lib/ruby_home/dns/service.rb +4 -6
  52. data/lib/ruby_home/dns/text_record.rb +10 -10
  53. data/lib/ruby_home/errors.rb +1 -0
  54. data/lib/ruby_home/factories/characteristic_factory.rb +38 -37
  55. data/lib/ruby_home/factories/service_factory.rb +72 -72
  56. data/lib/ruby_home/factories/templates/characteristic_template.rb +6 -6
  57. data/lib/ruby_home/factories/templates/service_template.rb +12 -11
  58. data/lib/ruby_home/hap/crypto/chacha20poly1305.rb +2 -2
  59. data/lib/ruby_home/hap/crypto/hkdf.rb +4 -4
  60. data/lib/ruby_home/hap/crypto/session_key.rb +7 -7
  61. data/lib/ruby_home/hap/decrypter.rb +8 -8
  62. data/lib/ruby_home/hap/encrypter.rb +5 -6
  63. data/lib/ruby_home/hap/ev_response.rb +17 -17
  64. data/lib/ruby_home/hap/hap_request.rb +1 -1
  65. data/lib/ruby_home/hap/server.rb +4 -4
  66. data/lib/ruby_home/hap/server_handler.rb +8 -10
  67. data/lib/ruby_home/hap/session.rb +22 -22
  68. data/lib/ruby_home/hap/values/base_value.rb +3 -3
  69. data/lib/ruby_home/hap/values/bool_value.rb +4 -4
  70. data/lib/ruby_home/hap/values/float_value.rb +4 -4
  71. data/lib/ruby_home/hap/values/identify_value.rb +1 -1
  72. data/lib/ruby_home/hap/values/int32_value.rb +4 -4
  73. data/lib/ruby_home/hap/values/null_value.rb +1 -1
  74. data/lib/ruby_home/hap/values/string_value.rb +11 -11
  75. data/lib/ruby_home/hap/values/uint32_value.rb +5 -5
  76. data/lib/ruby_home/hap/values/uint8_value.rb +14 -14
  77. data/lib/ruby_home/hex_helper.rb +3 -3
  78. data/lib/ruby_home/http/application.rb +7 -7
  79. data/lib/ruby_home/http/controllers/accessories_controller.rb +3 -3
  80. data/lib/ruby_home/http/controllers/application_controller.rb +6 -6
  81. data/lib/ruby_home/http/controllers/characteristics_controller.rb +29 -29
  82. data/lib/ruby_home/http/controllers/identify_controller.rb +10 -10
  83. data/lib/ruby_home/http/controllers/pair_setups_controller.rb +19 -19
  84. data/lib/ruby_home/http/controllers/pair_verifies_controller.rb +9 -9
  85. data/lib/ruby_home/http/controllers/pairings_controller.rb +6 -6
  86. data/lib/ruby_home/http/serializers/accessory_serializer.rb +5 -5
  87. data/lib/ruby_home/http/serializers/characteristic_serializer.rb +27 -19
  88. data/lib/ruby_home/http/serializers/characteristic_value_serializer.rb +5 -5
  89. data/lib/ruby_home/http/serializers/object_serializer.rb +1 -1
  90. data/lib/ruby_home/http/serializers/service_serializer.rb +19 -9
  91. data/lib/ruby_home/http/serializers/uuid_helper.rb +2 -2
  92. data/lib/ruby_home/http/services/session_notifier.rb +8 -8
  93. data/lib/ruby_home/http/services/start_srp_service.rb +3 -3
  94. data/lib/ruby_home/http/services/verify_finish_service.rb +22 -22
  95. data/lib/ruby_home/http/services/verify_srp_service.rb +22 -22
  96. data/lib/ruby_home/identifier_cache.rb +4 -5
  97. data/lib/ruby_home/password.rb +14 -14
  98. data/lib/ruby_home/persistable.rb +19 -12
  99. data/lib/ruby_home/service.rb +5 -2
  100. data/lib/ruby_home/service_collection.rb +1 -1
  101. data/lib/ruby_home/version.rb +1 -1
  102. data/rubyhome.gemspec +31 -31
  103. data/sbin/characteristic_generator.rb +22 -24
  104. data/sbin/service_generator.rb +38 -19
  105. metadata +85 -44
  106. data/.travis.yml +0 -31
@@ -1,10 +1,10 @@
1
- require_relative 'application_controller'
1
+ require_relative "application_controller"
2
2
 
3
3
  module RubyHome
4
4
  module HTTP
5
5
  class PairingsController < ApplicationController
6
- post '/' do
7
- content_type 'application/pairing+tlv8'
6
+ post "/" do
7
+ content_type "application/pairing+tlv8"
8
8
 
9
9
  case unpack_request[:method]
10
10
  when 3
@@ -20,9 +20,9 @@ module RubyHome
20
20
  pairing_params = {
21
21
  admin: !!unpack_request[:permissions],
22
22
  identifier: unpack_request[:identifier],
23
- public_key: unpack_request[:public_key].unpack1('H*')
23
+ public_key: unpack_request[:public_key].unpack1("H*")
24
24
  }
25
- accessory_info.add_paired_client pairing_params
25
+ accessory_info.add_paired_client(**pairing_params)
26
26
 
27
27
  tlv state: 2
28
28
  end
@@ -30,7 +30,7 @@ module RubyHome
30
30
  def remove_pairing
31
31
  accessory_info.remove_paired_client(unpack_request[:identifier])
32
32
 
33
- response['connection'] = 'close'
33
+ response["connection"] = "close"
34
34
  tlv state: 2
35
35
  end
36
36
  end
@@ -1,5 +1,5 @@
1
- require_relative 'object_serializer'
2
- require_relative 'service_serializer'
1
+ require_relative "object_serializer"
2
+ require_relative "service_serializer"
3
3
 
4
4
  module RubyHome
5
5
  module HTTP
@@ -7,13 +7,13 @@ module RubyHome
7
7
  include ObjectSerializer
8
8
 
9
9
  def root
10
- 'accessories'
10
+ "accessories"
11
11
  end
12
12
 
13
13
  def record_hash(accessory)
14
14
  {
15
- 'aid' => accessory.id,
16
- 'services' => ServiceSerializer.new(accessory.services).serializable_hash,
15
+ "aid" => accessory.id,
16
+ "services" => ServiceSerializer.new(accessory.services).serializable_hash
17
17
  }
18
18
  end
19
19
  end
@@ -1,5 +1,5 @@
1
- require_relative 'object_serializer'
2
- require_relative 'uuid_helper'
1
+ require_relative "object_serializer"
2
+ require_relative "uuid_helper"
3
3
 
4
4
  module RubyHome
5
5
  module HTTP
@@ -9,31 +9,39 @@ module RubyHome
9
9
 
10
10
  def record_hash(characteristic)
11
11
  {
12
- 'iid' => characteristic.instance_id,
13
- 'type' => uuid_short_form(characteristic.uuid),
14
- 'perms' => perms(characteristic),
15
- 'format' => characteristic.format,
16
- 'description' => characteristic.description,
17
- }.merge(value_hash(characteristic))
12
+ "iid" => characteristic.instance_id,
13
+ "type" => uuid_short_form(characteristic.uuid),
14
+ "perms" => perms(characteristic),
15
+ "format" => characteristic.format,
16
+ "description" => characteristic.description
17
+ }
18
+ .merge(value_hash(characteristic))
19
+ .merge(valid_values_hash(characteristic))
18
20
  end
19
21
 
20
22
  private
21
23
 
22
- HIDDEN_VALUE_OBJECTS = [ IdentifyValue ].freeze
24
+ def perms(characteristic)
25
+ characteristic.properties.map do |property|
26
+ RubyHome::Characteristic::PROPERTIES[property]
27
+ end.compact
28
+ end
23
29
 
24
- def perms(characteristic)
25
- characteristic.properties.map do |property|
26
- RubyHome::Characteristic::PROPERTIES[property]
27
- end.compact
30
+ def value_hash(characteristic)
31
+ if characteristic.properties.include?("read")
32
+ {"value" => characteristic.value}
33
+ else
34
+ {}
28
35
  end
36
+ end
29
37
 
30
- def value_hash(characteristic)
31
- if HIDDEN_VALUE_OBJECTS.include?(characteristic.value_object.class)
32
- {}
33
- else
34
- { 'value' => characteristic.value }.compact
35
- end
38
+ def valid_values_hash(characteristic)
39
+ if characteristic.valid_values.empty?
40
+ {}
41
+ else
42
+ {"valid-values" => characteristic.valid_values}
36
43
  end
44
+ end
37
45
  end
38
46
  end
39
47
  end
@@ -1,4 +1,4 @@
1
- require_relative 'object_serializer'
1
+ require_relative "object_serializer"
2
2
 
3
3
  module RubyHome
4
4
  module HTTP
@@ -6,14 +6,14 @@ module RubyHome
6
6
  include ObjectSerializer
7
7
 
8
8
  def root
9
- 'characteristics'
9
+ "characteristics"
10
10
  end
11
11
 
12
12
  def record_hash(characteristic)
13
13
  {
14
- 'aid' => characteristic.accessory_id,
15
- 'iid' => characteristic.instance_id,
16
- 'value' => characteristic.value,
14
+ "aid" => characteristic.accessory_id,
15
+ "iid" => characteristic.instance_id,
16
+ "value" => characteristic.value
17
17
  }
18
18
  end
19
19
  end
@@ -1,4 +1,4 @@
1
- require 'facets/hash/symbolize_keys'
1
+ require "facets/hash/symbolize_keys"
2
2
 
3
3
  module RubyHome
4
4
  module HTTP
@@ -1,6 +1,6 @@
1
- require_relative 'characteristic_serializer'
2
- require_relative 'object_serializer'
3
- require_relative 'uuid_helper'
1
+ require_relative "characteristic_serializer"
2
+ require_relative "object_serializer"
3
+ require_relative "uuid_helper"
4
4
 
5
5
  module RubyHome
6
6
  module HTTP
@@ -10,12 +10,22 @@ module RubyHome
10
10
 
11
11
  def record_hash(service)
12
12
  {
13
- 'iid' => service.instance_id,
14
- 'type' => uuid_short_form(service.uuid),
15
- 'characteristics' => CharacteristicSerializer.new(service.characteristics).serializable_hash,
16
- 'primary' => service.primary,
17
- 'hidden' => service.hidden,
18
- }
13
+ "iid" => service.instance_id,
14
+ "type" => uuid_short_form(service.uuid),
15
+ "characteristics" => CharacteristicSerializer.new(service.characteristics).serializable_hash,
16
+ "primary" => service.primary,
17
+ "hidden" => service.hidden
18
+ }.merge(linked_services(service))
19
+ end
20
+
21
+ private
22
+
23
+ def linked_services(service)
24
+ if service.linked.empty?
25
+ {}
26
+ else
27
+ {"linked" => service.linked.map(&:instance_id)}
28
+ end
19
29
  end
20
30
  end
21
31
  end
@@ -1,7 +1,7 @@
1
1
  module RubyHome
2
2
  module HTTP
3
3
  module UUIDHelper
4
- APPLE_BASE_UUID = -'0000-1000-8000-0026BB765291'
4
+ APPLE_BASE_UUID = -"0000-1000-8000-0026BB765291"
5
5
 
6
6
  def uuid_short_form(uuid)
7
7
  return uuid unless apple_defined_uuid?(uuid)
@@ -14,7 +14,7 @@ module RubyHome
14
14
  end
15
15
 
16
16
  def trim_leading_zeros(input)
17
- input.gsub(/^0*/, '')
17
+ input.gsub(/^0*/, "")
18
18
  end
19
19
  end
20
20
  end
@@ -16,21 +16,21 @@ module RubyHome
16
16
 
17
17
  def ==(other)
18
18
  self.class == other.class &&
19
- self.session == other.session &&
20
- self.characteristic == other.characteristic
19
+ session == other.session &&
20
+ characteristic == other.characteristic
21
21
  end
22
22
 
23
23
  attr_reader :session, :characteristic
24
24
 
25
25
  private
26
26
 
27
- def send_ev_response
28
- HAP::EVResponse.new(session, serialized_characteristic).send_response
29
- end
27
+ def send_ev_response
28
+ HAP::EVResponse.new(session, serialized_characteristic).send_response
29
+ end
30
30
 
31
- def serialized_characteristic
32
- HTTP::CharacteristicValueSerializer.new([characteristic]).serialized_json
33
- end
31
+ def serialized_characteristic
32
+ HTTP::CharacteristicValueSerializer.new([characteristic]).serialized_json
33
+ end
34
34
  end
35
35
  end
36
36
  end
@@ -1,16 +1,16 @@
1
1
  module RubyHome
2
2
  class StartSRPService
3
- def initialize(username: , password:)
3
+ def initialize(username:, password:)
4
4
  @username = username
5
5
  @password = password
6
6
  end
7
7
 
8
8
  def salt_bytes
9
- [salt].pack('H*')
9
+ [salt].pack("H*")
10
10
  end
11
11
 
12
12
  def public_key_bytes
13
- [public_key].pack('H*')
13
+ [public_key].pack("H*")
14
14
  end
15
15
 
16
16
  def proof
@@ -1,6 +1,6 @@
1
1
  module RubyHome
2
2
  class VerifyFinishService
3
- def initialize(accessory_info: , encrypted_data: , session_key:, shared_secret:)
3
+ def initialize(accessory_info:, encrypted_data:, session_key:, shared_secret:)
4
4
  @accessory_info = accessory_info
5
5
  @encrypted_data = encrypted_data
6
6
  @session_key = session_key
@@ -23,34 +23,34 @@ module RubyHome
23
23
 
24
24
  private
25
25
 
26
- NONCE = -'PV-Msg03'
26
+ NONCE = -"PV-Msg03"
27
27
 
28
- attr_reader :accessory_info, :encrypted_data, :session_key, :shared_secret
28
+ attr_reader :accessory_info, :encrypted_data, :session_key, :shared_secret
29
29
 
30
- def paired_client_exists?
31
- accessory_info.paired_clients.any? do |paired_client|
32
- paired_client[:identifier] == identifier
33
- end
30
+ def paired_client_exists?
31
+ accessory_info.paired_clients.any? do |paired_client|
32
+ paired_client[:identifier] == identifier
34
33
  end
34
+ end
35
35
 
36
- def chacha20poly1305
37
- HAP::Crypto::ChaCha20Poly1305.new(session_key)
38
- end
36
+ def chacha20poly1305
37
+ HAP::Crypto::ChaCha20Poly1305.new(session_key)
38
+ end
39
39
 
40
- def nonce
41
- HexHelper.pad(NONCE)
42
- end
40
+ def nonce
41
+ HexHelper.pad(NONCE)
42
+ end
43
43
 
44
- def decrypted_data
45
- chacha20poly1305.decrypt(nonce, encrypted_data)
46
- end
44
+ def decrypted_data
45
+ chacha20poly1305.decrypt(nonce, encrypted_data)
46
+ end
47
47
 
48
- def unpacked_decrypted_data
49
- TLV.decode(decrypted_data)
50
- end
48
+ def unpacked_decrypted_data
49
+ TLV.decode(decrypted_data)
50
+ end
51
51
 
52
- def identifier
53
- unpacked_decrypted_data[:identifier]
54
- end
52
+ def identifier
53
+ unpacked_decrypted_data[:identifier]
54
+ end
55
55
  end
56
56
  end
@@ -1,8 +1,8 @@
1
1
  module RubyHome
2
2
  class VerifySRPService
3
- def initialize(device_proof: , public_key: , srp_session: )
4
- @device_proof_bytes = device_proof.to_s.unpack1('H*')
5
- @public_key_bytes = public_key.to_s.unpack1('H*')
3
+ def initialize(device_proof:, public_key:, srp_session:)
4
+ @device_proof_bytes = device_proof.to_s.unpack1("H*")
5
+ @public_key_bytes = public_key.to_s.unpack1("H*")
6
6
  @srp_session = srp_session
7
7
  end
8
8
 
@@ -20,29 +20,29 @@ module RubyHome
20
20
 
21
21
  private
22
22
 
23
- def valid_session?
24
- !!verify_session
25
- end
23
+ def valid_session?
24
+ !!verify_session
25
+ end
26
26
 
27
- def session_key
28
- srp_verifier.K
29
- end
27
+ def session_key
28
+ srp_verifier.K
29
+ end
30
30
 
31
- def verify_session_bytes
32
- [verify_session].pack('H*')
33
- end
31
+ def verify_session_bytes
32
+ [verify_session].pack("H*")
33
+ end
34
34
 
35
- def verify_session
36
- srp_verifier.verify_session(
37
- srp_session.merge({A: public_key_bytes}),
38
- device_proof_bytes
39
- )
40
- end
35
+ def verify_session
36
+ srp_verifier.verify_session(
37
+ srp_session.merge({A: public_key_bytes}),
38
+ device_proof_bytes
39
+ )
40
+ end
41
41
 
42
- def srp_verifier
43
- @_verifier ||= RubyHome::SRP::Verifier.new
44
- end
42
+ def srp_verifier
43
+ @_verifier ||= RubyHome::SRP::Verifier.new
44
+ end
45
45
 
46
- attr_reader :public_key_bytes, :device_proof_bytes, :srp_session
46
+ attr_reader :public_key_bytes, :device_proof_bytes, :srp_session
47
47
  end
48
48
  end
@@ -1,10 +1,10 @@
1
- require_relative 'persistable'
1
+ require_relative "persistable"
2
2
 
3
3
  module RubyHome
4
4
  class IdentifierCache
5
5
  include Persistable
6
6
 
7
- self.source = 'identifier_cache.yml'
7
+ self.source = "identifier_cache.yml"
8
8
 
9
9
  def self.all
10
10
  raw_items = read || []
@@ -33,7 +33,7 @@ module RubyHome
33
33
  end
34
34
  end
35
35
 
36
- def initialize(accessory_id:, instance_id:, service_uuid: nil, subtype: , uuid: )
36
+ def initialize(accessory_id:, instance_id:, subtype:, uuid:, service_uuid: nil)
37
37
  @accessory_id = accessory_id
38
38
  @instance_id = instance_id
39
39
  @subtype = subtype
@@ -52,10 +52,9 @@ module RubyHome
52
52
  instance_id: identifier.instance_id,
53
53
  subtype: identifier.subtype,
54
54
  service_uuid: identifier.service_uuid,
55
- uuid: identifier.uuid,
55
+ uuid: identifier.uuid
56
56
  }
57
57
  end
58
58
  end
59
59
  end
60
60
  end
61
-
@@ -1,21 +1,21 @@
1
1
  module RubyHome
2
2
  module Password
3
3
  class << self
4
- DELIMITER = '-'
4
+ DELIMITER = "-"
5
5
  LENGTH = 8
6
6
  INVALIDS = [
7
- '00000000',
8
- '11111111',
9
- '22222222',
10
- '33333333',
11
- '44444444',
12
- '55555555',
13
- '66666666',
14
- '77777777',
15
- '88888888',
16
- '99999999',
17
- '12345678',
18
- '87654321',
7
+ "00000000",
8
+ "11111111",
9
+ "22222222",
10
+ "33333333",
11
+ "44444444",
12
+ "55555555",
13
+ "66666666",
14
+ "77777777",
15
+ "88888888",
16
+ "99999999",
17
+ "12345678",
18
+ "87654321"
19
19
  ]
20
20
 
21
21
  # The Setup Code must conform to the format XXX-XX-XXX where each X is a
@@ -34,7 +34,7 @@ module RubyHome
34
34
  [
35
35
  digits[0...3],
36
36
  digits[3...5],
37
- digits[5...8],
37
+ digits[5...8]
38
38
  ].join(DELIMITER)
39
39
  end
40
40