Add television service

Add Television service and required characteristics.
Opening as a draft, as I'm not sure I've done things correctly and need some input.
Closes #98

I went ahead and added the input_source and television_speaker sources and their required characteristics to see if that would help with the out of compliance error I'm getting, but it didn't help.

@karlentwistle Friendly bump in case you missed this over holidays. Would love your feedback so we can get support for televisions merged.

@karlentwistle Friendly bump in case you missed this over holidays. Would love your feedback so we can get support for televisions merged.

Thanks for working on this @johndbritton 🙇 I'm just trying to figure out why it isn't working. I have RubyHome configured like this:
television = RubyHome::ServiceFactory.create(:television,
  active: 0,
  active_identifier: 0,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 0
)

RubyHome.run

In order to investigate further I've removed the authentication requirements from accessories_controller.rb
diff --git a/lib/ruby_home/http/controllers/accessories_controller.rb b/lib/ruby_home/http/controllers/accessories_controller.rb
index 4e08b49..e01f8f8 100644
--- a/lib/ruby_home/http/controllers/accessories_controller.rb
+++ b/lib/ruby_home/http/controllers/accessories_controller.rb
@@ -6,12 +6,12 @@ module RubyHome
       get '/' do
         content_type 'application/hap+json'

-        if session.sufficient_privileges?
+        #if session.sufficient_privileges?
           AccessorySerializer.new(identifier_cache.accessories).serialized_json
-        else
-          status 401
-          JSON.generate({"status" => -70401})
-        end
+        # else
+        #   status 401
+        #   JSON.generate({"status" => -70401})
+        # end
       end
     end
   end

Now I can query http://<IP_ADDRESS>:4567/accessories I can see its returning:

Click to expand
{
  "accessories": [
    {
      "aid": 1,
      "services": [
        {
          "iid": 1,
          "type": "D8",
          "characteristics": [
            {
              "iid": 2,
              "type": "B0",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint8",
              "description": "Active",
              "value": 0
            },
            {
              "iid": 3,
              "type": "E7",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint32",
              "description": "Active Identifier",
              "value": 0
            },
            {
              "iid": 4,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "string",
              "description": "Configured Name",
              "value": "television"
            },
            {
              "iid": 5,
              "type": "E1",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "description": "Remote Key",
              "value": 10
            },
            {
              "iid": 6,
              "type": "E8",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Sleep Discovery Mode",
              "value": 0
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 7,
          "type": "3E",
          "characteristics": [
            {
              "iid": 8,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 9,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 10,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 11,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "RubyHome"
            },
            {
              "iid": 12,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 13,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    }
  ]
}

It looks like we're missing a speaker and an input which I am guessing are required. So I have expanded the script to include
television = RubyHome::ServiceFactory.create(:television,
  active: 0,
  active_identifier: 0,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 0
)

television_speaker = RubyHome::ServiceFactory.create(:television_speaker,
  mute: false
)

input_source = RubyHome::ServiceFactory.create(:input_source,
  configured_name: "HDMI 1",
  input_source_type: 3,
  is_configured: 1,
  name: "HDMI 1",
  current_visibility_state: 1
)

RubyHome.run

Unfortunately this still isn't working. At this point probably the easiest thing to do is compare the output to a known good output. Luckily it was quite easy to get this using https://github.com/brutella/hc/blob/master/_example/tv/main.go. The commands I ran where:
cd ~/go
git clone git@github.com:brutella/hc.git
cd hc/_example/tv
go build main.go
./main

I also simplified their example with
--- a/_example/tv/main.go
+++ b/_example/tv/main.go
@@ -137,16 +137,6 @@ func main() {
        t, err := hc.NewIPTransport(config, acc.Accessory)

        addInputSource(acc, 1, "HDMI 1", characteristic.InputSourceTypeHdmi)
-       addInputSource(acc, 2, "HDMI 2", characteristic.InputSourceTypeHdmi)
-       addInputSource(acc, 3, "Netflix", characteristic.InputSourceTypeApplication)
-       addInputSource(acc, 4, "YouTube", characteristic.InputSourceTypeApplication)
-       addInputSource(acc, 5, "Twitter", characteristic.InputSourceTypeApplication)
-       addInputSource(acc, 6, "Composite Video", characteristic.InputSourceTypeCompositeVideo)
-       addInputSource(acc, 7, "S-Video", characteristic.InputSourceTypeSVideo)
-       addInputSource(acc, 8, "Component Video", characteristic.InputSourceTypeComponentVideo)
-       addInputSource(acc, 9, "Dvi", characteristic.InputSourceTypeDvi)
-       addInputSource(acc, 10, "Airplay", characteristic.InputSourceTypeAirplay)
-       addInputSource(acc, 11, "Usb", characteristic.InputSourceTypeUsb)

        if err != nil {
                log.Info.Panic(err)

I was able to query http://localhost:61788/accessories which returned

Click to expand
{
  "accessories": [
    {
      "aid": 1,
      "services": [
        {
          "iid": 1,
          "type": "3E",
          "characteristics": [
            {
              "iid": 2,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool"
            },
            {
              "iid": 3,
              "type": "20",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            },
            {
              "iid": 4,
              "type": "21",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            },
            {
              "iid": 5,
              "type": "23",
              "perms": [
                "pr"
              ],
              "value": "Television",
              "format": "string"
            },
            {
              "iid": 6,
              "type": "30",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            },
            {
              "iid": 7,
              "type": "52",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            }
          ]
        },
        {
          "iid": 8,
          "type": "D8",
          "characteristics": [
            {
              "iid": 9,
              "type": "B0",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint8"
            },
            {
              "iid": 10,
              "type": "E7",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint32",
              "minValue": 0
            },
            {
              "iid": 11,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": "",
              "format": "string"
            },
            {
              "iid": 12,
              "type": "E8",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 1,
              "format": "uint8",
              "maxValue": 1,
              "minValue": 0
            },
            {
              "iid": 13,
              "type": "8",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "int32",
              "unit": "percentage",
              "maxValue": 100,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 14,
              "type": "DD",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 1,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 15,
              "type": "136",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": "",
              "format": "tlv8"
            },
            {
              "iid": 16,
              "type": "E0",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 1,
              "format": "uint8",
              "unit": "percentage",
              "maxValue": 3,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 17,
              "type": "137",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint8",
              "maxValue": 2,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 18,
              "type": "E2",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "uint16",
              "maxValue": 13,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 19,
              "type": "DF",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "maxValue": 1,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 20,
              "type": "E1",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "maxValue": 16,
              "minValue": 0,
              "minStep": 1
            }
          ],
          "linked": [
            0
          ]
        },
        {
          "iid": 21,
          "type": "113",
          "characteristics": [
            {
              "iid": 22,
              "type": "11A",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": false,
              "format": "bool"
            }
          ]
        },
        {
          "iid": 0,
          "type": "D9",
          "characteristics": [
            {
              "iid": 0,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": "HDMI 1",
              "format": "string"
            },
            {
              "iid": 0,
              "type": "DB",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 3,
              "format": "uint8",
              "maxValue": 10,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "D6",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint8"
            },
            {
              "iid": 0,
              "type": "135",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 3,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "E6",
              "perms": [
                "pr"
              ],
              "value": 1,
              "format": "uint32",
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "DC",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 5,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "134",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 2,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "23",
              "perms": [
                "pr"
              ],
              "value": "HDMI 1",
              "format": "string"
            }
          ]
        }
      ]
    }
  ]
}

Meanwhile RubyHome is returning

Click to expand
{
  "accessories": [
    {
      "aid": 1,
      "services": [
        {
          "iid": 1,
          "type": "D8",
          "characteristics": [
            {
              "iid": 2,
              "type": "B0",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint8",
              "description": "Active",
              "value": 0
            },
            {
              "iid": 3,
              "type": "E7",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint32",
              "description": "Active Identifier",
              "value": 0
            },
            {
              "iid": 4,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "string",
              "description": "Configured Name",
              "value": "television"
            },
            {
              "iid": 5,
              "type": "E1",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "description": "Remote Key",
              "value": 10
            },
            {
              "iid": 6,
              "type": "E8",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Sleep Discovery Mode",
              "value": 0
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 7,
          "type": "3E",
          "characteristics": [
            {
              "iid": 8,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 9,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 10,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 11,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "RubyHome"
            },
            {
              "iid": 12,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 13,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    },
    {
      "aid": 2,
      "services": [
        {
          "iid": 1,
          "type": "113",
          "characteristics": [
            {
              "iid": 2,
              "type": "11A",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "bool",
              "description": "Mute",
              "value": false
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 3,
          "type": "3E",
          "characteristics": [
            {
              "iid": 4,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 5,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 6,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 7,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "RubyHome"
            },
            {
              "iid": 8,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 9,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    },
    {
      "aid": 3,
      "services": [
        {
          "iid": 1,
          "type": "D9",
          "characteristics": [
            {
              "iid": 2,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "string",
              "description": "Configured Name",
              "value": "HDMI 1"
            },
            {
              "iid": 3,
              "type": "DB",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Input Source Type",
              "value": 3
            },
            {
              "iid": 4,
              "type": "D6",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint8",
              "description": "Is Configured",
              "value": 1
            },
            {
              "iid": 5,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "HDMI 1"
            },
            {
              "iid": 6,
              "type": "135",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Current Visibility State",
              "value": 1
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 7,
          "type": "3E",
          "characteristics": [
            {
              "iid": 8,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 9,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 10,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 11,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "HDMI 1"
            },
            {
              "iid": 12,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 13,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    }
  ]
}

There are a few differences
Accessory Information
RubyHome is automatically trying to include accessory information. I'm not sure if this matters or not. However we can stop this happening by using
--- a/lib/ruby_home/factories/service_factory.rb
+++ b/lib/ruby_home/factories/service_factory.rb
@@ -29,10 +29,6 @@ module RubyHome
       create_required_characteristics(service)
       create_optional_characteristics(service)

-      unless accessory_information_factory?
-        create_accessory_information
-      end
-
       service
     end

Services
The known good output has all the services nested under one accessory.

However RubyHome has configured each of the services independently within accessories.

We can make RubyHome do this using
television = RubyHome::ServiceFactory.create(:television,
  active: 1,
  active_identifier: 1,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 1
)

television_speaker = RubyHome::ServiceFactory.create(:television_speaker,
  accessory: television.accessory,
  mute: false
)

input_source = RubyHome::ServiceFactory.create(:input_source,
  accessory: television.accessory,
  configured_name: "HDMI 1",
  input_source_type: 3,
  is_configured: 1,
  name: "HDMI 1",
  current_visibility_state: 1
)

RubyHome.run

Unfortunately this still isn't working. I will investigate some more tomorrow. I'm not 100% sure why its not working at this point 🤔

Thanks for working on this @johndbritton 🙇 I'm just trying to figure out why it isn't working. I have RubyHome configured like this:
television = RubyHome::ServiceFactory.create(:television,
  active: 0,
  active_identifier: 0,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 0
)

RubyHome.run

In order to investigate further I've removed the authentication requirements from accessories_controller.rb
diff --git a/lib/ruby_home/http/controllers/accessories_controller.rb b/lib/ruby_home/http/controllers/accessories_controller.rb
index 4e08b49..e01f8f8 100644
--- a/lib/ruby_home/http/controllers/accessories_controller.rb
+++ b/lib/ruby_home/http/controllers/accessories_controller.rb
@@ -6,12 +6,12 @@ module RubyHome
       get '/' do
         content_type 'application/hap+json'

-        if session.sufficient_privileges?
+        #if session.sufficient_privileges?
           AccessorySerializer.new(identifier_cache.accessories).serialized_json
-        else
-          status 401
-          JSON.generate({"status" => -70401})
-        end
+        # else
+        #   status 401
+        #   JSON.generate({"status" => -70401})
+        # end
       end
     end
   end

Now I can query http://<IP_ADDRESS>:4567/accessories I can see its returning:

Click to expand
{
  "accessories": [
    {
      "aid": 1,
      "services": [
        {
          "iid": 1,
          "type": "D8",
          "characteristics": [
            {
              "iid": 2,
              "type": "B0",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint8",
              "description": "Active",
              "value": 0
            },
            {
              "iid": 3,
              "type": "E7",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint32",
              "description": "Active Identifier",
              "value": 0
            },
            {
              "iid": 4,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "string",
              "description": "Configured Name",
              "value": "television"
            },
            {
              "iid": 5,
              "type": "E1",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "description": "Remote Key",
              "value": 10
            },
            {
              "iid": 6,
              "type": "E8",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Sleep Discovery Mode",
              "value": 0
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 7,
          "type": "3E",
          "characteristics": [
            {
              "iid": 8,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 9,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 10,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 11,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "RubyHome"
            },
            {
              "iid": 12,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 13,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    }
  ]
}

It looks like we're missing a speaker and an input which I am guessing are required. So I have expanded the script to include
television = RubyHome::ServiceFactory.create(:television,
  active: 0,
  active_identifier: 0,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 0
)

television_speaker = RubyHome::ServiceFactory.create(:television_speaker,
  mute: false
)

input_source = RubyHome::ServiceFactory.create(:input_source,
  configured_name: "HDMI 1",
  input_source_type: 3,
  is_configured: 1,
  name: "HDMI 1",
  current_visibility_state: 1
)

RubyHome.run

Unfortunately this still isn't working. At this point probably the easiest thing to do is compare the output to a known good output. Luckily it was quite easy to get this using https://github.com/brutella/hc/blob/master/_example/tv/main.go. The commands I ran where:
cd ~/go
git clone git@github.com:brutella/hc.git
cd hc/_example/tv
go build main.go
./main

I also simplified their example with
--- a/_example/tv/main.go
+++ b/_example/tv/main.go
@@ -137,16 +137,6 @@ func main() {
        t, err := hc.NewIPTransport(config, acc.Accessory)

        addInputSource(acc, 1, "HDMI 1", characteristic.InputSourceTypeHdmi)
-       addInputSource(acc, 2, "HDMI 2", characteristic.InputSourceTypeHdmi)
-       addInputSource(acc, 3, "Netflix", characteristic.InputSourceTypeApplication)
-       addInputSource(acc, 4, "YouTube", characteristic.InputSourceTypeApplication)
-       addInputSource(acc, 5, "Twitter", characteristic.InputSourceTypeApplication)
-       addInputSource(acc, 6, "Composite Video", characteristic.InputSourceTypeCompositeVideo)
-       addInputSource(acc, 7, "S-Video", characteristic.InputSourceTypeSVideo)
-       addInputSource(acc, 8, "Component Video", characteristic.InputSourceTypeComponentVideo)
-       addInputSource(acc, 9, "Dvi", characteristic.InputSourceTypeDvi)
-       addInputSource(acc, 10, "Airplay", characteristic.InputSourceTypeAirplay)
-       addInputSource(acc, 11, "Usb", characteristic.InputSourceTypeUsb)

        if err != nil {
                log.Info.Panic(err)

I was able to query http://localhost:61788/accessories which returned

Click to expand
{
  "accessories": [
    {
      "aid": 1,
      "services": [
        {
          "iid": 1,
          "type": "3E",
          "characteristics": [
            {
              "iid": 2,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool"
            },
            {
              "iid": 3,
              "type": "20",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            },
            {
              "iid": 4,
              "type": "21",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            },
            {
              "iid": 5,
              "type": "23",
              "perms": [
                "pr"
              ],
              "value": "Television",
              "format": "string"
            },
            {
              "iid": 6,
              "type": "30",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            },
            {
              "iid": 7,
              "type": "52",
              "perms": [
                "pr"
              ],
              "value": "undefined",
              "format": "string"
            }
          ]
        },
        {
          "iid": 8,
          "type": "D8",
          "characteristics": [
            {
              "iid": 9,
              "type": "B0",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint8"
            },
            {
              "iid": 10,
              "type": "E7",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint32",
              "minValue": 0
            },
            {
              "iid": 11,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": "",
              "format": "string"
            },
            {
              "iid": 12,
              "type": "E8",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 1,
              "format": "uint8",
              "maxValue": 1,
              "minValue": 0
            },
            {
              "iid": 13,
              "type": "8",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "int32",
              "unit": "percentage",
              "maxValue": 100,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 14,
              "type": "DD",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 1,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 15,
              "type": "136",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": "",
              "format": "tlv8"
            },
            {
              "iid": 16,
              "type": "E0",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 1,
              "format": "uint8",
              "unit": "percentage",
              "maxValue": 3,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 17,
              "type": "137",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint8",
              "maxValue": 2,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 18,
              "type": "E2",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "uint16",
              "maxValue": 13,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 19,
              "type": "DF",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "maxValue": 1,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 20,
              "type": "E1",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "maxValue": 16,
              "minValue": 0,
              "minStep": 1
            }
          ],
          "linked": [
            0
          ]
        },
        {
          "iid": 21,
          "type": "113",
          "characteristics": [
            {
              "iid": 22,
              "type": "11A",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": false,
              "format": "bool"
            }
          ]
        },
        {
          "iid": 0,
          "type": "D9",
          "characteristics": [
            {
              "iid": 0,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": "HDMI 1",
              "format": "string"
            },
            {
              "iid": 0,
              "type": "DB",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 3,
              "format": "uint8",
              "maxValue": 10,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "D6",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 1,
              "format": "uint8"
            },
            {
              "iid": 0,
              "type": "135",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 3,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "E6",
              "perms": [
                "pr"
              ],
              "value": 1,
              "format": "uint32",
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "DC",
              "perms": [
                "pr",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 5,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "134",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "value": 0,
              "format": "uint8",
              "maxValue": 2,
              "minValue": 0,
              "minStep": 1
            },
            {
              "iid": 0,
              "type": "23",
              "perms": [
                "pr"
              ],
              "value": "HDMI 1",
              "format": "string"
            }
          ]
        }
      ]
    }
  ]
}

Meanwhile RubyHome is returning

Click to expand
{
  "accessories": [
    {
      "aid": 1,
      "services": [
        {
          "iid": 1,
          "type": "D8",
          "characteristics": [
            {
              "iid": 2,
              "type": "B0",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint8",
              "description": "Active",
              "value": 0
            },
            {
              "iid": 3,
              "type": "E7",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint32",
              "description": "Active Identifier",
              "value": 0
            },
            {
              "iid": 4,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "string",
              "description": "Configured Name",
              "value": "television"
            },
            {
              "iid": 5,
              "type": "E1",
              "perms": [
                "pw"
              ],
              "format": "uint8",
              "description": "Remote Key",
              "value": 10
            },
            {
              "iid": 6,
              "type": "E8",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Sleep Discovery Mode",
              "value": 0
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 7,
          "type": "3E",
          "characteristics": [
            {
              "iid": 8,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 9,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 10,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 11,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "RubyHome"
            },
            {
              "iid": 12,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 13,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    },
    {
      "aid": 2,
      "services": [
        {
          "iid": 1,
          "type": "113",
          "characteristics": [
            {
              "iid": 2,
              "type": "11A",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "bool",
              "description": "Mute",
              "value": false
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 3,
          "type": "3E",
          "characteristics": [
            {
              "iid": 4,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 5,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 6,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 7,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "RubyHome"
            },
            {
              "iid": 8,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 9,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    },
    {
      "aid": 3,
      "services": [
        {
          "iid": 1,
          "type": "D9",
          "characteristics": [
            {
              "iid": 2,
              "type": "E3",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "string",
              "description": "Configured Name",
              "value": "HDMI 1"
            },
            {
              "iid": 3,
              "type": "DB",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Input Source Type",
              "value": 3
            },
            {
              "iid": 4,
              "type": "D6",
              "perms": [
                "pr",
                "pw",
                "ev"
              ],
              "format": "uint8",
              "description": "Is Configured",
              "value": 1
            },
            {
              "iid": 5,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "HDMI 1"
            },
            {
              "iid": 6,
              "type": "135",
              "perms": [
                "pr",
                "ev"
              ],
              "format": "uint8",
              "description": "Current Visibility State",
              "value": 1
            }
          ],
          "primary": false,
          "hidden": false
        },
        {
          "iid": 7,
          "type": "3E",
          "characteristics": [
            {
              "iid": 8,
              "type": "14",
              "perms": [
                "pw"
              ],
              "format": "bool",
              "description": "Identify"
            },
            {
              "iid": 9,
              "type": "20",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Manufacturer",
              "value": "Default-Manufacturer"
            },
            {
              "iid": 10,
              "type": "21",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Model",
              "value": "Default-Model"
            },
            {
              "iid": 11,
              "type": "23",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Name",
              "value": "HDMI 1"
            },
            {
              "iid": 12,
              "type": "30",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Serial Number",
              "value": "Default-SerialNumber"
            },
            {
              "iid": 13,
              "type": "52",
              "perms": [
                "pr"
              ],
              "format": "string",
              "description": "Firmware Revision",
              "value": "1.0"
            }
          ],
          "primary": false,
          "hidden": false
        }
      ]
    }
  ]
}

There are a few differences
Accessory Information
RubyHome is automatically trying to include accessory information. I'm not sure if this matters or not. However we can stop this happening by using
--- a/lib/ruby_home/factories/service_factory.rb
+++ b/lib/ruby_home/factories/service_factory.rb
@@ -29,10 +29,6 @@ module RubyHome
       create_required_characteristics(service)
       create_optional_characteristics(service)

-      unless accessory_information_factory?
-        create_accessory_information
-      end
-
       service
     end

Services
The known good output has all the services nested under one accessory.

However RubyHome has configured each of the services independently within accessories.

We can make RubyHome do this using
television = RubyHome::ServiceFactory.create(:television,
  active: 1,
  active_identifier: 1,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 1
)

television_speaker = RubyHome::ServiceFactory.create(:television_speaker,
  accessory: television.accessory,
  mute: false
)

input_source = RubyHome::ServiceFactory.create(:input_source,
  accessory: television.accessory,
  configured_name: "HDMI 1",
  input_source_type: 3,
  is_configured: 1,
  name: "HDMI 1",
  current_visibility_state: 1
)

RubyHome.run

Unfortunately this still isn't working. I will investigate some more tomorrow. I'm not 100% sure why its not working at this point 🤔

@johndbritton I think I just figured out part of the problem. I tried to pair with https://github.com/brutella/hc/blob/master/_example/tv/main.go and received

I will see if I can get https://github.com/homebridge/HAP-NodeJS/blob/master/src/accessories/TV_accessory.ts working instead

@johndbritton I think I just figured out part of the problem. I tried to pair with https://github.com/brutella/hc/blob/master/_example/tv/main.go and received

I will see if I can get https://github.com/homebridge/HAP-NodeJS/blob/master/src/accessories/TV_accessory.ts working instead

Ok I managed to get a know good output from https://github.com/homebridge/HAP-NodeJS/blob/master/src/accessories/TV_accessory.ts This time I checked my phone can pair with the accessory as well

Click to expand
{
   "accessories":[
      {
         "aid":1,
         "services":[
            {
               "iid":1,
               "type":"3E",
               "characteristics":[
                  {
                     "iid":2,
                     "type":"14",
                     "perms":[
                        "pw"
                     ],
                     "format":"bool",
                     "description":"Identify"
                  },
                  {
                     "iid":3,
                     "type":"20",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Default-Manufacturer",
                     "description":"Manufacturer"
                  },
                  {
                     "iid":4,
                     "type":"21",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Default-Model",
                     "description":"Model"
                  },
                  {
                     "iid":5,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"TV 8BF9",
                     "description":"Name"
                  },
                  {
                     "iid":6,
                     "type":"30",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Default-SerialNumber",
                     "description":"Serial Number"
                  },
                  {
                     "iid":7,
                     "type":"52",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"0.0.0",
                     "description":"Firmware Revision"
                  }
               ]
            },
            {
               "iid":8,
               "type":"D8",
               "characteristics":[
                  {
                     "iid":9,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Television",
                     "description":"Name"
                  },
                  {
                     "iid":10,
                     "type":"B0",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Active",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":11,
                     "type":"E7",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint32",
                     "value":1,
                     "description":"Active Identifier"
                  },
                  {
                     "iid":12,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"Television",
                     "description":"Configured Name"
                  },
                  {
                     "iid":13,
                     "type":"E1",
                     "perms":[
                        "pw"
                     ],
                     "format":"uint8",
                     "description":"Remote Key",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13,
                        14,
                        15,
                        16
                     ],
                     "maxValue":16,
                     "minValue":0
                  },
                  {
                     "iid":14,
                     "type":"E8",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Sleep Discovery Mode",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":15,
                     "type":"E2",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Picture Mode",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13
                     ],
                     "maxValue":13,
                     "minValue":0
                  },
                  {
                     "iid":16,
                     "type":"DF",
                     "perms":[
                        "pw"
                     ],
                     "format":"uint8",
                     "description":"Power Mode Selection",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  }
               ],
               "linked":[
                  22,
                  29,
                  36
               ]
            },
            {
               "iid":17,
               "type":"113",
               "characteristics":[
                  {
                     "iid":18,
                     "type":"11A",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"bool",
                     "value":false,
                     "description":"Mute"
                  },
                  {
                     "iid":19,
                     "type":"B0",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Active",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":20,
                     "type":"E9",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":3,
                     "description":"Volume Control Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":21,
                     "type":"EA",
                     "perms":[
                        "pw"
                     ],
                     "format":"uint8",
                     "description":"Volume Selector",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  }
               ]
            },
            {
               "iid":22,
               "type":"D9",
               "characteristics":[
                  {
                     "iid":23,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"hdmi1",
                     "description":"Name"
                  },
                  {
                     "iid":24,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"HDMI 1",
                     "description":"Configured Name"
                  },
                  {
                     "iid":25,
                     "type":"DB",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":3,
                     "description":"Input Source Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10
                     ],
                     "maxValue":10,
                     "minValue":0
                  },
                  {
                     "iid":26,
                     "type":"D6",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Is Configured",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":27,
                     "type":"135",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Current Visibility State",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":28,
                     "type":"E6",
                     "perms":[
                        "pr"
                     ],
                     "format":"uint32",
                     "value":1,
                     "description":"Identifier",
                     "minValue":0,
                     "minStep":1
                  }
               ]
            },
            {
               "iid":29,
               "type":"D9",
               "characteristics":[
                  {
                     "iid":30,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"hdmi2",
                     "description":"Name"
                  },
                  {
                     "iid":31,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"HDMI 2",
                     "description":"Configured Name"
                  },
                  {
                     "iid":32,
                     "type":"DB",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":3,
                     "description":"Input Source Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10
                     ],
                     "maxValue":10,
                     "minValue":0
                  },
                  {
                     "iid":33,
                     "type":"D6",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Is Configured",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":34,
                     "type":"135",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Current Visibility State",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":35,
                     "type":"E6",
                     "perms":[
                        "pr"
                     ],
                     "format":"uint32",
                     "value":2,
                     "description":"Identifier",
                     "minValue":0,
                     "minStep":1
                  }
               ]
            },
            {
               "iid":36,
               "type":"D9",
               "characteristics":[
                  {
                     "iid":37,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"netflix",
                     "description":"Name"
                  },
                  {
                     "iid":38,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"Netflix",
                     "description":"Configured Name"
                  },
                  {
                     "iid":39,
                     "type":"DB",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":10,
                     "description":"Input Source Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10
                     ],
                     "maxValue":10,
                     "minValue":0
                  },
                  {
                     "iid":40,
                     "type":"D6",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Is Configured",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":41,
                     "type":"135",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Current Visibility State",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":42,
                     "type":"E6",
                     "perms":[
                        "pr"
                     ],
                     "format":"uint32",
                     "value":3,
                     "description":"Identifier",
                     "minValue":0,
                     "minStep":1
                  }
               ]
            },
            {
               "iid":43,
               "type":"DA",
               "characteristics":[
                  {
                     "iid":44,
                     "type":"E5",
                     "perms":[
                        "ev",
                        "pr",
                        "pw"
                     ],
                     "format":"uint16",
                     "value":0,
                     "description":"Access Control Level",
                     "maxValue":2,
                     "minValue":0,
                     "minStep":1
                  },
                  {
                     "iid":45,
                     "type":"E4",
                     "perms":[
                        "ev",
                        "pr",
                        "pw"
                     ],
                     "format":"tlv8",
                     "value":null,
                     "description":"Password Setting"
                  }
               ]
            },
            {
               "iid":46,
               "type":"A2",
               "characteristics":[
                  {
                     "iid":47,
                     "type":"37",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"1.1.0",
                     "description":"Version"
                  }
               ]
            }
         ]
      }
   ]
}

Ok I managed to get a know good output from https://github.com/homebridge/HAP-NodeJS/blob/master/src/accessories/TV_accessory.ts This time I checked my phone can pair with the accessory as well

Click to expand
{
   "accessories":[
      {
         "aid":1,
         "services":[
            {
               "iid":1,
               "type":"3E",
               "characteristics":[
                  {
                     "iid":2,
                     "type":"14",
                     "perms":[
                        "pw"
                     ],
                     "format":"bool",
                     "description":"Identify"
                  },
                  {
                     "iid":3,
                     "type":"20",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Default-Manufacturer",
                     "description":"Manufacturer"
                  },
                  {
                     "iid":4,
                     "type":"21",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Default-Model",
                     "description":"Model"
                  },
                  {
                     "iid":5,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"TV 8BF9",
                     "description":"Name"
                  },
                  {
                     "iid":6,
                     "type":"30",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Default-SerialNumber",
                     "description":"Serial Number"
                  },
                  {
                     "iid":7,
                     "type":"52",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"0.0.0",
                     "description":"Firmware Revision"
                  }
               ]
            },
            {
               "iid":8,
               "type":"D8",
               "characteristics":[
                  {
                     "iid":9,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"Television",
                     "description":"Name"
                  },
                  {
                     "iid":10,
                     "type":"B0",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Active",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":11,
                     "type":"E7",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint32",
                     "value":1,
                     "description":"Active Identifier"
                  },
                  {
                     "iid":12,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"Television",
                     "description":"Configured Name"
                  },
                  {
                     "iid":13,
                     "type":"E1",
                     "perms":[
                        "pw"
                     ],
                     "format":"uint8",
                     "description":"Remote Key",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13,
                        14,
                        15,
                        16
                     ],
                     "maxValue":16,
                     "minValue":0
                  },
                  {
                     "iid":14,
                     "type":"E8",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Sleep Discovery Mode",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":15,
                     "type":"E2",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Picture Mode",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10,
                        11,
                        12,
                        13
                     ],
                     "maxValue":13,
                     "minValue":0
                  },
                  {
                     "iid":16,
                     "type":"DF",
                     "perms":[
                        "pw"
                     ],
                     "format":"uint8",
                     "description":"Power Mode Selection",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  }
               ],
               "linked":[
                  22,
                  29,
                  36
               ]
            },
            {
               "iid":17,
               "type":"113",
               "characteristics":[
                  {
                     "iid":18,
                     "type":"11A",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"bool",
                     "value":false,
                     "description":"Mute"
                  },
                  {
                     "iid":19,
                     "type":"B0",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Active",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":20,
                     "type":"E9",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":3,
                     "description":"Volume Control Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":21,
                     "type":"EA",
                     "perms":[
                        "pw"
                     ],
                     "format":"uint8",
                     "description":"Volume Selector",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  }
               ]
            },
            {
               "iid":22,
               "type":"D9",
               "characteristics":[
                  {
                     "iid":23,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"hdmi1",
                     "description":"Name"
                  },
                  {
                     "iid":24,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"HDMI 1",
                     "description":"Configured Name"
                  },
                  {
                     "iid":25,
                     "type":"DB",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":3,
                     "description":"Input Source Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10
                     ],
                     "maxValue":10,
                     "minValue":0
                  },
                  {
                     "iid":26,
                     "type":"D6",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Is Configured",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":27,
                     "type":"135",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Current Visibility State",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":28,
                     "type":"E6",
                     "perms":[
                        "pr"
                     ],
                     "format":"uint32",
                     "value":1,
                     "description":"Identifier",
                     "minValue":0,
                     "minStep":1
                  }
               ]
            },
            {
               "iid":29,
               "type":"D9",
               "characteristics":[
                  {
                     "iid":30,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"hdmi2",
                     "description":"Name"
                  },
                  {
                     "iid":31,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"HDMI 2",
                     "description":"Configured Name"
                  },
                  {
                     "iid":32,
                     "type":"DB",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":3,
                     "description":"Input Source Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10
                     ],
                     "maxValue":10,
                     "minValue":0
                  },
                  {
                     "iid":33,
                     "type":"D6",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Is Configured",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":34,
                     "type":"135",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Current Visibility State",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":35,
                     "type":"E6",
                     "perms":[
                        "pr"
                     ],
                     "format":"uint32",
                     "value":2,
                     "description":"Identifier",
                     "minValue":0,
                     "minStep":1
                  }
               ]
            },
            {
               "iid":36,
               "type":"D9",
               "characteristics":[
                  {
                     "iid":37,
                     "type":"23",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"netflix",
                     "description":"Name"
                  },
                  {
                     "iid":38,
                     "type":"E3",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"string",
                     "value":"Netflix",
                     "description":"Configured Name"
                  },
                  {
                     "iid":39,
                     "type":"DB",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":10,
                     "description":"Input Source Type",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3,
                        4,
                        5,
                        6,
                        7,
                        8,
                        9,
                        10
                     ],
                     "maxValue":10,
                     "minValue":0
                  },
                  {
                     "iid":40,
                     "type":"D6",
                     "perms":[
                        "pr",
                        "pw",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":1,
                     "description":"Is Configured",
                     "valid-values":[
                        0,
                        1
                     ],
                     "maxValue":1,
                     "minValue":0
                  },
                  {
                     "iid":41,
                     "type":"135",
                     "perms":[
                        "pr",
                        "ev"
                     ],
                     "format":"uint8",
                     "value":0,
                     "description":"Current Visibility State",
                     "valid-values":[
                        0,
                        1,
                        2,
                        3
                     ],
                     "maxValue":3,
                     "minValue":0
                  },
                  {
                     "iid":42,
                     "type":"E6",
                     "perms":[
                        "pr"
                     ],
                     "format":"uint32",
                     "value":3,
                     "description":"Identifier",
                     "minValue":0,
                     "minStep":1
                  }
               ]
            },
            {
               "iid":43,
               "type":"DA",
               "characteristics":[
                  {
                     "iid":44,
                     "type":"E5",
                     "perms":[
                        "ev",
                        "pr",
                        "pw"
                     ],
                     "format":"uint16",
                     "value":0,
                     "description":"Access Control Level",
                     "maxValue":2,
                     "minValue":0,
                     "minStep":1
                  },
                  {
                     "iid":45,
                     "type":"E4",
                     "perms":[
                        "ev",
                        "pr",
                        "pw"
                     ],
                     "format":"tlv8",
                     "value":null,
                     "description":"Password Setting"
                  }
               ]
            },
            {
               "iid":46,
               "type":"A2",
               "characteristics":[
                  {
                     "iid":47,
                     "type":"37",
                     "perms":[
                        "pr"
                     ],
                     "format":"string",
                     "value":"1.1.0",
                     "description":"Version"
                  }
               ]
            }
         ]
      }
   ]
}

Awesome. Thanks for the updates @karlentwistle.

Awesome. Thanks for the updates @karlentwistle.

When we get this working we should probably add an example to the examples dir in this PR.

When we get this working we should probably add an example to the examples dir in this PR.

@johndbritton after a lot of trial and error I think i've got it working using
television = RubyHome::ServiceFactory.create(:television,
  active: 1,
  active_identifier: 1,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 1
)

RubyHome.run

I had to make this change to the characteristic serializer
--- a/lib/ruby_home/http/serializers/characteristic_serializer.rb
+++ b/lib/ruby_home/http/serializers/characteristic_serializer.rb
@@ -30,6 +30,8 @@ module RubyHome
         def value_hash(characteristic)
           if HIDDEN_VALUE_OBJECTS.include?(characteristic.value_object.class)
             {}
+          elsif characteristic.name == :remote_key
+            {}
           else
             { 'value' => characteristic.value }.compact
           end

It seems that outputting a value within Remote Key / 000000E1-0000-1000-8000-0026BB765291 is invalid
Valid
{
  "iid": 5,
  "type": "E1",
  "perms": [
    "pw"
  ],
  "format": "uint8",
  "description": "Remote Key"
}

Invalid
{
  "iid": 5,
  "type": "E1",
  "perms": [
    "pw"
  ],
  "format": "uint8",
  "description": "Remote Key",
  "value": 10
}

It makes me wonder if this should be the case for all properties that have only the permissions
  :properties:
  - write

and do not include read 🤔 🤔 🤔

Could you let me know if it works for you with the change

When we get this working we should probably add an example to the examples dir in this PR.

Yes, I agree, it would be great to include an example. I think ideally the example would be a TV, with Sound controls and a HDMI input.
It's getting a bit late for me now (I live in Bristol, UK so GMT) but I'll take another look at this tomorrow and see if I can get television_speaker and input_source working. Feel free to poke around yourself if you have any free time to kill 😃

@johndbritton after a lot of trial and error I think i've got it working using
television = RubyHome::ServiceFactory.create(:television,
  active: 1,
  active_identifier: 1,
  configured_name: 'television',
  remote_key: 10,
  sleep_discovery_mode: 1
)

RubyHome.run

I had to make this change to the characteristic serializer
--- a/lib/ruby_home/http/serializers/characteristic_serializer.rb
+++ b/lib/ruby_home/http/serializers/characteristic_serializer.rb
@@ -30,6 +30,8 @@ module RubyHome
         def value_hash(characteristic)
           if HIDDEN_VALUE_OBJECTS.include?(characteristic.value_object.class)
             {}
+          elsif characteristic.name == :remote_key
+            {}
           else
             { 'value' => characteristic.value }.compact
           end

It seems that outputting a value within Remote Key / 000000E1-0000-1000-8000-0026BB765291 is invalid
Valid
{
  "iid": 5,
  "type": "E1",
  "perms": [
    "pw"
  ],
  "format": "uint8",
  "description": "Remote Key"
}

Invalid
{
  "iid": 5,
  "type": "E1",
  "perms": [
    "pw"
  ],
  "format": "uint8",
  "description": "Remote Key",
  "value": 10
}

It makes me wonder if this should be the case for all properties that have only the permissions
  :properties:
  - write

and do not include read 🤔 🤔 🤔

Could you let me know if it works for you with the change

When we get this working we should probably add an example to the examples dir in this PR.

Yes, I agree, it would be great to include an example. I think ideally the example would be a TV, with Sound controls and a HDMI input.
It's getting a bit late for me now (I live in Bristol, UK so GMT) but I'll take another look at this tomorrow and see if I can get television_speaker and input_source working. Feel free to poke around yourself if you have any free time to kill 😃

Will give the update a try with my TV to see if I can get it to work.

Will give the update a try with my TV to see if I can get it to work.

@karlentwistle I just found this PR against this branch from @getowic: https://github.com/johndbritton/ruby_home/pull/1

@karlentwistle I just found this PR against this branch from @getowic: https://github.com/johndbritton/ruby_home/pull/1

@karlentwistle Can confirm that the accessory is working with your change as suggested

--- a/lib/ruby_home/http/serializers/characteristic_serializer.rb
+++ b/lib/ruby_home/http/serializers/characteristic_serializer.rb
@@ -30,6 +30,8 @@ module RubyHome
         def value_hash(characteristic)
           if HIDDEN_VALUE_OBJECTS.include?(characteristic.value_object.class)
             {}
+          elsif characteristic.name == :remote_key
+            {}
           else
             { 'value' => characteristic.value }.compact
           end

I haven't tested configuring inputs and volume yet, but a television does appear without error with just a power switch.

@karlentwistle Can confirm that the accessory is working with your change as suggested

--- a/lib/ruby_home/http/serializers/characteristic_serializer.rb
+++ b/lib/ruby_home/http/serializers/characteristic_serializer.rb
@@ -30,6 +30,8 @@ module RubyHome
         def value_hash(characteristic)
           if HIDDEN_VALUE_OBJECTS.include?(characteristic.value_object.class)
             {}
+          elsif characteristic.name == :remote_key
+            {}
           else
             { 'value' => characteristic.value }.compact
           end

I haven't tested configuring inputs and volume yet, but a television does appear without error with just a power switch.

I can't get any further into this tonight, but I think https://github.com/johndbritton/ruby_home/pull/1 has some useful stuff in there relating to linking devices together.
@karlentwistle Do you want to take a look at that PR and we can cherry-pick in the bits we want here. You should be able to push commits to this branch as the project owner.

I can't get any further into this tonight, but I think https://github.com/johndbritton/ruby_home/pull/1 has some useful stuff in there relating to linking devices together.
@karlentwistle Do you want to take a look at that PR and we can cherry-pick in the bits we want here. You should be able to push commits to this branch as the project owner.

Oh wow I hadn't see that PR from @getowic. That's fantastic! It looks like between yourself and @getowic we've pretty much got this wrapped up! 🥳 🎆 🙇
Just to note the changes @getowic made:

So it seems like they've also found that RubyHome is incorrectly exposing characteristic values which dont contain read link.
They've also added the ability to configure the servers category. I'm not sure this is strictly required but would be a welcome addition.
They've also added the concept of linked characteristics. This isnt something I am that familiar with but I did notice that HAP-NodeJS also contain. Its possibly required if you want to have a speaker and inputs configured with your television.

@karlentwistle Do you want to take a look at that PR and we can cherry-pick in the bits we want here. You should be able to push commits to this branch as the project owner.

Oh I didn't know I had this ability. I added a test commit here https://github.com/karlentwistle/ruby_home/pull/100/commits/a96a0416c5014ff4db12a3c0f54571ce1638fe0e will squish merge this PR when its ready to remove that for the history 😄
Looking forward to playing with all this later on tonight.

Oh wow I hadn't see that PR from @getowic. That's fantastic! It looks like between yourself and @getowic we've pretty much got this wrapped up! 🥳 🎆 🙇
Just to note the changes @getowic made:

So it seems like they've also found that RubyHome is incorrectly exposing characteristic values which dont contain read link.
They've also added the ability to configure the servers category. I'm not sure this is strictly required but would be a welcome addition.
They've also added the concept of linked characteristics. This isnt something I am that familiar with but I did notice that HAP-NodeJS also contain. Its possibly required if you want to have a speaker and inputs configured with your television.

@karlentwistle Do you want to take a look at that PR and we can cherry-pick in the bits we want here. You should be able to push commits to this branch as the project owner.

Oh I didn't know I had this ability. I added a test commit here https://github.com/karlentwistle/ruby_home/pull/100/commits/a96a0416c5014ff4db12a3c0f54571ce1638fe0e will squish merge this PR when its ready to remove that for the history 😄
Looking forward to playing with all this later on tonight.

Oh I didn't know I had this ability.

https://github.blog/2016-09-07-improving-collaboration-with-forks/

Looking forward to playing with all this later on tonight.

Awesome, thanks for your help.

Oh I didn't know I had this ability.

https://github.blog/2016-09-07-improving-collaboration-with-forks/

Looking forward to playing with all this later on tonight.

Awesome, thanks for your help.

@johndbritton I just pushed the cherry-picked changes from https://github.com/johndbritton/ruby_home/pull/1 and a couple of changes that I made. I tested it it a few times on my device and it seems to work nicely 🥳
There is just two remaining issues:

I can't seem to get the speaker to work. Not sure if this is a limitation of the HomeKit application or something else.
I just want to tweak the example a little bit so the puts statements are a bit more human readable.

@johndbritton I just pushed the cherry-picked changes from https://github.com/johndbritton/ruby_home/pull/1 and a couple of changes that I made. I tested it it a few times on my device and it seems to work nicely 🥳
There is just two remaining issues:

I can't seem to get the speaker to work. Not sure if this is a limitation of the HomeKit application or something else.
I just want to tweak the example a little bit so the puts statements are a bit more human readable.

@johndbritton I think this is ready to go. What do you think?

@johndbritton I think this is ready to go. What do you think?

Oh I forgot to mention I still couldn't get the television_speaker working. I tried with https://github.com/homebridge/HAP-NodeJS/blob/master/src/accessories/TV_accessory.ts and it also didn't display any sound inputs so I will put this down to some Home app peculiarities . Don't think this is a blocker.

Oh I forgot to mention I still couldn't get the television_speaker working. I tried with https://github.com/homebridge/HAP-NodeJS/blob/master/src/accessories/TV_accessory.ts and it also didn't display any sound inputs so I will put this down to some Home app peculiarities . Don't think this is a blocker.

the speaker isn't displayed in the home app. a television accessory will be displayed on ios devices in control center additionally as remote control. Inside the remote control you can select the the television. and send remote commands an select the volume with the device volume buttons.

In my setup it works with this configuration:
SPEAKER = RubyHome::ServiceFactory.create(:television_speaker,
  accessory: ACCESSORY,
  name: "Stereoanlage Volume",
  active: 1,
  mute: false,
  volume_control_type: 1,
  volume_selector: 0
)
SPEAKER.volume_selector.valid_values = [0, 1]
SPEAKER.volume_selector.after_update do |value|
  if (value == 0) then
    STDERR.puts "send volume up to entertainment system ..."
    mqtt_publish("entertainment_system/remote", "volume_up")
  else
    STDERR.puts "send volume down to entertainment system ..."
    mqtt_publish("entertainment_system/remote", "volume_down")
  end
end

the speaker isn't displayed in the home app. a television accessory will be displayed on ios devices in control center additionally as remote control. Inside the remote control you can select the the television. and send remote commands an select the volume with the device volume buttons.

In my setup it works with this configuration:
SPEAKER = RubyHome::ServiceFactory.create(:television_speaker,
  accessory: ACCESSORY,
  name: "Stereoanlage Volume",
  active: 1,
  mute: false,
  volume_control_type: 1,
  volume_selector: 0
)
SPEAKER.volume_selector.valid_values = [0, 1]
SPEAKER.volume_selector.after_update do |value|
  if (value == 0) then
    STDERR.puts "send volume up to entertainment system ..."
    mqtt_publish("entertainment_system/remote", "volume_up")
  else
    STDERR.puts "send volume down to entertainment system ..."
    mqtt_publish("entertainment_system/remote", "volume_down")
  end
end

@getowic Oh I see, thanks for sharing that. I had no idea that part of control centre existed. This all makes a lot more sense now 😂 Also I wanted to say a massive thank you for sharing your PR here https://github.com/johndbritton/ruby_home/pull/1 🙇

@getowic Oh I see, thanks for sharing that. I had no idea that part of control centre existed. This all makes a lot more sense now 😂 Also I wanted to say a massive thank you for sharing your PR here https://github.com/johndbritton/ruby_home/pull/1 🙇