Commit Graph

3 Commits (cebdc9529bd367bd0d82d102f6287289c4d1ff7e)

Author SHA1 Message Date
Amir Alexander Abdelbaki 86fe981d7c Stream Dock lighting controls, and Discord on the Loggia panel
Two changes that share the config file, the exporter and the validator, so
they land together.

--- stream-dock/ ---

Four rotary encoders on a desk-side MiraBox N4 Pro (the xVSDinside-branded
one; Ajazz AKP05 family) as R / G / B / brightness for one room's lamps,
through OpenDeck.

No new plugin, deliberately. cgiesche/streamdeck-homeassistant already does
Home Assistant over websocket with encoder actions, and opendeck-akp05 already
teaches OpenDeck this non-Elgato hardware. What was missing was the
configuration between them, and one thing neither can do: relative colour. An
encoder emits "three ticks clockwise" and HA has brightness_step_pct but no
equivalent for a colour channel, so the dock sends only which channel and how
many ticks, and ha-package/stream_dock.yaml does the read-clamp-write against
the lamp's current rgb_color. Room-agnostic — the scripts take entity_id as a
field, so one copy serves every room and a second dock needs no new HA config.

Bindings are generated as a document to paste, not as an OpenDeck profile
file. That schema is not documented anywhere this could be checked against,
and a profile written to a guessed schema fails in the least useful way
available: OpenDeck starts, the profile looks present, the dials do nothing.

Rings 1-3 show their own channel's value in their own colour; ring 4 shows
what the room is actually emitting (rgb scaled by brightness). Off the dock's
lighting layer they fall back to the desktop's own palette from
~/Dotfiles/colors.conf, chasing one ring at a time, and Home Assistant is not
polled at all — the rings are shared hardware, and on another layer those
dials mean something else. A gate that cannot tell which layer is showing
reports "cannot tell", which is treated as "not ours": going idle is the
recoverable mistake, hijacking is not.

The one gap is the reload. The akp05 plugin reads leds.toml at startup and
holds the USB device open, so nothing else can drive those LEDs and no local
change makes it re-read. apply-leds.sh carries four strategies and a --probe
that walks them cheapest-first with the dock in front of you — its FIRST test
is whether the plugin already watches the file, in which case the rings are
live for free. The apply is rate-limited separately from the file write, so a
spun dial cannot re-initialise the device per detent and the last state is
never dropped. The real fix is upstream and small;
upstream-file-watch-request.md is written and ready to file.

Nothing here has touched hardware. Verified against a stub Home Assistant:
ring colours on/off, unreachable HA, the layer gate in all three states, the
idle chase, and the rate limiter (12 colour changes in 6s -> 3 applies, final
state on disk). Unverified, in bite-order: whether {{ticks}} substitutes (an
absolute-position variant is in the generated bindings if it does not), the
ring reload, the gate's discovery of OpenDeck's profile state, and the HA
scripts themselves.

--- Discord on the touch panel ---

An optional fourth app, kiosks[].enable_discord, validator-restricted to the
touch-panel type: no other image installs the Flatpak or has a workspace for
it, so elsewhere the flag would be silently ignored on a panel that boots
looking fine.

It is for the Loggia — the point is a voice call that survives stepping
outside for a cigarette, which is a switch-device action, not a read-messages
one. So it starts logged in at session boot and every control path (dock
button, HA "Show Discord", the Screen select) focuses the running app rather
than launching it. The Screen select's options are now derived from the app
table instead of being fixed, so a dropdown never offers a workspace this
image has no app for.

Three things follow from it being XWayland rather than native Wayland: sway
matches class, not app_id (an app_id rule would silently never fire); touch is
the emulated-pointer tier; and it deliberately does not inhibit idle, because
a call must not hold the panel's screen on in an empty room.

The Loggia panel itself is a new kiosk entry in the template. The real
CoreSystemConfig.json is gitignored, so its copy of that entry is local only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B7yp4NcmX4zqja1MKRjeWJ
2026-08-31 13:04:17 +02:00
Amir Alexander Abdelbaki 20df328b63 Add touch-panel mouse-emulated-touchscreen fallback; revise components.md shopping list
hosts/touch-panel/: cheap touch controllers sometimes report as an absolute-
position HID mouse instead of a real digitizer, which makes libinput hand
sway a type:pointer device instead of type:touch. Add a type:pointer
fallback (flat accel profile, no pointer acceleration, cursor hidden on
idle) so taps still work as single-touch clicks in that case, plus a udev
rule template (configs/udev/99-touchscreen-override.rules) to re-tag a
specific known device back to full wl_touch semantics once its USB vendor/
product ID is known. Documented in a new README section and reflected in
project-plan.md's hardware/guardrail/open-decision entries for Phase 16.

docs/components.md: replace the Lenovo ThinkSmart View pick for Loggia (a
locked-down Teams/Zoom appliance, not a general Linux box) with a cheap
all-in-one touchscreen PC, then supersede that with the Lenovo all-in-one
already on hand for that room — moved from Need to Have throughout. Also
adds a Need section: missing components broken into sub-parts (Sound
System, Voice Reciever) with real Amazon listings found via search.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CrKjW3yVptUnjG35HjC1
2026-07-30 12:38:15 +02:00
Amir Alexander Abdelbaki f3f870c4b4 Add Phase 16 touch panel and Phase 17 kitchen/fridge display endpoints
hosts/touch-panel/: a touch-driven Sway kiosk with a full Spotify GUI client
(Flathub), a dedicated Home Assistant Chromium kiosk window, a general web
browser, an always-on eww touch dock for app switching, an on-screen keyboard
(wvkbd), and touchpanel-agent giving HA/the LLM the same MQTT-mediated control
the thin client has.

hosts/kitchen-display/ + pantry-vision/: a camera-vision grocery cataloguing
endpoint for the fridge/pantry. The kiosk's browser captures a photo via
getUserMedia and sends it to the new pantry-vision service, which asks an
Ollama vision model to identify the item and estimate shelf life; the
proposal is always human-confirmed before being written into Grocy stock.
The same display shows inventory sorted by soonest-to-expire and Grocy's
recipes.

Wires ENABLE_PANTRY_VISION into setup-container-host.sh and documents both
phases in docs/project-plan.md and README.md, matching this project's
existing per-host hardware/software/guardrail/open-decision conventions.
Nothing here has been run against real hardware, a real camera, or a real
Grocy/vision-model instance — see each new README's verification list.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CrKjW3yVptUnjG35HjC1
2026-07-30 11:33:08 +02:00