ruby_home 0.2.0 → 0.2.5
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 +4 -4
- data/.github/workflows/tests.yml +41 -0
- data/CHANGELOG.md +13 -0
- data/README.md +47 -84
- data/examples/air_purifier.rb +67 -0
- data/examples/air_quality_sensor.rb +120 -0
- data/examples/battery_service.rb +59 -0
- data/examples/carbon_dioxide_sensor.rb +79 -0
- data/examples/carbon_monoxide_sensor.rb +79 -0
- data/examples/contact_sensor.rb +67 -0
- data/examples/door.rb +49 -0
- data/examples/fan.rb +31 -0
- data/examples/fan_v2.rb +69 -0
- data/examples/garage_door_opener.rb +72 -0
- data/examples/heater_cooler.rb +93 -0
- data/examples/humidifier_dehumidifier.rb +89 -0
- data/examples/humidity_sensor.rb +63 -0
- data/examples/leak_sensor.rb +67 -0
- data/examples/light_sensor.rb +65 -0
- data/examples/lightbulb.rb +32 -0
- data/examples/lock_mechanism.rb +35 -0
- data/examples/motion_sensor.rb +67 -0
- data/examples/occupancy_sensor.rb +67 -0
- data/examples/outlet.rb +30 -0
- data/examples/security_system.rb +54 -0
- data/examples/smoke_sensor.rb +67 -0
- data/examples/switch.rb +17 -0
- data/examples/television.rb +78 -0
- data/examples/temperature_sensor.rb +63 -0
- data/examples/thermostat.rb +114 -0
- data/examples/window.rb +49 -0
- data/examples/window_covering.rb +73 -0
- data/lib/ruby_home.rb +0 -1
- data/lib/ruby_home/characteristic.rb +7 -1
- data/lib/ruby_home/config/categories.yml +39 -0
- data/lib/ruby_home/config/characteristics.yml +479 -3
- data/lib/ruby_home/config/services.yml +79 -4
- data/lib/ruby_home/configuration.rb +19 -0
- data/lib/ruby_home/dns/service.rb +2 -0
- data/lib/ruby_home/dns/text_record.rb +1 -1
- data/lib/ruby_home/errors.rb +4 -0
- data/lib/ruby_home/factories/characteristic_factory.rb +1 -0
- data/lib/ruby_home/factories/templates/characteristic_template.rb +1 -1
- data/lib/ruby_home/factories/templates/service_template.rb +1 -1
- data/lib/ruby_home/hap/server_handler.rb +4 -13
- data/lib/ruby_home/hap/values/uint8_value.rb +11 -1
- data/lib/ruby_home/http/controllers/application_controller.rb +10 -3
- data/lib/ruby_home/http/controllers/pair_setups_controller.rb +3 -3
- data/lib/ruby_home/http/controllers/pair_verifies_controller.rb +10 -12
- data/lib/ruby_home/http/controllers/pairings_controller.rb +1 -1
- data/lib/ruby_home/http/serializers/characteristic_serializer.rb +13 -5
- data/lib/ruby_home/http/serializers/service_serializer.rb +11 -1
- data/lib/ruby_home/http/services/verify_finish_service.rb +56 -0
- data/lib/ruby_home/http/services/verify_srp_service.rb +32 -41
- data/lib/ruby_home/persistable.rb +4 -12
- data/lib/ruby_home/service.rb +3 -0
- data/lib/ruby_home/version.rb +1 -1
- data/rubyhome.gemspec +7 -7
- data/sbin/service_generator.rb +12 -2
- metadata +65 -39
- data/.travis.yml +0 -31
| @@ -152,6 +152,14 @@ | |
| 152 152 | 
             
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 153 153 | 
             
              :required_characteristics_uuids:
         | 
| 154 154 | 
             
              - 000000AC-0000-1000-8000-0026BB765291
         | 
| 155 | 
            +
            - :name: :faucet
         | 
| 156 | 
            +
              :description: Faucet
         | 
| 157 | 
            +
              :uuid: 000000D7-0000-1000-8000-0026BB765291
         | 
| 158 | 
            +
              :optional_characteristics_uuids:
         | 
| 159 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 160 | 
            +
              - 00000077-0000-1000-8000-0026BB765291
         | 
| 161 | 
            +
              :required_characteristics_uuids:
         | 
| 162 | 
            +
              - 000000B0-0000-1000-8000-0026BB765291
         | 
| 155 163 | 
             
            - :name: :garage_door_opener
         | 
| 156 164 | 
             
              :description: Garage Door Opener
         | 
| 157 165 | 
             
              :uuid: 00000041-0000-1000-8000-0026BB765291
         | 
| @@ -206,6 +214,30 @@ | |
| 206 214 | 
             
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 207 215 | 
             
              :required_characteristics_uuids:
         | 
| 208 216 | 
             
              - 00000010-0000-1000-8000-0026BB765291
         | 
| 217 | 
            +
            - :name: :input_source
         | 
| 218 | 
            +
              :description: Input Source
         | 
| 219 | 
            +
              :uuid: 000000D9-0000-1000-8000-0026BB765291
         | 
| 220 | 
            +
              :optional_characteristics_uuids:
         | 
| 221 | 
            +
              - 000000E6-0000-1000-8000-0026BB765291
         | 
| 222 | 
            +
              - 000000DC-0000-1000-8000-0026BB765291
         | 
| 223 | 
            +
              - 00000134-0000-1000-8000-0026BB765291
         | 
| 224 | 
            +
              :required_characteristics_uuids:
         | 
| 225 | 
            +
              - 000000E3-0000-1000-8000-0026BB765291
         | 
| 226 | 
            +
              - 000000DB-0000-1000-8000-0026BB765291
         | 
| 227 | 
            +
              - 000000D6-0000-1000-8000-0026BB765291
         | 
| 228 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 229 | 
            +
              - 00000135-0000-1000-8000-0026BB765291
         | 
| 230 | 
            +
            - :name: :irrigation_system
         | 
| 231 | 
            +
              :description: Irrigation System
         | 
| 232 | 
            +
              :uuid: 000000CF-0000-1000-8000-0026BB765291
         | 
| 233 | 
            +
              :optional_characteristics_uuids:
         | 
| 234 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 235 | 
            +
              - 000000D4-0000-1000-8000-0026BB765291
         | 
| 236 | 
            +
              - 00000077-0000-1000-8000-0026BB765291
         | 
| 237 | 
            +
              :required_characteristics_uuids:
         | 
| 238 | 
            +
              - 000000B0-0000-1000-8000-0026BB765291
         | 
| 239 | 
            +
              - 000000D1-0000-1000-8000-0026BB765291
         | 
| 240 | 
            +
              - 000000D2-0000-1000-8000-0026BB765291
         | 
| 209 241 | 
             
            - :name: :leak_sensor
         | 
| 210 242 | 
             
              :description: Leak Sensor
         | 
| 211 243 | 
             
              :uuid: '00000083-0000-1000-8000-0026BB765291'
         | 
| @@ -221,11 +253,11 @@ | |
| 221 253 | 
             
              :description: Light Sensor
         | 
| 222 254 | 
             
              :uuid: '00000084-0000-1000-8000-0026BB765291'
         | 
| 223 255 | 
             
              :optional_characteristics_uuids:
         | 
| 256 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 224 257 | 
             
              - 00000075-0000-1000-8000-0026BB765291
         | 
| 225 258 | 
             
              - 00000077-0000-1000-8000-0026BB765291
         | 
| 226 259 | 
             
              - 0000007A-0000-1000-8000-0026BB765291
         | 
| 227 260 | 
             
              - '00000079-0000-1000-8000-0026BB765291'
         | 
| 228 | 
            -
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 229 261 | 
             
              :required_characteristics_uuids:
         | 
| 230 262 | 
             
              - 0000006B-0000-1000-8000-0026BB765291
         | 
| 231 263 | 
             
            - :name: :lightbulb
         | 
| @@ -236,6 +268,7 @@ | |
| 236 268 | 
             
              - 00000013-0000-1000-8000-0026BB765291
         | 
| 237 269 | 
             
              - 0000002F-0000-1000-8000-0026BB765291
         | 
| 238 270 | 
             
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 271 | 
            +
              - 000000CE-0000-1000-8000-0026BB765291
         | 
| 239 272 | 
             
              :required_characteristics_uuids:
         | 
