home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
70.16k stars 29.19k forks source link

Unable to connect Tado bridge as HomeKit climate device #16971

Closed luukdobber closed 5 years ago

luukdobber commented 5 years ago

Home Assistant release with the issue: 0.79.0

Last working Home Assistant release (if known):

Operating environment (Hass.io/Docker/Windows/etc.): Hass.io

Component/platform: https://www.home-assistant.io/components/climate.homekit_controller/

Description of problem: I am trying to add my Tado bridge to Home Assistant using the homekit_controller component. This would allow me to have offline control for my heating instead of using the tado API. Home Assistant throws an error when I try to pair the bridge in the UI. This is what I did:

  1. Reset HomeKit on the tado bridge so it's not connected to my iPad anymore. The devices disappeared from the Home app, so this seems to have worked.
  2. Add HomeKit discovery to my configuration.yaml and restart HA.
  3. Click "configure" on the "tado Internet Bridge" item in the UI.
  4. Enter the HomeKit code from the sticker on the bridge and click submit.

After a while the dialog closes end the stacktrace mentioned below appeared in the logs.

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):

discovery:
  enable:
    - homekit

Traceback (if applicable):

Error executing service <ServiceCall configurator.configure (c:53514ee038d142deafe498967e874b70): configure_id=1825889744-2, fields=code=<<HomeKit code from sticker on device>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 1177, in _event_to_service_call
    await service_handler.func(service_call)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/configurator.py", line 224, in async_handle_service_call
    call.data.get(ATTR_FIELDS, {}))
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/homekit_controller/__init__.py", line 146, in device_config_callback
    pairing_id)
  File "/usr/local/lib/python3.6/site-packages/homekit/protocol.py", line 69, in perform_pair_setup
    connection.request('POST', '/pair-setup', request_tlv, headers)
  File "/usr/local/lib/python3.6/http/client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/lib/python3.6/http/client.py", line 1250, in _send_request
    self.putrequest(method, url, **skips)
  File "/usr/local/lib/python3.6/http/client.py", line 1108, in putrequest
    raise CannotSendRequest(self.__state)
http.client.CannotSendRequest: Request-sent

Additional information:

wmalgadey commented 5 years ago

I don't know how this is related to the tado component? Does a component have to have some special behaviors to support homekit?

luukdobber commented 5 years ago

It's indeed not related to the tado component. I was trying to add my homekit compatable tado thermostat using the homekit protocol. That would allow offline control of the thermostat, instead of depending on tado's web API.

Fogh commented 5 years ago

I'm seeing the same problem. Entering HomeKit code does nothing image

wmalgadey commented 5 years ago

again homekit has nothing to do with tado!

luukdobber commented 5 years ago

As I tried to explain in my previous comment: this issue is indeed not about the tado component. It is about using the homekit_controller component to control a HomeKit compatible thermostat (that happens to be a tado) using the HomeKit protocol.

Maybe someone could remove the tado_component and climate.tado labels to make this clear 🙂

Fogh commented 5 years ago

Tado has HomeKit support if you are using the new bridge. So I guess it is being discovered by discovery when having HomeKit enabled

wmalgadey commented 5 years ago

Ahhhh now I understand the problem :)

@cgarwood the label of this issue should be platform: climate.homekit and component: homekit. We can't solve any problem here with the tado component, afaik!

cf00 commented 5 years ago

I am having the same issue. "tado Internet Bridge" is discovered as homekit device, but entering the HomeKit code does nothing. There is no error message in the UI or in the logs, but when I enable debug logging, the following appears in the log:

`2019-03-25 09:29:22 DEBUG (SyncWorker_12) [root] #1 ios -> accessory: send SRP start request

2019-03-25 09:29:22 DEBUG (SyncWorker_12) [homekit.protocol.tlv] sending [ 6: (1 bytes) 0x01 0: (1 bytes) 0x01 ] 2019-03-25 09:29:22 DEBUG (SyncWorker_12) [homekit.protocol.tlv] receiving [ 6: (1 bytes) 0x01 0: (1 bytes) 0x01 ] 2019-03-25 09:29:22 DEBUG (SyncWorker_12) [root] write message: [ 6: (1 bytes) 0x01 0: (1 bytes) 0x01 ]`

jimz011 commented 5 years ago

Having this problem as well, I need the homekit discovery for some devices. But there is no way to ignore or setup this tado bridge one.

Very annoying as the persistant notification is very very persistant now. Any way to either configure it or just to ignore this device entirely?

Edit: so I found a way to ignore this from discovery. Go to ~/site-packages/homeassistant/components/homekit_controller/init.py

Add the following to the ignore list (it is on the top, Tradfri Hub is listed there as well)

tado Internet Bridge

It will be ignored upon reboot now and it will no longer put a persistent notification.

Jc2k commented 5 years ago

@cf00 Are there any more log messages after that?

All three of those log messages are produced by the same bit of code - its trying to send:

[
        (TLV.kTLVType_State, TLV.M1),
        (TLV.kTLVType_Method, TLV.PairSetup)
]

to the device. This is the pairing start command. The 6 in your log is kTLVType_State and the 0 is the kTLVType_Method. So far this is completely normal.

The tado bridge should then reply with an TLV.M2 message. It might be responding with an error code or it might enter pairing mode.

If you don't see this in your logs then the tado bridge is not replying at all:

#3 ios -> accessory: send SRP verify request

The connection might be rejected or too slow or there could be a problem with discovery.

cf00 commented 5 years ago

@Jc2k No, there is nothing after that.

Would be really nice if this could be made to work. Currently, the only way to control the tado system is trough the cloud and this would allow local control.

Jc2k commented 5 years ago

Thanks for the reply. Do you have an iPhone to test it with so we can rule out weird networking issues?

Can you describe your environment a bit - is it arm/intel/etc? Docker? VM? Can you think of anything in your environment that’s non standard or weird?

Is it currently connected to the cloud? (Trying to rule out of the homekit functionality is somehow tied to the cloud being on or off).

Does everything work as expected through the cloud interface?

How comfortable are you with installing python packages outside of HA?

jimz011 commented 5 years ago

I use an iphone (not the one you responded to though). In my case everything works fine through the cloud. My environment is, Ubuntu 18.04 (desktop) on a Hyper-V server with HA installed in venv. In my particular case all is standard. (No weird stuff). I am perfectly comfortable with installing python packages outside of HA.

I know you weren’t asking me, however if there is a way to help I’d be willing to.

Jc2k commented 5 years ago

Thanks. Happy to have you help too if you can confirm you are in the same situation with the logs on latest HA (only one iOS -> accessory debug message)

jimz011 commented 5 years ago

I am at work now, but will figure out how to get those logs when I get back. In my particular case when trying to add the brigde in Home Assistant (where it asks for the homekit code), whenever I press submit nothing happens. (When looking at the console nothing happens either, in HA dev-tools there is nothing either)

So it is pretty strange, as I remember some time ago, that it would just throw errors in the console, but now it does absolutely nothing. Will check it again tonight.

Btw: I said nothing weird in my networking which is not entirely true. My network is in a domain (AD) and have dns/dhcp running on a windows server but I don’t think it would make a difference though.

cf00 commented 5 years ago

Unfortunately I don't have an iPhone to test it (only android devices).

I am now running homeassistant in docker on Ubuntu 18.10 on an Intel NUC. Previously I used docker on a QNAP NAS and had the identical issue. Networking is somewhat non-standard I think, in that use a macvlan network for docker (so that the container has its own IP). This setup works flawlessly for everything else and as I had the same issue before with my previous setup, I doubt it is the problem.

The tado bridge is connected to the tado cloud (plugged directly into the router) and works as expected. I just checked the tado website, and it doesn't mention anything about homekit and cloud functionality interfering with each other (as far as the cloud is concerned, changing settings via homekit is supposed to be treated as if the user had changed a setting manually on a a device)

As for installing python packages, I am moderately incompetent at anything linux, but I can access a shell inside the container and I can follow (and copy&paste) instructions.

jimz011 commented 5 years ago

Are you sure about that? I got the gut feeling that even homekit only gives a command to the “cloud”. I have tried searching for offline capabilities, but when the internet is down, the tado things don’t work for me (haven’t tried homekit though whilst internet is down). But I could try to simulate an outage and see what happens.

Jc2k commented 5 years ago

Here are the steps to pair a homekit device on the command line entirely outside of HA. I'm doing this on a Mac where python3 is previously installed via Brew, should work on Linux more or less the same.

If you are running it from a Docker container, i'd probably go with an Ubuntu 18.04 one.

$ python3 -m venv homekit_test

$ source homekit_test/bin/activate

$ pip install "homekit[IP]==0.13.0"

$ python -m homekit.init_controller_storage -f test.json

