Repository navigation
Releases: CheapDevotion/ThinkViewKiosk
Release list
v33 — software volume for play_media, fixes all-or-nothing
What's in v33
`set_volume` now drives a per-sample software gain inside MediaPlayer rather than mapping to STREAM_ALARM index. Fixes the all-or-nothing behavior we hit live: STREAM_ALARM's volume curve on the Lenovo CD-18781Y is so steep that mid-range values are effectively inaudible.
Volume model
- `set_volume 0.4` stores 0.4 in pref `media-volume`
- Next `play_media` pegs STREAM_ALARM to hardware max, then applies `MediaPlayer.setVolume(0.4, 0.4)` — a linear software multiplier
- 0.4 actually sounds like 40%
- `stop_media` restores STREAM_ALARM to whatever it was before
Security siren and Spotify Connect volume paths are unaffected (independent code paths, independent volume controls).
v32 — enable backdrop-filter (glassmorphism) in GeckoView
What's in v32
GeckoView 95 (Firefox 95 from Dec 2021) ships `backdrop-filter` behind a flag — disabled by default. HA dashboards using the glassmorphism / frosted-glass pattern (`backdrop-filter: blur(...)`) had that declaration silently no-op on our kiosks.
v32 writes a Gecko user_prefs file at runtime startup that flips `layout.css.backdrop-filter.enabled` to true. `backdrop-filter` now renders correctly.
Note on `filter` vs `backdrop-filter`
- `filter: blur(2px)` — blurs the element itself. Always worked in Firefox 35+. If this still isn't visible, the issue is elsewhere (e.g. element has no visible content, or the style is overridden by a more specific selector).
- `backdrop-filter: blur(2px)` — blurs what's behind a translucent element. The frosted-glass effect. Required v32 to work.
If you're applying the frosted-glass look, the element needs:
```css
backdrop-filter: blur(8px);
background: rgba(255, 255, 255, 0.1); /* must be at least partially transparent */
```
If it has a fully opaque background, there's nothing behind to blur and the property does nothing visible.
v31 — set_volume command for STREAM_ALARM
What's in v31
New `set_volume` kiosk_command. Sets the device's STREAM_ALARM volume — the loudness level used by `play_media` (and bypassed/overridden by the security siren). Companion to v30's `play_media` for alarm-clock automations.
Example: crank volume before wakeup, restore after
```yaml
-
alias: Bedroom wakeup
trigger:- platform: time
at: "06:59:55"
action: - event: kiosk_command
event_data: { device: Bedroom Dashboard, command: set_volume, value: "0.8" }
- platform: time
-
alias: Bedroom wakeup fire
trigger:- platform: time
at: "07:00:00"
action: - event: kiosk_command
event_data: { device: Bedroom Dashboard, command: play_media, value: "http://homeassistant.local:8123/local/wakeup.mp3" }
- platform: time
-
alias: Bedroom dismiss
trigger:- platform: state
entity_id: input_button.bedroom_dismiss
action: - event: kiosk_command
event_data: { device: Bedroom Dashboard, command: stop_media } - event: kiosk_command
event_data: { device: Bedroom Dashboard, command: set_volume, value: "0.3" }
```
- platform: state
What it doesn't affect
- Security siren — peg-to-max regardless of this setting
- Spotify Connect volume — separate path, controlled from phone Spotify slider or footer +/− buttons
- STREAM_MUSIC — not used by anything we control
For finer-grained control of those other paths, future commands like `set_media_volume` / `set_spotify_volume` would be obvious follow-ups.
v30 — play_media + stop_media commands
What's in v30
Two new kiosk_commands:
- `play_media` — takes an audio URL in `value`. Plays via Android MediaPlayer on STREAM_ALARM so it bypasses silent/DND, ducks Spotify automatically, and gets out of the way of the music when done. Single-track at a time: firing again replaces.
- `stop_media` — stops any in-progress play_media.
Primary use case: HA-driven alarm clocks.
Example: 7:00 AM wakeup automation
```yaml
- alias: Bedroom wakeup
trigger:- platform: time
at: "07:00:00"
action: - event: kiosk_command
event_data:
device: Bedroom Dashboard
command: play_media
value: "http://homeassistant.local:8123/local/wakeup.mp3"
```
- platform: time
Store `wakeup.mp3` in HA's `config/www/` folder; it's served at `/local/`. Or use an HA TTS proxy URL for spoken alarms (e.g. `http://.../api/tts_proxy/.mp3`).
Notes
- URL must be reachable from the kiosk's network (same Wi-Fi LAN as HA).
- File formats: anything Android MediaPlayer supports — MP3, AAC, OGG, WAV, FLAC, M4A.
- Spotify keeps playing under the alarm (ducked); stop the alarm via `stop_media` or let it complete naturally to return Spotify to normal volume.
- Volume: defaults to whatever the device's STREAM_ALARM is set to (~40% out of the box). Can be turned up via the device's hardware volume keys while playing.
v29 — kill the surprise 'play artist only' switch on hiccups
Disables librespot's autoplay (radio station fallback when queue exhausts) by default. After a network hiccup desyncs librespot's session state with Spotify's server, the queue appears empty and autoplay was switching the user's playlist over to a radio station based on the current artist without input. Now defaults to stop-at-end-of-queue. Per-device runtime override: set_autoplay kiosk_command with value 'true' or 'false'.
v28 — kill the 30-60s Spotify Connect delay
What's in v28
Spotify Connect device pickups now consistently complete in 1-2 seconds instead of 30-60.
Root cause
The kiosk's first session-creation attempt occasionally fails on the TCP connect to a Spotify accesspoint (random pick from a 6-AP pool, some are intermittently unreachable). The phone-side Connect protocol then waits ~33 seconds before re-sending /addUser, which is the user-visible delay. Identified via fleet logs from `get_logs`:
```
16:30:22.143 Accepted new user from iPhone
16:30:22.959 ERROR ZeroconfServer - Couldn't establish a new session.
(33s of phone-side retry timeout)
16:30:55.006 Accepted new user from iPhone ← retry, succeeds
```
Fix
Patched librespot's `ZeroconfServer.handleAddUser` (in our local clone) to retry session creation up to 5 times with 200ms backoff before giving up. Each retry picks a fresh random AP, so a different one is tried. With 6 APs in the typical pool and most working, retries usually succeed on attempt 2.
Worst case: ~5s before giving up. Still vastly better than the 33s phone-side timeout.
v27 — hold-to-repeat volume + visual feedback bar
Volume buttons now repeat while held (single tap = single step, 1.5s hold = full sweep). New volume indicator bar fades in over the track text whenever volume changes (your tap, hold, or phone-side slider), then fades back to the track text 1.5s after the last change. Volume step size doubled (~3% per tap).
v26 — flat white footer icons via custom Drawable
Replaces Unicode media glyphs (which Android 8.1 was rendering as orange color emoji from NotoColorEmoji on the Lenovo skin) with programmatic shapes drawn via a custom Drawable. Guaranteed flat white, no font fallback orange.
v25 — set_brightness remote command for HA-driven dimming
What's in v25
New `set_brightness` kiosk_command. Accepts fractional (`0.2`) or percentage (`20`) input. Updates the persisted `screen-brightness` pref and applies live to the running MainActivity window. Clamped to [5%, 100%].
Also absorbed at provisioning time via `--ef screen_brightness 0.2`.
HA automation example: alarm-armed dimming
```yaml
-
alias: Dim bedroom kiosk on alarm armed
trigger:- platform: state
entity_id: alarm_control_panel.alarmo
to:- armed_night
- armed_home
- armed_away
action:
- service: homeassistant.event
data:
event_type: kiosk_command
event_data:
device: Bedroom Dashboard
command: set_brightness
value: "0.2"
- platform: state
-
alias: Restore bedroom kiosk on alarm disarmed
trigger:- platform: state
entity_id: alarm_control_panel.alarmo
to: disarmed
action: - service: homeassistant.event
data:
event_type: kiosk_command
event_data:
device: Bedroom Dashboard
command: set_brightness
value: "1.0"
```
- platform: state
v24 — silence button actually disarms HA
What's in v24
The SILENCE SIREN button on the AlarmActivity overlay used to just stop the local siren. Now it calls HA's `alarm_control_panel.alarm_disarm` service. The resulting state change propagates over the WebSocket to every connected kiosk and each one auto-dismisses its overlay via the v23 onAlarmCleared path -- so one tap on a designated panel silences and dismisses the alarm fleet-wide.
`alarm_can_disarm` and `alarm_disarm_code` can now be set at provisioning time via intent extras (`--ez alarm_can_disarm true --es alarm_disarm_code 1234`) or remotely via the `set_can_disarm` / `set_disarm_code` kiosk_command events.
Practical pattern: enable siren on every room, set `can-disarm=true` only on the master bedroom panel. Anywhere in the house, the alarm fires loud and visible. Only the bedroom can silence it -- and one tap on the bedroom panel kills the alarm everywhere.