| 240 273 | 
             
              - 00000025-0000-1000-8000-0026BB765291
         | 
| 241 274 | 
             
            - :name: :lock_management
         | 
| @@ -265,9 +298,9 @@ | |
| 265 298 | 
             
              :description: Microphone
         | 
| 266 299 | 
             
              :uuid: 00000112-0000-1000-8000-0026BB765291
         | 
| 267 300 | 
             
              :optional_characteristics_uuids:
         | 
| 268 | 
            -
              - '00000119-0000-1000-8000-0026BB765291'
         | 
| 269 301 | 
             
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 270 302 | 
             
              :required_characteristics_uuids:
         | 
| 303 | 
            +
              - '00000119-0000-1000-8000-0026BB765291'
         | 
| 271 304 | 
             
              - 0000011A-0000-1000-8000-0026BB765291
         | 
| 272 305 | 
             
            - :name: :motion_sensor
         | 
| 273 306 | 
             
              :description: Motion Sensor
         | 
| @@ -284,11 +317,11 @@ | |
| 284 317 | 
             
              :description: Occupancy Sensor
         | 
| 285 318 | 
             
              :uuid: '00000086-0000-1000-8000-0026BB765291'
         | 
| 286 319 | 
             
              :optional_characteristics_uuids:
         | 
| 320 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 287 321 | 
             
              - 00000075-0000-1000-8000-0026BB765291
         | 
| 288 322 | 
             
              - 00000077-0000-1000-8000-0026BB765291
         | 
| 289 323 | 
             
              - 0000007A-0000-1000-8000-0026BB765291
         | 
| 290 324 | 
             
              - '00000079-0000-1000-8000-0026BB765291'
         | 
| 291 | 
            -
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 292 325 | 
             
              :required_characteristics_uuids:
         | 
| 293 326 | 
             
              - 00000071-0000-1000-8000-0026BB765291
         | 
| 294 327 | 
             
            - :name: :outlet
         | 
| @@ -343,8 +376,8 @@ | |
| 343 376 | 
             
              :description: Speaker
         | 
| 344 377 | 
             
              :uuid: 00000113-0000-1000-8000-0026BB765291
         | 
| 345 378 | 
             
              :optional_characteristics_uuids:
         | 
| 346 | 
            -
              - '00000119-0000-1000-8000-0026BB765291'
         | 
| 347 379 | 
             
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 380 | 
            +
              - '00000119-0000-1000-8000-0026BB765291'
         | 
| 348 381 | 
             
              :required_characteristics_uuids:
         | 
| 349 382 | 
             
              - 0000011A-0000-1000-8000-0026BB765291
         | 
| 350 383 | 
             
            - :name: :stateless_programmable_switch
         | 
| @@ -362,6 +395,34 @@ | |
| 362 395 | 
             
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 363 396 | 
             
              :required_characteristics_uuids:
         | 
| 364 397 | 
             
              - 00000025-0000-1000-8000-0026BB765291
         | 
| 398 | 
            +
            - :name: :television
         | 
| 399 | 
            +
              :description: Television
         | 
| 400 | 
            +
              :uuid: '000000D8-0000-1000-8000-0026BB765291'
         | 
| 401 | 
            +
              :optional_characteristics_uuids:
         | 
| 402 | 
            +
              - 00000008-0000-1000-8000-0026BB765291
         | 
| 403 | 
            +
              - 000000DD-0000-1000-8000-0026BB765291
         | 
| 404 | 
            +
              - 00000136-0000-1000-8000-0026BB765291
         | 
| 405 | 
            +
              - 000000E0-0000-1000-8000-0026BB765291
         | 
| 406 | 
            +
              - 00000137-0000-1000-8000-0026BB765291
         | 
| 407 | 
            +
              - 000000E2-0000-1000-8000-0026BB765291
         | 
| 408 | 
            +
              - 000000DF-0000-1000-8000-0026BB765291
         | 
| 409 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 410 | 
            +
              :required_characteristics_uuids:
         | 
| 411 | 
            +
              - 000000B0-0000-1000-8000-0026BB765291
         | 
| 412 | 
            +
              - 000000E7-0000-1000-8000-0026BB765291
         | 
| 413 | 
            +
              - 000000E3-0000-1000-8000-0026BB765291
         | 
| 414 | 
            +
              - 000000E1-0000-1000-8000-0026BB765291
         | 
| 415 | 
            +
              - 000000E8-0000-1000-8000-0026BB765291
         | 
| 416 | 
            +
            - :name: :television_speaker
         | 
| 417 | 
            +
              :description: Television Speaker
         | 
| 418 | 
            +
              :uuid: 00000113-0000-1000-8000-0026BB765291
         | 
| 419 | 
            +
              :optional_characteristics_uuids:
         | 
| 420 | 
            +
              - 000000B0-0000-1000-8000-0026BB765291
         | 
| 421 | 
            +
              - 00000119-0000-1000-8000-0026BB765291
         | 
| 422 | 
            +
              - 000000E9-0000-1000-8000-0026BB765291
         | 
| 423 | 
            +
              - 000000EA-0000-1000-8000-0026BB765291
         | 
| 424 | 
            +
              :required_characteristics_uuids:
         | 
| 425 | 
            +
              - 0000011A-0000-1000-8000-0026BB765291
         | 
| 365 426 | 
             
            - :name: :temperature_sensor
         | 
| 366 427 | 
             
              :description: Temperature Sensor
         | 
| 367 428 | 
             
              :uuid: '0000008A-0000-1000-8000-0026BB765291'
         | 
| @@ -388,6 +449,20 @@ | |
| 388 449 | 
             
              - 00000011-0000-1000-8000-0026BB765291
         | 
| 389 450 | 
             
              - 00000035-0000-1000-8000-0026BB765291
         | 
| 390 451 | 
             
              - 00000036-0000-1000-8000-0026BB765291
         | 
| 452 | 
            +
            - :name: :valve
         | 
| 453 | 
            +
              :description: Valve
         | 
| 454 | 
            +
              :uuid: 000000D0-0000-1000-8000-0026BB765291
         | 
| 455 | 
            +
              :optional_characteristics_uuids:
         | 
| 456 | 
            +
              - 000000D3-0000-1000-8000-0026BB765291
         | 
| 457 | 
            +
              - 000000D4-0000-1000-8000-0026BB765291
         | 
| 458 | 
            +
              - 000000D6-0000-1000-8000-0026BB765291
         | 
| 459 | 
            +
              - 000000CB-0000-1000-8000-0026BB765291
         | 
| 460 | 
            +
              - 00000077-0000-1000-8000-0026BB765291
         | 
| 461 | 
            +
              - 00000023-0000-1000-8000-0026BB765291
         | 
| 462 | 
            +
              :required_characteristics_uuids:
         | 
| 463 | 
            +
              - 000000B0-0000-1000-8000-0026BB765291
         | 
| 464 | 
            +
              - 000000D2-0000-1000-8000-0026BB765291
         | 
| 465 | 
            +
              - 000000D5-0000-1000-8000-0026BB765291
         | 
| 391 466 | 
             
            - :name: :window
         | 
| 392 467 | 
             
              :description: Window
         | 
| 393 468 | 
             
              :uuid: '0000008B-0000-1000-8000-0026BB765291'
         | 
| @@ -1,7 +1,12 @@ | |
| 1 1 | 
             
            module RubyHome
         | 
| 2 | 
            +
              class UnknownCategoriyIdentifierError < StandardError; end
         | 
| 3 | 
            +
             | 
| 2 4 | 
             
              class Configuration
         | 
| 3 5 | 
             
                extend Forwardable
         | 
| 4 6 |  | 
| 7 | 
            +
                CATEGORIES_FILEPATH = (File.dirname(__FILE__) + '/config/categories.yml').freeze
         | 
| 8 | 
            +
                CATEGORIES = YAML.load_file(CATEGORIES_FILEPATH).freeze
         | 
| 9 | 
            +
             | 
| 5 10 | 
             
                def initialize(accessory_info = AccessoryInfo.instance)
         | 
| 6 11 | 
             
                  @accessory_info = accessory_info
         | 
| 7 12 | 
             
                end
         | 
| @@ -11,6 +16,7 @@ module RubyHome | |
| 11 16 | 
             
                DEFAULT_PORT = 4567
         | 
