Closed niemyjski closed 4 years ago
Hey there @Jc2k, mind taking a look at this issue as its been labeled with a integration (homekit_controller
) you are listed as a codeowner for? Thanks!
Thanks for tagging me @niemyjski
Just a heads up - even if we get pairing to work we don't support the TV accessory type yet, although I can look into if if you want to do some backwards and forwards trying it out for me.
I think the timeout is from one of your other accessories so i'm ignoring that here.
It's normal behaviour for Homekit devices with screens to change the pairing code every time a controller (be it iPhone or Home Assistant) sends the M1 request to the pairing process. The act of showing the "enter pairing code" screen is what triggers the M1 request, so reloading that page or clicking on the form and back onto it will cause the code to change.
Step M3 is when we send a SRP Verify Request to the TV using the pairing code you entered. M4 is the response from the accessory. It should contain a kTLVType_State and either a kTLVType_Proof or a kTLVType_Error. An empty response is not a documented case. So we'll have to reverse engineer what the trigger for that is. It's clearly not an invalid pairing code format, as that is checked on our side before talking to the TV.
The best next step is to try pairing with the underlying library in debug mode. There are some notes on that here. As your device has a screen, don't specify -p
. Then the CLI will prompt you for a code after it has put the TV into pairing mode. Please do specify --log DEBUG
.
I seemed to have one timeout per one of these calls roughly around the same time so I decided to include it. I'd be more than happy to do any testing :), might be this weekend before I can try out the above.
On a separate request, it would be sooo nice if the input box automatically formatted the input to the correct homekit format.
Doesn't look like I was able to run discovery https://github.com/jlusiardi/homekit_python/issues/158
I was able to finally do discovery after they supplied a patch but I don't know what to put for the arguments -f
or -a
. Any ideas?
-f
is a path to a JSON file to store the encryption keys and metadata in. There is a method to initialize it (something like python -m homekit.init_controller_storage
) but TBH i just do echo "{}" > pairing.json
.
-a
is an alias for you to refer to the device by on the CLI. We use the acccessory id (the one that looks like a mac) in home assistant, but you can use mytv
or anything really.
There is a manual "test devices" workflow you can go through to try all the API's - here's an example for a Koogeek device.
I've updated the linked issue.
It seems problems with the tv
device class + HomeKit were first reported in May: #24006.
They are completely different issues affecting different integrations. This ticket is about the homekit_controller integration, the other is about the homekit one. One lets you control devices with the homekit logo (without any Apple phones or tablets involved), the other makes your home assistant look like a homekit accessory to your Apple phones, tablets, etc.
I see. The titles make it sound like they're similar problems. Thanks for pointing me in the right direction!
It doesn't help that https://www.home-assistant.io/components/homekit/ versus https://www.home-assistant.io/components/homekit_controller/ are super confusing too. At least for end users not intimately familiar with Home Assistant — which includes me :)
It'd be better if one were called homekit_producer
and the other homekit_consumer
— that'd leave less room for misinterpretation :)
Agreed, it's a shame neither of us were around when they were added to suggest that! That said, controlller is what Apple officially calls the consumer so I think it could be worse. Renaming would be hard at this point (too many users familiar with old names, and their configs would break if it changed), and we've tried to improve the docs. homekit_controller
calls out the difference in the first paragraph of its docs. homekit
has a callout right after the first paragraph. If you think you can improve the wording to be more noob friendly would definitely love to see a PR for that. But this is getting off topic - feel free to open a seperate ticket if you want to pursue this.
Is there anything else I can do to help out with this issue?
Hey,
I'm having the same issue I think trying to pair an LG C9 too, happy to help if I can. I have homeassistant running on a pi 2, installed manually so it's easy enough to run stuff if needed.
2019-10-03 21:56:39 ERROR (MainThread) [homeassistant.components.homekit_controller.config_flow] Pairing attempt failed with an unhandled exception
Traceback (most recent call last):
File "/home/homeassistant/lib/python3.7/site-packages/homeassistant/components/homekit_controller/config_flow.py", line 247, in async_step_pair
await self.hass.async_add_executor_job(self.finish_pairing, code)
File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/homeassistant/lib/python3.7/site-packages/homekit/controller/controller.py", line 391, in finish_pairing
pairing = perform_pair_setup_part2(pin, str(uuid.uuid4()), write_fun, salt, pub_key)
File "/home/homeassistant/lib/python3.7/site-packages/homekit/protocol/__init__.py", line 173, in perform_pair_setup_part2
assert response_tlv[0][0] == TLV.kTLVType_State and response_tlv[0][1] == TLV.M4, \
IndexError: list index out of range
For anyone following this issue - the current thinking is that our homekit library currently only supports pairing devices with hardware crypto chips provided by Apple. In the case of LG TV's that got HomeKit as a software update this seems to be clearly the case - and indeed pairing fails.
There is another pairing mode we can use, and it only needs a single line code change to test it out. Indeed it's a single character change. As we understand it it just disables "attestation" during the pairing key exchange but is still otherwise secure. You can try editing homekit/protocol/tlv.py in your virtualenv packages directory. There should be a line that looks like this:
PairSetup = bytearray(b'\x01')
Change the \x01 to \x00 and try and pair.
This fixes things for some devices. What we don't know with any certainty yet is when to send a \x00
and when to sent \x01
. It seems to be tied to the ff
data published in zeroconf. So far none of the problematic devices seem to have set ff
to \x01
or \x02
. There isn't much documentation around this for us to work off, though.
That did the trick for pairing. I have a device now in HA however there are no entities.
@dmulcahey cheers - can you post the output of python -m homekit.discover
from your HA env? Especially the ff
value.
That's what i'd expected btw - theres absolutely no mapping from HK to HA for the TV type yet - priority has been events for a while, and is now stateless button devices. Posting your config/.storage/homekit_controller-entity-map
for the TV might help get TV support added though.
@dmulcahey cheers - can you post the output of
python -m homekit.discover
from your HA env? Especially theff
value.
do I have to run this from my prod env? Just ran it on my dev machine and got a key error:
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/discover.py", line 51, in <module>
results = Controller.discover(args.timeout)
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/controller/controller.py", line 90, in discover
return discover_homekit_devices(max_seconds)
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/zeroconf_impl/__init__.py", line 102, in discover_homekit_devices
info.properties
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/zeroconf_impl/__init__.py", line 180, in parse_discovery_properties
d['category'] = Categories[int(category)]
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/model/categories.py", line 94, in __getitem__
raise KeyError('Item {item} not found'.format(item=item))
KeyError: 'Item 31 not found'
Here is the entity map stuff:
"EF:6E:6F:39:A2:32": {
"accessories": [
{
"aid": 1,
"services": [
{
"characteristics": [
{
"format": "bool",
"iid": 2,
"perms": [
"pw"
],
"type": "00000014-0000-1000-8000-0026BB765291"
},
{
"ev": false,
"format": "string",
"iid": 3,
"perms": [
"pr"
],
"type": "00000020-0000-1000-8000-0026BB765291",
"value": "LG Electronics"
},
{
"ev": false,
"format": "string",
"iid": 4,
"perms": [
"pr"
],
"type": "00000021-0000-1000-8000-0026BB765291",
"value": "OLED55B9PUA"
},
{
"ev": false,
"format": "string",
"iid": 5,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "LG webOS TV AF80"
},
{
"ev": false,
"format": "string",
"iid": 6,
"perms": [
"pr"
],
"type": "00000030-0000-1000-8000-0026BB765291",
"value": "907RMWVAW961"
},
{
"ev": false,
"format": "string",
"iid": 7,
"perms": [
"pr"
],
"type": "00000052-0000-1000-8000-0026BB765291",
"value": "04.71.04"
},
{
"ev": false,
"format": "string",
"iid": 8,
"perms": [
"pr"
],
"type": "00000053-0000-1000-8000-0026BB765291",
"value": "1"
},
{
"ev": false,
"format": "string",
"iid": 9,
"perms": [
"pr",
"hd"
],
"type": "34AB8811-AC7F-4340-BAC3-FD6A85F9943B",
"value": "2.1;16B62a"
}
],
"hidden": false,
"iid": 1,
"linked": [],
"primary": false,
"stype": "accessory-information",
"type": "0000003E-0000-1000-8000-0026BB765291"
},
{
"characteristics": [
{
"ev": false,
"format": "string",
"iid": 18,
"perms": [
"pr"
],
"type": "00000037-0000-1000-8000-0026BB765291",
"value": "1.1.0"
}
],
"hidden": false,
"iid": 16,
"linked": [],
"primary": false,
"stype": "service",
"type": "000000A2-0000-1000-8000-0026BB765291"
},
{
"characteristics": [
{
"ev": false,
"format": "string",
"iid": 50,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "LG webOS TV"
},
{
"ev": false,
"format": "string",
"iid": 51,
"maxLen": 25,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E3",
"value": "LG webOS TV OLED55B9PUA"
},
{
"ev": false,
"format": "uint8",
"iid": 52,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"pw",
"ev"
],
"type": "000000B0-0000-1000-8000-0026BB765291",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 53,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E7",
"value": 6
},
{
"ev": false,
"format": "uint8",
"iid": 54,
"maxValue": 2,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "E8",
"value": 1
},
{
"format": "uint8",
"iid": 57,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pw"
],
"type": "DF"
},
{
"format": "uint8",
"iid": 59,
"maxValue": 16,
"minStep": 1,
"minValue": 0,
"perms": [
"pw"
],
"type": "E1"
}
],
"hidden": false,
"iid": 48,
"linked": [
64,
80,
384,
256,
272,
288,
304,
320,
336,
352
],
"primary": true,
"stype": "Unknown Service: D8",
"type": "D8"
},
{
"characteristics": [
{
"ev": false,
"format": "uint16",
"iid": 66,
"maxValue": 2,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E5",
"value": 0
},
{
"ev": false,
"format": "tlv8",
"iid": 67,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E4",
"value": "AQACAQA="
}
],
"hidden": false,
"iid": 64,
"linked": [],
"primary": false,
"stype": "Unknown Service: DA",
"type": "DA"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 84,
"maxValue": 100,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"pw",
"ev"
],
"type": "00000119-0000-1000-8000-0026BB765291",
"unit": "percentage",
"value": 0
},
{
"ev": false,
"format": "bool",
"iid": 82,
"perms": [
"pr",
"pw",
"ev"
],
"type": "0000011A-0000-1000-8000-0026BB765291",
"value": 0
},
{
"ev": false,
"format": "string",
"iid": 83,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "Speaker"
},
{
"ev": false,
"format": "uint8",
"iid": 85,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"pw",
"ev"
],
"type": "000000B0-0000-1000-8000-0026BB765291",
"value": 1
},
{
"ev": false,
"format": "uint8",
"iid": 86,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "E9",
"value": 2
},
{
"format": "uint8",
"iid": 87,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pw"
],
"type": "EA"
}
],
"hidden": false,
"iid": 80,
"linked": [],
"primary": false,
"stype": "speaker",
"type": "00000113-0000-1000-8000-0026BB765291"
},
{
"characteristics": [
{
"ev": false,
"format": "tlv8",
"iid": 385,
"perms": [
"pr"
],
"type": "222",
"value": "AQgBBnRAvoQmJQIaAQYgF0KJBUICBiAXQokFQgAAAgZ0QL6EJiQ="
}
],
"hidden": false,
"iid": 384,
"linked": [],
"primary": false,
"stype": "Unknown Service: 221",
"type": "221"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 258,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 8
},
{
"ev": false,
"format": "uint8",
"iid": 259,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 260,
"perms": [
"pr"
],
"type": "E6",
"value": 1
},
{
"ev": false,
"format": "string",
"iid": 261,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "AirPlay"
},
{
"ev": false,
"format": "string",
"iid": 262,
"maxLen": 25,
"perms": [
"pr",
"ev"
],
"type": "E3",
"value": "AirPlay"
},
{
"ev": false,
"format": "uint8",
"iid": 264,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 0
},
{
"ev": false,
"format": "uint8",
"iid": 263,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 3
}
],
"hidden": false,
"iid": 256,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 274,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 2
},
{
"ev": false,
"format": "uint8",
"iid": 275,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 276,
"perms": [
"pr"
],
"type": "E6",
"value": 2
},
{
"ev": false,
"format": "string",
"iid": 277,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "Live TV"
},
{
"ev": false,
"format": "string",
"iid": 278,
"maxLen": 25,
"perms": [
"pr",
"ev"
],
"type": "E3",
"value": "Live TV"
},
{
"ev": false,
"format": "uint8",
"iid": 280,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 3
},
{
"ev": false,
"format": "uint8",
"iid": 279,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 3
}
],
"hidden": false,
"iid": 272,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 290,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 3
},
{
"ev": false,
"format": "uint8",
"iid": 291,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 292,
"perms": [
"pr"
],
"type": "E6",
"value": 3
},
{
"ev": false,
"format": "string",
"iid": 293,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "HDMI 1"
},
{
"ev": false,
"format": "string",
"iid": 294,
"maxLen": 25,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E3",
"value": "HDMI 1"
},
{
"ev": false,
"format": "uint8",
"iid": 296,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 4
},
{
"ev": false,
"format": "uint8",
"iid": 295,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 1
}
],
"hidden": false,
"iid": 288,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 306,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 3
},
{
"ev": false,
"format": "uint8",
"iid": 307,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 308,
"perms": [
"pr"
],
"type": "E6",
"value": 4
},
{
"ev": false,
"format": "string",
"iid": 309,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "HDMI 2"
},
{
"ev": false,
"format": "string",
"iid": 310,
"maxLen": 25,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E3",
"value": "Sony"
},
{
"ev": false,
"format": "uint8",
"iid": 312,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 4
},
{
"ev": false,
"format": "uint8",
"iid": 311,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 2
}
],
"hidden": false,
"iid": 304,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 322,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 3
},
{
"ev": false,
"format": "uint8",
"iid": 323,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 324,
"perms": [
"pr"
],
"type": "E6",
"value": 5
},
{
"ev": false,
"format": "string",
"iid": 325,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "HDMI 3"
},
{
"ev": false,
"format": "string",
"iid": 326,
"maxLen": 25,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E3",
"value": "Apple"
},
{
"ev": false,
"format": "uint8",
"iid": 328,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 4
},
{
"ev": false,
"format": "uint8",
"iid": 327,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 2
}
],
"hidden": false,
"iid": 320,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 338,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 4
},
{
"ev": false,
"format": "uint8",
"iid": 339,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 340,
"perms": [
"pr"
],
"type": "E6",
"value": 7
},
{
"ev": false,
"format": "string",
"iid": 341,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "AV"
},
{
"ev": false,
"format": "string",
"iid": 342,
"maxLen": 25,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E3",
"value": "AV"
},
{
"ev": false,
"format": "uint8",
"iid": 344,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 2
},
{
"ev": false,
"format": "uint8",
"iid": 343,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 1
}
],
"hidden": false,
"iid": 336,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
},
{
"characteristics": [
{
"ev": false,
"format": "uint8",
"iid": 354,
"maxValue": 10,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DB",
"value": 3
},
{
"ev": false,
"format": "uint8",
"iid": 355,
"maxValue": 1,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "D6",
"value": 1
},
{
"ev": false,
"format": "uint32",
"iid": 356,
"perms": [
"pr"
],
"type": "E6",
"value": 6
},
{
"ev": false,
"format": "string",
"iid": 357,
"perms": [
"pr"
],
"type": "00000023-0000-1000-8000-0026BB765291",
"value": "HDMI 4"
},
{
"ev": false,
"format": "string",
"iid": 358,
"maxLen": 25,
"perms": [
"pr",
"pw",
"ev"
],
"type": "E3",
"value": "HDMI 4"
},
{
"ev": false,
"format": "uint8",
"iid": 360,
"maxValue": 6,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "DC",
"value": 4
},
{
"ev": false,
"format": "uint8",
"iid": 359,
"maxValue": 3,
"minStep": 1,
"minValue": 0,
"perms": [
"pr",
"ev"
],
"type": "135",
"value": 2
}
],
"hidden": false,
"iid": 352,
"linked": [],
"primary": false,
"stype": "Unknown Service: D9",
"type": "D9"
}
]
}
],
"config_num": 1
}
Ah its a TV, and the current release of the homekit library doesn't know that key 31 is a TV. As a safe and quick work around maybe something like editing /Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/model/categories.py
. Instead of the raise on line 94, make it return something - maybe just "unknown"
.
If i cobble together a basic PR to for TV support would you be able to test it easily?
Hey,
I can test TV stuff if needed, happy to help
On Sun 1 Mar 2020, 19:22 Jc2k, notifications@github.com wrote:
Ah its a TV, and the current release of the homekit library doesn't know that key 31 is a TV. As a safe and quick work around maybe something like editing /Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/model/categories.py. Instead of the raise on line 94, make it return something - maybe just "unknown".
If i cobble together a basic PR to for TV support would you be able to test it easily?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/home-assistant/home-assistant/issues/25960?email_source=notifications&email_token=AAGVHT22J3KO35Y3Q3GF6CDRFKYVZA5CNFSM4IL44QA2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENNIHRA#issuecomment-593134532, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGVHT6MGYR7FKXCFITQFIDRFKYVZANCNFSM4IL44QAQ .
Hey @Ulrar - thanks for offering. I'm specifically looking for someone with a home-assistant dev environment (or experience running one) - how does that sound?
I have a regular home assistant, but manually installed, no docker or anything so I can pull specific branches to test them out. I can setup another instance just for the tests though, might be easier
On Sun 1 Mar 2020, 19:40 Jc2k, notifications@github.com wrote:
Hey @Ulrar https://github.com/Ulrar - thanks for offering. I'm specifically looking for someone with a home-assistant dev environment (or experience running one) - how does that sound?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/home-assistant/home-assistant/issues/25960?email_source=notifications&email_token=AAGVHT3N5MJOQ6XTJP4QPI3RFK22VA5CNFSM4IL44QA2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENNIW2A#issuecomment-593136488, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGVHT2VINLOBNEGJIZ3VP3RFK22VANCNFSM4IL44QAQ .
Ah its a TV, and the current release of the homekit library doesn't know that key 31 is a TV. As a safe and quick work around maybe something like editing
/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/homekit/model/categories.py
. Instead of the raise on line 94, make it return something - maybe just"unknown"
.If i cobble together a basic PR to for TV support would you be able to test it easily?
Yep, I run dev constantly with a venv
OK - first PR is up. Just to prove it works, should create a media_player
for the TV that supports play
, pause
and stop
. LG TV's don't seem to support the TargetMediaState
characteristic so they have to send a play/pause remote button (its a single event for both), and theres no explicit stop either.
So if you can verify that with this PR you can see your TV appear in HA, that you can see its current state (playing/paused/idle) and that you can play/pause.
This is off dev
so i'm hoping the current state should update immediately when you start playing something on the TV or pause it again. If it doesn't update immediately wait for a full minute and see if it enters the correct state. (It will use events if they are available, but fall back to polling).
Supporting channel switching and volume control should be do-able, but are much more complicated that unusual as they involve "linked services". Up till now there has been a 1-entity-1-service relationship, and this assumption will need a bit of re-factoring around.
So, I get the media player entity. None of the buttons do anything and I don't see much in the logs.
I get events: <Event call_service[L]: domain=media_player, service=turn_off, service_data=entity_id=media_player.lg_webos_tv_af80>
when I press buttons in the UI in HA but nothing happens.
powering off the TV I see this in the logs:
2020-03-02 19:46:58 INFO (MainThread) [aiohomekit.controller.ip.connection] Connection HomeKitConnection(host='192.168.1.5', port=37113) lost.
I don't notice anything in the logs after I power the set back on and play calls after that fail with:
2020-03-02 19:49:08 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection.4383849832]
Traceback (most recent call last):
File "/Users/davidmulcahey/development/home-assistant/homeassistant/components/websocket_api/commands.py", line 134, in handle_call_service
connection.context(msg),
File "/Users/davidmulcahey/development/home-assistant/homeassistant/core.py", line 1234, in async_call
await asyncio.shield(self._execute_service(handler, service_call))
concurrent.futures._base.CancelledError
Let me know what I can do to help here.
@dmulcahey Cheers. Lot to think about here.
The power button - i'm surprised it appears in the UI, its definitely not wired up to anything. What other buttons were there apart from play?
In terms of debugging why the state is Unknown
can we first check the state in the backend Dev / States and make sure i'm not just setting a state the UI doesn't recognise? Then if that checks out can you add some logging here:
This is called once a minute and will have the raw data from the poll request, including errors. We can verify that all the characteristics i expect are being polled and that the poll is working.
The other thing to look for is the log message:
Starting HomeKit controller update
and a corresponding "Finished". These will only be visible at debug level, though.
I'm sure i'm wrong but also I'm hoping that the play and pause events are "working" but that they just don't do anything on the screen of the TV you were on. The best way to test this is to add some logging here:
If results
is empty then that means the TV accepted the command. If it's not then there should be an error code that might give us a clue. Adding some logging either side to make sure the call happens and returns might be good.
That you see a Connection lost message is promising - i think you would have seen that sooner if the connection was so badly broken that the TV dropped it. So whatever is happening is a layer up. But it does look like I need to test error recovery a bit better. I have only been testing what happens when a device is missing at start up time. How long was the TV off for? How long did you wait after powering it on to press play? (Even if it's not this case, it's made me think that the re-connect has an exponential back off but is capped at a minute, so i guess if you turned on the TV and the re-connect hadn't yet reconnected then we'd see some weird unhandled error).
https://github.com/home-assistant/core/compare/dev...Jc2k:homekit_controller_channels has a crude pass at channel switching. Testing against HAP-NodeJS atm and can see the 3 input sources that test accessory has (and switch between them).
Code is a bit janky, need to do some refactoring to better support "linked services" before i can submit a PR for this one.
@dmulcahey Cheers. Lot to think about here.
The power button - i'm surprised it appears in the UI, its definitely not wired up to anything. What other buttons were there apart from play?
Here are the logs from pairing. It appears to lose its connection immediately:
2020-03-05 20:07:00 INFO (MainThread) [homeassistant.components.media_player] Setting up media_player.homekit_controller
2020-03-05 20:07:00 INFO (MainThread) [homeassistant.helpers.entity_registry] Registered new media_player.homekit_controller entity: media_player.lg_webos_tv_af80
2020-03-05 20:07:00 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event entity_registry_updated[L]: action=create, entity_id=media_player.lg_webos_tv_af80>
2020-03-05 20:07:00 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: entity_id=media_player.lg_webos_tv_af80, old_state=None, new_state=<state media_player.lg_webos_tv_af80=unknown; friendly_name=LG webOS TV AF80, supported_features=16385, device_class=tv @ 2020-03-05T20:07:00.383136-05:00>>
2020-03-05 20:07:00 INFO (MainThread) [aiohomekit.controller.ip.connection] Connection HomeKitConnection(host='192.168.1.5', port=43554) lost.
In terms of debugging why the state is
Unknown
can we first check the state in the backend Dev / States and make sure i'm not just setting a state the UI doesn't recognise?
Then if that checks out can you add some logging here:
This is called once a minute and will have the raw data from the poll request, including errors. We can verify that all the characteristics i expect are being polled and that the poll is working.
The other thing to look for is the log message:
Starting HomeKit controller update
and a corresponding "Finished". These will only be visible at debug level, though.
I added logging there as well. It doesn't log and the log lines you reference aren't there either. Assuming this is related to the lost connection referenced above?
I'm sure i'm wrong but also I'm hoping that the play and pause events are "working" but that they just don't do anything on the screen of the TV you were on. The best way to test this is to add some logging here:
If
results
is empty then that means the TV accepted the command. If it's not then there should be an error code that might give us a clue. Adding some logging either side to make sure the call happens and returns might be good.
2020-03-05 20:12:37 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=media_player, service=media_play_pause, service_data=entity_id=media_player.lg_webos_tv_af80>
2020-03-05 20:12:37 WARNING (MainThread) [homeassistant.components.homekit_controller.connection] Results with pairing lock: {}
That you see a Connection lost message is promising - i think you would have seen that sooner if the connection was so badly broken that the TV dropped it. So whatever is happening is a layer up. But it does look like I need to test error recovery a bit better. I have only been testing what happens when a device is missing at start up time. How long was the TV off for? How long did you wait after powering it on to press play? (Even if it's not this case, it's made me think that the re-connect has an exponential back off but is capped at a minute, so i guess if you turned on the TV and the re-connect hadn't yet reconnected then we'd see some weird unhandled error).
When I first turn off the tv:
2020-03-05 20:18:55 INFO (MainThread) [aiohomekit.controller.ip.connection] Connection HomeKitConnection(host='192.168.1.5', port=43554) lost.
2020-03-05 20:18:55 INFO (MainThread) [aiohomekit.controller.ip.connection] Connection HomeKitConnection(host='192.168.1.5', port=43554) lost.
This is weird as I don't see anything related to a new connection being established after the original connection lost message above. Is HCK connecting a bunch of times to the TV?
I waited about 5 minutes after turning the TV back on and I don't see anything about a new connection to the TV being established in the logs and now the play button does this:
2020-03-05 20:25:35 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection.4383805000]
Traceback (most recent call last):
File "/Users/davidmulcahey/development/home-assistant/homeassistant/components/websocket_api/commands.py", line 134, in handle_call_service
connection.context(msg),
File "/Users/davidmulcahey/development/home-assistant/homeassistant/core.py", line 1234, in async_call
await asyncio.shield(self._execute_service(handler, service_call))
concurrent.futures._base.CancelledError
Let me know what else I can do to help.
EDIT:
Interesting... when shutting down my dev environment I got these (I had to force kill the env):
2020-03-05 20:33:25 ERROR (MainThread) [aiohomekit.controller.ip.connection] Unhandled error from reconnecter.
Traceback (most recent call last):
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/aiohomekit/controller/ip/connection.py", line 212, in done_callback
result.result()
concurrent.futures._base.CancelledError
2020-03-05 20:33:25 ERROR (MainThread) [aiohomekit.controller.ip.connection] Unhandled error from reconnecter.
Traceback (most recent call last):
File "/Users/davidmulcahey/development/home-assistant/lib/python3.7/site-packages/aiohomekit/controller/ip/connection.py", line 212, in done_callback
result.result()
concurrent.futures._base.CancelledError
maybe something is screwy in the "reconnecter"?
Here are the logs from pairing. It appears to lose its connection immediately:
Losing connection after pairing is normal. It closes an insecure channel and then opens a secure one. What is a bit screwy here though is that the logging is asymmetric - i'm not logging new connections at all.
I added logging there as well. It doesn't log and the log lines you reference aren't there either. Assuming this is related to the lost connection referenced above?
I'm unsure about this. Later on we see seemingl see the put call succeed. Let's come back to this. Oh, maybe if you wait for the 2nd poll you'll see something?
2020-03-05 20:12:37 DEBUG (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=media_player, service=media_play_pause, service_data=entity_id=media_player.lg_webos_tv_af80> 2020-03-05 20:12:37 WARNING (MainThread) [homeassistant.components.homekit_controller.connection] Results with pairing lock: {}
Empty {}
is from the TV itself and means it accepts the payload. aiohomekit
will return {}
itself if it sees a 204 from the request, otherwise it will return the json paylaod as is. So what happens if e.g. you play a movie and then hit the play/pause button in Home Assistant?
Reconnection is definitely screwy and have been able to recreate most of what you are seeing. Right now i suggest restarting HA before performing any tests, i'll figure out whats going on over here and then push a PR.
I managed to do the refactoring i wanted so the PR with channel switching support should go up today (need to finish the tests) then we can test with that.
Cool. I see the PR. Are you on discord at all?
I'm going to close this now, all the code should be queued up to go into 0.107.0 @dmulcahey has an LG TV paired and can switch input sources. Play/pause also works (but it is context sensitive). The LG implementation doesn't report much state (like playing vs paused etc). Volume support will be added later.
Hi,
I can confirm, with 107 I can play/pause (at least in the apps I tried), change source (only HDMI, live TV and airplay, it's not showing apps like Netflix) and other services seem to either do nothing or complain about a missing key. The media player card has the name of the TV and that's it, no info about what is playing or any status.
Still, great start, thanks for the work !
On Wed 11 Mar 2020, 21:14 Jc2k, notifications@github.com wrote:
Closed #25960 https://github.com/home-assistant/core/issues/25960.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/home-assistant/core/issues/25960#event-3120573455, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGVHT242KZPFUDGNIPMPATRG75LPANCNFSM4IL44QAQ .
Thanks! Unfortunately we probably won't get to see more than that from what I can see. The "current state" characteristic is limited to "playing", "paused" and "stopped" and not every manufacturer implements it :-(
I hope to come back and expose the other remote buttons at some point, and volume control.
Home Assistant release with the issue: 0.97.2
Operating environment (Hass.io/Docker/Windows/etc.): hassio stable x64
Component/platform: homekit_controller
Description of problem: My tv got the update for homekit support last week and I decided to finally try adding it to homekit but it fails to set up which then the tv generates a completely new pairing code. I finally got time to try and add it and keep the logs open.
Traceback (if applicable):
Additional information: cc @Jc2k