$ python -m homekit.discover
Name: DemoAccessory._hap._tcp.local.
Url: http_impl://192.168.1.254:8085
Configuration number (c#): 67
Feature Flags (ff): No support for HAP Pairing (Flag: 0)
Device ID (id): ff:f0:00:00:00:00
Model Name (md): DemoAccessory
Protocol Version (pv): 1.0
State Number (s#): 1
Status Flags (sf): Accessory has not been paired with any controllers. (Flag: 1)
Category Identifier (ci): Lightbulb (Id: 5)

$ python -m homekit.identify -d ff:f0:00:00:00:00 --log DEBUG

$ python -m homekit.pair -f test.json -p 031-45-154 -a test -d ff:f0:00:00:00:00 --log DEBUG
2019-04-12 21:31:36,880 __init__.py:0108 DEBUG #1 ios -> accessory: send SRP start request
2019-04-12 21:31:36,881 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-12 21:31:36,884 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-12 21:31:36,884 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-12 21:31:36,926 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x02
  3: (384 bytes) 0xe13d364821d9beb8c2a48253cb748657bc64de9b7b5217fd3c9719fad276ace63ea8dce38e43c242590e74d8448cd5740b1326fe9784ee4567f4b34393c9d1aa146d88e885770d67bfb8c6ce73cee2ff8fe38537145e6172fcc2ca783f01fe5f76e3b07ad0e324c7d8a7e01e3c734bd553f5aa252d2fb2da287d8309d3fa4b3a5a384e887e1d3dd0fcbac27a4bfa037af5dc3717a87698e1d9ae202d4d092e4c86532b846aedf4094685952ca99696b6db4c0d2b786698700b4289f6b2b8c158e3a4c9accf07396008d168517bddba8d7b52359a982ba7b1524f06bffc60eedbd97898bcede7edbce025d4f7ec8b765969d909cdd458f6b8dc972e2e0f215a6a0a9cde161c26781c1746bf4202b427a7a6553e6ebfdc466c05366c370cd0092c5dab811f2ba92059aea92f53e65ffa10c98d800d970cc47e1357b4cbc4fc9cfca0ef9d8b14aebf943efd3cf21904ea1aef41a8044088548dbbce47fbaa1d3e18371fe779b960e1d8b44a0825e7cdf9be5b07b0c1b9b55a01ca8ffd4bf14e3de5
  2: (16 bytes) 0x65685766785a4d6a774566593954486c
]

2019-04-12 21:31:36,926 __init__.py:0068 DEBUG response: [
  6: (1 bytes) 0x02
  3: (384 bytes) 0xe13d364821d9beb8c2a48253cb748657bc64de9b7b5217fd3c9719fad276ace63ea8dce38e43c242590e74d8448cd5740b1326fe9784ee4567f4b34393c9d1aa146d88e885770d67bfb8c6ce73cee2ff8fe38537145e6172fcc2ca783f01fe5f76e3b07ad0e324c7d8a7e01e3c734bd553f5aa252d2fb2da287d8309d3fa4b3a5a384e887e1d3dd0fcbac27a4bfa037af5dc3717a87698e1d9ae202d4d092e4c86532b846aedf4094685952ca99696b6db4c0d2b786698700b4289f6b2b8c158e3a4c9accf07396008d168517bddba8d7b52359a982ba7b1524f06bffc60eedbd97898bcede7edbce025d4f7ec8b765969d909cdd458f6b8dc972e2e0f215a6a0a9cde161c26781c1746bf4202b427a7a6553e6ebfdc466c05366c370cd0092c5dab811f2ba92059aea92f53e65ffa10c98d800d970cc47e1357b4cbc4fc9cfca0ef9d8b14aebf943efd3cf21904ea1aef41a8044088548dbbce47fbaa1d3e18371fe779b960e1d8b44a0825e7cdf9be5b07b0c1b9b55a01ca8ffd4bf14e3de5
  2: (16 bytes) 0x65685766785a4d6a774566593954486c
]

2019-04-12 21:31:36,926 __init__.py:0120 DEBUG #3 ios -> accessory: send SRP verify request
2019-04-12 21:31:36,969 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xe26fa60c00933e27c616aa4b5d1c2bfc5c7cbfa2b587ed3d0d0f2b4c5295dc0340b1abf4f07fadc567bdf28096d33630679baaa5e7399678f64c1c2d44525ef26867aefa04b2c0f6a220beacc0cdcd38fb9bbdd9c8f23c16d10a7caf5856baea8dd3d18cc614fa122d887353489adc3f531404d3963cfa4b0817f168544ea365772e25e3f1a76702ca3a518ede9e021a1f0537955c530cc2b6c6c0310f4a40cf21e972051f761513c3e9290660b20c3956c0620d821a94ccc90a8925bca44da3f77d1d80e414bd939c10d88d02ac88b48a3be9f82e2b6c5a268b14576ede2692e3b8ab501187caf62d100daf9781a61122bd78dfc4ff68a2a565608e781f05e51b09dfd0661f6357f26100b2e4acd4798ba2f5935315b8cb6c8e3fbf7fb9b9b395213d083ccfb94f21da6c210ecdf3da9685817988678b3038dff457c709c1e5a65bed40ba6a8c4106c877008fd4d1559f7bd0dfb82131480f3796f31b7bae2dc7957e03c1924b263a070eab373638d5b7d313dd7cacdc3c0cf36f2e07f529bf
  4: (64 bytes) 0xa08e93477fed158e16e27bac4d25aef5f03d89f4529c4fafbbd43c5330672e8b52c8f4eaf6e324d4d4ce3737ebd24bd43041bb9ed87a0cab2a650e20388e9c37
]

2019-04-12 21:31:36,969 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xe26fa60c00933e27c616aa4b5d1c2bfc5c7cbfa2b587ed3d0d0f2b4c5295dc0340b1abf4f07fadc567bdf28096d33630679baaa5e7399678f64c1c2d44525ef26867aefa04b2c0f6a220beacc0cdcd38fb9bbdd9c8f23c16d10a7caf5856baea8dd3d18cc614fa122d887353489adc3f531404d3963cfa4b0817f168544ea365772e25e3f1a76702ca3a518ede9e021a1f0537955c530cc2b6c6c0310f4a40cf21e972051f761513c3e9290660b20c3956c0620d821a94ccc90a8925bca44da3f77d1d80e414bd939c10d88d02ac88b48a3be9f82e2b6c5a268b14576ede2692e3b8ab501187caf62d100daf9781a61122bd78dfc4ff68a2a565608e781f05e51b09dfd0661f6357f26100b2e4acd4798ba2f5935315b8cb6c8e3fbf7fb9b9b395213d083ccfb94f21da6c210ecdf3da9685817988678b3038dff457c709c1e5a65bed40ba6a8c4106c877008fd4d1559f7bd0dfb82131480f3796f31b7bae2dc7957e03c1924b263a070eab373638d5b7d313dd7cacdc3c0cf36f2e07f529bf
  4: (64 bytes) 0xa08e93477fed158e16e27bac4d25aef5f03d89f4529c4fafbbd43c5330672e8b52c8f4eaf6e324d4d4ce3737ebd24bd43041bb9ed87a0cab2a650e20388e9c37
]

2019-04-12 21:31:36,969 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xe26fa60c00933e27c616aa4b5d1c2bfc5c7cbfa2b587ed3d0d0f2b4c5295dc0340b1abf4f07fadc567bdf28096d33630679baaa5e7399678f64c1c2d44525ef26867aefa04b2c0f6a220beacc0cdcd38fb9bbdd9c8f23c16d10a7caf5856baea8dd3d18cc614fa122d887353489adc3f531404d3963cfa4b0817f168544ea365772e25e3f1a76702ca3a518ede9e021a1f0537955c530cc2b6c6c0310f4a40cf21e972051f761513c3e9290660b20c3956c0620d821a94ccc90a8925bca44da3f77d1d80e414bd939c10d88d02ac88b48a3be9f82e2b6c5a268b14576ede2692e3b8ab501187caf62d100daf9781a61122bd78dfc4ff68a2a565608e781f05e51b09dfd0661f6357f26100b2e4acd4798ba2f5935315b8cb6c8e3fbf7fb9b9b395213d083ccfb94f21da6c210ecdf3da9685817988678b3038dff457c709c1e5a65bed40ba6a8c4106c877008fd4d1559f7bd0dfb82131480f3796f31b7bae2dc7957e03c1924b263a070eab373638d5b7d313dd7cacdc3c0cf36f2e07f529bf
  4: (64 bytes) 0xa08e93477fed158e16e27bac4d25aef5f03d89f4529c4fafbbd43c5330672e8b52c8f4eaf6e324d4d4ce3737ebd24bd43041bb9ed87a0cab2a650e20388e9c37
]

2019-04-12 21:31:37,030 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x04
  4: (64 bytes) 0xc489cc99cfb0c1f7096811d3a8473408828f0ff51957a63db293676a863528d5b92202cb7cd3c83e3942a1b3f6b5f451047d038fc9e5bc5bf64bb6c6e37b79ef
]

2019-04-12 21:31:37,030 __init__.py:0068 DEBUG response: [
  6: (1 bytes) 0x04
  4: (64 bytes) 0xc489cc99cfb0c1f7096811d3a8473408828f0ff51957a63db293676a863528d5b92202cb7cd3c83e3942a1b3f6b5f451047d038fc9e5bc5bf64bb6c6e37b79ef
]

2019-04-12 21:31:37,030 __init__.py:0171 DEBUG #5 ios -> accessory: send SRP exchange request
2019-04-12 21:31:37,148 tlv.py:0134 DEBUG sending [
  1: (36 bytes) b'8c811e54-1163-4ee9-8ca3-8c7de1487a4f'
  3: (32 bytes) b'3\xf8,\xe8,v[\xa2\xbf\xb9\x15\x06a\x84ad\xb0\xce\x86*&\x03\n\xb1\xef\xef\x94\xe9Uq1\xe7'
  10: (64 bytes) b'\xd3\xbe\t\xd9\x0cj,\xf0\x13\xa6\xbc\x9e\xf9F\xfcEe\xd6\xc8b\xd5\xf0\xf0\x88\xb9\xb9\xfa\xda\x07d\xcd\x84%P\x10\x02\x9e\x9e\x08\xf3\x07\x82\xfd=\xd0b\xb7\xfc\x98\x07)+I6RJ\x82T\xfco%\xa1i\x01'
]

2019-04-12 21:31:37,150 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x05
  5: (154 bytes) 0xadea234c19f4f498b2837067abbef1e3ff1270402b9d7597cab187d741e6dffb820326e364e9e49416a5e51124e3f52fd063ac27a51e9fd4cf32d5054221dfb645a13e630c94b3b8a221d9c3c33891f431afc9294bd95aad94b0b082285aa971920953d4f969cfed6d8039277f5a96108f1f8281824145a429015d1d1d32c19a576dd74749666ed795cf9c06776428a8d10c732d9c667696cc23
]

2019-04-12 21:31:37,151 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x05
  5: (154 bytes) 0xadea234c19f4f498b2837067abbef1e3ff1270402b9d7597cab187d741e6dffb820326e364e9e49416a5e51124e3f52fd063ac27a51e9fd4cf32d5054221dfb645a13e630c94b3b8a221d9c3c33891f431afc9294bd95aad94b0b082285aa971920953d4f969cfed6d8039277f5a96108f1f8281824145a429015d1d1d32c19a576dd74749666ed795cf9c06776428a8d10c732d9c667696cc23
]

2019-04-12 21:31:37,151 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x05
  5: (154 bytes) 0xadea234c19f4f498b2837067abbef1e3ff1270402b9d7597cab187d741e6dffb820326e364e9e49416a5e51124e3f52fd063ac27a51e9fd4cf32d5054221dfb645a13e630c94b3b8a221d9c3c33891f431afc9294bd95aad94b0b082285aa971920953d4f969cfed6d8039277f5a96108f1f8281824145a429015d1d1d32c19a576dd74749666ed795cf9c06776428a8d10c732d9c667696cc23
]

2019-04-12 21:31:38,240 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x06
  5: (135 bytes) 0x3935b5c4930fc0662a40b6aeaa3e00949226612c323cea5927a5ef561fb087a88a7c1d7c702dbd203c213b129f00adb90e085849df604c6db928ecf25e5e472da612d6df57bbb89b2b81d71cf8f718253f740e5ad580ca28a1a5999ba037b82263799ccf44f01bbca5ab899be9d1b9fe9328094784a92eb7d6ed0244349a9ed23264ee6b837495
]

2019-04-12 21:31:38,241 __init__.py:0068 DEBUG response: [
  6: (1 bytes) 0x06
  5: (135 bytes) 0x3935b5c4930fc0662a40b6aeaa3e00949226612c323cea5927a5ef561fb087a88a7c1d7c702dbd203c213b129f00adb90e085849df604c6db928ecf25e5e472da612d6df57bbb89b2b81d71cf8f718253f740e5ad580ca28a1a5999ba037b82263799ccf44f01bbca5ab899be9d1b9fe9328094784a92eb7d6ed0244349a9ed23264ee6b837495
]