| 12 17 | 
             
                DEFAULT_MODEL_NAME = DEFAULT_NAME
         | 
| 13 18 | 
             
                DEFAULT_DISCOVERY_NAME = DEFAULT_NAME
         | 
| 19 | 
            +
                DEFAULT_CATEGORY_IDENTIFIER = 2
         | 
| 14 20 |  | 
| 15 21 | 
             
                def discovery_name
         | 
| 16 22 | 
             
                  @discovery_name || DEFAULT_DISCOVERY_NAME
         | 
| @@ -28,6 +34,19 @@ module RubyHome | |
| 28 34 | 
             
                  @host || DEFAULT_HOST
         | 
| 29 35 | 
             
                end
         | 
| 30 36 |  | 
| 37 | 
            +
                def category_identifier
         | 
| 38 | 
            +
                  @category_identifier || DEFAULT_CATEGORY_IDENTIFIER
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def category_identifier=(value)
         | 
| 42 | 
            +
                  if value.is_a?(Symbol)
         | 
| 43 | 
            +
                    raise UnknownCategoriyIdentifierError if !CATEGORIES.include?(value)
         | 
| 44 | 
            +
                    @category_identifier = CATEGORIES[value]
         | 
| 45 | 
            +
                  else
         | 
| 46 | 
            +
                    @category_identifier = value.to_i
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 31 50 | 
             
                attr_writer :discovery_name, :model_name, :host, :port
         | 
| 32 51 |  | 
| 33 52 | 
             
                def_delegators :@accessory_info, :password, :password=
         | 
| @@ -35,29 +35,20 @@ module RubyHome | |
| 35 35 | 
             
                      Host: bind_address,
         | 
| 36 36 | 
             
                      ServerSoftware: 'RubyHome',
         | 
| 37 37 | 
             
                      Logger: server_logger,
         | 
| 38 | 
            -
                      AccessLog:  | 
| 38 | 
            +
                      AccessLog: []
         | 
| 39 39 | 
             
                    }
         | 
| 40 40 | 
             
                  end
         | 
| 41 41 |  | 
| 42 42 | 
             
                  def server_logger
         | 
| 43 | 
            -
                    if ENV['DEBUG']
         | 
| 43 | 
            +
                    if ENV['DEBUG'] == 'debug'
         | 
| 44 44 | 
             
                      WEBrick::Log::new(STDOUT, WEBrick::BasicLog::DEBUG)
         | 
| 45 | 
            +
                    elsif ENV['DEBUG'] == 'info'
         | 
| 46 | 
            +
                      WEBrick::Log::new(STDOUT, WEBrick::BasicLog::INFO)
         | 
| 45 47 | 
             
                    else
         | 
| 46 48 | 
             
                      WEBrick::Log::new("/dev/null", WEBrick::BasicLog::WARN)
         | 
| 47 49 | 
             
                    end
         | 
| 48 50 | 
             
                  end
         | 
| 49 51 |  | 
| 50 | 
            -
                  def access_logger
         | 
| 51 | 
            -
                    if ENV['DEBUG']
         | 
