Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
db98f0a
Bump binaries to 64bit versions, add extra steps and checks to config…
SteveMicroNova Jan 14, 2026
67dac1f
Update to use Lyrion
SteveMicroNova Jan 20, 2026
4fd8eca
Add dev flag to deploy script, use it to ignore previous version chec…
SteveMicroNova Feb 20, 2026
7c2d6e9
Merge main
SteveMicroNova Mar 9, 2026
8b71fd2
Fix bootstrap script
SteveMicroNova Mar 9, 2026
da2f043
Sync dd changes
SteveMicroNova Mar 10, 2026
6f27095
Make lite the default bootstrap edition, add an autoboot.txt
SteveMicroNova Mar 13, 2026
3c3cc21
Initial support for the /data directory
SteveMicroNova Mar 19, 2026
6ab3d68
Add uv install and configuration step to ensure we use the right python
SteveMicroNova Mar 26, 2026
fcf2f34
Put uv where it actually needs to be, temporarily deactivate a few im…
SteveMicroNova Mar 27, 2026
9a0e10a
Readd bluetooth support, improve custom deps installation, fix failur…
SteveMicroNova Mar 27, 2026
93d2a6c
Add manual bluealsa install
SteveMicroNova Apr 17, 2026
1d56f62
Deactivate frontend caching via the backend
SteveMicroNova Feb 19, 2026
f6e4480
Bump version
SteveMicroNova May 7, 2026
59ce620
Add vol_f_buffer functionality, imporving relativistic volume changes
SteveMicroNova Oct 23, 2025
acdfa6e
Add global alert bar, dynamic webapp version warning
SteveMicroNova Feb 25, 2026
1f9c303
Update to use Lyrion
SteveMicroNova Jan 20, 2026
5985907
move .config to /data for sharing configs between partitions
SteveMicroNova Jun 26, 2026
ac38b7e
Simplify workflow of repeated bootstrappings
SteveMicroNova Jun 26, 2026
e726383
Add futureproofing to configure.py
SteveMicroNova Jun 26, 2026
d6f9d64
Update python deps script to manage the swap to UV, update configure.…
SteveMicroNova Jun 29, 2026
2d5c71a
Add initial form of flash endpoint
SteveMicroNova Jul 1, 2026
1743c3a
Add progress feedback on checksumming, flashing processes
SteveMicroNova Jul 1, 2026
4ee2771
Fine tune flashing endpoint vars, add post-imaging configuration steps
SteveMicroNova Jul 2, 2026
7fda498
Fix patching steps by mounting the inactive boot with correct permiss…
SteveMicroNova Jul 2, 2026
c9127f2
Fix flash finalization steps by running shell commands directly
SteveMicroNova Jul 2, 2026
e22593c
Add automated validation flow for freshly flashed systems
SteveMicroNova Jul 2, 2026
860c472
Fix tryboot script for better actuation of the local variables
SteveMicroNova Jul 7, 2026
64365d2
Update cleanup script to handle multiple partitions of cleaning
SteveMicroNova Jul 7, 2026
4e15c31
Plumb the new location of .config throughout all files
SteveMicroNova Jul 10, 2026
42880db
Migrate all services to /data to persist them and their settings better
SteveMicroNova Jul 20, 2026
219df1d
Add documentation to flash endpoint and related models
SteveMicroNova Jul 20, 2026
2d2ae89
Remove leftover $ from fstring removals
SteveMicroNova Jul 21, 2026
26ae9ab
Add autoboot toggle script to git
SteveMicroNova Jul 21, 2026
bed6423
Document the --dev option of the deploy script in a reasonable way
SteveMicroNova Jul 21, 2026
939cb4e
Add post-flash partition branding so you can tell what boot slot you'…
SteveMicroNova Jul 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

# Future Release
* System
* Upgrade from 32 bit raspbian Bookworm Desktop to 64 bit raspbian Trixie Lite
* Upgraded volume calculations to preserve relative positions when hitting the min or max setting via source volume bar
* Added volume matching between AmpliPi and Spotify and vice-versa
* Update our spotify provider `go-librespot` to `0.7.3`
* Upgrade from Logitech Media Server 8.5.2 to Lyrion Music Server 9.0.3
* Added in-place preamp recovery when I2C writes fail persistently
Expand Down
2 changes: 1 addition & 1 deletion amplipi/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ async def get_response(self, path, scope):


# Website
app.mount('/', StaticFiles(directory=WEB_DIR, html=True), name='web')
app.mount('/', CachelessFiles(directory=WEB_DIR, html=True), name='web')


def create_app(mock_ctrl=None, mock_streams=None, config_file=None, delay_saves=None, settings: models.AppSettings = models.AppSettings()) -> FastAPI:
Expand Down
2 changes: 1 addition & 1 deletion amplipi/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
# This is duplicated from amplipi.config intentionally. This file is pulled in
# via the updater and we'd like to avoid as many external Amplipi dependencies in the updater
# as possible.
USER_CONFIG_DIR = os.path.join(os.path.expanduser('~'), '.config', 'amplipi')
USER_CONFIG_DIR = os.path.join('/data', '.config', 'amplipi')

USERS_FILE = os.path.join(USER_CONFIG_DIR, 'users.json')