2019-04-12 21:31:38,245 tlv.py:0117 DEBUG receiving [
  1: (17 bytes) 0x66663a66303a30303a30303a30303a3030
  3: (32 bytes) 0xdaaf0d8f58130830efe7aaaefbd7fc2ed08075a9210aef1bed60bac0c1537a90
  10: (64 bytes) 0xdc44351e094ec9154ef63d57990d5d0e4b2c1ccc62ac0b0256302ffdca413427a1b846f9005eb19ee0d06adbea0c88309b2afd2cd1ced4d392ab5ec1bf245207
]

2019-04-12 21:31:38,286 ip_implementation.py:0399 DEBUG init session
2019-04-12 21:31:38,451 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  3: (32 bytes) b'lu\xf0a:\xf9\x854\x8b\x05\x18\xbf\xb8|\x82{\xd3\x9a\x11\x0e\x08\x14\xce*>^\x03\xbbB\x13\xe6Z'
]

2019-04-12 21:31:38,451 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  3: (32 bytes) 0x6c75f0613af985348b0518bfb87c827bd39a110e0814ce2a3e5e03bb4213e65a
]

2019-04-12 21:31:38,451 __init__.py:0076 DEBUG write message: [
  6: (1 bytes) 0x01
  3: (32 bytes) 0x6c75f0613af985348b0518bfb87c827bd39a110e0814ce2a3e5e03bb4213e65a
]

2019-04-12 21:31:38,496 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x02
  3: (32 bytes) 0x067658394b89dd5c5740e47b57f39d2897b2e6ba595e3da8791c645a35d0f94a
  5: (101 bytes) 0xcb50c52b604f25fb7c64ae3fc2c5fd72ba9e6852130401f6dc4e88b5388165c9081274ca0cf598d2b29c211b5d62d1d8370a04513327e51e510864cf4163d4a3832a002d7140476b9cd9852a143792e1c6fde36b64b47539deb57981a9df3d84e22218cfa6
]

2019-04-12 21:31:38,497 __init__.py:0084 DEBUG response: [
  6: (1 bytes) 0x02
  3: (32 bytes) 0x067658394b89dd5c5740e47b57f39d2897b2e6ba595e3da8791c645a35d0f94a
  5: (101 bytes) 0xcb50c52b604f25fb7c64ae3fc2c5fd72ba9e6852130401f6dc4e88b5388165c9081274ca0cf598d2b29c211b5d62d1d8370a04513327e51e510864cf4163d4a3832a002d7140476b9cd9852a143792e1c6fde36b64b47539deb57981a9df3d84e22218cfa6
]

2019-04-12 21:31:38,498 tlv.py:0117 DEBUG receiving [
  1: (17 bytes) 0x66663a66303a30303a30303a30303a3030
  10: (64 bytes) 0xe3b8be49ba2e99c780d4da9238d98773a3d7a0861e6716f9fd2a03921a6480a524f46e9f43991999ecae5edc0609572922b89b43c5e731c064a9a5d79f4fcc01
]

2019-04-12 21:31:38,500 tlv.py:0134 DEBUG sending [
  1: (36 bytes) b'8c811e54-1163-4ee9-8ca3-8c7de1487a4f'
  10: (64 bytes) b'tS\x0c..\xb7\xba/=\xe1\x1f\x97\xef\xc41j\xba\xf7<\xa5\xb2\xf5\xecx\xac\xce\xdf~{\xf9\xda2W\xa0Y?\x8aW^g\x91,\\\xc6;\xf5\x97\x1c?{q\xb9^\x05\x1b7\xed\x8c\xaes\xfd\xafq\x07'
]

2019-04-12 21:31:38,501 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x290e654ba597f4b3bec256d49c074268aaf430f4dba87febd6ffba9272b25b638e979fe3ff98ffbce3b30cb1da89da22b177cfffb76e18c5b5d04bf534b5c2cf14237881e351040e1cf9ec739b7d3860f81bdf2a3641b1935357788255ea798588f2521875b753847aa6446e8a5075218ececbd6f692c707
]

2019-04-12 21:31:38,501 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x290e654ba597f4b3bec256d49c074268aaf430f4dba87febd6ffba9272b25b638e979fe3ff98ffbce3b30cb1da89da22b177cfffb76e18c5b5d04bf534b5c2cf14237881e351040e1cf9ec739b7d3860f81bdf2a3641b1935357788255ea798588f2521875b753847aa6446e8a5075218ececbd6f692c707
]

2019-04-12 21:31:38,502 __init__.py:0076 DEBUG write message: [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x290e654ba597f4b3bec256d49c074268aaf430f4dba87febd6ffba9272b25b638e979fe3ff98ffbce3b30cb1da89da22b177cfffb76e18c5b5d04bf534b5c2cf14237881e351040e1cf9ec739b7d3860f81bdf2a3641b1935357788255ea798588f2521875b753847aa6446e8a5075218ececbd6f692c707
]

2019-04-12 21:31:38,505 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x04
]

2019-04-12 21:31:38,505 __init__.py:0084 DEBUG response: [
  6: (1 bytes) 0x04
]

2019-04-12 21:31:38,505 ip_implementation.py:0426 DEBUG session established
Pairing for "test" was established.

I kind of expect the same result as HA - that it hangs shortly after

#1 ios -> accessory: send SRP start request

If it does then we have ruled out an interaction with HA code and i'll need to have a think about next steps. Might involve tcpdump...

Jc2k commented 5 years ago

(Obviously you'll need to change the homekit id from ff:f0:00:00:00:00 to whatever is in homekit.discover's output, and change the pin too).

Especially interested in the output of the discover and pair commands.

cf00 commented 5 years ago

@jimz011 I am not really sure, that's why I would like to see this work to test it :-) But the last time tado servers were down for a couple of hours, I remember that tado was asked on twitter about local control. They replied that the system currently does not allow for local control (and they wouldn't give any info if it was a planned feature) but they mentioned that local control is currently only possible via homekit. That gave me the idea to try the homekit componenet in homeassistant in the first place.

cf00 commented 5 years ago

Ok, here are my results.

