Skip to content

Conversation

@aramshaw
Copy link

0x2B - Extended Status - System status including available favorites, timers, and system counters.
0x31 - Favorite Status - Provides the names of all configured favorite scenes and indicates which one is currently active. This message is sent when the active favorite changes.
0x45 - System Identity Broadcast - Broadcasts system identity information. The payload contains the string "Polyaire Atch2PM", likely identifying the manufacturer and "AirTouch 2 Plus Module". This message appears to be sent periodically (e.g., every ~24 hours).

aramshaw and others added 16 commits July 19, 2025 17:02
The AirTouch2+ controller requires the CRC checksum to be calculated from the address field to the end of the data payload. The previous implementation used an incorrect offset, resulting in invalid checksums and causing the controller to reject messages and lock out the client.

This commit corrects the checksum calculation in `message_common.py` to use the proper starting offset (`CommonMessageOffsets.ADDRESS`).

It also adds the `get_data_from_offset` method to the `Buffer` class, which was necessary to support the corrected checksum logic and resolve a subsequent `AttributeError`.
Cleans up ACK handling for several control status message subtypes.

- Fixes rate limiting to remove special handling for 0x2B.
- Comments out legacy ACK generation code that was found to be unnecessary.
- Minor formatting fixes
testing: the ACK handling of 0x45 messages
@nathanvdh
Copy link
Owner

Thank you. Just confirming I am alive and have seen this. I'm very preoccupied with other things in my life at the moment. I plan to take a look at this but I don't know when I'll get a chance.

My first bit of feedback is - what you have written in the GitHub description is a very nice summary describing that you've added support for 3 new message types. It would be good if this was reflected in the commits - currently there are 16, it would be nice if it was 3 commits, one for each message type, with the commit messages basically what you've written in the GitHub comment text.

@aramshaw
Copy link
Author

"very preoccupied with other things in my life at the moment" - all good mate. I persevered on the PULL request because I committed to @gavintweedie, and myself, to get it done.

You would be shocked, and saddened, if you knew how long it took me to add these few measly lines to your excellent base code. Lots of learning, false turns, restarts. It was not a direct sequence of steps from start to finish and the commits were really just my way of backing up what seemed like progress at the time.

I think if you look at the changes in my pull request it will be clear what was done, and not too much to review.

I'd do what you asked (3 x commit) if I was better at Git than I am. Sorry.

