michaelarnauts / aiocomfoconnect

Python AsyncIO Zehnder ComfoConnect LAN C library to interface with ComfoAir Q350/450/600 units.
Other
75 stars 16 forks source link

Q350 cannot be discovered and cannot connect #44

Open marioverhaeg opened 1 month ago

marioverhaeg commented 1 month ago

Hi, The connection to my Q350 doesn't work. I have a feeling this is related to the PIN, but I don't think I can change this in the device. Error when connecting:

_python -m aiocomfoconnect --debug register --host 192.168.20.36

DEBUG:asyncio:Using proactor: IocpProactor INFO:asyncio:Datagram endpoint local_addr=('0.0.0.0', 0) remote_addr=None created: (<_ProactorDatagramTransport fd=424>, <aiocomfoconnect.discovery.BridgeDiscoveryProtocol object at 0x0000021860064980>) DEBUG:aiocomfoconnect.discovery:Socket has been created DEBUG:aiocomfoconnect.discovery:Sending discovery request to 192.168.20.36:56747 DEBUG:aiocomfoconnect.discovery:Data received from ('192.168.20.36', 56747): b'\x12#\n\r192.168.20.36\x12\x10\x00\x00\x00\x00\x00\x10\x10\x18\x80\x01\x14O\xd7\x1d\xefV\x18\x01' DEBUG:aiocomfoconnect.bridge:Connecting to bridge 192.168.20.36 DEBUG:asyncio:<asyncio.TransportSocket fd=508, family=2, type=1, proto=6, laddr=('192.168.20.100', 62312), raddr=('192.168.20.36', 56747)> connected to 192.168.20.36:56747: (<_ProactorSocketTransport fd=508 read=<_OverlappedFuture pending cb=[_ProactorReadPipeTransport._loop_reading()] created at C:\Users\mverh\AppData\Local\Programs\Python\Python312\Lib\asyncio\windows_events.py:506>>, <asyncio.streams.StreamReaderProtocol object at 0x00000218600B7F50>) DEBUG:aiocomfoconnect.bridge:Connected to bridge 192.168.20.36 DEBUG:aiocomfoconnect.bridge:StartSessionRequest DEBUG:aiocomfoconnect.bridge:Adding listener for event 1 DEBUG:aiocomfoconnect.bridge:TX 00000000000000000000000000000001 -> 00000000001010188001144fd71def56: 08032001 0801 type: StartSessionRequestType reference: 1

takeover: true

DEBUG:aiocomfoconnect.bridge:RX 00000000001010188001144fd71def56 -> 00000000000000000000000000000001: 083510052001 type: StartSessionConfirmType result: NOT_ALLOWED reference: 1

DEBUG:aiocomfoconnect.bridge:Emitting for event 1_

Is the PIN the "password" that needs to be used when logging into the display on the device? If so, can I change the default PIN with a parameter, or do I need to adjust the code for this?

michaelarnauts commented 1 month ago

You can pass --pin for this.

marioverhaeg commented 1 month ago

I'm getting the same error. Is the PIN equal to the password on the unit itself or is this something different?

michaelarnauts commented 1 month ago

Not sure. It's what you also need to enter in the mobile app to register.

marioverhaeg commented 1 month ago

Thank you for your fast responses.

I changed the PIN but still get a NOT_ALLOWED error.

marioverhaeg commented 1 month ago

Hi Michael, could it be that the PIN argument is not used in the code? Looking at line 86 of main.py you're only passing the found bridge and the UUID to the connect method. If the PIN is not passed this would explain why there is no difference in behavior between the different PINs?

michaelarnauts commented 1 month ago

The pin is passed to cmd_register_app‎ at line 97. To login, only the UUID is needed. It's only when registering that the pin needs to be passed.

The library is using a DEFAULT_UUID of 000...1, maybe this is giving issues. You could try to change this, or pass another --uuid on the command line. It needs to be a random 32 char hexadecimal string.

marioverhaeg commented 1 month ago

Got it working now with a test sample. Thanks!

michaelarnauts commented 1 month ago

Can you indicate what the problem was and how you fixed it? This might help someone in the future :)

marioverhaeg commented 1 month ago

Sure: I've created a short test script and this works fine now.

`import asyncio

from aiocomfoconnect import ComfoConnect from aiocomfoconnect.const import VentilationSpeed from aiocomfoconnect.sensors import SENSORS

async def main(): """ Basic example.""" uuid = '00000000001010188001144fd71def56' local_uuid = '74FFBA365BB2E62C635349CE17881B09' host = 'x.x.x.x' pin = 'xxxx' name = 'pythontest' registered = False

# Connect to the bridge
comfoconnect = ComfoConnect(host, uuid)

try:
    # Login
    await comfoconnect.connect(local_uuid)
    print("UUID is already registered: " + local_uuid)
    registered = True
except:    
    print("UUID is not registered: " + local_uuid)
    try:
        # Register application
        await comfoconnect.cmd_register_app(local_uuid, name, pin)
        print(f"UUID {local_uuid} is now registered.")
    except:
        await comfoconnect.disconnect()
        print("Registration failed. Please check the PIN.")
await comfoconnect.disconnect()

if registered:
    def sensor_callback(sensor, value):
        """ Print sensor updates. """
        print(f"{sensor.name} = {value}")

    comfoconnect = ComfoConnect(host, uuid, sensor_callback=sensor_callback)
    await comfoconnect.connect(local_uuid)

    # Register all sensors
    for key in SENSORS:
        await comfoconnect.register_sensor(SENSORS[key])
    # Wait 2 minutes so we can see some sensor updates
    await asyncio.sleep(120)

    # Disconnect from the bridge
    await comfoconnect.disconnect()

if name == "main": asyncio.run(main())

`

blueglyph commented 3 weeks ago

I assume the correct Python program is this one (the one above has a funny indentation and mispelled __name__ and __main__). Hope it helps.

Note that host and pin must be changed with the actual values before running this script.

import asyncio

from aiocomfoconnect import ComfoConnect
from aiocomfoconnect.const import VentilationSpeed
from aiocomfoconnect.sensors import SENSORS

async def main():
    """ Basic example."""
    uuid = '00000000001010188001144fd71def56'
    local_uuid = '74FFBA365BB2E62C635349CE17881B09'
    host = 'x.x.x.x'
    pin = 'xxxx'
    name = 'pythontest'
    registered = False

    # Connect to the bridge
    comfoconnect = ComfoConnect(host, uuid)

    try:
        # Login
        await comfoconnect.connect(local_uuid)
        print("UUID is already registered: " + local_uuid)
        registered = True
    except:    
        print("UUID is not registered: " + local_uuid)
        try:
            # Register application
            await comfoconnect.cmd_register_app(local_uuid, name, pin)
            print(f"UUID {local_uuid} is now registered.")
        except:
            await comfoconnect.disconnect()
            print("Registration failed. Please check the PIN.")

    await comfoconnect.disconnect()

    if registered:
        def sensor_callback(sensor, value):
            """ Print sensor updates. """
            print(f"{sensor.name} = {value}")

        comfoconnect = ComfoConnect(host, uuid, sensor_callback=sensor_callback)
        await comfoconnect.connect(local_uuid)

        # Register all sensors
        for key in SENSORS:
            await comfoconnect.register_sensor(SENSORS[key])
        # Wait 2 minutes so we can see some sensor updates
        await asyncio.sleep(120)

        # Disconnect from the bridge
        await comfoconnect.disconnect()

if __name__ == "__main__":
    asyncio.run(main())

Yet, it fails for me, too, as does any command like register, discover, or show-sensors (even if I give the IP address that it fails to discover).

It's a Q600, with a ComfoConnect Gateway firmware version U1.1.10 (I think there's a newer version, but I can't get a straight answer from Zehnder's support, which is abysmal).

Should I report that in a new issue, or is that something being worked on? It looks like the latter.

marioverhaeg commented 3 weeks ago

For me this is working at this moment.

blueglyph commented 3 weeks ago

Yes, you said so before. Good for you, I guess. 😉