Introducing our 0.4 series

We’ve just released our 0.4.2 version of AmpliPi! We’ve spent a lot of time on fit & finish as well as features, and we’re quite proud of these releases. The full changelog is available here; in this blog post, I am going to give an overview on our bigger changes that lead to or are a part of the 0.4 release series.

Home Assistant

We’ve revisited AmpliPi’s Home Assistant integration. AmpliPi now exposes itself as a media player entity! This permits deeper integrations with the Home Assistant suite of integrations. This means any media player integrations supported by Home Assistant are now capable of being played on AmpliPro - the list is pretty long. This also enables very deep automations based on other Home Assistant triggers and events. This integration can be installed via a HACS-compliant custom repository. This is by far what we’re most excited to release! Try it out and let us know how you like it! We’ll also have a blog article with more details on this integration soon, so hang tight :sunglasses:

Streams

We’ve souped up the File Player. This stream type now supports playing a file without having to configure a stream, through the /api/play endpoint. This is particularly nice for using the API of the AmpliPi directly - playing arbitrary media from a script on a particular zone/group is one easy request away! We’ll be creating a recipe book of simple scripts one can adapt and modify for their use cases.

We’ve also fixed a ton of bugs in different stream types and updated backing services, notably Spotify Connect, Pandora, Internet Radio, DLNA, Lyrion Music Server (formerly Logitech Media Server) and FM Radio. The cumulative polish on these streams, over the past release cycle and over the lifetime of AmpliPi, produces extremely robust experiences and we’re quite proud of these.

User interface

Our React-based frontend has seen a ton of polish and bug fixes. We’ve consolidated many components to use MUI for an experience that is seamlessly reactive and beautiful. There are a couple of visual tweaks for better call-to-actions when the AmpliPro needs input - for example, adding zones on a playing stream that currently has none. Long track titles and artist names scroll gracefully across the screen instead of scaling or truncating. There are also a ton more minor bug fixes, too many to list here.

We’ve added some details to our appliance’s display - we now show how many streams are playing, stopped, muted, etc, as well as the AmpliPro’s serial number (if it is a newer AmpliPro.)

Support

We’ve put in a ton of effort in making sure we can support our appliances when things aren’t quite as they should be. We’ve implemented Python’s logging library everywhere and made use of appropriate log levels; this has enabled us to get the correct amount of detail on each device when folks send us logs. We’ve also implemented an opt-in temporary support tunnel to permit users to securely grant us access to their appliance during support requests. We’ve set up nightly backups of system state that rotate every 30 days, which allows support or a technical user to rollback to a prior state.

What’s next

Our next big feature release, 0.5, has a very lofty target - being able to install full disk images during software upgrades, such that we can safely and securely upgrade our entire Linux distribution (Raspbian/Debian), while keeping user data intact (/home on a separate partition.) This has a lot of moving parts - rewriting our updater, moving where we store the AmpliPi software and running state, creating an upstream upgrade API that can offer compatible upgrades for AmpliPros, utilizing Raspberry Pi’s TRYBOOT functionality to safely revert failed upgrades, and much more. We’re super excited for this, as it unlocks a whole host of optimisations and modernization - 64 bit OS & userland, newer Python, newer dependencies, newer kernel to support the latest Bluetooth dongles, and more.

Conclusion

We hope you’ll give our latest update a try! You can upgrade your AmpliPro/AmpliPi by navigating to the Updater and clicking “Start Update” in the Latest tab.

3 Likes

Problem, the Home Assistant integration is from a fork that is too old, it literally doesn’t work. You need to rebase it on the version that had the async changes.

@bshootz could you clarify what version you’re referring to? A great amount of our fork is async, fully 50% of the methods at first blush. We’re using this integration in-house on Home Assistant 2024.6.3:

Below is what I got after switching to GitHub - micro-nova/hacs_amplipi: Adds media player support for the AmpliPi MultiZone Audio Player

I then switched back to the original and it worked fine.

2024-08-09 12:07:35.815 INFO (MainThread) [custom_components.amplipi.config_flow] Attempting to retrieve AmpliPi details
2024-08-09 12:07:35.955 INFO (MainThread) [homeassistant.setup] Setting up amplipi
2024-08-09 12:07:35.982 WARNING (MainThread) [homeassistant.util.loop] Detected blocking call to import_module with args (‘custom_components.amplipi.media_player’,) inside the event loop by custom integration ‘amplipi’ at custom_components/amplipi/init.py, line 33: await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) (offender: /usr/src/homeassistant/homeassistant/loader.py, line 1296: return importlib.import_module(f"{self.pkg_path}.{platform_name}“)), please report it to the author of the ‘amplipi’ custom integration
For developers, please see Blocking operations with asyncio | Home Assistant Developer Docs
Traceback (most recent call last):
File “”, line 198, in _run_module_as_main
File “”, line 88, in _run_code
File “/usr/src/homeassistant/homeassistant/main.py”, line 223, in
sys.exit(main())
File “/usr/src/homeassistant/homeassistant/main.py”, line 209, in main
exit_code = runner.run(runtime_conf)
File “/usr/src/homeassistant/homeassistant/runner.py”, line 190, in run
return loop.run_until_complete(setup_and_run_hass(runtime_config))
File “/usr/local/lib/python3.12/asyncio/base_events.py”, line 674, in run_until_complete
self.run_forever()
File “/usr/local/lib/python3.12/asyncio/base_events.py”, line 641, in run_forever
self._run_once()
File “/usr/local/lib/python3.12/asyncio/base_events.py”, line 1990, in _run_once
handle._run()
File “/usr/local/lib/python3.12/asyncio/events.py”, line 88, in _run
self._context.run(self._callback, *self._args)
File “/usr/src/homeassistant/homeassistant/config_entries.py”, line 752, in async_setup_locked
await self.async_setup(hass, integration=integration)
File “/usr/src/homeassistant/homeassistant/config_entries.py”, line 604, in async_setup
result = await component.async_setup_entry(hass, self)
File “/config/custom_components/amplipi/init.py”, line 33, in async_setup_entry
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
2024-08-09 12:07:35.985 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry AmpliPi for amplipi
Traceback (most recent call last):
File “/usr/src/homeassistant/homeassistant/config_entries.py”, line 604, in async_setup
result = await component.async_setup_entry(hass, self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/config/custom_components/amplipi/init.py”, line 33, in async_setup_entry
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
File “/usr/src/homeassistant/homeassistant/config_entries.py”, line 2085, in async_forward_entry_setups
await integration.async_get_platforms(platforms)
File “/usr/src/homeassistant/homeassistant/loader.py”, line 1177, in async_get_platforms
import_future.result()
File “/usr/src/homeassistant/homeassistant/loader.py”, line 1165, in async_get_platforms
platforms.update(self._load_platforms(platform_names))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/loader.py”, line 1090, in _load_platforms
platform_name: self._load_platform(platform_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/loader.py”, line 1264, in _load_platform
cache[full_name] = self._import_platform(platform_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/loader.py”, line 1296, in _import_platform
return importlib.import_module(f”{self.pkg_path}.{platform_name}")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/usr/src/homeassistant/homeassistant/util/loop.py”, line 200, in protected_loop_func
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File “/usr/local/lib/python3.12/importlib/init.py”, line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “”, line 1387, in _gcd_import
File “”, line 1360, in _find_and_load
File “”, line 1331, in _find_and_load_unlocked
File “”, line 935, in _load_unlocked
File “”, line 995, in exec_module
File “”, line 488, in _call_with_frames_removed
File “/config/custom_components/amplipi/media_player.py”, line 20, in
from pyamplipi.models import ZoneUpdate, Source, SourceUpdate, GroupUpdate, Stream, Group, Zone, Announcement,
ImportError: cannot import name ‘PlayMedia’ from ‘pyamplipi.models’ (/usr/local/lib/python3.12/site-packages/pyamplipi/models.py)

What version of Home Assistant are you running?

The latest, 2024.08.0

Which is currently working perfectly with GitHub - brianhealey/hacs_amplipi: Adds media player support for the AmpliPi MultiZone Audio Player

Aha, I think I see what’s wrong. At a minimum, the version of pyamplipi, the backing library this integration calls, isn’t running the latest. This line here is what clues me in:

ImportError: cannot import name ‘PlayMedia’ from ‘pyamplipi.models’ (/usr/local/lib/python3.12/site-packages/pyamplipi/models.py)

This is a bug I fixed earlier today. If you could ensure the git tag referenced in the AmpliPi integration details page is 6d32704, that would be helpful. If this issue persists, definitely get in touch; for what it’s worth, I’ve also upgraded our in-house Home Assistant to 2024.08.0 to test the integration there and it functions.

Just updated to the latest integration after updating to 0.4.2 and getting the same issue;

Sorry about the log format it’s pasted from the iOS app copy function :person_shrugging:

logger:%20homeassistant.config_entries%0ASource%3A%20config_entries.py%3A586%0AFirst%20occurred%3A%2008%3A44%3A43%20(1%20occurrences)%0ALast%20logged%3A%2008%3A44%3A43%0A%0AError%20setting%20up%20entry%20AmpliPi%20for%20amplipi%0ATraceback%20(most%20recent%20call%20last)%3A%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/config_entries.py%22,%20line%20586,%20in%20async_setup%0A%20%20%20%20result%20=%20await%20component.async_setup_entry(hass,%20self)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22/config/custom_components/amplipi/init.py%22,%20line%2033,%20in%20async_setup_entry%0A%20%20%20%20await%20hass.config_entries.async_forward_entry_setups(entry,%20PLATFORMS)%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/config_entries.py%22,%20line%202046,%20in%20async_forward_entry_setups%0A%20%20%20%20await%20integration.async_get_platforms(platforms)%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/loader.py%22,%20line%201177,%20in%20async_get_platforms%0A%20%20%20%20import_future.result()%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/loader.py%22,%20line%201165,%20in%20async_get_platforms%0A%20%20%20%20platforms.update(self._load_platforms(platform_names))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/loader.py%22,%20line%201090,%20in%20_load_platforms%0A%20%20%20%20platform_name:%20self._load_platform(platform_name)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/loader.py%22,%20line%201264,%20in%20_load_platform%0A%20%20%20%20cache%5Bfull_name%5D%20=%20self._import_platform(platform_name)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/loader.py%22,%20line%201296,%20in%20_import_platform%0A%20%20%20%20return%20importlib.import_module(f%22%7Bself.pkg_path%7D.%7Bplatform_name%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22/usr/src/homeassistant/homeassistant/util/loop.py%22,%20line%20200,%20in%20protected_loop_func%0A%20%20%20%20return%20func(*args,%20**kwargs)%0A%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22/usr/local/lib/python3.12/importlib/init.py%22,%20line%2090,%20in%20import_module%0A%20%20%20%20return%20_bootstrap._gcd_import(name%5Blevel:%5D,%20package,%20level)%0A%20%20%20%20%20%20%20%20%20%20%20%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%5E%0A%20%20File%20%22%3Cfrozen%20importlib._bootstrap%3E%22,%20line%201387,%20in%20_gcd_import%0A%20%20File%20%22%3Cfrozen%20importlib._bootstrap%3E%22,%20line%201360,%20in%20_find_and_load%0A%20%20File%20%22%3Cfrozen%20importlib._bootstrap%3E%22,%20line%201331,%20in%20_find_and_load_unlocked%0A%20%20File%20%22%3Cfrozen%20importlib._bootstrap%3E%22,%20line%20935,%20in%20_load_unlocked%0A%20%20File%20%22%3Cfrozen%20importlib._bootstrap_external%3E%22,%20line%20995,%20in%20exec_module%0A%20%20File%20%22%3Cfrozen%20importlib._bootstrap%3E%22,%20line%20488,%20in%20_call_with_frames_removed%0A%20%20File%20%22/config/custom_components/amplipi/media_player.py%22,%20line%2020,%20in%20%3Cmodule%3E%0A%20%20%20%20from%20pyamplipi.models%20import%20ZoneUpdate,%20Source,%20SourceUpdate,%20GroupUpdate,%20Stream,%20Group,%20Zone,%20Announcement,%20%5C%0AImportError:%20cannot%20import%20name%20’PlayMedia’%20from%20’pyamplipi.models’%20(/usr/local/lib/python3.12/site-packages/pyamplipi/models.py)%0A

I had updated well after that was updated. But just to be sure, I tried it again just now and have the same issue.

There’s also another really bad regression, even with the GitHub - brianhealey/hacs_amplipi: Adds media player support for the AmpliPi MultiZone Audio Player version, I’m getting a prior issue with volume control that had been fixed prior to 0.4.2, now I’m getting 10% volume changes instead of 1% volume changes.

Hopeful this can be fixed asap, otherwise I’m going to need to downgrade back into 0.3.x

Oh, ouch, I just noticed a major problem that happened with the upgrade from 0.3.x to 0.4.2, I lost every internet radio station I had configured on streams. That’s a brutal one.

That bug is even worse, I can’t add internet radio stations either.

2 issues with this one, first, even though I updated the AmpliPi a few days ago, my browser was still feeding me the old html+css+js, I didn’t know that it changed. I happened to hard reload my browser while trying to diagnose what was going on and noticed the interface changed a bit.

So now that it’s updated, the interface tells me that my Internet radio station’s url is invalid, which is not accurate. I suspect that someone went overboard with url validation but missed something. For reference I’m using the SiriusXM python referenced in Amplipi/python/SiriusXM.md at main · vszander/Amplipi · GitHub and have been doing so for over a year.

It really looks like I need to downgrade back to 0.3.6 since this is functionally unusable for me. Is downgrading to 0.3.6 from 0.4.2 possible?

For folks testing the Home Assistant integration, can you try our latest commit f671269 from micro-nova/hacs_amplipi? I was able to reproduce this bug by first installing the prior version of the integration and then upgrading to our fork. As a result, I have tested and merged a fix. This bug only occurs on installations upgrading from the prior integration.

@bshootz, you can definitely downgrade to 0.3.6; I also just tested that on the box sitting next to me and haven’t seen anything amiss. I’m looking at the stream validation stuff momentarily and should have something to address this problem more holistically going forward (imo, streams present in the config that fail validation should not disappear.) Do you have any more details about your AmpliPi regarding the volume percentages? Does this happen with the webapp, the api directly, homeassistant? That could be happening software or firmware and I’d like to narrow that down.

1 Like

Just updated to f671269 and that made the integration work.

FYI, it’s a little unorthodox in Home Assistant to prefix the device name, i.e. media_player.amplipi_zone_name vs media_player.zone_name. The previous extension did the latter rather than the former and it’s more common to do so.

The volume issue only appears in Home Assistant. Using the web interface on the AmpliPi I can change the volume in increments of 1%, and it’ll reflect in the interface of Home Assistant. But in HA, changing the volume using the +/- buttons results in a jump of 10%, you can use the slider to change to exact % locations.

I just remembered that this is due to SUPPORT_VOLUME_STEP needing to be added, and that I did this in my own fork with the intent of issuing a pull request to get it merged. I did this back in 2023 and completely forgot about it. I rebased my branch on yours and updated the patch I’ve been using since then.

1 Like

Now the integration is working again thank you @amplipi

If a zone is not connected to a source it is not controllable through HA, is that expected behaviour at this stage?


Yeah I noticed this as well. I would have expected to be able to “turn on” the zone and then pick a source from the list to link them up.

1 Like

Yeah, it seems that it’s exposing the zone as “off” to Home Assistant, but HA can’t turn it on (throws an error that the entity doesn’t support the option to turn on), nor can it assign a source (at least not in the frontend, I haven’t tried through an automation yet).

This is another change from the original HACS extension. The old extension would toggle the disabled flag for on/off. I’m not sure that’s a great behavior either, but the current one needs work because it’s not optimal as it currently is.

1 Like

Chiming in after updating from 0.3.x to 0.4.2. Lost my two Spotify “Streams” and my presets seem messed up and have to be redone. For what it’s worth

@rwarner did you happen to take a backup of your configuration from before your upgrade? We’d love to have a look. (If you want to pull on that thread with us, out of band in the DMs or support@micro-nova.com are good options.)

Unfortunately I did not :-/

If the other HACS is working okay for me right now, is there a reason to move to this new one since it’s not quite working yet?

I guess I’m just trying to see functionally why we should change over?