Xantech / Dayton Audio / Sonance multi-zone amps

I don’t think you have to reset anything to make the RS232 work (I don’t think it ever gets shut off). I do know that for some units where there are multiple RS232, the port you pick to plug into does matter, not all expose the control interface. I don’t recall the models.

However, all of them except the MX88* models I think were very easy to just plugin a USB to RS232 adapter and get up and running. There was some nuances on the connected for the MX88 that was documented on the pyxantech project page in github.

Units that I have (just not hooked up right now):

  • MRAUDIO8x8
  • MRC8
  • MX88ai

I am able to install v 0.1.4:

but still get errors and can’t connect:

Any troubleshooting advice? Thank you!

When connecting the MRAUDIO8X8 to a Windows PC (USB to serial cable), I am able to communicate with the unit using Universal Dragon, turning zones ON/OFF, etc. I was even able to upgrade the firmware.

With the upgraded firmware + HA with the same usb-Serial cable, I only get this error (I’ve tried both 1,2,3, etc and 11,12,13, etc as “zones:”)

configuration:

media_player:
  - platform: xantech
    type: xantech8
    port: /dev/serial/by-id/usb-FTDI_USB_Serial_Converter_FTE1FC8L-if00-port0
    zones:
      11:
        name: "myzone11"
    sources:
      1:
        name: "mysource1"      

Maybe some unfortunate incompatibility between the integration and my specific model (see details below). Let me know what you think:

MRAUDIO8X8
Product Code: MRA88m
Version: 3.17 (2.03 before upgrade)
Zone Controller Version: 1.09
MRIP Version: N/A
IR Library version: 47554C314755423100

if you eventually reconnect your MRAUDIO8X8 I’d be interested to know your product/version to compare.

Since I have access to the unit via PC/Windows/Universal Dragon, anything I could extract from there to troubleshoot and/or update the API?

Otherwise I am out of options.

As ever, I’m so grateful for your work on this. Whole-home audio is a huge part of my quality of life, and your plugin plays an essential role in that. :heart:

Recently I have been having asynio / eventloop issues, many things in my house have become sluggish. I see that you have done some work to move sync off of the main thread. :pray:

Just now I updated to 1.4 (by cloning, and copying the custom component directory). It seems that my DAX88 is still working. Thank you!

I’ll keep an eye on it today to see if performance overall improves.

I am still, however, seeing errors like these:

2025-09-28 07:13:23.782 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 17 (Garage):
2025-09-28 07:13:26.417 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 18 (Family room):
2025-09-28 07:13:35.749 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 13 (Kitchen):
2025-09-28 07:13:39.701 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 15 (Primary bedroom):
2025-09-28 07:13:41.565 WARNING (MainThread) [homeassistant.components.media_player] Updating xantech media_player took longer than the scheduled update interval 0:00:10

I want to reassure @Montreal666 that these issues seem (in my case) to be non-fatal.

I want to ask, @ryans, is it expected that these messages say (MainThread)? Is that an issue?

Thanks for the feedback @sorrygofish, however in my case entities are created but I can’t control the unit (“failed to perform the action”)
Would you mind providing screenshots of your entities so I can compare to mine? :

With 1.4 I am now seeing thousands of these messages:

2025-09-28 16:09:08.511 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 16 (Scott's room): 'NoneType' object has no attribute 'reset_output_buffer'
2025-09-28 16:09:08.511 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 17 (Garage): 'NoneType' object has no attribute 'reset_output_buffer'
2025-09-28 16:09:08.512 WARNING (MainThread) [custom_components.xantech.media_player] Failed updating Xantech House Audio zone 18 (Family room): 'NoneType' object has no attribute 'reset_output_buffer'

My entities show up properly:

I have a Xantech MRC88 that I’ve been using one of my own Flask projects to control for the last several years via USB → RS232 using a RPi4.

I’d like to integrate it into Home Assistant. Is there a way to install @ryans project on the current RPi and control it via the HA integration, or does the serial have to feed from the HA computer? @skavan , I saw your comments re: IP → RS232 and all the pieces involved, how did you actually get that integrated with HA? Would this be the way to accomplish what I’m asking above?

New:

Platform error ‘media_player’ from integration ‘xantech’ - cannot import name ‘HomeAssistantType’ from ‘homeassistant.helpers.typing’ (/usr/src/homeassistant/homeassistant/helpers/typing.py)


This error occurs because HomeAssistantType was a deprecated alias in homeassistant.helpers.typing that was officially removed in Home Assistant Core 2025.5. Custom integrations that have not been updated for 2025 releases will fail with this import error.

How to Fix the Xantech Integration

Since the xantech integration is likely a custom component (often installed via HACS or manual copy), you must manually update its source code to use the modern naming convention.

  1. Locate the File: Navigate to your Home Assistant configuration directory and open:
    /config/custom_components/xantech/media_player.py (or similar .py files in that folder).
  2. Update the Imports:
  • Remove the line attempting to import HomeAssistantType from homeassistant.helpers.typing.
  • Add or ensure this line exists:

python

from homeassistant.core import HomeAssistant
  1. Replace References:
  • Search the file for any instance of HomeAssistantType and replace it with HomeAssistant.
  • If you see ServiceCallType, replace it with ServiceCall (imported from homeassistant.core).
  1. Restart Home Assistant: Save the changes and restart Core to apply the fix.
1 Like

I love seeing the new update! Thanks so much. Being able to setup from the UI is fantastic.

My log is showing a lot of these errors:

This error originated from a custom integration.

Logger: custom_components.xantech.coordinator
Source: custom_components/xantech/coordinator.py:63
integration: Xantech Multi-Zone Audio (documentation, issues)
First occurred: 3:18:25 PM (58 occurrences)
Last logged: 3:35:38 PM

Failed to get status for zone 17
Failed to get status for zone 13
Failed to get status for zone 11
Failed to get status for zone 14
Failed to get status for zone 15
Traceback (most recent call last):
  File "/config/custom_components/xantech/coordinator.py", line 63, in _async_update_data
    status = await self.amp.zone_status(zone_id)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 447, in wrapper
    return await coro(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 494, in zone_status
    status = ZoneStatus.from_string(self._amp_type, status_string)
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 72, in from_string
    match_dict = match.groupdict()
                 ^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'groupdict'

This happens at pyxantech/init.py:72 where ZoneStatus.from_string() doesn’t handle the case when the regex doesn’t match.

Root cause possibilities:

  1. Those zones (11, 13, 14, 15, 17) don’t physically exist on your amplifier
  2. The amplifier is returning an unexpected response format for those zones
  3. Serial communication issues causing corrupted responses

Questions to help diagnose:

  • What amplifier model do you have and how many zones does it actually support?
  • Did you configure zones 11-17 in the setup? The default config suggests a 6-zone amp but zone 17 implies 7+ zones.

The integration is already handling this gracefully (catching the exception and continuing with other zones), but it’s logging at WARNING level with full traceback, which creates the log spam.

Quick fix options:

  1. Remove non-existent zones from your config - reconfigure the integration with only the zones your amp actually has

I am also releasing a new pyxantech which should cause the log to go away.

It’s a DAX88. Yes it has 8 zones. Yes all 8 were setup (and exist).

I have several template sensors that indicate how many zones are attached to each source. For example:

{{ expand('media_player.dax88_speakers') |
        selectattr('attributes.source', 'eq', 'Shared') | list | count }}

With 0.2.1, this occasionally dips to 0 and then comes back. (To work around this, I set a 45 second condition before acting on this change.) It seems the power status of the media players is cycling between off and on (even though they are actually staying on).

With 0.2.2 I don’t see the log, but I also see the status as “off” for all zones now, and can not turn them on (using the home assistant media player entity).

Update I downgraded to 0.2.1 (and restarted HA), and somehow the power status is still not changing from the media_player power buttons. All zones report being off, and can not be toggled. But other changes (like volume and source selection) seem to work.

Does the DAX88 actually use zone 1-8, instead of 11-18? Just curious because from what I can tell it should be zone 1-8 (01-08 in the protocol) and that might be the root of the issue.

I’m going to release another version with DAX88 fixes in a few minutes, but I dont have one to test against so we might have to do another round of updates.

Can you post a photo of your configuration UX for how you are setting all this up?

I am using a DAX-88. I finally figured the integration. I am able to name my zones, but I only have 4 sources available and am not able to add sources 5, 6, 7 and 8. I can turn on the speakers, but not off. So far, not 100% sold.

The DAX uses zones 11-18 for the first DAX, uses 21-28 and 31-38 if you have 2 or 3 connected amps in series.

I’ve been using your integration for years. Here’s what I used to have in YAML (I edited it to fit the new format when I re-setup the 2.0.x version in the UI):

- platform: xantech
  type: dax88
  port: /dev/ttyUSB0
  zones:
    11:
      name: "BAZ room"
    12:
      name: "FOO room"
    13:
      name: "Kitchen"
    14:
      name: "Back yard"
    15:
      name: "Primary bedroom"
    16:
      name: "BOB"
    17:
      name: "Garage"
    18:
      name: "Family room"
  sources:
    1:
      name: "ALICE"
    2:
      name: "BAZ"
    3:
      name: "BAR"
    4:
      name: "FOO"
    5:
      name: "Shared"
    7:
      name: "Home assistant"
    8:
      name: "Wifi"

The new 0.2.2 is giving these errors in the log:

This error originated from a custom integration.

Logger: custom_components.xantech.coordinator
Source: custom_components/xantech/coordinator.py:63
integration: Xantech Multi-Zone Audio (documentation, issues)
First occurred: 6:43:30 PM (9 occurrences)
Last logged: 8:08:53 PM

Failed to get status for zone 13
Failed to get status for zone 16
Failed to get status for zone 18
Failed to get status for zone 14
Failed to get status for zone 12
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/asyncio/tasks.py", line 507, in wait_for
    return await fut
           ^^^^^^^^^
  File "/usr/local/lib/python3.13/asyncio/queues.py", line 186, in get
    await getter
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/config/custom_components/xantech/coordinator.py", line 63, in _async_update_data
    status = await self.amp.zone_status(zone_id)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 623, in wrapper
    return await coro(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 643, in zone_status
    status_string = await self._protocol.send(cmd, skip=skip)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/protocol.py", line 195, in send
    return await self._read_response(skip)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/protocol.py", line 214, in _read_response
    chunk = await asyncio.wait_for(self._queue.get(), self._timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/asyncio/tasks.py", line 506, in wait_for
    async with timeouts.timeout(timeout):
               ~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/local/lib/python3.13/asyncio/timeouts.py", line 116, in __aexit__
    raise TimeoutError from exc_val
TimeoutError

and

This error originated from a custom integration.

Logger: custom_components.xantech.coordinator
Source: custom_components/xantech/coordinator.py:63
integration: Xantech Multi-Zone Audio (documentation, issues)
First occurred: 7:45:17 PM (3 occurrences)
Last logged: 7:46:19 PM

Failed to get status for zone 17
Failed to get status for zone 13
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/asyncio/tasks.py", line 507, in wait_for
    return await fut
           ^^^^^^^^^
  File "/usr/local/lib/python3.13/asyncio/queues.py", line 186, in get
    await getter
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/pyxantech/protocol.py", line 214, in _read_response
    chunk = await asyncio.wait_for(self._queue.get(), self._timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/asyncio/tasks.py", line 506, in wait_for
    async with timeouts.timeout(timeout):
               ~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/local/lib/python3.13/asyncio/timeouts.py", line 116, in __aexit__
    raise TimeoutError from exc_val
TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/config/custom_components/xantech/coordinator.py", line 63, in _async_update_data
    status = await self.amp.zone_status(zone_id)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 623, in wrapper
    return await coro(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/__init__.py", line 643, in zone_status
    status_string = await self._protocol.send(cmd, skip=skip)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/protocol.py", line 195, in send
    return await self._read_response(skip)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyxantech/protocol.py", line 243, in _read_response
    self._log_timeout(request=b'', data=data, response_eol=response_eol)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/ratelimit/decorators.py", line 77, in wrapper
    raise RateLimitException('too many calls', period_remaining)
ratelimit.exception.RateLimitException: too many calls

If there’s more I can do to debug, please let me know. I am able to install the custom component locally from a branch (and make changes), but I have never figured out how to make changes to pyxantech on the HA machine that actually has the USB connection since I believe the python environment is managed globally (?).

I am not able to control the volume of my speakers through HomeAssistant via my DAX-88. The speaker entity has a dropdown of my sources and a button to turn on the zone, but doesn’t toggle on/off. And like I said, I have no way to turn the volume up/down through home assistant.

I may have to remove and re-setup the integration. Let me know what would be most helpful.

Log says:

Logger: aiohttp.server
Source: /usr/local/lib/python3.13/site-packages/aiohttp/web_protocol.py:481
First occurred: 8:26:29 PM (1 occurrence)
Last logged: 8:26:29 PM

Error handling request from 192.168.2.234
Traceback (most recent call last):
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_protocol.py", line 510, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_app.py", line 569, in _handle
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 87, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 41, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 83, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 272, in post
    return await super().post(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
    return await method(view, request, data, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 76, in post
    return await self._post_impl(request, data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 83, in _post_impl
    result = await self._flow_mgr.async_init(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<2 lines>...
    )
    ^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 316, in async_init
    flow = await self.async_create_flow(handler, context=context, data=data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 3701, in async_create_flow
    return handler.async_get_options_flow(entry)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
  File "/config/custom_components/xantech/config_flow.py", line 243, in async_get_options_flow
    return XantechOptionsFlow(config_entry)
  File "/config/custom_components/xantech/config_flow.py", line 251, in __init__
    self.config_entry = config_entry
    ^^^^^^^^^^^^^^^^^
AttributeError: property 'config_entry' of 'XantechOptionsFlow' object has no setter

Even though everything was working on 0.2.1 for me (on my DAX-88), upgrading to 0.2.2 has broken the power status. I have removed the integration, restarted, installed 0.2.1 and still cannot get power status to work.

I see nothing in the logs (even with debug logging enabled), just:

2026-01-11 06:56:39.508 DEBUG (MainThread) [custom_components.xantech.media_player] Turning on zone 17
2026-01-11 06:56:39.949 DEBUG (MainThread) [custom_components.xantech.coordinator] Updated 8 zones for dax88__dev_ttyUSB0
2026-01-11 06:56:39.949 DEBUG (MainThread) [custom_components.xantech.coordinator] Finished fetching xantech_dax88__dev_ttyUSB0 data in 0.398 seconds (success: True)

Trying 0.2.5, I am hoping that has resolved all your issues. Thanks Geoff!

Thanks ryans. I installed 0.2.5 and my DAX-88 is working. Volume control and toggle on/off is working. Thanks for speedy fixes.

1 Like