Aprilaire Thermostat 8800 any MODBUS experts?

The proxy was a tool to allow me to do development while allowing HA plug-in to run in parallel. Since only one client is allowed to connect to the thermostat. I wouldn’t recommend deploying it unless you are doing development.

The proxy does nothing fancy, just standard debouncing. I make sure that only one connection attempt can be established with the thermostat every 10 seconds, all others are rejected.

I stumbled into this after discovering that the thermostat gets easily overwhelmed by connection attempts if you don’t give it enough time to recover. The 10 seconds is probably overkill, but kept my thermostat stable for going on 2 weeks now. This is likely due to a CPU or OS limitation on sockets.

Once the connection is established you can send as many commands as you like.

Gotcha, thanks for that info. I think that my changes in the 0.5.0 release will address that issue, then. As I noted in Plugin gets into a tight connection loop · Issue #8 · chamberlain2007/aprilaire-ha · GitHub, I did locate the issue there, it should now respect the reconnect delay (10s) when the connection is dropped, previously it was only respecting this delay when initially trying to establish the connection. For what it’s worth, I did also refactor the logic for the write queue processing, so that is a little less aggressive as well, though probably not the issue you were seeing.

That all said, if there are other issues with the socket doing weird things as you mentioned above with it not doing a FIN, it’s hard to catch and I would need more data about that. It’s using asyncio which wrap Pythons normal sockets, so I don’t see anything that would allow doing anything fancy.

Thanks again for this hard work. Recently I haven’t noticed any connection drops. I’m on the latest version.

Just a separate question: is it possible to add Zone 2 entities for a thermostat? For example my master bedroom thermostat is only reporting zone 1 data but I’d like to see and control zone 2 which is my upstairs area.

Maybe. The problem is that I don’t have one, which makes it pretty difficult for me to do. I’m honestly not even clear what the data for them is. The best that I have seen in the documentation is around “support modules”, which appear to only be to add additional temperature/humidity non-controlling sensors. For a proper zone, I don’t see anything in the documentation about it. I have seen some references in the installer docs, but it’s only about setting the value by the installer.

If you are adept and able to find what it corresponds to in the protocol, I could definitely mock it and implement it. But, as it stands I don’t know enough about it and don’t have a device to test with.

Not sure on the wifi stuff but 8800 uses the 422 protocol so each t stat has it’s own id on the wire I have a lot of documentation on that one and can go into a terminal window and control all my t stats

I am also a Meritage home owner. I have a thermostat downstairs and one upstairs but the house uses one AC Unit. I was able to connect both to HA but only my downstairs thermostat has entities and show a device. Which is awesome, but wondering if there is a reason that the upstairs one is blank. Both thermostats are 800 series. I looked into my HA Logs and I see maybe it’s an issue with the Mac number? I looked at the .5 build and wondering if this is related. Is there anything I can do?

To confirm, you have two thermostats with different IP addresses, correct? And you were able to add both successfully in the integrations UI? If you go to the integration and go to the device (not the entities), does it show any devices? Or, are they all Unavailable?

A screenshot of the device page for the problematic one would help.

The following would do debug logging. You would want to first disable the device, set this in your configuration.yaml, restart Home Assistant, wait till everything is initialized and then clear the log. Then go re-add the device and copy the resulting debug lines from your log. You can comment out the log and reboot once you have logs for the first minute or so after adding.

logger:
  default: error
  logs:
    custom_components.aprilaire: debug

So oddly enough, I added the logger, then enabled the services again and saw that both thermostats have devices and are functioning. I restarted Home Assistant again just to check and then saw that my second thermostat retains the device and entities but now all unavailable. Looking at the logs, possible it has to do with the NACK?

The first thermostat still has all the entities and is functional

