2 Commits

Author SHA1 Message Date
d8eb61e967 fix: allow 'reboot' to application when on on battery
All checks were successful
Build RPi Pico firmware image / Build-Firmware (push) Successful in 4m43s
Check code formatting / Check-C-Format (push) Successful in 7s
Check code formatting / Check-Python-Flake8 (push) Successful in 10s
Check code formatting / Check-Bash-Shellcheck (push) Successful in 5s
Run unit tests on host / Run-Unit-Tests (push) Successful in 8s
Run pytests / Check-Pytest (push) Successful in 10s
Having to press the power button again to wake up the device is less
annoying to the user than not being able to apply settings when the
device is on battery.

Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-23 18:23:20 +01:00
a1d71964f7 feat: Allow limiting max. volume
Signed-off-by: Matthias Blankertz <matthias@blankertz.org>
2025-12-23 18:23:20 +01:00
5 changed files with 26 additions and 11 deletions

View File

@@ -167,7 +167,7 @@
<div id="screen-config" class="screen">
<h2>Configuration Editor</h2>
<div id="config-container">Loading…</div>
<button id="config-save-btn" disabled>Save</button>
<button id="config-save-btn" disabled>Save &amp; Reboot</button>
</div>
<!-- PLAYLIST EDITOR SCREEN 1: list of playlists -->
@@ -316,7 +316,9 @@
return;
}
alert("Configuration saved successfully!");
alert("Configuration saved successfully, device will now reboot/shutdown! " +
"On battery, press Power button after shutdown to restart.");
await fetch('/api/v1/reboot/application', {'method': 'POST'});
} catch (err) {
alert("Error saving configuration: " + err);
}
@@ -354,7 +356,8 @@
'root.BUTTON_MAP.PLAY_PAUSE': 'Play/Pause',
'root.TAG_TIMEOUT_SECS': 'Tag removal timeout (seconds)',
'root.TAGMODE': 'Tag mode',
'root.LED_COUNT': 'Length of WS2182 (Neopixel) LED chain'
'root.LED_COUNT': 'Length of WS2182 (Neopixel) LED chain',
'root.VOLUME_MAX': 'Maximum volume (0-255)'
};
const config_input_override = {
'root.TAGMODE': {
@@ -393,6 +396,9 @@
},
'root.WLAN.PASSPHRASE': {
'input-type': 'text'
},
'root.VOLUME_MAX': {
'input-type': 'number'
}
};

View File

@@ -9,8 +9,8 @@ from utils import TimerManager
Dependencies = namedtuple('Dependencies', ('mp3player', 'nfcreader', 'buttons', 'playlistdb', 'hwconfig', 'leds',
'config'))
# Should be ~ 6dB steps
VOLUME_CURVE = [1, 2, 4, 8, 16, 32, 63, 126, 251]
# Should be ~ 3dB steps
VOLUME_CURVE = [1, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 91, 128, 181, 255]
class PlayerApp:
@@ -52,6 +52,7 @@ class PlayerApp:
self.hwconfig = deps.hwconfig(self)
self.leds = deps.leds(self)
self.tag_mode = self.config.get_tagmode()
self.volume_max = self.config.get_volume_max()
self.playing_tag = None
self.playlist = None
self.buttons = deps.buttons(self) if deps.buttons is not None else None
@@ -91,8 +92,10 @@ class PlayerApp:
def onButtonPressed(self, what):
assert self.buttons is not None
if what == self.buttons.VOLUP:
self.volume_pos = min(self.volume_pos + 1, len(VOLUME_CURVE) - 1)
self.player.set_volume(VOLUME_CURVE[self.volume_pos])
new_volume = min(self.volume_pos + 1, len(VOLUME_CURVE) - 1)
if VOLUME_CURVE[new_volume] <= self.volume_max:
self.volume_pos = new_volume
self.player.set_volume(VOLUME_CURVE[self.volume_pos])
elif what == self.buttons.VOLDOWN:
self.volume_pos = max(self.volume_pos - 1, 0)
self.player.set_volume(VOLUME_CURVE[self.volume_pos])

View File

@@ -26,7 +26,8 @@ class Configuration:
'WIFI': {
'SSID': '',
'PASSPHRASE': '',
}
},
'VOLUME_MAX': 255
}
def __init__(self, config_path='/config.json'):
@@ -97,6 +98,9 @@ class Configuration:
def get_wifi_passphrase(self) -> str:
return self._get('WIFI')['PASSPHRASE']
def get_volume_max(self) -> int:
return self._get('VOLUME_MAX')
# For the web API
def get_config(self) -> Mapping[str, Any]:
return self.config

View File

@@ -269,10 +269,9 @@ async def audiofile_delete(request):
@webapp.route('/api/v1/reboot/<method>', methods=['POST'])
async def reboot(request, method):
if hwconfig.get_on_battery():
return 'not allowed: usb not connected', 403
if method == 'bootloader':
if hwconfig.get_on_battery():
return 'not possible: connect USB first', 403
leds.set_state(LedManager.REBOOTING)
timer_manager.schedule(time.ticks_ms() + 1500, machine.bootloader)
elif method == 'application':

View File

@@ -139,6 +139,9 @@ class FakeConfig:
def get_tagmode(self):
return 'tagremains'
def get_volume_max(self):
return 255
def fake_open(filename, mode):
return FakeFile(filename, mode)