(homekit_test) root@ha:/usr/src/app# python -m homekit.discover
Name: tado Internet Bridge IBXXXXXXXXXX._hap._tcp.local.
Url: http_impl://10.X.X.101:3000
Configuration number (c#): 6
Feature Flags (ff): Supports HAP Pairing (Flag: 1)
Device ID (id): a3:d1:5e:1f:6c:03
Model Name (md): tado Internet Bridge
Protocol Version (pv): 1.0
State Number (s#): 1
Status Flags (sf): Accessory has not been paired with any controllers. (Flag: 1)
Category Identifier (ci): Bridge (Id: 2)

(homekit_test) root@ha:/usr/src/app# python -m homekit.identify -d a3:d1:5e:1f:6c:03 --log DEBUG No response. I interrupted it after waiting 5 minutes.

(homekit_test) root@ha:/usr/src/app# python -m homekit.pair -f test.json -p XXX-XX-XXX -a test -d a3:d1:5e:1f:6c:03 --log DEBUG
2019-04-12 23:08:50,080 __init__.py:0111 DEBUG #1 ios -> accessory: send SRP start request
2019-04-12 23:08:50,080 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-12 23:08:50,081 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-12 23:08:50,082 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

Nothing after that. ^C after 5 minutes.

Jc2k commented 5 years ago

Ok - thats good in that it proves its not anything in the HA code. But bad in that we are not any closer to understanding it.

Let's try poking it from outside of the library altogether. HomeKit is HTTP based so we can poke some of it without anything more than curl. Here is the HomeKit interface for a Phillips Hue.

$ curl --verbose 192.168.X.X:8080/accessories
*   Trying 192.168.X.X...
* TCP_NODELAY set
* Connected to 192.168.X.X (192.168.X.X) port 8080 (#0)
> GET /accessories HTTP/1.1
> Host: 192.168.X.X:8080
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 470 Connection Authorization Required
< Content-Length: 21
< Content-Type: application/hap+json
< 
* Connection #0 to host 192.168.1.5 left intact
{ "status" : -70401 }

(The 70401 error means its not a secure session, but it proves it spoke HTTP to the device).

Again, i'm expecting it to hang or timeout here.

Also, heres a little python script that will verify the bonjour addresses are all connectable. In particular, this will try the ipv6 addresses. This is one of the few known differences I can think of with the Apple implementation that could cause the behaviour we are seeing.

from zeroconf import ServiceBrowser, Zeroconf
import socket

class MyListener:

    def add_service(self, zeroconf, type, name):
        info = zeroconf.get_service_info(type, name)
        print("service: %s"  % name)

        result = socket.getaddrinfo(
            info.server,
            info.port,
            proto=socket.IPPROTO_TCP,
        )

        for (family, type, proto, canonname, sockaddr) in result:
            print("server: %s, %s, %s" % (info.server, info.port, sockaddr))

            try:
                s = socket.socket(family, type, proto)
                s.settimeout(10)
                s.connect(sockaddr)
            except Exception as e:
                print("error: %s, %s" % (sockaddr, e))
                continue
            print("connection: %s" % (sockaddr, ))

zeroconf = Zeroconf()
listener = MyListener()
browser = ServiceBrowser(zeroconf, "_hap._tcp.local.", listener)
try:
    input("Press enter to exit...\n\n")
finally:
    zeroconf.close()

Drop this in a file like listener.py and run it in the same virtualenv you set up before. e.g.

$ source homekit_test/bin/activate
$ python listener.py

Output will be something like:

Press enter to exit...

service: Philips hue - 371433._hap._tcp.local.
server: Philips-hue.local., 8080, ('fe80::217:88ff:fe48:2544%en0', 8080, 0, 8)
connection: ('fe80::217:88ff:fe48:2544%en0', 8080, 0, 8)
server: Philips-hue.local., 8080, ('192.168.1.5', 8080)
connection: ('192.168.1.5', 8080)
cf00 commented 5 years ago

No ipv6 addresses here:

Press enter to exit...

service: tado Internet Bridge IB3183151360._hap._tcp.local.
server: tadoBridgeIB3183151360.local., 3000, ('10.6.6.101', 3000)
connection: ('10.6.6.101', 3000)
service: Philips hue - A58C06._hap._tcp.local.
server: Philips-hue.local., 8080, ('10.6.6.106', 8080)
connection: ('10.6.6.106', 8080)

btw I also tried the pair command with the hue bridge now and it was paired successfully.

cf00 commented 5 years ago

And here the output of a curl command. It seems to connect but there is no response.

$ curl --verbose 10.6.6.101:3000
* Rebuilt URL to: 10.6.6.101:3000/
*   Trying 10.6.6.101...
* TCP_NODELAY set
* Connected to 10.6.6.101 (10.6.6.101) port 3000 (#0)
> GET / HTTP/1.1
> Host: 10.6.6.101:3000
> User-Agent: curl/7.61.0
> Accept: */*
>
Jc2k commented 5 years ago

OK current theories in play:

To help diagnose the first 2 of these I have updated listener.py:

from zeroconf import ServiceBrowser, Zeroconf
import socket

HTTP_HEADER = """
POST /pair-setup HTTP/1.1
Host: %s
Content-Length: 6
Content-Type: application/pairing+tlv8
""".strip().replace("\n", "\r\n") + ("\r\n" * 2)

HTTP_PAYLOAD = b"\x06\x01\x01\x00\x01\x01"

class MyListener:

    def add_service(self, zeroconf, type, name):
        info = zeroconf.get_service_info(type, name)
        print("service: %s"  % name)

        if "tado" not in name:
            print("SKIPPING")
            return

        result = socket.getaddrinfo(
            info.server,
            info.port,
            proto=socket.IPPROTO_TCP,
        )

        for (family, type, proto, canonname, sockaddr) in result:
            print("server: %s, %s, %s" % (info.server, info.port, sockaddr))

            s = socket.socket(family, type, proto)

            try:
                s.settimeout(10)
                s.connect(sockaddr)
            except Exception as e:
                print("error connecting: %s, %s" % (sockaddr, e))
                continue
            print("connection: %s" % (sockaddr, ))

            payload = (HTTP_HEADER % name.rstrip(".")).encode("utf-8") + HTTP_PAYLOAD
            print(payload)
            s.send(payload)

            buffer = b''
            try:
                next = s.recv(1024)
                while next:
                    buffer += next
                    next = s.recv(1024)
            except socket.timeout:
                print("TIMEOUT RECV: %s" % buffer)
                continue

            print(buffer)

zeroconf = Zeroconf()
listener = MyListener()
browser = ServiceBrowser(zeroconf, "_hap._tcp.local.", listener)
try:
    input("Press enter to exit...\n\n")
finally:
    zeroconf.close()

It sends a payload based on packet dumps of what an iPhone sends to pair with an accessory, and it will print the entire response, it doesn't try to parse it. I tweaked it to only target your todo and not your Hue.

Note that the connection will be left open and timeout after 10s (no parsing means can't see when full message has been sent) so will take longer to run this time.

It does look like the homekit client isn't byte for byte perfect - there are 2 differents in the initial handshake:

So it could be this variation that the tado doesn't like...

cf00 commented 5 years ago
$ python listener.py
Press enter to exit...

service: tado Internet Bridge IB3183151360._hap._tcp.local.
server: tadoBridgeIB3183151360.local., 3000, ('10.6.6.101', 3000)
connection: ('10.6.6.101', 3000)
b'POST /pair-setup HTTP/1.1\r\nHost: tado Internet Bridge IB3183151360._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x06\x01\x01\x00\x01\x01'
TIMEOUT RECV: b'HTTP/1.1 200 OK\r\nContent-Length:409\r\nContent-Type:application/pairing+tlv8\r\n\r\n\x06\x01\x02\x03\xff\xa2\x0bM\x17\xf8\xcd\xf0mz6`\xb66\x96\xaa\xe0_\x14\xb1\xdf\xc3\xcb)\x05\x95\xb4\xc3\xb5\xbe\xed5\xfe\'\xc2\x94\xbea\x84\x85w\xac\xe3\xe2F\x89\x82\xaa0\xad\x99\x1bx,\xde\x16\x9d\x93\\v{\xbe\xa87\xfb\xc0\xf6\xad\x8f \xce\xbd\x90\xb1\x17[W\xb4&\xeaN\'\xe6\xbcTo0\xe2\xbf\xb0\x04C\xc6Y\xb0\x08\xf3\xc9\x14\xbdW\xc0\x14\x82&\xc1\x85\x0eH8\xc2`\xfaXY\xbd\x01\\\xee$Yy\x9e\x97\xe1\x94\xb5\x80\xb6\xa3\x8c\x9c2\x8e3\x08\xd3\xd6\xc2\xffI\x1bJ\xf2\x11\x1b\x86\xe3\xe2\x19\xa7\xeb\xe7J\xdd*fX{\xd1\xdbw\x95KB\xf1\x04\xf0pz\nZ_\x9e\x04`e\x83(5!\x0fDC\x0c\xe0"\x13\xed\xabd49\x0c\xfc\x96\x1d\xfc\xa8\x91;G\xfe\x01\xff8\x17\xc0i\xc7u\x94S\x15\x1d\x9b\xeby\xc8\x14\xb1\'\xdd\xe39\x81\x81\xe3\x0f\x81\xe4\xe4\xb4n:\xe6l\x02\xad{(]\xc1\xec\xc8\xcd\xad\xe0m&\xca\x81\xcb\xc1\xf4\x1e\x03\x81\x89\t*t\xd2\xd0\xc9\xe6e\xce\xc7\xe7\xb3\x98\xaai\x9d\xa6\xbbp\x9d4\xda\x18\xbf\xa5M\xbd\xa8\xee\x01\xce~%\xabe\xaa\xac\xc9)w\xb6\xcb\x1f\xe2\xa4\x1av\xc3\xe9\xfem\xf6|\x91,L\x9f\xfb\xae\x96\xa5\xf2\x84\x02\xc2s\xb7\xa6\xb3U\x95\x0f;\xe9#\xc9m\xaa\x96}\xc1\x19\x17\x7f\\\x93\xba\x8dW\x11\xca\x8dh\xa4=\xb0m\xf8\x8c#\xba\xcd0\xd1\xad@L\xb7`5e\x00\xc0\xeeLC4T.\xb5\xbes\x90\xc1,\x94\xf7\xa9\x02\x10\xa0\x91-F\x7f\xd0R(\xf5\xe8\xd4Q\\\xd87\xab'
Jc2k commented 5 years ago

OK two changes to try. First, change the HTTP_HEADER bit from:

Host: %s
Content-Length: 6
Content-Type: application/pairing+tlv8

Make it

Host: %s
Accept-Encoding: identity
Content-Length: 6
Content-Type: application/pairing+tlv8

And try again

cf00 commented 5 years ago
$ python listener.py
Press enter to exit...

service: Philips hue - A58C06._hap._tcp.local.
SKIPPING
service: tado Internet Bridge IB3183151360._hap._tcp.local.
server: tadoBridgeIB3183151360.local., 3000, ('10.6.6.101', 3000)
connection: ('10.6.6.101', 3000)
b'POST /pair-setup HTTP/1.1\r\nHost: tado Internet Bridge IB3183151360._hap._tcp.local\r\nAccept-Encoding: identity\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x06\x01\x01\x00\x01\x01'
TIMEOUT RECV: b''
Jc2k commented 5 years ago

So the python library is sending an extra header that it doesn't understand and its not replying because of that. Let's just make sure. Go back to the previous version without the Accept-Encoding change (i.e. as it was in https://github.com/home-assistant/home-assistant/issues/16971#issuecomment-482843011).

Then change this line:

payload = (HTTP_HEADER % name.rstrip(".")).encode("utf-8") + HTTP_PAYLOAD

for

payload = (HTTP_HEADER % "10.6.6.101:3000").encode("utf-8") + HTTP_PAYLOAD

I got lazy and hardcoded it, but thats the format that the python currently uses for the Host header. Hopefully it still has some output after the timeout with this variant.

cf00 commented 5 years ago

Yes, the output is still there.

So, I guess that's good news in that you at least know what the problem seems to be ...

$ python listener.py
Press enter to exit...

service: Philips hue - A58C06._hap._tcp.local.
SKIPPING
service: tado Internet Bridge IB3183151360._hap._tcp.local.
server: tadoBridgeIB3183151360.local., 3000, ('10.6.6.101', 3000)
connection: ('10.6.6.101', 3000)
b'POST /pair-setup HTTP/1.1\r\nHost: 10.6.6.101:3000\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x06\x01\x01\x00\x01\x01'
TIMEOUT RECV: b'HTTP/1.1 200 OK\r\nContent-Length:409\r\nContent-Type:application/pairing+tlv8\r\n\r\n\x06\x01\x02\x03\xff;\x87\xdf\xa7\xfb\xcfu\x83P\xe9\xd7\xf4S\xcf\x19c\xd9K\x0b\xe8z\xf3\x12\xdb`\xff\x14]g\x9b\xebl\xb6[\xfe-X\xb8\xban$\x99\x0b\xe2"2s\xff\xedr\x05Y\xbd\x9c\xa5Kw\xbc\x90wd\xad,\xb5\xe2\x8b=\x9b\x07k\x08\x00B\xd2w\xa6\x80R\xb6Y\xa2\xc4\x06\xadM\xbdp\x84(\x16\x9cO\xc1\xd61\x88`\x14\x8e\xe4=\xa5\'\x9c9\xeb\x14\xe9\xc3\xad\xb9)\xa5n\xa5\x01\x82\x18:aN\x89\xd00\xd2Y2Vb\xa4\x92\x8eh\x8a\x0ebk\xc2"\xa4\xbe\xfe\x9f\xf9v\xde\xfa\xb4f\x8a\xfe)x\x00N41\xc9\x7f\xda\x94\xe0H9\xb2\x13\x07h\x0c\xfe\xda\xd2\xa6\xf9\xb6\xcb\xaa%\xd8\xa5Z9\xce\x82,hc\x16{\xb9\x9f\xa1m\xd2\xd8\x92=\xb1\x8e\xc6\x95\xe1\xa5*\xa12K;\xbf/\xaa\x9ah\x9f=\xb1\x08\xe7\x01\xdc\x18\xbe\xf3\t\xfbU\x14PR\x13\x0c\xa53\xadq\xe6\xa1G\x94\x8d!x\xa0\x92\x9a\xf5}\xccH\xbf\x9b\xb3\xe5\xd3D\x03\x81eY\xc9\x0f\x917\xec\x95\x10\x13\x98\xa1\xeca\r\r\xd8\xb0M\xbd\x01\xe1\x8em\x03\x9e\x1acn3\x00t\x80\xb5\xcc@\xbf\x8d\xc3\xb4\xce\xef\xf7\xf36\x05sV\x1f\xc7\x02\xf3\x15\xae\xc7\x7fDy;F\xf3\xdc\x8f\xcc-\x87\x05\x11\xbf!u\x0c\xccwE\x85o\xef\xd9n\x86\xc6F\xd5\xe8}\x8a\xf9\xe0\x1f$\x84\xe6\x8eaW1\x99\x9a\xb0k`1x\xc0Qb\x93L\xa9\n\xb8\x91\x18\\\xbe\x18i|^Pc\xed\xaa\xdb*\xc0\xc2\x81\x02\x10\xa0\x91-F\x7f\xd0R(\xf5\xe8\xd4Q\\\xd87\xab'
Jc2k commented 5 years ago

Yep =) Pretty sure I can write a patch to fix this.

cf00 commented 5 years ago

Great! Thanks for your help and your efforts.

As at total noob in those things: how long until I can use it in homeassistant to manage my heating? :-)

Jc2k commented 5 years ago

I need to write the patch, i'll need you to test it, i'll need to get it merged into homekit_python, then get a new homekit_python released, then open a PR to point HA at the new release of homekit_python, then wait for that to get reviewed and merged, and from then it will be up to 2 weeks or so for it to appear in a tag :-/ So, anything from 2 to 6 weeks at this stage!

Noticed that the pairing code is different to the code for actually talking over a secure session so may have to make changes there too :-/

Jc2k commented 5 years ago

OK, pairing patch attempt 1:

$ source venv/bin/activate
$ pip install -U https://github.com/Jc2k/homekit_python/archive/fix_tado_bridge.zip

It should say its uninstalled the old homekit and installed the new one.

Then try pairing again as in previous comment -> https://github.com/home-assistant/home-assistant/issues/16971#issuecomment-482720750

Jc2k commented 5 years ago

(Annnnd just pushed a fix for python 3.5, too)

cf00 commented 5 years ago

Seems like progress to me, but there is an error at the end ...

$ python -m homekit.pair -f test2.json -p XXX-XX-XXX -a test -d a3:d1:5e:1f:6c:03 --log DEBUG
2019-04-13 22:49:18,372 __init__.py:0106 DEBUG #1 ios -> accessory: send SRP start request
2019-04-13 22:49:18,372 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-13 22:49:18,374 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-13 22:49:18,374 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-13 22:49:19,527 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x02
  3: (384 bytes) 0x1bc6fc36d2488e408a54d850d10e73a468d51ea81413276d959f4b787e7e2d2ab355001727183db4ec09d5299938f61d4fb7f436ff983156390220bf71f67683ef153aaa38eb33ca04b8de2c7669cbe6a4742eb66a32bd977de8ac469bc99c513b1cb708d977d1d5cce822fc630695d9e7d300b9dbe961eccd5f47c0a22be81b2ec3851558b643f2bbdc1b6828ddd411753b96674ad2ba985bba73642dbefc1bcd4c2ad6ce6de91d4862d50b7a2e9ae6462d550c096a71f7d5dbd4f6c4af00f1ddd98660ccefed388783186f4cec0670a7c80504316c2530f1eb57bd000376c4670627dc9a2ac85424eaf687fe18a2e8f5a5e7c2091e6752327170ba3cb7bda0ab1156deef4194e0cb81b3fe021229103c7bc76d15a72481e9156a27d2aa4aa9d23c521824c845c98f7191e461e5158c47429afa4a6b052ba3984808c9cc52995211e3202bc67107f23e64521e84f0585b10c8e9007afdbe19cf5fe8ab9e18e0c6227faa8d3987275c7e31e8c398cb19af50205db05cc14e375a029c3454b332
  2: (16 bytes) 0xa0912d467fd05228f5e8d4515cd837ab
]

2019-04-13 22:49:19,528 __init__.py:0067 DEBUG response: [
  6: (1 bytes) 0x02
  3: (384 bytes) 0x1bc6fc36d2488e408a54d850d10e73a468d51ea81413276d959f4b787e7e2d2ab355001727183db4ec09d5299938f61d4fb7f436ff983156390220bf71f67683ef153aaa38eb33ca04b8de2c7669cbe6a4742eb66a32bd977de8ac469bc99c513b1cb708d977d1d5cce822fc630695d9e7d300b9dbe961eccd5f47c0a22be81b2ec3851558b643f2bbdc1b6828ddd411753b96674ad2ba985bba73642dbefc1bcd4c2ad6ce6de91d4862d50b7a2e9ae6462d550c096a71f7d5dbd4f6c4af00f1ddd98660ccefed388783186f4cec0670a7c80504316c2530f1eb57bd000376c4670627dc9a2ac85424eaf687fe18a2e8f5a5e7c2091e6752327170ba3cb7bda0ab1156deef4194e0cb81b3fe021229103c7bc76d15a72481e9156a27d2aa4aa9d23c521824c845c98f7191e461e5158c47429afa4a6b052ba3984808c9cc52995211e3202bc67107f23e64521e84f0585b10c8e9007afdbe19cf5fe8ab9e18e0c6227faa8d3987275c7e31e8c398cb19af50205db05cc14e375a029c3454b332
  2: (16 bytes) 0xa0912d467fd05228f5e8d4515cd837ab
]

2019-04-13 22:49:19,528 __init__.py:0118 DEBUG #3 ios -> accessory: send SRP verify request
2019-04-13 22:49:19,604 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xb75b048cd845f409f079b448cd37612aad7d92bdb89393c1473dc2f2d00532f29df4260e8d6d9f5f3859b41d9addbcb5889182405f17d4ed0f7d9280c681ef00a98c0d67f1b7fd782cff83432b14ce951c1179abe564d119f1593dde422c4caaa3c007fb5e5bc331abd4ca255601932a973abd64e08ceb727c30aa032ce6aec81204fd2cf0cdf43d4b9eeb84526ae1b0d91d3cfaeaa7048a5e8bb80a349a655c4fbe7e41992cef1c5b5d5df70f085ba6f91c1203a48cb05af3282747780438b49fe9ad291d841eea755256e47c2e42f4027c461ddbd73bc56c03bacdd852c88b893b3e5095d58dff9099bdd86fd9fb54877fc4f4dcdfe2168657e988232953e25dae3c5c551f77affea197a43d98a7acf6c131d25ae9c59688af4ea3d5970c4268dcf341fb9777009ee6f1345d5a4b4af541fe3fe26ccdce87a0d8342bc504b50f6118d32da53e76f6181266377445f9185ca4d0b90573e9afd2ec538753d610ba4c34a71c1a7b33850ceba43caff9eeea53852b089c8e8b98e8ed2ff2510a33
  4: (64 bytes) 0xfc85bfd1fa1062f87709628016a68a1af72a87e3283d2bf197849698ab5ce0835e0eb498eb2bab7f21db68f2d41cdcc4210dba886c264a757f85ad96a6d50797
]

2019-04-13 22:49:19,605 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xb75b048cd845f409f079b448cd37612aad7d92bdb89393c1473dc2f2d00532f29df4260e8d6d9f5f3859b41d9addbcb5889182405f17d4ed0f7d9280c681ef00a98c0d67f1b7fd782cff83432b14ce951c1179abe564d119f1593dde422c4caaa3c007fb5e5bc331abd4ca255601932a973abd64e08ceb727c30aa032ce6aec81204fd2cf0cdf43d4b9eeb84526ae1b0d91d3cfaeaa7048a5e8bb80a349a655c4fbe7e41992cef1c5b5d5df70f085ba6f91c1203a48cb05af3282747780438b49fe9ad291d841eea755256e47c2e42f4027c461ddbd73bc56c03bacdd852c88b893b3e5095d58dff9099bdd86fd9fb54877fc4f4dcdfe2168657e988232953e25dae3c5c551f77affea197a43d98a7acf6c131d25ae9c59688af4ea3d5970c4268dcf341fb9777009ee6f1345d5a4b4af541fe3fe26ccdce87a0d8342bc504b50f6118d32da53e76f6181266377445f9185ca4d0b90573e9afd2ec538753d610ba4c34a71c1a7b33850ceba43caff9eeea53852b089c8e8b98e8ed2ff2510a33
  4: (64 bytes) 0xfc85bfd1fa1062f87709628016a68a1af72a87e3283d2bf197849698ab5ce0835e0eb498eb2bab7f21db68f2d41cdcc4210dba886c264a757f85ad96a6d50797
]

2019-04-13 22:49:19,605 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xb75b048cd845f409f079b448cd37612aad7d92bdb89393c1473dc2f2d00532f29df4260e8d6d9f5f3859b41d9addbcb5889182405f17d4ed0f7d9280c681ef00a98c0d67f1b7fd782cff83432b14ce951c1179abe564d119f1593dde422c4caaa3c007fb5e5bc331abd4ca255601932a973abd64e08ceb727c30aa032ce6aec81204fd2cf0cdf43d4b9eeb84526ae1b0d91d3cfaeaa7048a5e8bb80a349a655c4fbe7e41992cef1c5b5d5df70f085ba6f91c1203a48cb05af3282747780438b49fe9ad291d841eea755256e47c2e42f4027c461ddbd73bc56c03bacdd852c88b893b3e5095d58dff9099bdd86fd9fb54877fc4f4dcdfe2168657e988232953e25dae3c5c551f77affea197a43d98a7acf6c131d25ae9c59688af4ea3d5970c4268dcf341fb9777009ee6f1345d5a4b4af541fe3fe26ccdce87a0d8342bc504b50f6118d32da53e76f6181266377445f9185ca4d0b90573e9afd2ec538753d610ba4c34a71c1a7b33850ceba43caff9eeea53852b089c8e8b98e8ed2ff2510a33
  4: (64 bytes) 0xfc85bfd1fa1062f87709628016a68a1af72a87e3283d2bf197849698ab5ce0835e0eb498eb2bab7f21db68f2d41cdcc4210dba886c264a757f85ad96a6d50797
]

2019-04-13 22:49:21,549 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x04
  4: (64 bytes) 0x2acd377c72c5b446f471068657f2bf74df344fb4acaccc1eb6018edb8053fc57378102dabf241c264c7618154a810c7713c6e3b1b9e76eb0052657e633a6ee24
]

2019-04-13 22:49:21,549 __init__.py:0067 DEBUG response: [
  6: (1 bytes) 0x04
  4: (64 bytes) 0x2acd377c72c5b446f471068657f2bf74df344fb4acaccc1eb6018edb8053fc57378102dabf241c264c7618154a810c7713c6e3b1b9e76eb0052657e633a6ee24
]

2019-04-13 22:49:21,550 __init__.py:0169 DEBUG #5 ios -> accessory: send SRP exchange request
2019-04-13 22:49:21,671 tlv.py:0134 DEBUG sending [
  1: (36 bytes) b'23f4dc6d-45ff-44ad-8057-4db76babd60d'
  3: (32 bytes) b'v\x81\xec\xbaf\xf51\x95\xc4\xc0\xf4\xa2\xf3\x88\x1e\xfe)\xca\xd7\x9f\xef\xcb\xd9\xf9\xd6\x7fV\xa5\xe0\x9a\xe4\xe8'
  10: (64 bytes) b"%\xb2\xc4\x01\xb8\x0f\xd5H\xe0\xb6xi\xe1'\xdc\x87/W#\xcd[\x86\x03\x91\xb0}\xf9\xc6\xe2\xb5S\xf5\xed\xea\\U\x8a\xeft\x8e\x08C\xd3\xa0'\x9a\x16\n\xd0\x8d\x96\x10\x1b\xec\xfd\xb8\xcf:\x10$\xc5f/\x0c"
]

2019-04-13 22:49:21,673 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x05
  5: (154 bytes) 0x46c18cf32ffd62a7304f744d6fac11dc21af953745c5e0dcf10c11658bb17ecb5d162a17cf88bbbd5b8ff9f8a2a702ef614d7185cc882b58ae4ac378e5efcf6fd20070bbe12341b51a13336f9849d8d21b165a310c1c8fb0ddd7b03418cf9cd39d357d471b27c8d221b4881589d53a296d72917983c1825eff6c029278e17c22c48741933687c5e9fe00a85594c04244aa7eae49a1ad4f9615dd
]

2019-04-13 22:49:21,673 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x05
  5: (154 bytes) 0x46c18cf32ffd62a7304f744d6fac11dc21af953745c5e0dcf10c11658bb17ecb5d162a17cf88bbbd5b8ff9f8a2a702ef614d7185cc882b58ae4ac378e5efcf6fd20070bbe12341b51a13336f9849d8d21b165a310c1c8fb0ddd7b03418cf9cd39d357d471b27c8d221b4881589d53a296d72917983c1825eff6c029278e17c22c48741933687c5e9fe00a85594c04244aa7eae49a1ad4f9615dd
]

2019-04-13 22:49:21,673 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x05
  5: (154 bytes) 0x46c18cf32ffd62a7304f744d6fac11dc21af953745c5e0dcf10c11658bb17ecb5d162a17cf88bbbd5b8ff9f8a2a702ef614d7185cc882b58ae4ac378e5efcf6fd20070bbe12341b51a13336f9849d8d21b165a310c1c8fb0ddd7b03418cf9cd39d357d471b27c8d221b4881589d53a296d72917983c1825eff6c029278e17c22c48741933687c5e9fe00a85594c04244aa7eae49a1ad4f9615dd
]

2019-04-13 22:49:22,080 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x06
  5: (135 bytes) 0x6725e07d561bfa7d70934ba94def1ef4b31a1ce8da49997fddc4ba9e43aaa8605378bfa51b23819e74c3f89087965a92c2599bd3ee42469e42b706bdee9ad9a77d6150fb62a0cefd7aa2b874fbe3bd3af6044f66483298a05254e3bc9a4d7c23d4b796e5b14141aaf3de0463c6e8d0fdd4da3edc17c7f46c6bce187a4e2448c487afef2275d14d
]

2019-04-13 22:49:22,081 __init__.py:0067 DEBUG response: [
  6: (1 bytes) 0x06
  5: (135 bytes) 0x6725e07d561bfa7d70934ba94def1ef4b31a1ce8da49997fddc4ba9e43aaa8605378bfa51b23819e74c3f89087965a92c2599bd3ee42469e42b706bdee9ad9a77d6150fb62a0cefd7aa2b874fbe3bd3af6044f66483298a05254e3bc9a4d7c23d4b796e5b14141aaf3de0463c6e8d0fdd4da3edc17c7f46c6bce187a4e2448c487afef2275d14d
]

2019-04-13 22:49:22,084 tlv.py:0117 DEBUG receiving [
  1: (17 bytes) 0x61333a64313a35653a31663a36633a3033
  3: (32 bytes) 0x47f4a56162de3b5104b04ea4a3ded80d38b2528819a8c2137c49830c797225f8
  10: (64 bytes) 0xede3da5e7f357ac96f045bbff3b64bf025f6100607e2480a55762566a814107c4236ef78ca570d1ca65253b0af6d936669593721000e938d218625848cdd4309
]

2019-04-13 22:49:22,130 ip_implementation.py:0399 DEBUG init session
2019-04-13 22:49:22,209 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  3: (32 bytes) b'\xe8\xe5&R\xb5 I\xdb0\x10\xe2g\xe2\x80VD\xd6\xbc\x96\x9d\xcb\x13\x91r\xaa_\xc5\xc5\x9eU\xf4)'
]

2019-04-13 22:49:22,210 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  3: (32 bytes) 0xe8e52652b52049db3010e267e2805644d6bc969dcb139172aa5fc5c59e55f429
]

2019-04-13 22:49:22,210 __init__.py:0075 DEBUG write message: [
  6: (1 bytes) 0x01
  3: (32 bytes) 0xe8e52652b52049db3010e267e2805644d6bc969dcb139172aa5fc5c59e55f429
]

2019-04-13 22:49:22,253 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x02
  3: (32 bytes) 0x6a05c612e54eaec1644602f05eac95859a6feea77d3769125fdc423ee7d06a6e
  5: (101 bytes) 0x5ee784e9e00a13fa7c16c8813b4e879e266375515dd32b1531a7bd8d238547efd63d0163387ac83f68eb95d3fb048481812868d121ee7c218e29ede9ecfbf080a225a5a769e8685d155162db9ecfaf81f096636495dbd086ef102eaa85a8764698a453c968
]

2019-04-13 22:49:22,253 __init__.py:0082 DEBUG response: [
  6: (1 bytes) 0x02
  3: (32 bytes) 0x6a05c612e54eaec1644602f05eac95859a6feea77d3769125fdc423ee7d06a6e
  5: (101 bytes) 0x5ee784e9e00a13fa7c16c8813b4e879e266375515dd32b1531a7bd8d238547efd63d0163387ac83f68eb95d3fb048481812868d121ee7c218e29ede9ecfbf080a225a5a769e8685d155162db9ecfaf81f096636495dbd086ef102eaa85a8764698a453c968
]

2019-04-13 22:49:22,256 tlv.py:0117 DEBUG receiving [
  1: (17 bytes) 0x61333a64313a35653a31663a36633a3033
  10: (64 bytes) 0x8f667540b07073dcf500225fc7becc8eeaa90bfae348af4da61eb6d97cadd9eca441d6630db2ab35f83427aef0f6e81a4c6091915e8db683c9956514f6ff940c
]

2019-04-13 22:49:22,263 tlv.py:0134 DEBUG sending [
  1: (36 bytes) b'23f4dc6d-45ff-44ad-8057-4db76babd60d'
  10: (64 bytes) b'\xa1\xcd\xcd\x98\x9f{T\xc2\xfb\x08\xf0\xe4\x1a\xc6|\xb9w7-\\\xf9\x07^\x04+\x16\xad\xe0nA\\\xc2W\x00\'=\xfb\xe4"p>\x86\xfc\x9f\x8d\xbc\xae\xfc\x8d~\x8a\xa3\x82\x86\xeb\xc6[\xa8\x8d\xfaU\xe9\x10\x00'
]

2019-04-13 22:49:22,266 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x47225e29d54b7ae043ad8c5550ec41fdd3692cc048d1871450267e833a6952fe4d238a6046c351a13c73201a02ddbb22f0f4e87d7ba3725817c8d4f96654452261b35a24f911463c675293b219bccf8f67f9ba951a486c522e335997376801d0dadd1d5b28a2c97625d2b718b2f0d53cc7d1870fa522b9c2
]

2019-04-13 22:49:22,266 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x47225e29d54b7ae043ad8c5550ec41fdd3692cc048d1871450267e833a6952fe4d238a6046c351a13c73201a02ddbb22f0f4e87d7ba3725817c8d4f96654452261b35a24f911463c675293b219bccf8f67f9ba951a486c522e335997376801d0dadd1d5b28a2c97625d2b718b2f0d53cc7d1870fa522b9c2
]

2019-04-13 22:49:22,266 __init__.py:0075 DEBUG write message: [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x47225e29d54b7ae043ad8c5550ec41fdd3692cc048d1871450267e833a6952fe4d238a6046c351a13c73201a02ddbb22f0f4e87d7ba3725817c8d4f96654452261b35a24f911463c675293b219bccf8f67f9ba951a486c522e335997376801d0dadd1d5b28a2c97625d2b718b2f0d53cc7d1870fa522b9c2
]

2019-04-13 22:49:22,346 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x04
]

2019-04-13 22:49:22,346 __init__.py:0082 DEBUG response: [
  6: (1 bytes) 0x04
]

2019-04-13 22:49:22,347 ip_implementation.py:0426 DEBUG session established
Expecting value: line 1 column 1 (char 0)
2019-04-13 22:49:32,363 pair.py:0085 DEBUG Expecting value: line 1 column 1 (char 0)
Traceback (most recent call last):
  File "/home/cf/homekit_test/lib/python3.6/site-packages/homekit/pair.py", line 80, in <module>
    pairing.list_accessories_and_characteristics()
  File "/home/cf/homekit_test/lib/python3.6/site-packages/homekit/controller/ip_implementation.py", line 81, in list_accessories_and_characteristics
    accessories = json.loads(tmp)['accessories']
  File "/usr/lib/python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Jc2k commented 5 years ago

Ok - next step is to figure out how to clear the homekit pairing on the bridge - i think it will now think its paired, but on the python code side it crashed before it saved the crypto keys.

It's hard to tell what's going on in that function because by that point it is encrypted in the pcap dumps. I have a few ideas but it will probably be tomorrow now.

Jc2k commented 5 years ago

I used the homekit library to make a mock accessory, then dumped out the HTTP requests right after decrypting them. Right now, only /accessories is relevant but i did a few types while i was in there.

Decrypted HTTP requests from iPhone client:

GET /accessories HTTP/1.1
Host: DemoAccessory._hap._tcp.local

GET /characteristics?id=1.10 HTTP/1.1
Host: DemoAccessory._hap._tcp.local

PUT /characteristics HTTP/1.1
Host: DemoAccessory._hap._tcp.local
Content-Length: 52
Content-Type: application/hap+json

Decrypted HTTP requests from HA/homekit_python client:

GET /accessories HTTP/1.1

GET /characteristics?id=1.10&meta=0&perms=0&type=0&ev=0 HTTP/1.1

PUT /characteristics HTTP/1.1
Content-Type: application/hap+json
Content-Length: 56

The most stand out difference is that for encrypted sessions we aren't sending a Host header at all.

My latest change adds a Host header to the 3 request types. Pick up the change the same way as before:

$ source venv/bin/activate
$ pip install -U https://github.com/Jc2k/homekit_python/archive/fix_tado_bridge.zip

Make sure pip reports it had uninstalled and then installed homekit or you might still have the old code.

Then you'll probaby need to reset HomeKit on the tado to make it forget its paired:

https://support.tado.com/hc/en-gb/articles/115005185843-How-do-I-perform-a-HomeKit-configuration-reset-of-the-Internet-Bridge-

Then follow the pairing steps again.

cf00 commented 5 years ago

Success!

# python -m homekit.pair -f test.json -p XXX-XX-XXX -a test -d cf:35:33:9d:4b:91 --log DEBUG
2019-04-14 09:53:14,895 __init__.py:0106 DEBUG #1 ios -> accessory: send SRP start request
2019-04-14 09:53:14,896 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-14 09:53:14,896 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-14 09:53:14,896 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x01
  0: (1 bytes) 0x01
]

2019-04-14 09:53:16,037 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x02
  3: (384 bytes) 0x608867e07404d6067f2c21a1cbeffdac5c859d33364f51764604688797b3002c5a46a4757816424179fcaa94376b4a9c92cdf4114ff93ebe8f6526a20973901fe3e89e25a931b176e6cac14a050465728a98ea2bf97a5855c5b0953e9edc3b9f26d754f1594ca18b949ebd0b295c720891ec75bde7d72e68f063015c4d0394f69b16c4e8bf01cbafef8c3c790cfdab3b5e8b035f18e66630c4722bd40ea0833383240372e23514fe9c0f816b12a920f2afb6f8073d36ec64fde2ef4f5476a865dee79812bc4e22a6be238f4e01e8c923d8a24178d1dabaac9221f0058d67a50c1f11409393c1dcfea07356076b229e23a07fdb5cb8adf8996bf3ec7d6e4670ee42baaab4a705cb56404350bb37af1c5238a4e0307557eddfa57995da6cf319a576f757bfd3862d00bb76362b065c74b47327f47812dfbe687f3cfc34a71260bc5893d3d6c22409ede5bc93687b124082d892c9b0b14e7826cd1b1bdec20a9a1b081e57da1798dfe5522ef5d09aef970ff23f1ff3a4b9932f5a03390e3b21bf2a
  2: (16 bytes) 0xa0912d467fd05228f5e8d4515cd837ab
]

2019-04-14 09:53:16,038 __init__.py:0067 DEBUG response: [
  6: (1 bytes) 0x02
  3: (384 bytes) 0x608867e07404d6067f2c21a1cbeffdac5c859d33364f51764604688797b3002c5a46a4757816424179fcaa94376b4a9c92cdf4114ff93ebe8f6526a20973901fe3e89e25a931b176e6cac14a050465728a98ea2bf97a5855c5b0953e9edc3b9f26d754f1594ca18b949ebd0b295c720891ec75bde7d72e68f063015c4d0394f69b16c4e8bf01cbafef8c3c790cfdab3b5e8b035f18e66630c4722bd40ea0833383240372e23514fe9c0f816b12a920f2afb6f8073d36ec64fde2ef4f5476a865dee79812bc4e22a6be238f4e01e8c923d8a24178d1dabaac9221f0058d67a50c1f11409393c1dcfea07356076b229e23a07fdb5cb8adf8996bf3ec7d6e4670ee42baaab4a705cb56404350bb37af1c5238a4e0307557eddfa57995da6cf319a576f757bfd3862d00bb76362b065c74b47327f47812dfbe687f3cfc34a71260bc5893d3d6c22409ede5bc93687b124082d892c9b0b14e7826cd1b1bdec20a9a1b081e57da1798dfe5522ef5d09aef970ff23f1ff3a4b9932f5a03390e3b21bf2a
  2: (16 bytes) 0xa0912d467fd05228f5e8d4515cd837ab
]

2019-04-14 09:53:16,038 __init__.py:0118 DEBUG #3 ios -> accessory: send SRP verify request
2019-04-14 09:53:16,083 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xebe1ffb5fd386845a48f4b2fb540509297da809b26a53582d8237edf28c3bd99445c2e6b617dfcfbec684c8291d5f55b4874777f2618bd1ab56b46cc6eba757b37ccc19332027712137510bdd4797033c8a8c312aebdc0dbe322bdd4a5255d7ca4c4d25c1888184e29cfe394a24858e5da69a20c73622fa061e7c1e7a5f8df7871adcc5170f6219ab53312f3a8c34f602fa7816bbff8d979abdde07114b378488301c5df9e00232ef8738fc4e23b86c3748d7d8d7b2af39590e7befb70eae20d7d93dd63f25675791d72808f57684af775e68f8c79886e0727e196eb2de69013a5d9f87e06da8e90663f7c25544cde04bb7849c1b051c602ea5b85849d4bffb84caee2a2317f0751ef61b5a435e79f084fcefaf5461e225304e1929e695c604055e6efea36b23dec1160126c31c3f3515746ae04178f51c4dca1b6932bcbba011454fd1f301c87b13cec3c771f01a0768be387dba9211c299c88ae794c464550eb4cb27c3be7a0445b5fa90d4808a9e6974e9c6616126ad9cca6be94e951b5d8
  4: (64 bytes) 0xbe90fc95199b146b00dc66574df10da47be4be62eeae631c812839f63de31a1adfa9c27ba4854739c3b63e4ede36155de82c1b5499439bcfc2f76bc8fc867aea
]

2019-04-14 09:53:16,084 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xebe1ffb5fd386845a48f4b2fb540509297da809b26a53582d8237edf28c3bd99445c2e6b617dfcfbec684c8291d5f55b4874777f2618bd1ab56b46cc6eba757b37ccc19332027712137510bdd4797033c8a8c312aebdc0dbe322bdd4a5255d7ca4c4d25c1888184e29cfe394a24858e5da69a20c73622fa061e7c1e7a5f8df7871adcc5170f6219ab53312f3a8c34f602fa7816bbff8d979abdde07114b378488301c5df9e00232ef8738fc4e23b86c3748d7d8d7b2af39590e7befb70eae20d7d93dd63f25675791d72808f57684af775e68f8c79886e0727e196eb2de69013a5d9f87e06da8e90663f7c25544cde04bb7849c1b051c602ea5b85849d4bffb84caee2a2317f0751ef61b5a435e79f084fcefaf5461e225304e1929e695c604055e6efea36b23dec1160126c31c3f3515746ae04178f51c4dca1b6932bcbba011454fd1f301c87b13cec3c771f01a0768be387dba9211c299c88ae794c464550eb4cb27c3be7a0445b5fa90d4808a9e6974e9c6616126ad9cca6be94e951b5d8
  4: (64 bytes) 0xbe90fc95199b146b00dc66574df10da47be4be62eeae631c812839f63de31a1adfa9c27ba4854739c3b63e4ede36155de82c1b5499439bcfc2f76bc8fc867aea
]

2019-04-14 09:53:16,084 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x03
  3: (384 bytes) 0xebe1ffb5fd386845a48f4b2fb540509297da809b26a53582d8237edf28c3bd99445c2e6b617dfcfbec684c8291d5f55b4874777f2618bd1ab56b46cc6eba757b37ccc19332027712137510bdd4797033c8a8c312aebdc0dbe322bdd4a5255d7ca4c4d25c1888184e29cfe394a24858e5da69a20c73622fa061e7c1e7a5f8df7871adcc5170f6219ab53312f3a8c34f602fa7816bbff8d979abdde07114b378488301c5df9e00232ef8738fc4e23b86c3748d7d8d7b2af39590e7befb70eae20d7d93dd63f25675791d72808f57684af775e68f8c79886e0727e196eb2de69013a5d9f87e06da8e90663f7c25544cde04bb7849c1b051c602ea5b85849d4bffb84caee2a2317f0751ef61b5a435e79f084fcefaf5461e225304e1929e695c604055e6efea36b23dec1160126c31c3f3515746ae04178f51c4dca1b6932bcbba011454fd1f301c87b13cec3c771f01a0768be387dba9211c299c88ae794c464550eb4cb27c3be7a0445b5fa90d4808a9e6974e9c6616126ad9cca6be94e951b5d8
  4: (64 bytes) 0xbe90fc95199b146b00dc66574df10da47be4be62eeae631c812839f63de31a1adfa9c27ba4854739c3b63e4ede36155de82c1b5499439bcfc2f76bc8fc867aea
]

2019-04-14 09:53:19,114 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x04
  4: (64 bytes) 0xbd8dba9e33869b7dc2b9af5c6b44a2d61b4ade9f1af125c9f73ef2b868098a574a0f8d0c8527fe2dbeaa2714655c716c65e74c1fe3ed0bccb394b123dd3bcc12
]

2019-04-14 09:53:19,114 __init__.py:0067 DEBUG response: [
  6: (1 bytes) 0x04
  4: (64 bytes) 0xbd8dba9e33869b7dc2b9af5c6b44a2d61b4ade9f1af125c9f73ef2b868098a574a0f8d0c8527fe2dbeaa2714655c716c65e74c1fe3ed0bccb394b123dd3bcc12
]

2019-04-14 09:53:19,114 __init__.py:0169 DEBUG #5 ios -> accessory: send SRP exchange request
2019-04-14 09:53:19,234 tlv.py:0134 DEBUG sending [
  1: (36 bytes) b'99e5afd4-a211-48b5-a8a9-bdbc5f0389e2'
  3: (32 bytes) b"\xc9&\xda\x94\xbb\xa4\xc6\xfb\xd4\xf4\xe9\x07[\xbd\xf7\xd7\x82\x889\x1a'E:A j\xe2\xa7\xd77\n\xde"
  10: (64 bytes) b"\x88>\xe3\xcf\xea\xd4\x9f\xb7p\xf4\x8d\xa5\xff2['\x9bL\x9al$\xa2_Q\xc5\x82z\x9d\x94\x17\x89\xc2A[1\x0e\xd6\xc8o\xa8P\xec\x7fM\x0bsv\xce\xf6\x0c\xa9\xe6\xc0\x03v\x14e\xfa\xb8\xcd\x12\x9e\xc5\x00"
]

2019-04-14 09:53:19,237 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x05
  5: (154 bytes) 0xfa04d738913993285891dc5978f127e56d7cb4d34d695aac5dc00e83b3d0ab711e12fd2152abbc8dc058eade63efa07f092d9f1f9be53c5b4d52026c828d64868cf959458f6c3e8b46db5e21ef3f4550ba438f6ff672e336a9e0bec9d5f7399d2b9d56142c58a406d771f6c8c22bd8ebb6e2a8710854a84f969b96b1618dd31a1f8783531f4ed6defc6407a902109e648758dbb5d1d121f88700
]

2019-04-14 09:53:19,237 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x05
  5: (154 bytes) 0xfa04d738913993285891dc5978f127e56d7cb4d34d695aac5dc00e83b3d0ab711e12fd2152abbc8dc058eade63efa07f092d9f1f9be53c5b4d52026c828d64868cf959458f6c3e8b46db5e21ef3f4550ba438f6ff672e336a9e0bec9d5f7399d2b9d56142c58a406d771f6c8c22bd8ebb6e2a8710854a84f969b96b1618dd31a1f8783531f4ed6defc6407a902109e648758dbb5d1d121f88700
]

2019-04-14 09:53:19,237 __init__.py:0060 DEBUG write message: [
  6: (1 bytes) 0x05
  5: (154 bytes) 0xfa04d738913993285891dc5978f127e56d7cb4d34d695aac5dc00e83b3d0ab711e12fd2152abbc8dc058eade63efa07f092d9f1f9be53c5b4d52026c828d64868cf959458f6c3e8b46db5e21ef3f4550ba438f6ff672e336a9e0bec9d5f7399d2b9d56142c58a406d771f6c8c22bd8ebb6e2a8710854a84f969b96b1618dd31a1f8783531f4ed6defc6407a902109e648758dbb5d1d121f88700
]

2019-04-14 09:53:20,575 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x06
  5: (135 bytes) 0x67a32cddb67ccfd765715f25dccee02d5e4d45a75b162c6d0e3c9afb10a2734817b280d3eaa529f22ffa27c912415fad81d51eb971ec4de49957c67d6d695f6e95661f607056038a00e85e8a57ca232af3171de7ba6e7782baef1c3de22da6fdd2eaacd10dec82b9ee3760cd236cb122737e9908393494224d10cad8413d9fb4710f713092bf38
]

2019-04-14 09:53:20,576 __init__.py:0067 DEBUG response: [
  6: (1 bytes) 0x06
  5: (135 bytes) 0x67a32cddb67ccfd765715f25dccee02d5e4d45a75b162c6d0e3c9afb10a2734817b280d3eaa529f22ffa27c912415fad81d51eb971ec4de49957c67d6d695f6e95661f607056038a00e85e8a57ca232af3171de7ba6e7782baef1c3de22da6fdd2eaacd10dec82b9ee3760cd236cb122737e9908393494224d10cad8413d9fb4710f713092bf38
]

2019-04-14 09:53:20,578 tlv.py:0117 DEBUG receiving [
  1: (17 bytes) 0x63663a33353a33333a39643a34623a3931
  3: (32 bytes) 0x4dd47cb2d600bd12b17371f00e10d365fa50d996b236e3f49629ef52ff9485e0
  10: (64 bytes) 0x43cb2c1a0c510d651b5c90d0b58c6d807b74d294a1a7d42aa99da4666fc368ea97d20f4c8c04c6e44c66717ddba135643b16a9f9914ac2d2256147df3eb5280a
]

2019-04-14 09:53:20,621 ip_implementation.py:0399 DEBUG init session
2019-04-14 09:53:20,688 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x01
  3: (32 bytes) b'()\xdf\xa7\tT\x16\x1e\xbd\xe5\xff\xa1\x080o\x07\xc3\xb4\x81\xbd\xbd\xcez\xda\xda\x98\xc8S\xb1\xc6Ar'
]

2019-04-14 09:53:20,688 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x01
  3: (32 bytes) 0x2829dfa70954161ebde5ffa108306f07c3b481bdbdce7adada98c853b1c64172
]

2019-04-14 09:53:20,688 __init__.py:0075 DEBUG write message: [
  6: (1 bytes) 0x01
  3: (32 bytes) 0x2829dfa70954161ebde5ffa108306f07c3b481bdbdce7adada98c853b1c64172
]

2019-04-14 09:53:20,732 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x02
  3: (32 bytes) 0x1344be3244ed13b367f8017fa08c758b3559ff3b738807081f45885db5c8543e
  5: (101 bytes) 0x81ea55e9016156c3c567e04c82455b3b66d2b0feb9ff61f9365de28e133cb6550133f9168d8cb5b52f993a17647059317d8fe5f6a4e58535ec31d9189214de3f0aaa24d68c39d0fb143a91ccfd7ab74754c649732b83bd9c64ae8104d075d35556ab37c4b8
]

2019-04-14 09:53:20,732 __init__.py:0082 DEBUG response: [
  6: (1 bytes) 0x02
  3: (32 bytes) 0x1344be3244ed13b367f8017fa08c758b3559ff3b738807081f45885db5c8543e
  5: (101 bytes) 0x81ea55e9016156c3c567e04c82455b3b66d2b0feb9ff61f9365de28e133cb6550133f9168d8cb5b52f993a17647059317d8fe5f6a4e58535ec31d9189214de3f0aaa24d68c39d0fb143a91ccfd7ab74754c649732b83bd9c64ae8104d075d35556ab37c4b8
]

2019-04-14 09:53:20,734 tlv.py:0117 DEBUG receiving [
  1: (17 bytes) 0x63663a33353a33333a39643a34623a3931
  10: (64 bytes) 0x11d13ec860cb519cf8ad32587602a72dc912f01fac0cc3cb3c94a65ae18f7c56bae34dbd4b9293a0dfae7007a618c4d97b2f98c48ba8e57c0842fc0ee1c0f40c
]

2019-04-14 09:53:20,738 tlv.py:0134 DEBUG sending [
  1: (36 bytes) b'99e5afd4-a211-48b5-a8a9-bdbc5f0389e2'
  10: (64 bytes) b"L\xf3\x86Kd\x00\xb2A\xf2J\xfd\xa2\xe7@\xeb\x98e\xc3\xef'|U\x80\x17\x14\x98\x0e?O5\xf5\x07\xef%\x1f\xe1cF1:\x07\x9fl\xfe\xa1\xc2\x1aW\xee\xac\xf4A\x19Q\xa5\xac\t\x8eM\x02\xa6IO\n"
]

2019-04-14 09:53:20,740 tlv.py:0134 DEBUG sending [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x47d60563806cdf3ee4f96cd89cbec61456ec22316c14ccb67a0418a75cdbd1c981103bad5b27cb6277dbe195bceea085c6ae3db8deb832b94569f3b834a118f48d4d47a15fd71d90881b231dbcda78b6b75c584affb2a8570f4edcd7c93908b49c71b95ca7c5cc2e2fcb82461b48fd90ef293ce3b97fd3ab
]

2019-04-14 09:53:20,740 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x47d60563806cdf3ee4f96cd89cbec61456ec22316c14ccb67a0418a75cdbd1c981103bad5b27cb6277dbe195bceea085c6ae3db8deb832b94569f3b834a118f48d4d47a15fd71d90881b231dbcda78b6b75c584affb2a8570f4edcd7c93908b49c71b95ca7c5cc2e2fcb82461b48fd90ef293ce3b97fd3ab
]

2019-04-14 09:53:20,740 __init__.py:0075 DEBUG write message: [
  6: (1 bytes) 0x03
  5: (120 bytes) 0x47d60563806cdf3ee4f96cd89cbec61456ec22316c14ccb67a0418a75cdbd1c981103bad5b27cb6277dbe195bceea085c6ae3db8deb832b94569f3b834a118f48d4d47a15fd71d90881b231dbcda78b6b75c584affb2a8570f4edcd7c93908b49c71b95ca7c5cc2e2fcb82461b48fd90ef293ce3b97fd3ab
]

2019-04-14 09:53:20,825 tlv.py:0117 DEBUG receiving [
  6: (1 bytes) 0x04
]

2019-04-14 09:53:20,825 __init__.py:0082 DEBUG response: [
  6: (1 bytes) 0x04
]

2019-04-14 09:53:20,825 ip_implementation.py:0426 DEBUG session established
Pairing for "test" was established.
cf00 commented 5 years ago

I went ahead and applied the fix to my homeassistant instance:

I can now pair the bridge and the climate devices (both smart thermostats and radiator thermostats) show up in homeassistant with the following attributes:

current_temperature: 22.2
min_temp: 7
max_temp: 35
temperature: null
operation_mode: heat
friendly_name: tado Smart Thermostat RU2280984064
supported_features: 129

So it doesn't report the currently set target temperature. The UI doesn't work, but I can successfully use climate.set_temperature and climate.set_operation_mode to set the target temperature and turn it on and off.

Using climate.set_temperature works but throws an error in the log:

2019-04-14 10:04:02 ERROR (MainThread) [homeassistant.core] Error doing job: Future exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/app/homeassistant/components/homekit_controller/__init__.py", line 189, in discovery_dispatch
    device.pairing_info is not None:
AttributeError: 'HKDevice' object has no attribute 'pairing_info'
Jc2k commented 5 years ago

Excellent news.

I've already opened a PR for adding Humidity support - it is available here.

The pairing_info bug is also squished here.

The HA maintainers are really busy, but hopefully both of them should land soon.

I'll see what I can see about the target temperature not showing.

Jc2k commented 5 years ago

There is one command i'd like to see the output of with the old CLI setup, first in human format:

python -m homekit.get_accessories -f test.json -a test

This should dump a table like this:

1.2: >accessory-information<
  1.3:  (Identify) >identify< [pw]
  1.4: lusiardi.de (Manufacturer) >manufacturer< [pr]
  1.5: Demoserver (Model) >model< [pr]
  1.6: Testlicht (Name) >name< [pr]
  1.7: 0001 (Serial Number) >serial-number< [pr]
  1.8: 0.1 (Firmware Revision) >firmware.revision< [pr]
1.9: >lightbulb<
  1.10: False (Switch state (on/off)) >on< [pw,pr,ev]

It will have a lot more entries for you. This will tell us if your device has all the characteristics we are expecting and if pr isn't set then the characteristic isn't readable for some reason. It will also read the value of the characteristic and show us if its a HA bug or a homekit_python bug or something else.

Then there is a version of this comand that returns the data as JSON. I'd like to see a copy of that as it means I can create a virtual/mock tado bridge locally and see what the problem with the UI is. It also means I can add some integration tests to HA to protect you from regressions in the future. The command for that is:

python -m homekit.get_accessories -f test.json -a test4 -o json

It looks like it tries to read the target temperature already, so hopefully with this we can figure out why it's not working for you.

cf00 commented 5 years ago

Here you are:

tado_get_accessories.txt tado_get_accessories_json.txt

Jc2k commented 5 years ago

Can you describe what you are trying to do in the UI? E.g. for me, it looks like setting the target temperature works. Setting the operation mode doesn't work because the drop down isn't populated, but i think thats because my mock isn't complete, still working on it. Right now I get:

current_temperature: 21.8
min_temp: 7
max_temp: 35
temperature: 21.5
operation_mode: heat
friendly_name: tado Smart Radiator Thermostat VA0032246272
supported_features: 129

I do seem to see both temperature and current_temperature for all of your thermostats.

(I am testing with dev though - what tag are you running and i can try that).

Jc2k commented 5 years ago

^ sent in a PR for the list of supported operations not being populated correctly.

Jc2k commented 5 years ago

Have opened upstream PR https://github.com/jlusiardi/homekit_python/pull/130 for the pairing changes.

cf00 commented 5 years ago

In the UI, the target temperature setting doesn't show up at all, and the drop-down isn't populated, so there is nothing I can change in the UI. Current temperature and current operation mode (idle, heat or off) is displayed correctly (but both update only with about one minute delay - would that be normal?).

Other than what you see, I still see the attribute temperature: null.

I understand that the humidity and operation_list attributes are supposed to eventually show up once the PRs you mentioned are implemented?

Have you come across any other sensor values which could be retrieved via homekit? I am particularily interested in the Heating Power value (a % value indicating how much heat the device is requesting). I can retrieve it with a rest sensor through their cloud api but it would be very nice to have that locally too.

I am on the normal homeassistant (docker) version 0.91.3.

Jc2k commented 5 years ago

It is very weird about target temp. With the JSON you’ve sent me the same code on my end can see the target, and I can set it through the UI. We will need to do some more debugging there.

The delay is normal for now. HomeKit has events, and so does the library we are using, but stitching it all together is going to take a while.

Hopefully yes - we are 2 merged away from operation list and humidity.

There is one non official characteristic ID that I haven’t looked at yet. But it looks write only. All the endpoints we can see are in the text file you sent if you can see your value there let me know.

If I put together a branch with all the changes merged would you be able to test it?

cf00 commented 5 years ago

I am sure I could manage if your provide instructions taking into account my general level of incompetence in those things.

The json I sent was from the bridge paired in the venv outside homeassistant. How can I run homekit.get_accessories with the bridge paired in homeassistant? What would be the parameters for the -f and -a arguments?

cf00 commented 5 years ago

@jimz011 I can now confirm that tado via homekit works without the cloud. I tested it by blocking the interent access of the bridge and I could set temperatures and turn the devices on and off via the homekit component.