2023-03-15 16:07:08.442 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:08.457 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:08.457 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:08.506 INFO (MainThread) [custom_components.aprilaire] Aprilaire connection made
2023-03-15 16:07:08.508 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.508 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=1, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.IDENTIFICATION, attribute=2
2023-03-15 16:07:10.508 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=2, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.CONTROL, attribute=7
2023-03-15 16:07:10.509 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=3, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.CONTROL, attribute=1
2023-03-15 16:07:10.509 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=4, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.SENSORS, attribute=2
2023-03-15 16:07:10.509 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=5, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.IDENTIFICATION, attribute=5
2023-03-15 16:07:10.509 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=6, action=Action.WRITE, functional_domain=FunctionalDomain.STATUS, attribute=1
2023-03-15 16:07:10.509 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=7, action=Action.WRITE, functional_domain=FunctionalDomain.STATUS, attribute=2
2023-03-15 16:07:10.513 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 01 00 03 02 08 02 fb
2023-03-15 16:07:10.514 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 02 00 03 02 02 07 19
2023-03-15 16:07:10.514 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 03 00 03 02 02 01 e8
2023-03-15 16:07:10.515 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 04 00 03 02 05 02 81
2023-03-15 16:07:10.515 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 05 00 03 02 08 05 01
2023-03-15 16:07:10.516 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 06 00 20 01 07 01 01 00 00 00 00 01 00 00 00 00 01 00 00 00 01 00 00 00 00 00 01 00 01 00 01 01 01 00 00 6f
2023-03-15 16:07:10.517 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 07 00 04 01 07 02 01 3b
2023-03-15 16:07:10.520 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 03 00 02 06 03 96
2023-03-15 16:07:10.520 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.NACK, functional_domain=FunctionalDomain.NACK, attribute=0
2023-03-15 16:07:10.520 ERROR (MainThread) [custom_components.aprilaire] Received NACK for attribute 3
2023-03-15 16:07:10.522 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 04 00 02 06 03 cd 01 01 00 11 03 08 02 b4 82 55 50 93 6d 01 49 02 01 02 0d 04 0e 51
2023-03-15 16:07:10.522 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.NACK, functional_domain=FunctionalDomain.NACK, attribute=0
2023-03-15 16:07:10.522 ERROR (MainThread) [custom_components.aprilaire] Received NACK for attribute 3
2023-03-15 16:07:10.524 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 02 00 08 03 02 07 04 01 00 00 00 ef
2023-03-15 16:07:10.524 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.READ_RESPONSE, functional_domain=FunctionalDomain.CONTROL, attribute=7
2023-03-15 16:07:10.524 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.529 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 2f 05 01 01 01 01 00 00 00 00 00 01 00 00 04 05 00 01 00 00 00 00 01 02 02 04 00 03 00 00 00 00 00 02 00 3d 51 00 0d 01 01 01 00 00 00 0d 0d 00 d3
2023-03-15 16:07:10.530 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.SETUP, attribute=1
2023-03-15 16:07:10.530 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.530 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 07 05 02 01 03 03 18 55 bc
2023-03-15 16:07:10.530 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.CONTROL, attribute=1
2023-03-15 16:07:10.531 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.533 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 08 05 02 07 04 01 00 00 00 3e
2023-03-15 16:07:10.534 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.CONTROL, attribute=7
2023-03-15 16:07:10.534 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.534 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 0d 05 03 04 01 03 18 55 ff 1e 13 0f 03 17 ff
2023-03-15 16:07:10.535 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.SCHEDULING, attribute=4
2023-03-15 16:07:10.535 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.537 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 0b 05 05 02 00 55 03 92 04 00 03 00 f6
2023-03-15 16:07:10.537 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.SENSORS, attribute=2
2023-03-15 16:07:10.538 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.539 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 07 05 07 06 00 00 00 00 59 01 80 00 07 05 07 07 00 00 00 00 8a
2023-03-15 16:07:10.539 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.STATUS, attribute=6
2023-03-15 16:07:10.539 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.STATUS, attribute=7
2023-03-15 16:07:10.539 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.539 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.541 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 0a 05 08 01 49 02 01 02 0d 04 0e b0
2023-03-15 16:07:10.541 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.IDENTIFICATION, attribute=1
2023-03-15 16:07:10.542 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.542 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 80 00 04 05 07 08 00 ab 01 80 00 04 05 07 02 01 74
2023-03-15 16:07:10.542 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.STATUS, attribute=8
2023-03-15 16:07:10.542 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.COS, functional_domain=FunctionalDomain.STATUS, attribute=2
2023-03-15 16:07:10.542 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 16:07:10.542 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data

Thank you! That helped me see the issue. tl;dr there is a prerelease 0.5.2 in HACS, update to that and let me know if that fixes your issue. I’ll be running it for the next bit to make sure it doesn’t have issues.

Longer explanation, the thermostat can send multiple packets in the same response. If you look at this one:

01 04 00 02 06 03 cd 01 01 00 11 03 08 02 b4 82 55 50 93 6d 01 49 02 01 02 0d 04 0e 51

It is actually multiple packets:

01 04 00 02 06 03 cd
01 01 00 11 03 08 02 b4 82 55 50 93 6d 01 49 02 01 02 0d 04 0e 51

The first one is a NACK, but the second one is the MAC address (03 08 02)

There was a bug that aborted the processing of other packets if a NACK is received, so it got the MAC address but then didn’t pass it along. In 0.5.2 that will be fixed and you should be good to go.

That is awesome! I am very excited. Thank you thank you thank you for building this. Ill keep an eye out for 0.5.2

If you’d like to use it now, you can enable the pre-release option on the repo in HACS and it will show you 0.5.2. Otherwise, expect it in the next couple days as a stable release.

1 Like

I had downloaded and installed 0.5.2 but the device is still Unknown. Here are the logs

EDT: Actually, it became available but I needed to change the Operation for it to initiate. Some of the other entries are still Unavailable. Not sure if that’s related

2023-03-15 22:06:44.639 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 22:06:44.650 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 22:06:44.651 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 22:06:44.681 INFO (MainThread) [custom_components.aprilaire] Aprilaire connection made
2023-03-15 22:06:44.682 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=1, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.IDENTIFICATION, attribute=2
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=2, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.CONTROL, attribute=7
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=3, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.CONTROL, attribute=1
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=4, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.SENSORS, attribute=2
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=5, action=Action.READ_REQUEST, functional_domain=FunctionalDomain.IDENTIFICATION, attribute=5
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=6, action=Action.WRITE, functional_domain=FunctionalDomain.STATUS, attribute=1
2023-03-15 22:06:46.683 DEBUG (MainThread) [custom_components.aprilaire] Queuing data, sequence=7, action=Action.WRITE, functional_domain=FunctionalDomain.STATUS, attribute=2
2023-03-15 22:06:46.687 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 01 00 03 02 08 02 fb
2023-03-15 22:06:46.688 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 02 00 03 02 02 07 19
2023-03-15 22:06:46.689 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 03 00 03 02 02 01 e8
2023-03-15 22:06:46.689 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 04 00 03 02 05 02 81
2023-03-15 22:06:46.689 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 05 00 03 02 08 05 01
2023-03-15 22:06:46.691 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 06 00 20 01 07 01 01 00 00 00 00 01 00 00 00 00 01 00 00 00 01 00 00 00 00 00 01 00 01 00 01 01 01 00 00 6f
2023-03-15 22:06:46.691 INFO (MainThread) [custom_components.aprilaire] Sent data: 01 07 00 04 01 07 02 01 3b
2023-03-15 22:06:46.697 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 03 00 02 06 03 96
2023-03-15 22:06:46.697 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.NACK, functional_domain=FunctionalDomain.NACK, attribute=0
2023-03-15 22:06:46.698 ERROR (MainThread) [custom_components.aprilaire] Received NACK for attribute 3
2023-03-15 22:06:46.704 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 05 00 02 06 03 1e 01 06 00 02 06 03 5a 01 07 00 02 06 03 89 01 01 00 11 03 08 02 b4 82 55 50 93 6d 01 49 02 01 02 0d 04 0e 51
2023-03-15 22:06:46.704 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.NACK, functional_domain=FunctionalDomain.NACK, attribute=0
2023-03-15 22:06:46.705 ERROR (MainThread) [custom_components.aprilaire] Received NACK for attribute 3
2023-03-15 22:06:46.707 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.NACK, functional_domain=FunctionalDomain.NACK, attribute=0
2023-03-15 22:06:46.708 ERROR (MainThread) [custom_components.aprilaire] Received NACK for attribute 3
2023-03-15 22:06:46.710 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.NACK, functional_domain=FunctionalDomain.NACK, attribute=0
2023-03-15 22:06:46.710 ERROR (MainThread) [custom_components.aprilaire] Received NACK for attribute 3
2023-03-15 22:06:46.712 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.READ_RESPONSE, functional_domain=FunctionalDomain.IDENTIFICATION, attribute=2
2023-03-15 22:06:46.714 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data
2023-03-15 22:06:46.715 INFO (MainThread) [custom_components.aprilaire] Aprilaire data received 01 02 00 08 03 02 07 04 01 00 00 00 ef
2023-03-15 22:06:46.715 DEBUG (MainThread) [custom_components.aprilaire] Received data, action=Action.READ_RESPONSE, functional_domain=FunctionalDomain.CONTROL, attribute=7
2023-03-15 22:06:46.716 DEBUG (MainThread) [custom_components.aprilaire] Manually updated aprilaire data

You’re getting so many NACKs, I would recommend restarting the thermostat if you didn’t already.

I reset it. The actions are working as I need it, I really appreciate your help!

Great! Glad I could help! Thank you for providing the diagnostic information.

Are these two full thermostats or a thermostat and support module combo like seen here?

My two story house has an 8920W on the main floor (that @chamberlain2007 's integration works great with, thanks loads!!) and an 8476W on the second floor. Anyone have any thoughts on how to get the 8476W hooked up to Home Assistant?

As far as I can tell by the docs, both the 8920W and 8476W should be supported. They would both need to be connected to the network, and you would then just add the integration once per thermostat specifying each one’s IP. So the integration would be added twice and there would be two separate HA devices.

I tried to adding the integration again, specifying the IP of the 8476W but I get “An unknown error occurred”. I tried both port 7000 and 8000. I know on the 8920W I had to go into the contractor menu and enable automation mode but I don’t know if the same needs to be done on the 8476W (or if that’s even an option). Enabling debug logging gives “[Errno 111] Connect call failed (‘192.168.0.22’, 7000)” and “[Errno 111] Connect call failed (‘192.168.0.22’, 8000)”. Which I believe supports the thought that automation mode isn’t enabled.

Ya, definitely looks like it’s not in Home Automation mode. I tried to look up the installers guide and didn’t see anything in there about it, and I don’t see any other info.

My recommendation would be to email Aprilaire and just ask how to turn on Home Automation mode on your model.