(Sure glad I don't get paid by the line of code.)

@nathanvdh
Copy link
Owner

Hi, I've taken a look. Can you clarify for me which messages need a response (ack)?
Here you say 5 need a response - 0x2B, 0x31, 0x10, 0x40, 0x27.
In your markdown doc you say 0x10, 0x2B, 0x40, 0x45 and that 0x27 doesn't need a response.
In the description of this PR you only mention 3 - 0x2B, 0x31 and 0x45.

I find it very strange that you would need to put something other than 0x80 or 0x90 into the first byte of the top-level Message Header's 'Address' field. It's even stranger to me that this would only be for 2 of the several new message types you describe. You say it needs to be 0xC0 - the identifer for control/status messages - but this is already present in a later field in the header, so that seems redundant to me. Have you intercepted traffic between the mobile app the server to see exactly what their official app is responding with? I was using pcapdroid to do this.

Another special-case you have is that the 0x10 ack requires a 2-byte payload but all the others only 1-byte. Seems odd - why should that message be special? Does it really not work if you only send a 1-byte empty payload, the same as the others?

My initial approach is going to be to make the smallest possible change that stops the server from abandoning us, like it seems to if we don't respond. So I'm just going to hard-code a list of message types that require acking and ack them, even if there's no decode/encode support for them. If the new message types actually provide functionality that you want, we can add that later.

@aramshaw
Copy link
Author

aramshaw commented Sep 8, 2025

Hi @nathanvdh - sorry - I did mention at the outset that this sort of comms was (way) above my paygrade and I did use a fair bit of AI support so doubtless there is some AI slop in there. But the code has been working well on my system for a couple of weeks now. I have additional change for a broadcast message that I have not submitted a PULL for (0x27).

To your specific questions;

  • The markdown in the project is the most up to date document. I tried to add everything I learned there so there was a record.
  • I looked at the comms between the phone and controller via Wireshark but found there was none. All comms seems to go via an AWS server so I never did get any meaningful information on that route - but again I may be 100% wrong on my conclusion.
  • At the time of the PR I had only sorted 0x2B, 0x31 and 0x45. I have since added a small amount of code for 0x27 which seems like a simple "I'm here" not requiring any response. That's sitting on my local system.
  • On the comms questions I would fully defer to your knowledge. There was A LOT of trial and error to get where I got - and the chance there is some garbage left over in the messages is quite high.

It's your code base and I defer to you in all things in it.

(I'm on vacation to the end of Sep and don't have access to my dev system so am limited in my ability to review details.)

@nathanvdh
Copy link
Owner

Hi, I've pushed a commit to the ack-testing branch in my repo. Currently I'm handling all the acks the same, although you've described that there are some special cases. I can't understand why different messages would need to be acknowledged differently, as you've described. So I've started out with the simplest thing possible (except I left the 1-byte payload in).

There's a test in tests/protocol/at2plus/messages/test_ack.py that demonstrates what bytes I'm sending, and shows how it's the same for all messages. Run all the tests, including this one, with python -m unittest discover tests/protocol. If you need make changes, please update the test to keep it passing.

I see in your code there's a cooldown for sending repeat acks - why are you doing that? How have you decided what's required? How do you even know these 'acks' are required? Did you try just sending one of the control messages or the status request message repeatedly to see if that keeps the keeps the server from ignoring us? I've read back through some of the discussion in other issues and never found your reasoning behind why you thought messages need acking, nor how you then found which specific ones needed it.

@gavintweedie
Copy link

@nathanvdh I've removed @aramshaw repo and reset things back to yours, and manually adjusted airtouch2-python with your changes. Will report back if it fixes the core issues here (server ignoring client / dropouts).

@nathanvdh
Copy link
Owner

nathanvdh commented Sep 16, 2025

Ok thanks, I expect there will be issues given I've ignored a lot of what aramshaw said... But who knows.

@gavintweedie
Copy link

Had a 0x27 unknown already, which is expected since this change is just sorting the acking. Hasn't caused a dropout however which is good.

Usually see a dropout within a few hours of switching off for the evening, so will report back in the morning.

@nathanvdh
Copy link
Owner

That's fine 0x27 doesn't need acknowledgement according to aramshaw, so I deliberately haven't handled it yet.

@gavintweedie
Copy link

Morning update. Temps continued to update overnight which they didn't use to, so that's an improvement. However connection was lost. Logs below.

20:29:55 Turned off (from heating) turned off triggered by action Climate: Set HVAC mode
~ bit over half an hour later disconnected

Temp updated overnight, at 6:55 attemped to turn on via home-assistant, no response even after multiple attempts. Woke touchpad and turned on, and able to adjust temp etc remotely now via home-assistant.

Sep 16 20:29:55 homeassistant homeassistant[490]: 2025-09-16 20:29:55.648 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 16 20:29:55 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 16 20:29:55 homeassistant homeassistant[490]: 2025-09-16 20:29:55.648 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=00 Sep 16 21:12:59 homeassistant homeassistant[490]: 2025-09-16 21:12:59.945 WARNING (MainThread) [airtouch2.common.NetClient] Connection lost, reconnecting Sep 17 06:55:22 homeassistant homeassistant[490]: 2025-09-17 06:55:22.668 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 06:55:22 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 06:55:22 homeassistant homeassistant[490]: 2025-09-17 06:55:22.668 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=01

@gavintweedie
Copy link

Multiple disconnects today, had the touchpad stop responding once too which hasn't happened before. Reboot fixed it.

Sep 17 06:55:22 homeassistant homeassistant[490]: 2025-09-17 06:55:22.668 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 06:55:22 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 06:55:22 homeassistant homeassistant[490]: 2025-09-17 06:55:22.668 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=01 Sep 17 09:13:04 homeassistant homeassistant[490]: 2025-09-17 09:13:04.009 WARNING (MainThread) [airtouch2.common.NetClient] Connection lost, reconnecting Sep 17 09:38:35 homeassistant homeassistant[490]: 2025-09-17 09:38:35.491 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 09:38:35 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 09:38:35 homeassistant homeassistant[490]: 2025-09-17 09:38:35.491 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=00 Sep 17 11:24:41 homeassistant homeassistant[490]: 2025-09-17 11:24:41.511 WARNING (MainThread) [airtouch2.common.NetClient] Connection lost, reconnecting Sep 17 11:24:43 homeassistant homeassistant[490]: 2025-09-17 11:24:43.340 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 11:24:43 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 11:24:43 homeassistant homeassistant[490]: 2025-09-17 11:24:43.340 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=01 Sep 17 17:41:15 homeassistant homeassistant[490]: 2025-09-17 17:41:15.862 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 17:41:15 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 17:41:15 homeassistant homeassistant[490]: 2025-09-17 17:41:15.863 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=00 Sep 17 17:42:17 homeassistant homeassistant[490]: 2025-09-17 17:42:17.042 WARNING (MainThread) [airtouch2.common.NetClient] Connection lost, reconnecting Sep 17 18:09:10 homeassistant homeassistant[490]: 2025-09-17 18:09:10.782 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 18:09:10 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 18:09:10 homeassistant homeassistant[490]: 2025-09-17 18:09:10.782 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=01 Sep 17 19:05:49 homeassistant homeassistant[490]: 2025-09-17 19:05:49.721 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 19:05:49 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 19:05:49 homeassistant homeassistant[490]: 2025-09-17 19:05:49.722 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=00 Sep 17 19:05:51 homeassistant homeassistant[490]: 2025-09-17 19:05:51.682 WARNING (MainThread) [airtouch2.protocol.at2plus.message_common] Unknown message type in header (0x27) Sep 17 19:05:51 homeassistant homeassistant[490]: File "/usr/local/lib/python3.13/site-packages/airtouch2/protocol/at2plus/message_common.py", line 73, in from_bytes Sep 17 19:05:51 homeassistant homeassistant[490]: 2025-09-17 19:05:51.682 WARNING (MainThread) [airtouch2.at2plus.At2PlusClient] Unknown message type, header=55:55:b0:80:01:00:00:01, data=01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants