nathanvdh / airtouch2-python

Python client for the Polyaire AirTouch 2 airconditioning system
MIT License
7 stars 6 forks source link

Don't expect magic byte in received addresses #9

Closed phardy closed 1 year ago

phardy commented 1 year ago

Here's what I did:

at2plus_test.py receives a status message and errors out:

Read payload of size 8: 55:55:9f:80:33:c0:00:12
ValueError: Unexpected address byte: expected 0xb0, got 0x9f
Failed reading header, trying again
Read payload of size 8: 23:00:00:00:00:0a:00:01
ValueError: Message header magic is invalid

There's several other 8-byte payloads that also, obviously, complain about invalid header magic. But put together they do look a lot like a valid AC status message (0x23).

The protocol documentation only says this about the address for received messages:

When receiving from AirTouch, last byte of address will be 0x80 or 0x90 (for Extended message).

I'm getting the impression the controller only uses an address of 0xb0 0x80 when it's replying to the client that requested the status, and a different address otherwise (perhaps 0x9f represents an automatic status message as a result of a status change?). The way I read the documentation though, the first byte of the address from the controller is undefined.

So this PR simply ignores the first byte of the address in received messages. Repeating the above test with this branch, after changing the fan speed the test script outputs this:

Read payload of size 8: 55:55:9f:80:35:c0:00:12
Read payload of size 18: 23:00:00:00:00:0a:00:01:10:12:50:c1:02:b2:00:00:80:00
Read payload of size 2: f0:bc
Handling status message

            id: 0
            power: 1
            mode: 1
            fan_speed: 2
            set_point: 18.0
            temperature: 19.0
            turbo: False
            bypass: False
            spill: False
            timer: True
            error: 0

        id: 0
        name: Daikin
        start_group: 0
        group_count: 4
        supported_modes: [<AcSetMode.AUTO: 0>, <AcSetMode.HEAT: 1>, <AcSetMode.DRY: 2>, <AcSetMode.FAN: 3>, <AcSetMode.COOL: 4>]
        supported_fan_speeds: [<AcFanSpeed.AUTO: 0>, <AcFanSpeed.LOW: 2>, <AcFanSpeed.MEDIUM: 3>, <AcFanSpeed.HIGH: 4>]
        setpoint_limits:
        cool:
        min: 16
        max: 16

        heat:
        min: 16
        max: 16

Updated AC 0 with value
            id: 0
            power: 1
            mode: 1
            fan_speed: 2
            set_point: 18.0
            temperature: 19.0
            turbo: False
            bypass: False
            spill: False
            timer: True
            error: 0

Finished handling status message

Worth noting that very shortly afterwards another status message is received by the test script, this time with an address of 0xb0 0x80. Huh.

Read payload of size 8: 55:55:b0:80:28:c0:00:12
Read payload of size 18: 23:00:00:00:00:0a:00:01:10:12:50:c1:02:b2:00:00:80:00
Read payload of size 2: cf:59
nathanvdh commented 1 year ago

There's several other 8-byte payloads that also, obviously, complain about invalid header magic. But put together they do look a lot like a valid AC status message (0x23).

Because if it fails to read a header, it continues to try and read the next 8 bytes as a header, with the assumption that eventually it'll find the header of the next message. So yes, you'll see all the bytes of the 0x23 message as it goes through them, 8 at a time.

The way I read the documentation though, the first byte of the address from the controller is undefined

This could be true, they really don't like being explicit...

I don't like the idea of silently ignoring that byte, so far we've identified it's either 0xb0 (as the spec says) or 0x9f. I'd rather add it to a list of magic bytes we expect could go there (currently [0xb0, 0x9f]). I want the software to crash whenever something unexpected happens so people actually notice and have to complain to get it fixed, and then I can learn more about how it actually works. The most helpful and useful thing to do would be to understand when each of 0xb0 and 0x9f is sent in the responses and what it means. Could you please have a go at adding in some logs that print something like GOT 0xXX IN FIRST BYTE OF ADDRESS? Then you can play around with changing fan speed and setpoint from the test script, the app, the control panel etc... See if there's any pattern to when you get 0xb0 and when you get 0x9f. I'd rather be methodical and learn what's going on than just ignore the byte to make it work.

Thanks for testing and contributing - I do appreciate it a lot :)

phardy commented 1 year ago

I don't like the idea of silently ignoring that byte

That's fair. I was going for being as precise as the documentation, but can totally see why you'd want to be more explicit. :)

No problem. I'll make sure I do some testing that exercises both group and AC status packets, from the test script, a different remote client and the console. And anything else I can think of in the next few days.

phardy commented 1 year ago

I'll come back to this after some more testing.