Show a minimal fullscreen fallback while WFB video is absent, then hide it when decoded video is present.
Required behavior
WFB/video absent → black background + “Brak połączenia WFB”
first decoded frame → video becomes visual priority; fallback text disappears
video ends → fallback text returns
Constraints
Do not use WFB process existence as the only video-presence signal.
Pilot video must remain low-latency and independent from UI telemetry refresh.
No OSD layout work in this issue.
## Goal
Show a minimal fullscreen fallback while WFB video is absent, then hide it when decoded video is present.
## Required behavior
```text
WFB/video absent → black background + “Brak połączenia WFB”
first decoded frame → video becomes visual priority; fallback text disappears
video ends → fallback text returns
```
## Constraints
- Do not use WFB process existence as the only video-presence signal.
- Pilot video must remain low-latency and independent from UI telemetry refresh.
- No OSD layout work in this issue.
grzesiu
was assigned by piotr2026-10-01 14:14:10 +02:00
go test -race ./internal/display ./cmd/groundstation-display
go test ./...
go vet ./...
gofmt -l
build ARM64 obu binariów
git diff --check i skan nowych linii pod kątem sekretów
Review wykrył i naprawił fałszywe rozpoznawanie pomocniczych okien X11, śledzenie tylko jednego okna video oraz możliwość przecięcia pary zastępczej UTF-16.
CI dla PR: brak skonfigurowanego uruchomienia — jedyny workflow .gitea/workflows/build-arm64.yml reaguje wyłącznie na push do main lub ręczne uruchomienie. Dla SHA PR Gitea potwierdza 0 statusów i 0 runów; nie istnieje oczekujący job. Test na docelowej sesji Orange Pi/X11 pozostaje walidacją wdrożeniową.
Gotowe: PR https://git.piksar.eu/piotr/groundstation/pulls/9
Head: `b169a64ad539f85f11cb49b36c1865733b87e018`.
Walidacja końcowego drzewa:
- `go test -race ./internal/display ./cmd/groundstation-display`
- `go test ./...`
- `go vet ./...`
- `gofmt -l`
- build ARM64 obu binariów
- `git diff --check` i skan nowych linii pod kątem sekretów
Review wykrył i naprawił fałszywe rozpoznawanie pomocniczych okien X11, śledzenie tylko jednego okna video oraz możliwość przecięcia pary zastępczej UTF-16.
CI dla PR: brak skonfigurowanego uruchomienia — jedyny workflow `.gitea/workflows/build-arm64.yml` reaguje wyłącznie na push do `main` lub ręczne uruchomienie. Dla SHA PR Gitea potwierdza 0 statusów i 0 runów; nie istnieje oczekujący job. Test na docelowej sesji Orange Pi/X11 pozostaje walidacją wdrożeniową.
Piotr reports that the updated Orange Pi supervisor repeatedly opens new kiosk windows every few seconds. The current journal only shows the root supervisor and runuser session; it does not expose the underlying X11 session error.
The current display.Run intentionally catches Session.WaitEvent errors, closes the session, and retries, but it discards the error. This makes an X11 reconnect loop silent and prevents hardware diagnosis.
Please add structured error logging at the reconnect boundary, including target, error and retry delay, e.g. when WaitEvent breaks a session and when Open fails. Preserve the existing resilience: temporary X11 failure must not restart the UART supervisor.
Piotr will collect the resulting journal output on the physical Orange Pi after a reviewable build. Do not require hardware access from Grzesiu.
## Hardware finding: kiosk window repeatedly recreates
Piotr reports that the updated Orange Pi supervisor repeatedly opens new kiosk windows every few seconds. The current journal only shows the root supervisor and `runuser` session; it does not expose the underlying X11 session error.
The current `display.Run` intentionally catches `Session.WaitEvent` errors, closes the session, and retries, but it discards the error. This makes an X11 reconnect loop silent and prevents hardware diagnosis.
Please add structured error logging at the reconnect boundary, including target, error and retry delay, e.g. when `WaitEvent` breaks a session and when `Open` fails. Preserve the existing resilience: temporary X11 failure must not restart the UART supervisor.
Piotr will collect the resulting journal output on the physical Orange Pi after a reviewable build. Do not require hardware access from Grzesiu.
Head: baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50, zsynchronizowany z main@41552b4797e9d5761feefe0aaeb1a3c2411272a0.
Dodano po jednym strukturalnym rekordzie dla nieudanego Open i zerwanej sesji WaitEvent, z polami target, layer, event, error i retry delay. Anulowanie pozostaje ciche, a błędy X11 nadal pozostają wewnątrz pętli reconnect i nie restartują supervisora UART/root. Integracja zachowuje nową wielowarstwową architekturę display z main.
Walidacja końcowego drzewa po merge z aktualnym main:
focused tests diagnostyki i formatowania logów
go test -race ./internal/display ./cmd/groundstation-display
go test ./...
go vet ./..., gofmt -l
build ARM64 obu binariów
git diff --check i skan nowych linii pod kątem sekretów
CI dla PR nie jest skonfigurowane: workflow nadal uruchamia się wyłącznie po push do main lub ręcznie; Gitea zwraca 0 statusów i 0 runów dla SHA PR. Po reviewowalnym buildzie Piotr może zebrać nowe rekordy z journala na Orange Pi.
Follow-up sprzętowy gotowy: PR https://git.piksar.eu/piotr/groundstation/pulls/13
Head: `baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50`, zsynchronizowany z `main@41552b4797e9d5761feefe0aaeb1a3c2411272a0`.
Dodano po jednym strukturalnym rekordzie dla nieudanego `Open` i zerwanej sesji `WaitEvent`, z polami target, layer, event, error i retry delay. Anulowanie pozostaje ciche, a błędy X11 nadal pozostają wewnątrz pętli reconnect i nie restartują supervisora UART/root. Integracja zachowuje nową wielowarstwową architekturę display z `main`.
Walidacja końcowego drzewa po merge z aktualnym `main`:
- focused tests diagnostyki i formatowania logów
- `go test -race ./internal/display ./cmd/groundstation-display`
- `go test ./...`
- `go vet ./...`, `gofmt -l`
- build ARM64 obu binariów
- `git diff --check` i skan nowych linii pod kątem sekretów
CI dla PR nie jest skonfigurowane: workflow nadal uruchamia się wyłącznie po push do `main` lub ręcznie; Gitea zwraca 0 statusów i 0 runów dla SHA PR. Po reviewowalnym buildzie Piotr może zebrać nowe rekordy z journala na Orange Pi.
Rebasing (1/1)
error: could not apply 3bf2230... feat: log structured reconnect diagnostics for kiosk display (#2)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Could not apply 3bf2230... # feat: log structured reconnect diagnostics for kiosk display (#2)
Rebasing (1/1)
error: could not apply 3bf2230... feat: log structured reconnect diagnostics for kiosk display (#2)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Could not apply 3bf2230... # feat: log structured reconnect diagnostics for kiosk display (#2)
Auto-merging cmd/groundstation-display/main.go
CONFLICT (content): Merge conflict in cmd/groundstation-display/main.go
Auto-merging cmd/groundstation-display/main_test.go
Auto-merging internal/display/display.go
Rekomendacja: przerwać rebase i scalić PR #13 metodą merge commit. Zdalna gałąź nie jest w stanie konfliktu: PR #13 jest obecnie mergeable=true, ma head baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50 i zawiera już main@41552b4797e9d5761feefe0aaeb1a3c2411272a0 przez zwalidowany normalny merge.
Rebase próbuje ponownie odtworzyć starszy commit 3bf2230 sprzed refaktoru warstw display z #8, dlatego konfliktuje w cmd/groundstation-display/main.go; ten konflikt został już semantycznie rozwiązany w merge commicie baf36fd8.
Jeżeli repo wymaga historii rebase-only, potrzebne jest jawne potwierdzenie przepisania i force-pusha dedykowanej gałęzi PR. Wtedy zlinearyzuję zmianę na aktualnym main i ponownie wykonam walidację.
Rekomendacja: przerwać rebase i scalić PR #13 metodą **merge commit**. Zdalna gałąź nie jest w stanie konfliktu: PR https://git.piksar.eu/piotr/groundstation/pulls/13 jest obecnie `mergeable=true`, ma head `baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50` i zawiera już `main@41552b4797e9d5761feefe0aaeb1a3c2411272a0` przez zwalidowany normalny merge.
Rebase próbuje ponownie odtworzyć starszy commit `3bf2230` sprzed refaktoru warstw display z #8, dlatego konfliktuje w `cmd/groundstation-display/main.go`; ten konflikt został już semantycznie rozwiązany w merge commicie `baf36fd8`.
Jeżeli repo wymaga historii rebase-only, potrzebne jest jawne potwierdzenie przepisania i force-pusha dedykowanej gałęzi PR. Wtedy zlinearyzuję zmianę na aktualnym `main` i ponownie wykonam walidację.
Force-push wykonany zgodnie z autoryzacją. PR #13 otrzymał liniową historię: pojedynczy commit 2ced44b47b7adc698f177eebf9bf001341dbfe2e bezpośrednio na main@41552b4797e9d5761feefe0aaeb1a3c2411272a0.
Push użył --force-with-lease przypiętego do poprzedniego SHA baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50. Drzewo po przepisaniu było bajtowo identyczne z wcześniej zreviewowanym rozwiązaniem, a diff względem bazy obejmował wyłącznie 4 pliki follow-upu.
Ponowna walidacja liniowego drzewa: focused/race tests, pełne go test ./..., vet, gofmt, oba buildy ARM64, git diff --check i skan sekretów — wszystko zaliczone.
PR został następnie scalony przez Piotra metodą rebase/fast-forward: main, head PR i merge SHA są równe 2ced44b47b7adc698f177eebf9bf001341dbfe2e. CI push dla tego dokładnego SHA zakończyło się sukcesem: run 187, kontekst Build Ground Station / build (push). Issue pozostaje otwarte na zebranie diagnostyki z fizycznego Orange Pi.
Force-push wykonany zgodnie z autoryzacją. PR https://git.piksar.eu/piotr/groundstation/pulls/13 otrzymał liniową historię: pojedynczy commit `2ced44b47b7adc698f177eebf9bf001341dbfe2e` bezpośrednio na `main@41552b4797e9d5761feefe0aaeb1a3c2411272a0`.
Push użył `--force-with-lease` przypiętego do poprzedniego SHA `baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50`. Drzewo po przepisaniu było bajtowo identyczne z wcześniej zreviewowanym rozwiązaniem, a diff względem bazy obejmował wyłącznie 4 pliki follow-upu.
Ponowna walidacja liniowego drzewa: focused/race tests, pełne `go test ./...`, vet, gofmt, oba buildy ARM64, `git diff --check` i skan sekretów — wszystko zaliczone.
PR został następnie scalony przez Piotra metodą rebase/fast-forward: `main`, head PR i merge SHA są równe `2ced44b47b7adc698f177eebf9bf001341dbfe2e`. CI push dla tego dokładnego SHA zakończyło się sukcesem: run 187, kontekst `Build Ground Station / build (push)`. Issue pozostaje otwarte na zebranie diagnostyki z fizycznego Orange Pi.
The new reconnect logging exposed the exact XGB API misuse:
map kiosk window: Cannot call 'Check' on a cookie that is expecting a *reply*. Use 'Reply' instead.
In internal/display/x11.go, X11Opener.Open maps a window and then calls:
xproto.GetInputFocus(conn).Check()
GetInputFocus returns a reply-bearing cookie, so Check() is invalid and makes every display open fail. The same misuse exists in the session liveness probe.
Use GetInputFocus(conn).Reply() (discard the reply, propagate its error) for these synchronization/liveness checks, or use a true void-cookie request when Check() is wanted. Add a unit/integration seam that makes Open succeed with a reply-bearing liveness request; current Orange Pi acceptance then becomes one successful kiosk window with no open_failed reconnect loop.
Piotr supplied the physical log; no hardware access is expected from Grzesiu.
## Root cause from Orange Pi log
The new reconnect logging exposed the exact XGB API misuse:
```text
map kiosk window: Cannot call 'Check' on a cookie that is expecting a *reply*. Use 'Reply' instead.
```
In `internal/display/x11.go`, `X11Opener.Open` maps a window and then calls:
```go
xproto.GetInputFocus(conn).Check()
```
`GetInputFocus` returns a reply-bearing cookie, so `Check()` is invalid and makes every display open fail. The same misuse exists in the session liveness probe.
Use `GetInputFocus(conn).Reply()` (discard the reply, propagate its error) for these synchronization/liveness checks, or use a true void-cookie request when `Check()` is wanted. Add a unit/integration seam that makes Open succeed with a reply-bearing liveness request; current Orange Pi acceptance then becomes one successful kiosk window with no `open_failed` reconnect loop.
Piotr supplied the physical log; no hardware access is expected from Grzesiu.
Head: ffae3560c423ab221d991885639612549b057b12, baza main@2ced44b47b7adc698f177eebf9bf001341dbfe2e.
Oba reply-bearing cookies GetInputFocus — synchronizacja po mapowaniu i probe liveness sesji — są teraz konsumowane przez Reply(), z propagacją błędu i zachowaniem cleanup/reconnect. Prawidłowy void-cookie shape.RectanglesChecked nadal używa Check(). Test regresyjny korzysta z rzeczywistego API cookie XGB i behawioralnie odróżnia poprawne Reply() od błędu sprzętowego wywoływanego przez Check().
Walidacja: focused tests, go test -race ./internal/display, pełne go test ./..., vet, gofmt, oba buildy ARM64, git diff --check i skan sekretów — zaliczone.
CI PR nie jest skonfigurowane: dla SHA są 0 statusów i 0 runów. Po merge kryterium sprzętowe to jedno stabilne okno kiosku bez powtarzającej się pętli open_failed.
Naprawa root cause gotowa: PR https://git.piksar.eu/piotr/groundstation/pulls/14
Head: `ffae3560c423ab221d991885639612549b057b12`, baza `main@2ced44b47b7adc698f177eebf9bf001341dbfe2e`.
Oba reply-bearing cookies `GetInputFocus` — synchronizacja po mapowaniu i probe liveness sesji — są teraz konsumowane przez `Reply()`, z propagacją błędu i zachowaniem cleanup/reconnect. Prawidłowy void-cookie `shape.RectanglesChecked` nadal używa `Check()`. Test regresyjny korzysta z rzeczywistego API cookie XGB i behawioralnie odróżnia poprawne `Reply()` od błędu sprzętowego wywoływanego przez `Check()`.
Walidacja: focused tests, `go test -race ./internal/display`, pełne `go test ./...`, vet, gofmt, oba buildy ARM64, `git diff --check` i skan sekretów — zaliczone.
CI PR nie jest skonfigurowane: dla SHA są 0 statusów i 0 runów. Po merge kryterium sprzętowe to jedno stabilne okno kiosku bez powtarzającej się pętli `open_failed`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
Show a minimal fullscreen fallback while WFB video is absent, then hide it when decoded video is present.
Required behavior
Constraints
Gotowe: PR #9
Head:
b169a64ad539f85f11cb49b36c1865733b87e018.Walidacja końcowego drzewa:
go test -race ./internal/display ./cmd/groundstation-displaygo test ./...go vet ./...gofmt -lgit diff --checki skan nowych linii pod kątem sekretówReview wykrył i naprawił fałszywe rozpoznawanie pomocniczych okien X11, śledzenie tylko jednego okna video oraz możliwość przecięcia pary zastępczej UTF-16.
CI dla PR: brak skonfigurowanego uruchomienia — jedyny workflow
.gitea/workflows/build-arm64.ymlreaguje wyłącznie na push domainlub ręczne uruchomienie. Dla SHA PR Gitea potwierdza 0 statusów i 0 runów; nie istnieje oczekujący job. Test na docelowej sesji Orange Pi/X11 pozostaje walidacją wdrożeniową.Hardware finding: kiosk window repeatedly recreates
Piotr reports that the updated Orange Pi supervisor repeatedly opens new kiosk windows every few seconds. The current journal only shows the root supervisor and
runusersession; it does not expose the underlying X11 session error.The current
display.Runintentionally catchesSession.WaitEventerrors, closes the session, and retries, but it discards the error. This makes an X11 reconnect loop silent and prevents hardware diagnosis.Please add structured error logging at the reconnect boundary, including target, error and retry delay, e.g. when
WaitEventbreaks a session and whenOpenfails. Preserve the existing resilience: temporary X11 failure must not restart the UART supervisor.Piotr will collect the resulting journal output on the physical Orange Pi after a reviewable build. Do not require hardware access from Grzesiu.
Follow-up sprzętowy gotowy: PR #13
Head:
baf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50, zsynchronizowany zmain@41552b4797e9d5761feefe0aaeb1a3c2411272a0.Dodano po jednym strukturalnym rekordzie dla nieudanego
Openi zerwanej sesjiWaitEvent, z polami target, layer, event, error i retry delay. Anulowanie pozostaje ciche, a błędy X11 nadal pozostają wewnątrz pętli reconnect i nie restartują supervisora UART/root. Integracja zachowuje nową wielowarstwową architekturę display zmain.Walidacja końcowego drzewa po merge z aktualnym
main:go test -race ./internal/display ./cmd/groundstation-displaygo test ./...go vet ./...,gofmt -lgit diff --checki skan nowych linii pod kątem sekretówCI dla PR nie jest skonfigurowane: workflow nadal uruchamia się wyłącznie po push do
mainlub ręcznie; Gitea zwraca 0 statusów i 0 runów dla SHA PR. Po reviewowalnym buildzie Piotr może zebrać nowe rekordy z journala na Orange Pi.Rebasing (1/1)
error: could not apply 3bf2230... feat: log structured reconnect diagnostics for kiosk display (#2)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Could not apply 3bf2230... # feat: log structured reconnect diagnostics for kiosk display (#2)
Auto-merging cmd/groundstation-display/main.go
CONFLICT (content): Merge conflict in cmd/groundstation-display/main.go
Auto-merging cmd/groundstation-display/main_test.go
Auto-merging internal/display/display.go
Rekomendacja: przerwać rebase i scalić PR #13 metodą merge commit. Zdalna gałąź nie jest w stanie konfliktu: PR #13 jest obecnie
mergeable=true, ma headbaf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50i zawiera jużmain@41552b4797e9d5761feefe0aaeb1a3c2411272a0przez zwalidowany normalny merge.Rebase próbuje ponownie odtworzyć starszy commit
3bf2230sprzed refaktoru warstw display z #8, dlatego konfliktuje wcmd/groundstation-display/main.go; ten konflikt został już semantycznie rozwiązany w merge commiciebaf36fd8.Jeżeli repo wymaga historii rebase-only, potrzebne jest jawne potwierdzenie przepisania i force-pusha dedykowanej gałęzi PR. Wtedy zlinearyzuję zmianę na aktualnym
maini ponownie wykonam walidację.zrób force pusha
Force-push wykonany zgodnie z autoryzacją. PR #13 otrzymał liniową historię: pojedynczy commit
2ced44b47b7adc698f177eebf9bf001341dbfe2ebezpośrednio namain@41552b4797e9d5761feefe0aaeb1a3c2411272a0.Push użył
--force-with-leaseprzypiętego do poprzedniego SHAbaf36fd8b61d8f1a1c75dc6341ee0ab35d7c8d50. Drzewo po przepisaniu było bajtowo identyczne z wcześniej zreviewowanym rozwiązaniem, a diff względem bazy obejmował wyłącznie 4 pliki follow-upu.Ponowna walidacja liniowego drzewa: focused/race tests, pełne
go test ./..., vet, gofmt, oba buildy ARM64,git diff --checki skan sekretów — wszystko zaliczone.PR został następnie scalony przez Piotra metodą rebase/fast-forward:
main, head PR i merge SHA są równe2ced44b47b7adc698f177eebf9bf001341dbfe2e. CI push dla tego dokładnego SHA zakończyło się sukcesem: run 187, kontekstBuild Ground Station / build (push). Issue pozostaje otwarte na zebranie diagnostyki z fizycznego Orange Pi.Root cause from Orange Pi log
The new reconnect logging exposed the exact XGB API misuse:
In
internal/display/x11.go,X11Opener.Openmaps a window and then calls:GetInputFocusreturns a reply-bearing cookie, soCheck()is invalid and makes every display open fail. The same misuse exists in the session liveness probe.Use
GetInputFocus(conn).Reply()(discard the reply, propagate its error) for these synchronization/liveness checks, or use a true void-cookie request whenCheck()is wanted. Add a unit/integration seam that makes Open succeed with a reply-bearing liveness request; current Orange Pi acceptance then becomes one successful kiosk window with noopen_failedreconnect loop.Piotr supplied the physical log; no hardware access is expected from Grzesiu.
Naprawa root cause gotowa: PR #14
Head:
ffae3560c423ab221d991885639612549b057b12, bazamain@2ced44b47b7adc698f177eebf9bf001341dbfe2e.Oba reply-bearing cookies
GetInputFocus— synchronizacja po mapowaniu i probe liveness sesji — są teraz konsumowane przezReply(), z propagacją błędu i zachowaniem cleanup/reconnect. Prawidłowy void-cookieshape.RectanglesCheckednadal używaCheck(). Test regresyjny korzysta z rzeczywistego API cookie XGB i behawioralnie odróżnia poprawneReply()od błędu sprzętowego wywoływanego przezCheck().Walidacja: focused tests,
go test -race ./internal/display, pełnego test ./..., vet, gofmt, oba buildy ARM64,git diff --checki skan sekretów — zaliczone.CI PR nie jest skonfigurowane: dla SHA są 0 statusów i 0 runów. Po merge kryterium sprzętowe to jedno stabilne okno kiosku bez powtarzającej się pętli
open_failed.