Expand Down
4 changes: 2 additions & 2 deletions amplipi/ctrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,15 +852,15 @@ def set_vol():
vol, vol_f, vol_f_delta, vol_min, or vol_max.
"""
# Field precedence: vol (db) > vol_delta > vol (float)
# vol (db) is first in precedence yet last in the stack to cover the default case of no volume change

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a rebase error. This branch is long lived and had some merge conflicts on rebase and so may need to be combed for reversions like this before merging

# vol (db) is first in precedence yet last in the stack to cover the default case of a None volume change, but when it does have a value it overrides the other options
if update.vol_delta_f is not None and update.vol is None:
true_vol_f = zone.vol_f + zone.vol_f_overflow
expected_vol_total = update.vol_delta_f + true_vol_f
vol_f_new = utils.clamp(expected_vol_total, models.MIN_VOL_F, models.MAX_VOL_F)

vol_db = utils.vol_float_to_db(vol_f_new, zone.vol_min, zone.vol_max)
zone.vol_f_overflow = 0 if models.MIN_VOL_F < expected_vol_total and expected_vol_total < models.MAX_VOL_F \
else utils.clamp((expected_vol_total - vol_f_new), models.MIN_VOL_F_OVERFLOW, models.MAX_VOL_F_OVERFLOW)
else utils.clamp((expected_vol_total - vol_f_new), models.MIN_VOL_F_OVERFLOW, models.MAX_VOL_F_OVERFLOW)
# Clamp the remaining delta to be between -1 and 1

elif update.vol_f is not None and update.vol is None:
Expand Down
2 changes: 1 addition & 1 deletion amplipi/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
RCAs = [996, 997, 998, 999]
LMS_DEFAULTS = [1000, 1001, 1002, 1003]

USER_CONFIG_DIR = os.path.join(os.path.expanduser('~'), '.config', 'amplipi')
USER_CONFIG_DIR = os.path.join('/data', '.config', 'amplipi')

DEFAULT_CONFIG = { # This is the system state response that will come back from the amplipi box
"version": 1,
Expand Down
4 changes: 3 additions & 1 deletion amplipi/display/check_pass
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python3

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version of python we run has to be installed via UV on Trixie, so I had to move the invocation paths on a few files

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we replace this with something more generic like uv run?

#!/home/pi/.local/share/uv/python/cpython-3.8.20-linux-aarch64-gnu/bin/python3.8
# This is a separate script as it must be run with root privileges
# Example: sudo python check_pass 'raspberry'

Expand All @@ -9,5 +9,7 @@ import sys
default_password = sys.argv[1]
current_password = spwd.getspnam('pi').sp_pwd
if crypt.crypt(default_password, current_password) == current_password:
print("Correct Password")
sys.exit(0)
print("Incorrect Password")
sys.exit(1)
12 changes: 6 additions & 6 deletions amplipi/display/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class DefaultPass:
the stored default AmpliPi password."""

# Password config location
PASS_DIR = os.path.join(os.path.expanduser('~'), '.config', 'amplipi')

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole .config folder and a few services got moved to /data to ensure they persist post-update, many lines like this had to be changed as a result

PASS_DIR = os.path.join('/data', '.config', 'amplipi')
PASS_FILE = os.path.join(PASS_DIR, 'default_password.txt')
DEFAULT_PI_PASSWORD = 'raspberry'

Expand Down Expand Up @@ -115,7 +115,7 @@ def get_default_pw(self) -> str:
def check_pw(pw: str) -> bool:
""" Check if the given password is the pi user's current password. """
try:
subprocess.run(f'sudo python3 amplipi/display/check_pass {pw}', shell=True, check=True)
subprocess.run(f'sudo ./amplipi/display/check_pass {pw}', shell=True, check=True)
return True
except subprocess.CalledProcessError:
return False
Expand Down Expand Up @@ -177,9 +177,9 @@ def get_zone_status(zone, sources) -> STATUS:
else:
return STATUS.PLAYING
elif source_for_zone.state == 'stopped':
return STATUS.STOPPED
return STATUS.STOPPED
elif source_for_zone.state == 'paused':
return STATUS.PAUSED
return STATUS.PAUSED
return STATUS.IGNORE
return STATUS.IGNORE

Expand Down Expand Up @@ -222,7 +222,7 @@ def get_emoji_status(url: str, max_length: int = 16) -> Union[str, int]:

result = ''
if status_counts[STATUS.PLAYING] > 0:
result += f'▶x{status_counts[STATUS.PLAYING]} '
result += f'▶x{status_counts[STATUS.PLAYING]} '
if status_counts[STATUS.PAUSED] > 0:
result += f'⏸x{status_counts[STATUS.PAUSED]} '
if status_counts[STATUS.STOPPED] > 0:
Expand All @@ -248,7 +248,7 @@ def get_status(url: str, no_serial_ok: bool = False, emoji: bool = True, max_len
result_status = st

# Check if API is running
api_on = subprocess.run("systemctl --user is-active amplipi.service".split(), stdout=subprocess.DEVNULL)
api_on = subprocess.run("systemctl is-active amplipi.service".split(), stdout=subprocess.DEVNULL)
if api_on.returncode != 0:
return DisplayError.NO_AMPLIPI_SERVICE, None, 0

Expand Down
8 changes: 8 additions & 0 deletions amplipi/rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ def _recover_preamps(self) -> bool:
try:
self.reset_preamps()
self.set_i2c_addr()
try:
self.bus.close()
except Exception:
pass
Comment on lines +286 to +289

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an additional fix for the issue fixed by #1098 which was merged in #1091

My unit actually got into a bad state during testing, which led to me having the ability to test those changes and add a little more to the fix

My own issue was downstream of some configuration file providing an environment that the I2C didn't like

self.bus = SMBus(1)
for addr, regs in list(self.preamps.items()):
for reg, val in enumerate(regs):
Expand Down Expand Up @@ -319,6 +323,10 @@ def write_byte_data(self, preamp_addr, reg, data):
# Fallback 1: reopen the bus handle and retry (transient bus glitch).
try:
time.sleep(0.001)
try:
self.bus.close()
except Exception:
pass
self.bus = SMBus(1)
self.bus.write_byte_data(preamp_addr, reg, data)
except Exception:
Expand Down
Loading
Loading