| 52 | 
            -
                      [
         | 
| 53 | 
            -
                        [ STDOUT, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
         | 
| 54 | 
            -
                        [ STDOUT, WEBrick::AccessLog::REFERER_LOG_FORMAT ]
         | 
| 55 | 
            -
                      ]
         | 
| 56 | 
            -
                    else
         | 
| 57 | 
            -
                      []
         | 
| 58 | 
            -
                    end
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 52 | 
             
                  def bind_address
         | 
| 62 53 | 
             
                    configuration.host
         | 
| 63 54 | 
             
                  end
         | 
| @@ -13,7 +13,17 @@ module RubyHome | |
| 13 13 | 
             
                  end
         | 
| 14 14 |  | 
| 15 15 | 
             
                  def valid_values
         | 
| 16 | 
            -
                    template.constraints. | 
| 16 | 
            +
                    defined_values || range_values || raise(UnknownValueError, "Constraint contains an unrecognized list of values: #{template.constraints.inspect }")
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def defined_values
         | 
| 20 | 
            +
                    template.constraints.dig('ValidValues')
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def range_values
         | 
| 24 | 
            +
                    if min = template.constraints.dig('MinimumValue')
         | 
| 25 | 
            +
                      { min.to_s => min }
         | 
| 26 | 
            +
                    end
         | 
| 17 27 | 
             
                  end
         | 
| 18 28 | 
             
              end
         | 
| 19 29 | 
             
            end
         | 
| @@ -5,10 +5,17 @@ module RubyHome | |
| 5 5 | 
             
                class ApplicationController < Sinatra::Base
         | 
| 6 6 | 
             
                  disable :protection
         | 
| 7 7 |  | 
| 8 | 
            -
                   | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 8 | 
            +
                  logger = Logger.new(STDOUT)
         | 
| 9 | 
            +
                  logger.level = case ENV['DEBUG']
         | 
| 10 | 
            +
                  when 'debug'
         | 
| 11 | 
            +
                    Logger::DEBUG
         | 
| 12 | 
            +
                  when 'info'
         | 
| 13 | 
            +
                    Logger::INFO
         | 
| 14 | 
            +
                  else
         | 
| 15 | 
            +
                    Logger::WARN
         | 
| 11 16 | 
             
                  end
         | 
| 17 | 
            +
                  set :logger, logger
         | 
| 18 | 
            +
                  enable :logging if ENV['DEBUG']
         | 
| 12 19 |  | 
| 13 20 | 
             
                  before do
         | 
| 14 21 | 
             
                    logger.debug "Session"
         | 
| @@ -38,9 +38,9 @@ module RubyHome | |
| 38 38 | 
             
                      device_proof: unpack_request[:proof],
         | 
| 39 39 | 
             
                      srp_session: session.srp_session,
         | 
| 40 40 | 
             
                      public_key: unpack_request[:public_key],
         | 
| 41 | 
            -
                    )
         | 
| 41 | 
            +
                    ).run
         | 
| 42 42 |  | 
| 43 | 
            -
                    if verify_srp. | 
| 43 | 
            +
                    if verify_srp.success?
         | 
| 44 44 | 
             
                      session.session_key = verify_srp.session_key
         | 
| 45 45 | 
             
                      session.srp_session = nil
         | 
| 46 46 |  | 
| @@ -96,7 +96,7 @@ module RubyHome | |
| 96 96 | 
             
                      encrypted_data = chacha20poly1305ietf.encrypt(nonce, subtlv)
         | 
| 97 97 |  | 
| 98 98 | 
             
                      pairing_params = { admin: true, identifier: iosdevicepairingid, public_key: iosdeviceltpk.unpack1('H*') }
         | 
| 99 | 
            -
                      accessory_info.add_paired_client | 
| 99 | 
            +
                      accessory_info.add_paired_client(**pairing_params)
         | 
| 100 100 |  | 
| 101 101 | 
             
                      tlv state: 6, encrypted_data: encrypted_data
         | 
| 102 102 | 
             
                    end
         | 
| @@ -48,18 +48,16 @@ module RubyHome | |
| 48 48 | 
             
                  end
         | 
| 49 49 |  | 
| 50 50 | 
             
                  def verify_finish_response
         | 
| 51 | 
            -
                     | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
                     | 
| 57 | 
            -
             | 
| 58 | 
            -
                    if  | 
| 59 | 
            -
                       | 
| 60 | 
            -
             | 
| 61 | 
            -
                      session.controller_to_accessory_key = shared_secret.controller_to_accessory_key
         | 
| 62 | 
            -
                      session.accessory_to_controller_key = shared_secret.accessory_to_controller_key
         | 
| 51 | 
            +
                    verify_finish = VerifyFinishService.new(
         | 
| 52 | 
            +
                      encrypted_data: unpack_request[:encrypted_data],
         | 
| 53 | 
            +
                      session_key: session.session_key,
         | 
| 54 | 
            +
                      shared_secret: session.shared_secret,
         | 
| 55 | 
            +
                      accessory_info: accessory_info
         | 
| 56 | 
            +
                    ).run
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    if verify_finish.success?
         | 
| 59 | 
            +
                      session.controller_to_accessory_key = verify_finish.controller_to_accessory_key
         | 
| 60 | 
            +
                      session.accessory_to_controller_key = verify_finish.accessory_to_controller_key
         | 
| 63 61 |  | 
| 64 62 | 
             
                      session.session_key = nil
         | 
| 65 63 | 
             
                      session.shared_secret = nil
         | 
| @@ -14,13 +14,13 @@ module RubyHome | |
| 14 14 | 
             
                      'perms' => perms(characteristic),
         | 
| 15 15 | 
             
                      'format' => characteristic.format,
         | 
| 16 16 | 
             
                      'description' => characteristic.description,
         | 
| 17 | 
            -
                    } | 
| 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
         | 
| 23 | 
            -
             | 
| 24 24 | 
             
                    def perms(characteristic)
         | 
| 25 25 | 
             
                      characteristic.properties.map do |property|
         | 
| 26 26 | 
             
                        RubyHome::Characteristic::PROPERTIES[property]
         | 
| @@ -28,10 +28,18 @@ module RubyHome | |
| 28 28 | 
             
                    end
         | 
| 29 29 |  | 
| 30 30 | 
             
                    def value_hash(characteristic)
         | 
| 31 | 
            -
                      if  | 
| 31 | 
            +
                      if characteristic.properties.include?('read')
         | 
| 32 | 
            +
                        { 'value' => characteristic.value }
         | 
| 33 | 
            +
                      else
         | 
| 34 | 
            +
                        {}
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def valid_values_hash(characteristic)
         | 
| 39 | 
            +
                      if characteristic.valid_values.empty?
         | 
| 32 40 | 
             
                        {}
         | 
| 33 41 | 
             
                      else
         | 
| 34 | 
            -
                        { ' | 
| 42 | 
            +
                        { 'valid-values' => characteristic.valid_values }
         | 
| 35 43 | 
             
                      end
         | 
| 36 44 | 
             
                    end
         | 
| 37 45 | 
             
                end
         | 
| @@ -15,7 +15,17 @@ module RubyHome | |
| 15 15 | 
             
                      'characteristics' => CharacteristicSerializer.new(service.characteristics).serializable_hash,
         | 
| 16 16 | 
             
                      'primary' => service.primary,
         | 
| 17 17 | 
             
                      'hidden' => service.hidden,
         | 
| 18 | 
            -
                    }
         | 
| 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
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            module RubyHome
         | 
| 2 | 
            +
              class VerifyFinishService
         | 
| 3 | 
            +
                def initialize(accessory_info: , encrypted_data: , session_key:, shared_secret:)
         | 
| 4 | 
            +
                  @accessory_info = accessory_info
         | 
| 5 | 
            +
                  @encrypted_data = encrypted_data
         | 
| 6 | 
            +
                  @session_key = session_key
         | 
| 7 | 
            +
                  @shared_secret = HAP::Crypto::SessionKey.new(shared_secret)
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def run
         | 
| 11 | 
            +
                  if paired_client_exists?
         | 
| 12 | 
            +
                    RubyHome.dns_service.update
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    OpenStruct.new(
         | 
| 15 | 
            +
                      success?: true,
         | 
| 16 | 
            +
                      controller_to_accessory_key: shared_secret.controller_to_accessory_key,
         | 
| 17 | 
            +
                      accessory_to_controller_key: shared_secret.accessory_to_controller_key
         | 
| 18 | 
            +
                    )
         | 
| 19 | 
            +
                  else
         | 
| 20 | 
            +
                    OpenStruct.new(success?: false)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                private
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  NONCE = -'PV-Msg03'
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  attr_reader :accessory_info, :encrypted_data, :session_key, :shared_secret
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def paired_client_exists?
         | 
| 31 | 
            +
                    accessory_info.paired_clients.any? do |paired_client|
         | 
| 32 | 
            +
                      paired_client[:identifier] == identifier
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def chacha20poly1305
         | 
| 37 | 
            +
                    HAP::Crypto::ChaCha20Poly1305.new(session_key)
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def nonce
         | 
| 41 | 
            +
                    HexHelper.pad(NONCE)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def decrypted_data
         | 
| 45 | 
            +
                    chacha20poly1305.decrypt(nonce, encrypted_data)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def unpacked_decrypted_data
         | 
| 49 | 
            +
                    TLV.decode(decrypted_data)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def identifier
         | 
| 53 | 
            +
                    unpacked_decrypted_data[:identifier]
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
            end
         |