first commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
@@ -0,0 +1,498 @@
|
||||
# Kiosk Dwuekranowy — Chromium + Prezentacja PowerPoint — Debian 13
|
||||
|
||||
Kiosk na dwa monitory. Lewy ekran wyświetla `http://diluals31/terminal/ift/5/DE/index` w Chromium; prawy ekran wyświetla w pętli prezentację PowerPoint z zamontowanego udziału SMB. Używa **X11** (xinit + openbox) i **LibreOffice Impress** w trybie pokazu (`--show`) — bez konwersji, z zachowanymi animacjami i przejściami.
|
||||
|
||||
---
|
||||
|
||||
## Architektura
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ kiosk.service │
|
||||
│ (xinit + openbox — tty7) │
|
||||
│ │
|
||||
│ Wirtualny desktop 3840×1080 (xrandr --right-of) │
|
||||
│ ┌──────────────────────────┐ ┌──────────────────────────────┐ │
|
||||
│ │ Chromium (fullscreen) │ │ LibreOffice Impress --show │ │
|
||||
│ │ DP-1 (0,0–1920×1080) │ │ HDMI-1 (1920,0–3840×1080) │ │
|
||||
│ │ http://diluals31/... │ │ terminal_live.pptx │ │
|
||||
│ └──────────────────────────┘ └──────────────────────────────┘ │
|
||||
│ ▲ above (wmctrl) ▲ │
|
||||
│ kiosk-manager.sh presentation-manager.sh │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
▲
|
||||
/mnt/presentation (CIFS/SMB)
|
||||
montowany przez skrypt (fstab user)
|
||||
▲
|
||||
//192.168.40.201/DatyFirmowe/ALS
|
||||
```
|
||||
|
||||
**Przepływ — lewy ekran (kiosk-manager.sh):**
|
||||
1. Konfiguruje X11: xrandr dual-screen, wyłącza DPMS, uruchamia openbox
|
||||
2. Zapisuje `registrymodifications.xcu` — wyłącza presenter console LO
|
||||
3. Uruchamia watchdog sesji (co 0.4 s chowa okna LO z lewego ekranu)
|
||||
4. Uruchamia `presentation-manager.sh` w tle
|
||||
5. Otwiera `waiting.html` fullscreen + always-on-top
|
||||
6. Czeka na: sieć (`ping diluals31`) **oraz** sygnał od `presentation-manager.sh` (plik `/tmp/kiosk-smb-ready`)
|
||||
7. Po otrzymaniu obu sygnałów: `sleep 10` — daje LO czas na otwarcie i pozycjonowanie okna na prawym ekranie
|
||||
8. Przełącza Chromium na docelowy URL
|
||||
|
||||
> `sleep 10` jest kluczowe: zapewnia, że LibreOffice zdąży otworzyć i ustawić okno pokazu zanim Chromium wejdzie w tryb fullscreen+above na lewym ekranie. Bez tego opóźnienia konsola prezentacji była widoczna po reboot.
|
||||
|
||||
**Przepływ — prawy ekran (presentation-manager.sh):**
|
||||
1. Montuje udział SMB (`mount /mnt/presentation`) z retry co 5 s
|
||||
2. Synchronizuje czcionki z `$SMB_MOUNT/fonts/` do `~/.local/share/fonts/smb/`
|
||||
3. Tworzy plik `/tmp/kiosk-smb-ready` — sygnał dla `kiosk-manager.sh`
|
||||
4. Czeka na plik `terminal_live.pptx`
|
||||
5. Uruchamia persistentny watchdog konsoli (co 0.3 s)
|
||||
6. Uruchamia `soffice --show terminal_live.pptx`
|
||||
7. Przesuwa okno pokazu na prawy ekran i stosuje fullscreen
|
||||
8. Co 5 s: sprawdza mtime pliku i restartuje po zmianie
|
||||
|
||||
---
|
||||
|
||||
## Wymagania
|
||||
|
||||
- Debian 13 netinst — instalacja minimalna bez środowiska graficznego
|
||||
- Dwa monitory: `DP-1` (lewy, primary) i `HDMI-1` (prawy)
|
||||
- Dostęp do udziału SMB/CIFS z plikiem prezentacji
|
||||
|
||||
---
|
||||
|
||||
## Instalacja krok po kroku
|
||||
|
||||
### 1. Utwórz użytkownika kiosk
|
||||
|
||||
```bash
|
||||
useradd -m -s /usr/sbin/nologin kiosk
|
||||
usermod -aG tty,input,video,render,dialout kiosk
|
||||
```
|
||||
|
||||
### 2. Zainstaluj pakiety
|
||||
|
||||
```bash
|
||||
apt update && apt install -y \
|
||||
xorg xinit openbox \
|
||||
chromium \
|
||||
libreoffice-impress \
|
||||
cifs-utils \
|
||||
xdotool wmctrl \
|
||||
x11-xserver-utils \
|
||||
iputils-ping \
|
||||
ethtool \
|
||||
wakeonlan
|
||||
```
|
||||
|
||||
> Nie są już potrzebne:
|
||||
|
||||
### 2a. Zainstaluj czcionki
|
||||
|
||||
LibreOffice podstawia czcionkę zastępczą gdy oryginalna nie jest zainstalowana w systemie — może to zmienić układ tekstu na slajdach.
|
||||
|
||||
#### Automatyczna instalacja przez udział SMB (zalecane)
|
||||
|
||||
`presentation-manager.sh` automatycznie synchronizuje czcionki z folderu `fonts/` na udziale SMB do `/home/kiosk/.local/share/fonts/smb/`. Wystarczy wrzucić pliki `.ttf`/`.otf` na udział — zostaną zainstalowane przy najbliższym restarcie kiosku.
|
||||
|
||||
**Na maszynie Windows** — skopiuj pliki czcionek do `\\192.168.40.201\DatyFirmowe\ALS\fonts\`:
|
||||
|
||||
```powershell
|
||||
# Calibri (C:\Windows\Fonts\ lub %LOCALAPPDATA%\Microsoft\Windows\Fonts\)
|
||||
Copy-Item C:\Windows\Fonts\calibri*.ttf \\192.168.40.201\DatyFirmowe\ALS\fonts\
|
||||
|
||||
# Aptos — zazwyczaj w cache czcionek chmurowych Microsoft 365:
|
||||
$src = "$env:LOCALAPPDATA\Microsoft\FontCache\4\CloudFonts\Aptos"
|
||||
Copy-Item "$src\*" \\192.168.40.201\DatyFirmowe\ALS\fonts\
|
||||
```
|
||||
|
||||
> Nazwy plików Aptos w cache mogą być numeryczne — to normalne, fontconfig czyta metadane wewnętrzne, nie nazwę pliku.
|
||||
|
||||
**Restart kiosku** — czcionki zostaną zainstalowane automatycznie:
|
||||
|
||||
```bash
|
||||
systemctl restart kiosk.service
|
||||
# Sprawdź w logach:
|
||||
journalctl -u kiosk.service -b | grep "czcionka\|Cache czcionek"
|
||||
```
|
||||
|
||||
#### Carlito — open-source'owy zamiennik Calibri (opcjonalnie)
|
||||
|
||||
Jeśli nie masz dostępu do oryginalnych plików Calibri, `Carlito` ma identyczne metryki (ten sam układ tekstu i łamania linii):
|
||||
|
||||
```bash
|
||||
apt install fonts-crosextra-carlito fonts-crosextra-caladea
|
||||
```
|
||||
|
||||
`fonts-crosextra-caladea` to odpowiednik Cambrii. Nie wymaga wrzucania plików na SMB — instalowany systemowo.
|
||||
|
||||
#### Inne czcionki Microsoft (Arial, Times New Roman, Verdana)
|
||||
|
||||
```bash
|
||||
apt install ttf-mscorefonts-installer
|
||||
```
|
||||
|
||||
> Nie są już potrzebne: `sway`, `swayidle`, `wlopm`, `wlr-randr`, `seatd`, `mpv`, `poppler-utils`.
|
||||
|
||||
### 3. Skonfiguruj montowanie udziału SMB
|
||||
|
||||
#### 3a. Utwórz plik poświadczeń
|
||||
|
||||
```bash
|
||||
mkdir -p /etc/samba
|
||||
cat > /etc/samba/kiosk-credentials << 'EOF'
|
||||
username=NAZWA_UZYTKOWNIKA
|
||||
password=HASLO
|
||||
domain=WORKGROUP
|
||||
EOF
|
||||
chmod 600 /etc/samba/kiosk-credentials
|
||||
chown root:root /etc/samba/kiosk-credentials
|
||||
```
|
||||
|
||||
#### 3b. Utwórz punkt montowania
|
||||
|
||||
```bash
|
||||
mkdir -p /mnt/presentation
|
||||
```
|
||||
|
||||
#### 3c. Dodaj wpis w /etc/fstab (montowanie przez użytkownika kiosk)
|
||||
|
||||
```bash
|
||||
echo '//192.168.40.201/DatyFirmowe/ALS /mnt/presentation cifs credentials=/etc/samba/kiosk-credentials,uid=kiosk,gid=kiosk,vers=3.0,user,noauto,_netdev 0 0' >> /etc/fstab
|
||||
```
|
||||
|
||||
Opcja `user` pozwala użytkownikowi `kiosk` wykonać `mount /mnt/presentation` bez uprawnień roota. Opcja `noauto` wyłącza automatyczne montowanie przy starcie — skrypt sam zarządza montem z retry.
|
||||
|
||||
> **Uwaga:** Systemd unit `mnt-presentation.mount` jest **wyłączony** — skrypt `presentation-manager.sh` przejął odpowiedzialność za montowanie.
|
||||
|
||||
```bash
|
||||
systemctl disable mnt-presentation.mount
|
||||
systemctl stop mnt-presentation.mount
|
||||
```
|
||||
|
||||
### 4. Wykryj nazwy wyjść wideo
|
||||
|
||||
```bash
|
||||
for p in /sys/class/drm/card*-*; do
|
||||
echo "$(basename $p | sed 's/card[0-9]*-//'): $(cat $p/status)"
|
||||
done
|
||||
```
|
||||
|
||||
Przykładowe wyjście:
|
||||
```
|
||||
DP-1: connected
|
||||
HDMI-1: connected
|
||||
```
|
||||
|
||||
Ustaw właściwe nazwy w `kiosk-manager.sh`:
|
||||
```bash
|
||||
OUTPUT_LEFT="DP-1" # lewy ekran — primary
|
||||
OUTPUT_RIGHT="HDMI-1" # prawy ekran
|
||||
```
|
||||
|
||||
### 5. Skopiuj pliki konfiguracyjne
|
||||
|
||||
```bash
|
||||
cp kiosk-manager.sh /home/kiosk/kiosk-manager.sh
|
||||
cp presentation-manager.sh /home/kiosk/presentation-manager.sh
|
||||
cp waiting.html /home/kiosk/waiting.html
|
||||
chmod +x /home/kiosk/kiosk-manager.sh /home/kiosk/presentation-manager.sh
|
||||
chown -R kiosk:kiosk /home/kiosk/
|
||||
|
||||
cp kiosk.service /etc/systemd/system/kiosk.service
|
||||
```
|
||||
|
||||
### 6. Rozwiązanie problemu z domenami .local
|
||||
|
||||
Jeśli `diluals31` jest rozwiązywany przez DNS firmowy (nie mDNS):
|
||||
|
||||
- Otwórz `/etc/nsswitch.conf`
|
||||
- Zmień linię `hosts:` na: `hosts: files dns mdns4_minimal [NOTFOUND=return]`
|
||||
|
||||
### 7. Włącz i uruchom serwis
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable kiosk.service
|
||||
systemctl start kiosk.service
|
||||
```
|
||||
|
||||
### 8. Skonfiguruj GRUB — natychmiastowy start
|
||||
|
||||
```bash
|
||||
# /etc/default/grub
|
||||
GRUB_DEFAULT=0
|
||||
GRUB_TIMEOUT=0
|
||||
```
|
||||
|
||||
```bash
|
||||
/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Harmonogram — Automatyczne wyłączanie i Wake on LAN
|
||||
|
||||
Kiosk wyłącza się automatycznie w **sobotę o 7:00** i jest budzony przez Magic Packet (Wake on LAN) w **niedzielę o 21:00**.
|
||||
|
||||
### Na kiosku
|
||||
|
||||
#### 9a. Cron — automatyczne wyłączanie
|
||||
|
||||
```bash
|
||||
cp kiosk-schedule /etc/cron.d/kiosk-schedule
|
||||
chmod 644 /etc/cron.d/kiosk-schedule
|
||||
```
|
||||
|
||||
#### 9b. Wake on LAN — włączanie i utrwalanie
|
||||
|
||||
```bash
|
||||
cp wol-enable.service /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now wol-enable.service
|
||||
```
|
||||
|
||||
Sprawdź, czy WoL jest aktywne:
|
||||
|
||||
```bash
|
||||
ip link show | grep -A1 "state UP" | grep ether # MAC adres kiosku
|
||||
ethtool enp2s0 | grep -i wake # zamień enp2s0 na właściwy interfejs
|
||||
```
|
||||
|
||||
> **Wymagane ręcznie: BIOS kiosku** — wejdź w ustawienia firmware i włącz opcję **Wake on LAN** lub **Power on by PCI-E/PCI**. Bez tego ustawienia Magic Packet jest ignorowany przez sprzęt.
|
||||
|
||||
#### 9c. Pobierz MAC adres kiosku
|
||||
|
||||
```bash
|
||||
ip link show | grep -A1 "state UP" | grep ether | awk '{print $2}'
|
||||
```
|
||||
|
||||
Zanotuj ten adres — potrzebny do konfiguracji serwera (krok poniżej).
|
||||
|
||||
### Na serwerze (192.168.40.201)
|
||||
|
||||
Zainstaluj narzędzie do wysyłania Magic Packet:
|
||||
|
||||
```bash
|
||||
apt install wakeonlan
|
||||
```
|
||||
|
||||
Utwórz plik crona wysyłającego WoL w niedzielę o 21:00 (wstaw MAC kiosku):
|
||||
|
||||
```bash
|
||||
cat > /etc/cron.d/kiosk-wol << 'EOF'
|
||||
SHELL=/bin/sh
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
# Obuć kiosk WS-VK016 w niedzielę o 21:00
|
||||
0 21 * * 0 root wakeonlan XX:XX:XX:XX:XX:XX
|
||||
EOF
|
||||
chmod 644 /etc/cron.d/kiosk-wol
|
||||
```
|
||||
|
||||
Zastąp `XX:XX:XX:XX:XX:XX` adresem MAC pobranym w kroku 9c.
|
||||
|
||||
> WoL działa w obrębie jednej podsieci (broadcast). Kiosk i serwer są w sieci `192.168.40.x` — brak potrzeby konfiguracji routera.
|
||||
|
||||
---
|
||||
|
||||
### `kiosk.service` → `/etc/systemd/system/kiosk.service`
|
||||
|
||||
Jednostka systemd uruchamiająca sesję X11 jako użytkownik `kiosk`.
|
||||
|
||||
| Opcja | Wartość | Opis |
|
||||
|---|---|---|
|
||||
| `ExecStart` | `xinit kiosk-manager.sh -- :0 vt7` | Uruchamia X11 na tty7 |
|
||||
| `ExecStartPre` | `chvt 7` | Przełącza konsolę na tty7 |
|
||||
| `PAMName` | `login` | Wymagane do bezrootowego X11 (xinit jako user) |
|
||||
| `TTYPath` | `/dev/tty7` | Przypisuje serwis do tty7 |
|
||||
| `SLIDE_DURATION` | `10` | Czas slajdu (s) — aktualnie nieużywany, LO używa timingów z PPTX |
|
||||
| `Restart=always` | — | Automatyczny restart po awarii |
|
||||
|
||||
> Serwis startuje **bez** `network-online.target` — celowo, aby `waiting.html` było widoczne od razu po uruchomieniu systemu. Montowanie SMB obsługuje skrypt z retry.
|
||||
|
||||
---
|
||||
|
||||
### `kiosk-manager.sh` → `/home/kiosk/kiosk-manager.sh`
|
||||
|
||||
Uruchamiany przez xinit. Konfiguruje X11 i obsługuje lewy ekran.
|
||||
|
||||
**Co robi:**
|
||||
1. `xrandr` — tryb rozszerzony: `DP-1` primary (0,0), `HDMI-1` po prawej (1920,0)
|
||||
2. `xsetroot` + `xset` — czarne tło, wyłączony wygaszacz i DPMS
|
||||
3. `openbox --sm-disable` — lekki WM wymagany przez `wmctrl fullscreen`
|
||||
4. Zapisuje `registrymodifications.xcu` — wyłącza presenter console LO (`StartWithPresenterScreen=false`)
|
||||
5. Uruchamia watchdog sesji w tle — co 0.4 s chowa okna soffice z lewego ekranu (x < 1920)
|
||||
6. Uruchamia `presentation-manager.sh` w tle
|
||||
7. Chromium otwiera `waiting.html` z `fullscreen` + `above`
|
||||
8. Czeka na sieć (`ping diluals31`) **i** na plik `/tmp/kiosk-smb-ready`
|
||||
9. `sleep 10` — LO ma czas na pełny start i pozycjonowanie okna przed Chromium
|
||||
10. Kill waiting Chromium → exec Chromium z docelowym URL
|
||||
|
||||
**Flagi Chromium (`CHROMIUM_OPTS`):**
|
||||
|
||||
| Flaga | Opis |
|
||||
|---|---|
|
||||
| `--app=URL` | Tryb aplikacji — brak paska adresu, brak kart |
|
||||
| `--window-position=0,0 --window-size=1920,1080` | Pozycja na lewym ekranie (X11: bez `--kiosk`, który rozciąga na cały wirtualny desktop) |
|
||||
| `--no-first-run` | Pomija ekran powitalny |
|
||||
| `--noerrdialogs` | Ukrywa okna dialogowe błędów |
|
||||
| `--disable-gpu-suspend` | Zapobiega zawieszaniu GPU przy wygaszaniu |
|
||||
| `--force-device-scale-factor=1` | Skalowanie 1:1 |
|
||||
| `--disable-features=Translate,MediaRouter` | Wyłącza tłumaczenie i Chromecast |
|
||||
| `--disable-sync` | Wyłącza synchronizację Google |
|
||||
| `--disable-extensions` | Wyłącza rozszerzenia |
|
||||
| `--password-store=basic` | Nie używa systemowego portfela haseł |
|
||||
| `--disable-pinch` | Wyłącza pinch-to-zoom |
|
||||
|
||||
> **Uwaga:** `--kiosk` na X11 rozciąga okno na cały wirtualny desktop 3840×1080 (oba ekrany). Używamy `--app` + `--window-position/size` + `wmctrl fullscreen`.
|
||||
|
||||
**Zmiana hosta / URL kiosku:**
|
||||
```bash
|
||||
# kiosk-manager.sh
|
||||
KIOSK_HOST="diluals31"
|
||||
KIOSK_URL="http://diluals31/terminal/ift/5/DE/index"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `presentation-manager.sh` → `/home/kiosk/presentation-manager.sh`
|
||||
|
||||
Obsługuje prawy ekran — montowanie SMB i wyświetlanie prezentacji.
|
||||
|
||||
**Montowanie SMB:**
|
||||
```bash
|
||||
until mountpoint -q "$SMB_MOUNT"; do
|
||||
mount "$SMB_MOUNT" # korzysta z wpisu fstab z opcją 'user'
|
||||
sleep 5 # retry co 5 s
|
||||
done
|
||||
```
|
||||
Przy zakończeniu skryptu (trap EXIT/INT/TERM): `umount /mnt/presentation`.
|
||||
|
||||
**Ustawianie okien LibreOffice (`start_lo`):**
|
||||
|
||||
Iteruje wszystkie widoczne okna `soffice` wg pozycji X:
|
||||
- `x ≥ 1920` → okno pokazu slajdów → `wmctrl fullscreen`
|
||||
- `x < 1920` → konsola prezentacji → przesunięcie na `x=3840` (poza desktop) + `wmctrl below`
|
||||
- Fallback po 5 s: jeśli nadal brak okna na prawym ekranie → przeniesienie pierwszego znalezionego
|
||||
|
||||
Po ustawieniu LO: Chromium podniesiony jako `above` (always-on-top na lewym ekranie).
|
||||
|
||||
**Watchdog (co 5 s w głównej pętli):**
|
||||
- Sprawdza wszystkie widoczne okna `soffice` — jeśli któreś wróciło na `x < 1920`, wysyła je z powrotem na `x=3840`
|
||||
- Sprawdza `mtime` pliku PPTX — po zmianie restartuje pokaz
|
||||
- Sprawdza czy `soffice` żyje — jeśli zakończył (koniec pokazu), restartuje
|
||||
|
||||
**Konfiguracja:**
|
||||
```bash
|
||||
SMB_MOUNT="/mnt/presentation"
|
||||
SMB_SOURCE="//192.168.40.201/DatyFirmowe/ALS"
|
||||
PRESENTATION_FILE="$SMB_MOUNT/terminal_live.pptx"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `kiosk.service` (wyłączone) `mnt-presentation.mount`
|
||||
|
||||
Systemd unit do montowania SMB jest **wyłączony**. Skrypt `presentation-manager.sh` przejął montowanie przez `mount /mnt/presentation` (wpis fstab z opcją `user,noauto`).
|
||||
|
||||
---
|
||||
|
||||
### `sway-config`
|
||||
|
||||
Nieużywany — zachowany jako archiwum poprzedniej architektury (Wayland/sway).
|
||||
|
||||
---
|
||||
|
||||
### `kiosk-schedule` → `/etc/cron.d/kiosk-schedule`
|
||||
|
||||
Plik crona systemu wyłączający kiosk w sobotę o 7:00 (`shutdown -h now` jako root).
|
||||
|
||||
---
|
||||
|
||||
### `wol-enable.service` → `/etc/systemd/system/wol-enable.service`
|
||||
|
||||
Jednostka systemd uruchamiana przy każdym starcie systemu. Wywołuje `ethtool -s IFACE wol g` na wszystkich interfejsach sieciowych — utrzymuje Wake on LAN włączone po rebootach (niektóre sterowniki resetują ustawienie WoL przy wyłączaniu).
|
||||
|
||||
---
|
||||
|
||||
### `waiting.html` → `/home/kiosk/waiting.html`
|
||||
|
||||
Lokalna strona HTML wyświetlana przez Chromium podczas oczekiwania na sieć. Ciemne tło, animowany spinner. Widoczna od startu systemu do momentu, gdy `diluals31` odpowie na ping.
|
||||
|
||||
---
|
||||
|
||||
## Zarządzanie i diagnostyka
|
||||
|
||||
### Logi
|
||||
|
||||
```bash
|
||||
# Logi kiosku na żywo
|
||||
journalctl -u kiosk.service -f
|
||||
|
||||
# Ostatnie 100 linii
|
||||
journalctl -u kiosk.service -b -n 100
|
||||
|
||||
# Tylko logi prezentacji
|
||||
journalctl -u kiosk.service -b | grep presentation-manager
|
||||
|
||||
# Logi montowania SMB
|
||||
journalctl -u kiosk.service -b | grep "mount:"
|
||||
```
|
||||
|
||||
### Restart / zatrzymanie
|
||||
|
||||
```bash
|
||||
systemctl restart kiosk.service
|
||||
systemctl stop kiosk.service
|
||||
```
|
||||
|
||||
### Ręczne montowanie / odmontowanie SMB (jako root)
|
||||
|
||||
```bash
|
||||
mount /mnt/presentation
|
||||
umount /mnt/presentation
|
||||
mountpoint /mnt/presentation && echo "zamontowany"
|
||||
```
|
||||
|
||||
### Wykrycie nazw wyjść wideo (bez uruchomionego kiosku)
|
||||
|
||||
```bash
|
||||
for p in /sys/class/drm/card*-*; do
|
||||
echo "$(basename $p | sed 's/card[0-9]*-//'): $(cat $p/status)"
|
||||
done
|
||||
```
|
||||
|
||||
### Wymuszenie restartu pokazu (zmiana pliku)
|
||||
|
||||
```bash
|
||||
touch /mnt/presentation/terminal_live.pptx
|
||||
# skrypt wykryje zmianę mtime w ciągu 5 s i zrestartuje LO
|
||||
```
|
||||
|
||||
### Czyszczenie cache Chromium
|
||||
|
||||
```bash
|
||||
systemctl stop kiosk.service
|
||||
rm -rf /home/kiosk/.cache/chromium
|
||||
systemctl start kiosk.service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rozwiązywanie problemów
|
||||
|
||||
| Objaw | Przyczyna | Rozwiązanie |
|
||||
|---|---|---|
|
||||
| `waiting.html` nie pojawia się | Sieć dostępna natychmiast, ping loop kończy się w <2 s | Normalne zachowanie — `sleep 2` zapewnia min. 2 s widoczności |
|
||||
| Prezentacja się nie wyświetla | SMB nie zamontowany | `journalctl -u kiosk.service -b \| grep mount` — sprawdź błędy |
|
||||
| `mount: Permission denied` | Opcja `user` brak w fstab lub kiosk nie jest właścicielem | Sprawdź wpis fstab: `grep presentation /etc/fstab` |
|
||||
| `mount: not found in /etc/fstab` | Brak wpisu fstab | Dodaj wpis zgodnie z sekcją 3c |
|
||||
| Konsola LibreOffice widoczna na lewym ekranie po reboot | LibreOffice startuje przed Chromium (kiosk URL) i konsola zdąży się pokazać | Zwiększ `sleep 10` w `kiosk-manager.sh` (linia po pętli `kiosk-smb-ready`) |
|
||||
| Chromium rozciągnięty na oba ekrany | Użyto `--kiosk` zamiast `--app` | Sprawdź `kiosk-manager.sh` — nie używamy `--kiosk` |
|
||||
| Lewy ekran czarny, tylko prawy działa | Chromium nie znalazł okna w 30 s | `journalctl \| grep "kiosk-manager"` — sprawdź błędy Chromium |
|
||||
| `openbox: command not found` | Brak pakietu | `apt install openbox` |
|
||||
| `wmctrl: command not found` | Brak pakietu | `apt install wmctrl` |
|
||||
| `xdotool: command not found` | Brak pakietu | `apt install xdotool` |
|
||||
| Animacje nie działają | LO konwertuje do PNG/PDF (stare podejście) | Aktualna wersja używa `soffice --show` bezpośrednio — animacje powinny działać |
|
||||
| Tekst źle wyświetlany (zła czcionka, zły układ) | Brak czcionki | Skopiuj pliki `.ttf`/`.otf` do `\\serwer\DatyFirmowe\ALS\fonts\` i zrestartuj kiosk — skrypt zainstaluje je automatycznie |
|
||||
| Udział SMB z protokołem SMB 1.0 | `vers=3.0` nieobsługiwany | Zmień na `vers=2.1` lub `vers=1.0` w `/etc/fstab` |
|
||||
| Czarny ekran po restarcie | Chromium trzyma zablokowany profil | `rm -rf /home/kiosk/.cache/chromium` |
|
||||
| X11 nie startuje (`cannot open display`) | Brak pakietu xorg | `apt install xorg` |
|
||||
@@ -0,0 +1,175 @@
|
||||
#!/bin/bash
|
||||
# kiosk-manager.sh — konfiguracja X11 + lewy ekran: Chromium
|
||||
# Plik docelowy: /home/kiosk/kiosk-manager.sh
|
||||
|
||||
# Jawnie ustawiamy HOME — serwis może startować jako root (xinit bez User=kiosk),
|
||||
# a LibreOffice szuka profilu w $HOME/.config/libreoffice/ (nie w /home/kiosk/).
|
||||
# Wszystkie procesy potomne (soffice, chromium) dziedziczą tę wartość.
|
||||
export HOME=/home/kiosk
|
||||
|
||||
KIOSK_HOST="diluals31"
|
||||
KIOSK_URL="http://diluals31/terminal/ift/5/DE/index"
|
||||
WAITING_PAGE="file:///home/kiosk/waiting.html"
|
||||
|
||||
OUTPUT_LEFT="DP-1"
|
||||
OUTPUT_RIGHT="HDMI-1"
|
||||
RES_W=1920
|
||||
RES_H=1080
|
||||
|
||||
# ─── Niewidoczny kursor ──────────────────────────────────────────────────────
|
||||
# Tworzymy motyw XCursor (1×1 px, ARGB 0x00000000) i eksportujemy XCURSOR_THEME
|
||||
# zanim uruchomią się Chromium i LibreOffice — dziedziczą środowisko procesu.
|
||||
# Brak myszy w kiosku nie usuwa kursora X11; bez tego wskaźnik jest widoczny
|
||||
# w środku między ekranami (domyślna pozycja X11 = centrum wirtualnego desktopa).
|
||||
_BLANK_DIR="/home/kiosk/.icons/blank/cursors"
|
||||
mkdir -p "$_BLANK_DIR"
|
||||
# printf pisze binarnie bezpośrednio do pliku — nie przez zmienną (bash $() ucina null-byte'y)
|
||||
for _n in left_ptr default pointer crosshair text watch wait move size_all fleur; do
|
||||
printf '\x58\x63\x75\x72\x10\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x02\x00\xfd\xff\x01\x00\x00\x00\x1c\x00\x00\x00\x24\x00\x00\x00\x02\x00\xfd\xff\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00\x00\x00\x00\x00' > "$_BLANK_DIR/$_n"
|
||||
done
|
||||
printf '[Icon Theme]\nName=blank\n' > /home/kiosk/.icons/blank/index.theme
|
||||
export XCURSOR_THEME=blank
|
||||
export XCURSOR_SIZE=1
|
||||
|
||||
|
||||
|
||||
# Dual-screen rozszerzony: lewy ekran primary, prawy po prawej
|
||||
# --auto wykrywa tryb automatycznie (bezpieczniejsze niż --mode 1920x1080)
|
||||
xrandr --output "$OUTPUT_LEFT" --auto --primary --pos 0x0
|
||||
xrandr --output "$OUTPUT_RIGHT" --auto --right-of "$OUTPUT_LEFT"
|
||||
# Rozszerz wirtualny framebuffer 200 px poniżej ekranów — kursor trafi w ten obszar
|
||||
# i nie będzie widoczny na żadnym fizycznym monitorze (bez potrzeby dodatkowych pakietów)
|
||||
xrandr --fb "$((RES_W * 2))x$((RES_H + 200))"
|
||||
echo "[kiosk-manager] Konfiguracja xrandr:"
|
||||
xrandr | grep -E "connected|[0-9]+x[0-9]+\+"
|
||||
|
||||
# Czarne tło na obu ekranach
|
||||
xsetroot -solid black
|
||||
|
||||
# Wyłącz wygaszacz ekranu i DPMS (kiosk działa non-stop)
|
||||
xset s off
|
||||
xset -dpms
|
||||
xset s noblank
|
||||
|
||||
# Przesuń kursor poniżej fizycznych ekranów — w obszar framebuffera bez outputu
|
||||
# Kursor istnieje w X11, ale nie jest wyświetlany na żadnym monitorze
|
||||
xdotool mousemove "$RES_W" "$((RES_H + 100))"
|
||||
|
||||
# Uruchom lekki WM — wymagany do per-screen fullscreen przez wmctrl
|
||||
openbox --sm-disable &
|
||||
sleep 0.5
|
||||
|
||||
# ─── Start aplikacji ─────────────────────────────────────────────────────────
|
||||
# Konfiguracja LO (wyłączenie konsoli prezentera) jest zarządzana przez
|
||||
# presentation-manager.sh → start_lo() via -env:UserInstallation=/tmp/lo-kiosk-profile
|
||||
|
||||
# Uruchom menedżera prezentacji w tle (prawy ekran)
|
||||
/home/kiosk/presentation-manager.sh &
|
||||
|
||||
# Watchdog sesji: ukrywa okna konsoli LibreOffice przez cały czas trwania sesji X.
|
||||
# Uruchomiony tu — nie czeka na SMB, działa od startu X niezależnie od timing'u LO.
|
||||
(
|
||||
while sleep 0.4; do
|
||||
for _wid in $(xdotool search --class soffice --onlyvisible 2>/dev/null); do
|
||||
_wx=$(xdotool getwindowgeometry "$_wid" 2>/dev/null \
|
||||
| awk '/Position:/{split($2,a,","); print a[1]+0}')
|
||||
if [ "${_wx:-0}" -lt 1920 ]; then
|
||||
wmctrl -i -r "$_wid" -b remove,above 2>/dev/null
|
||||
wmctrl -i -r "$_wid" -b add,below 2>/dev/null
|
||||
xdotool windowmove --sync "$_wid" 4000 0 2>/dev/null
|
||||
echo "[kiosk-manager/watchdog] Konsola LO ukryta (WID=$_wid, x=${_wx:-?})"
|
||||
fi
|
||||
done
|
||||
done
|
||||
) &
|
||||
|
||||
CHROMIUM_OPTS=(
|
||||
--no-first-run
|
||||
--noerrdialogs
|
||||
--disable-infobars
|
||||
--disable-gpu-suspend
|
||||
--force-device-scale-factor=1
|
||||
--user-data-dir=/home/kiosk/.cache/chromium
|
||||
--disable-features=AutofillServerCommunication,AutofillKeyValueService,Translate,MediaRouter
|
||||
--disable-save-password-bubble
|
||||
--disable-sync
|
||||
--disable-extensions
|
||||
--disable-background-networking
|
||||
--disable-notifications
|
||||
--disable-component-update
|
||||
--password-store=basic
|
||||
--disable-pinch
|
||||
--window-position=0,0
|
||||
--window-size=${RES_W},${RES_H}
|
||||
)
|
||||
|
||||
# Strona oczekiwania — lewy ekran
|
||||
# Bez --kiosk: na X11 --kiosk rozciąga okno na cały wirtualny desktop (oba ekrany)
|
||||
chromium --app="$WAITING_PAGE" "${CHROMIUM_OPTS[@]}" &
|
||||
CHROMIUM_PID=$!
|
||||
|
||||
# Czekaj na okno i zastosuj fullscreen (synchronicznie)
|
||||
for _i in $(seq 1 40); do
|
||||
sleep 0.5
|
||||
WID=$(xdotool search --pid "$CHROMIUM_PID" --onlyvisible 2>/dev/null | head -1)
|
||||
if [ -n "$WID" ]; then
|
||||
wmctrl -i -r "$WID" -b add,fullscreen
|
||||
wmctrl -i -r "$WID" -b add,above
|
||||
break
|
||||
fi
|
||||
done
|
||||
sleep 2 # Minimalny czas wyświetlania strony oczekiwania
|
||||
|
||||
# Czekaj na dostępność serwera kiosku
|
||||
while ! ping -c 1 -W 1 "$KIOSK_HOST" > /dev/null 2>&1; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Czekaj na zamontowanie SMB (sygnał od presentation-manager.sh).
|
||||
# waiting.html zostaje do czasu gdy oba ekrany są gotowe do startu.
|
||||
while [ ! -f /tmp/kiosk-smb-ready ]; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
sleep 5
|
||||
|
||||
# Zamknij ekran oczekiwania i uruchom właściwy kiosk
|
||||
kill "$CHROMIUM_PID"
|
||||
wait "$CHROMIUM_PID" 2>/dev/null
|
||||
rm -f /tmp/kiosk-chromium-restart
|
||||
|
||||
launch_chromium() {
|
||||
rm -f /tmp/kiosk-chromium-restart
|
||||
chromium --app="$KIOSK_URL" "${CHROMIUM_OPTS[@]}" &
|
||||
CHROMIUM_PID=$!
|
||||
echo "[kiosk-manager] Chromium uruchomiony (PID=$CHROMIUM_PID)"
|
||||
(
|
||||
for _i in $(seq 1 30); do
|
||||
sleep 1
|
||||
WID=$(xdotool search --pid "$CHROMIUM_PID" --onlyvisible 2>/dev/null | head -1)
|
||||
if [ -n "$WID" ]; then
|
||||
wmctrl -i -r "$WID" -b add,fullscreen
|
||||
wmctrl -i -r "$WID" -b add,above
|
||||
echo "[kiosk-manager] Chromium na lewym ekranie (próba $_i)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
) &
|
||||
}
|
||||
|
||||
launch_chromium
|
||||
|
||||
# Pętla: reaguje na sygnał restartu od presentation-manager.sh
|
||||
# (zmiana pliku prezentacji) lub na awarię Chromium
|
||||
while true; do
|
||||
sleep 1
|
||||
if [ -f /tmp/kiosk-chromium-restart ]; then
|
||||
echo "[kiosk-manager] Sygnał restart Chromium — restartuje"
|
||||
kill "$CHROMIUM_PID" 2>/dev/null
|
||||
wait "$CHROMIUM_PID" 2>/dev/null
|
||||
launch_chromium
|
||||
elif ! kill -0 "${CHROMIUM_PID:-0}" 2>/dev/null; then
|
||||
echo "[kiosk-manager] Chromium zakończył się — restartuje"
|
||||
launch_chromium
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,9 @@
|
||||
# /etc/cron.d/kiosk-schedule
|
||||
# Harmonogram kiosku WS-VK016
|
||||
# Instalacja: cp kiosk-schedule /etc/cron.d/kiosk-schedule
|
||||
# chmod 644 /etc/cron.d/kiosk-schedule
|
||||
SHELL=/bin/sh
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
# Wyłącz kiosk w sobotę o 7:00
|
||||
0 7 * * 6 root /sbin/shutdown -h now
|
||||
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=Kiosk Dwuekranowy — Instrukcje + Prezentacja
|
||||
After=systemd-user-sessions.service
|
||||
|
||||
[Service]
|
||||
User=kiosk
|
||||
Group=kiosk
|
||||
Type=simple
|
||||
PAMName=login
|
||||
|
||||
TTYPath=/dev/tty7
|
||||
StandardInput=tty
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
# Czas wyświetlania każdego slajdu prezentacji (sekundy)
|
||||
Environment=SLIDE_DURATION=10
|
||||
|
||||
ExecStartPre=/usr/bin/chvt 7
|
||||
ExecStart=/usr/bin/xinit /home/kiosk/kiosk-manager.sh -- :0 vt7 -nolisten tcp
|
||||
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=SMB Share z prezentacją kiosku
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Mount]
|
||||
# Zmień na adres IP i nazwę udziału swojego serwera SMB:
|
||||
What=//192.168.x.x/nazwa-udzialu
|
||||
Where=/mnt/presentation
|
||||
Type=cifs
|
||||
Options=credentials=/etc/samba/kiosk-credentials,uid=kiosk,gid=kiosk,iocharset=utf8,vers=3.0,_netdev
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,227 @@
|
||||
#!/bin/bash
|
||||
# presentation-manager.sh — prawy ekran: prezentacja PowerPoint z udziału SMB
|
||||
#
|
||||
# Działanie:
|
||||
# 1. Czeka na zamontowanie udziału SMB
|
||||
# 2. Sprawdza obecność pliku $SMB_MOUNT/terminal_live.pptx
|
||||
# 3. Wyświetla prezentację bezpośrednio przez LibreOffice Impress (--show)
|
||||
# → zachowane animacje, przejścia i efekty z oryginalnego pliku PPTX
|
||||
# 4. Po zakończeniu pokazu automatycznie restartuje (pętla)
|
||||
# 5. Co 5 sekund sprawdza, czy plik się zmienił — jeśli tak, restartuje pokaz
|
||||
|
||||
SMB_MOUNT="/mnt/presentation"
|
||||
SMB_SOURCE="//192.168.40.201/DatyFirmowe/ALS"
|
||||
SMB_OPTS="credentials=/etc/samba/kiosk-credentials,uid=kiosk,gid=kiosk,vers=3.0"
|
||||
PRESENTATION_FILE="$SMB_MOUNT/terminal_live.pptx"
|
||||
# Lokalna kopia PPTX — LibreOffice otwiera ten plik zamiast pliku z SMB.
|
||||
# Dzięki temu SMB nie jest blokowany i można nadpisać terminal_live.pptx
|
||||
# w dowolnej chwili z innego komputera (Windows/macOS/Linux).
|
||||
LOCAL_PRESENTATION="/tmp/kiosk-live.pptx"
|
||||
|
||||
CURRENT_MTIME=""
|
||||
LO_PID=""
|
||||
WATCHDOG_PID=""
|
||||
|
||||
# Usuń stary plik sygnałowy (restart serwisu)
|
||||
rm -f /tmp/kiosk-smb-ready
|
||||
|
||||
# Odmontuj udział przy zamknięciu skryptu
|
||||
trap 'stop_lo; kill "${WATCHDOG_PID:-0}" 2>/dev/null; umount "$SMB_MOUNT" 2>/dev/null' EXIT INT TERM
|
||||
|
||||
stop_lo() {
|
||||
if [ -n "${LO_PID:-}" ] && kill -0 "$LO_PID" 2>/dev/null; then
|
||||
kill "$LO_PID"
|
||||
wait "$LO_PID" 2>/dev/null
|
||||
LO_PID=""
|
||||
fi
|
||||
}
|
||||
|
||||
# Persistentny watchdog co 0.3s — przenosi konsolę LO poza ekran zanim stanie się widoczna.
|
||||
# Działa przez cały czas życia skryptu. Fullscreen i Chromium above obsługuje start_lo().
|
||||
console_watchdog() {
|
||||
while true; do
|
||||
sleep 0.3
|
||||
for _wid in $(xdotool search --class soffice --onlyvisible 2>/dev/null); do
|
||||
_wx=$(xdotool getwindowgeometry "$_wid" 2>/dev/null \
|
||||
| awk '/Position:/{split($2,a,","); print a[1]+0}')
|
||||
if [ "${_wx:-0}" -lt 1920 ]; then
|
||||
wmctrl -i -r "$_wid" -b remove,above 2>/dev/null
|
||||
wmctrl -i -r "$_wid" -b add,below 2>/dev/null
|
||||
xdotool windowmove --sync "$_wid" 4000 0 2>/dev/null
|
||||
echo "[watchdog] Konsola ukryta (WID=$_wid, x=${_wx:-?})"
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
start_lo() {
|
||||
stop_lo
|
||||
# Usuń plik blokady LO — pozostaje po kill i blokuje kolejne uruchomienie
|
||||
rm -f /tmp/.~lock.kiosk-live.pptx\#
|
||||
|
||||
# Wyłącz konsolę prezentera — izolowany profil w /tmp eliminuje problemy
|
||||
# z HOME=/root (usługa bez User=kiosk) i z cache LO z poprzednich sesji.
|
||||
# -env:UserInstallation wskazuje LO dokładnie który profil ma użyć.
|
||||
_LO_PROFILE_DIR="/tmp/lo-kiosk-profile"
|
||||
_LO_PROFILE="$_LO_PROFILE_DIR/user"
|
||||
rm -rf "$_LO_PROFILE_DIR" # wymuś świeży profil — bez żadnych zapisanych preferencji
|
||||
mkdir -p "$_LO_PROFILE"
|
||||
cat > "$_LO_PROFILE/registrymodifications.xcu" << 'XCUEOF'
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<oor:items xmlns:oor="http://openoffice.org/2001/registry"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<item oor:path="/org.openoffice.Office.Impress/Misc">
|
||||
<prop oor:name="StartWithPresenterScreen" oor:op="fuse">
|
||||
<value xsi:type="xs:boolean">false</value>
|
||||
</prop>
|
||||
</item>
|
||||
</oor:items>
|
||||
XCUEOF
|
||||
|
||||
echo "[presentation-manager] Kopiowanie pliku z SMB do /tmp..."
|
||||
cp "$PRESENTATION_FILE" "$LOCAL_PRESENTATION" || {
|
||||
echo "[presentation-manager] Błąd kopiowania pliku — retry za 5s"
|
||||
sleep 5
|
||||
return 1
|
||||
}
|
||||
echo "[presentation-manager] Uruchamianie pokazu: $LOCAL_PRESENTATION"
|
||||
# --show otwiera bezpośrednio pokaz (bez Start Center)
|
||||
# -env:UserInstallation wymusza użycie naszego profilu (bez konsoli prezentera)
|
||||
soffice \
|
||||
"-env:UserInstallation=file://$_LO_PROFILE_DIR" \
|
||||
--norestore \
|
||||
--nofirststartwizard \
|
||||
--show "$LOCAL_PRESENTATION" &
|
||||
LO_PID=$!
|
||||
echo "[presentation-manager] LibreOffice Impress uruchomiony (PID=$LO_PID)"
|
||||
|
||||
# Obsłuż wszystkie okna LO wg pozycji:
|
||||
# x >= 1920 (prawy ekran) → okno pokazu slajdów → fullscreen
|
||||
# x < 1920 (lewy ekran) → konsola prezentacji → zminimalizuj
|
||||
# Fallback po 5s: przenieś pierwsze znalezione okno na prawy ekran
|
||||
(
|
||||
for _i in $(seq 1 30); do
|
||||
sleep 1
|
||||
WIDS=$(xdotool search --pid "$LO_PID" --onlyvisible 2>/dev/null)
|
||||
[ -z "$WIDS" ] && WIDS=$(xdotool search --class soffice --onlyvisible 2>/dev/null)
|
||||
[ -z "$WIDS" ] && continue
|
||||
|
||||
PRES_WID=""
|
||||
for WID in $WIDS; do
|
||||
WIN_X=$(xdotool getwindowgeometry "$WID" 2>/dev/null \
|
||||
| awk '/Position:/{split($2,a,","); print a[1]+0}')
|
||||
if [ "${WIN_X:-0}" -ge 1920 ]; then
|
||||
PRES_WID=$WID
|
||||
fi
|
||||
# Konsola (x<1920) obsługiwana przez console_watchdog()
|
||||
done
|
||||
|
||||
if [ -n "$PRES_WID" ]; then
|
||||
wmctrl -i -r "$PRES_WID" -b add,fullscreen 2>/dev/null
|
||||
echo "[presentation-manager] Pokaz fullscreen na prawym ekranie (próba $_i)"
|
||||
break
|
||||
fi
|
||||
|
||||
# Fallback: po 5s nadal brak okna na prawym ekranie → przenieś pierwsze
|
||||
if [ "$_i" -ge 5 ]; then
|
||||
FIRST_WID=$(echo "$WIDS" | head -1)
|
||||
if [ -n "$FIRST_WID" ]; then
|
||||
wmctrl -i -r "$FIRST_WID" -b remove,fullscreen 2>/dev/null
|
||||
sleep 0.3
|
||||
xdotool windowmove --sync "$FIRST_WID" 1920 0
|
||||
xdotool windowsize --sync "$FIRST_WID" 1920 1080
|
||||
wmctrl -i -r "$FIRST_WID" -b add,fullscreen 2>/dev/null
|
||||
echo "[presentation-manager] Fallback: przeniesiono na prawy ekran (próba $_i)"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Podnieś Chromium na wierzch lewego ekranu (przykrywa konsolę jeśli się pojawiła)
|
||||
sleep 1
|
||||
CHROMIUM_WID=$(xdotool search --class chromium --onlyvisible 2>/dev/null | head -1)
|
||||
if [ -n "$CHROMIUM_WID" ]; then
|
||||
xdotool windowraise "$CHROMIUM_WID"
|
||||
wmctrl -i -r "$CHROMIUM_WID" -b add,above
|
||||
echo "[presentation-manager] Chromium always-on-top (above)"
|
||||
fi
|
||||
) &
|
||||
}
|
||||
|
||||
# ─── GŁÓWNA LOGIKA ───────────────────────────────────────────────────────────
|
||||
|
||||
echo "[presentation-manager] Montowanie udziału SMB: $SMB_SOURCE"
|
||||
until mountpoint -q "$SMB_MOUNT" 2>/dev/null; do
|
||||
mount "$SMB_MOUNT" 2>&1 \
|
||||
| sed 's/^/[presentation-manager] mount: /'
|
||||
mountpoint -q "$SMB_MOUNT" 2>/dev/null || sleep 5
|
||||
done
|
||||
echo "[presentation-manager] SMB zamontowany."
|
||||
|
||||
# Synchronizuj czcionki z udziału SMB do katalogu użytkownika kiosk.
|
||||
# Fontconfig i LibreOffice odczytują ~/.local/share/fonts/ bez uprawnień roota.
|
||||
# Wystarczy wrzucić nowe pliki .ttf/.otf do $SMB_MOUNT/fonts/ — zostaną
|
||||
# automatycznie zainstalowane przy następnym starcie kiosku.
|
||||
FONTS_SRC="$SMB_MOUNT/fonts"
|
||||
FONTS_DST="/home/kiosk/.local/share/fonts/smb"
|
||||
if [ -d "$FONTS_SRC" ]; then
|
||||
mkdir -p "$FONTS_DST"
|
||||
FONTS_NEW=0
|
||||
for _f in "$FONTS_SRC"/*.ttf "$FONTS_SRC"/*.otf "$FONTS_SRC"/*.TTF "$FONTS_SRC"/*.OTF; do
|
||||
[ -f "$_f" ] || continue
|
||||
_dest="$FONTS_DST/$(basename "$_f")"
|
||||
if [ ! -f "$_dest" ]; then
|
||||
cp "$_f" "$_dest" 2>/dev/null && FONTS_NEW=1
|
||||
echo "[presentation-manager] Nowa czcionka: $(basename "$_f")"
|
||||
fi
|
||||
done
|
||||
if [ "$FONTS_NEW" -eq 1 ]; then
|
||||
fc-cache "$FONTS_DST"
|
||||
echo "[presentation-manager] Cache czcionek zaktualizowany"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Sygnał dla kiosk-manager.sh: SMB zamontowany, można przełączyć Chromium
|
||||
touch /tmp/kiosk-smb-ready
|
||||
echo "[presentation-manager] SMB gotowy — sygnał wysłany"
|
||||
|
||||
until [ -f "$PRESENTATION_FILE" ]; do
|
||||
echo "[presentation-manager] Oczekiwanie na plik: $PRESENTATION_FILE" >&2
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Uruchom persistentny watchdog przed pierwszym startem LO
|
||||
console_watchdog &
|
||||
WATCHDOG_PID=$!
|
||||
echo "[presentation-manager] Watchdog uruchomiony (PID=$WATCHDOG_PID)"
|
||||
|
||||
CURRENT_MTIME=$(stat -c %Y "$PRESENTATION_FILE" 2>/dev/null || echo "0")
|
||||
start_lo
|
||||
|
||||
# Pętla: restartuje pokaz po zakończeniu lub gdy wykryje zmianę pliku
|
||||
while true; do
|
||||
sleep 5
|
||||
|
||||
NEW_MTIME=$(stat -c %Y "$PRESENTATION_FILE" 2>/dev/null || echo "0")
|
||||
|
||||
# Plik zmieniony — odśwież pokaz
|
||||
if [ "$NEW_MTIME" != "$CURRENT_MTIME" ]; then
|
||||
echo "[presentation-manager] Wykryto zmianę pliku — restart pokazu"
|
||||
CURRENT_MTIME="$NEW_MTIME"
|
||||
start_lo
|
||||
# Po 5 s wyślij sygnał do kiosk-manager.sh — restartuje Chromium po tym jak LO
|
||||
# zakończy ładowanie i ustawi okno pokazu na prawym ekranie
|
||||
( sleep 5
|
||||
touch /tmp/kiosk-chromium-restart
|
||||
echo "[presentation-manager] Sygnał restart Chromium wysłany"
|
||||
) &
|
||||
continue
|
||||
fi
|
||||
|
||||
# LibreOffice zakończył (koniec pokazu) — uruchom ponownie
|
||||
if ! kill -0 "${LO_PID:-0}" 2>/dev/null; then
|
||||
echo "[presentation-manager] Pokaz zakończony — restart"
|
||||
start_lo
|
||||
fi
|
||||
done
|
||||
@@ -0,0 +1,5 @@
|
||||
# Plik poświadczeń SMB dla kiosku
|
||||
|
||||
username=NAZWA_UZYTKOWNIKA
|
||||
password=HASLO
|
||||
domain=WORKGROUP
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# Konfiguracja sway dla kiosku dwuekranowego
|
||||
# Plik docelowy: /home/kiosk/.config/sway/config
|
||||
#
|
||||
# Nazwy wyjść wideo wykryj BEZ uruchomionego sway (działa zawsze jako root):
|
||||
# for p in /sys/class/drm/card*-*; do echo "$(basename $p | sed 's/card[0-9]*-//'): $(cat $p/status)"; done
|
||||
#
|
||||
# lub gdy sway/kiosk JUŻ działa:
|
||||
# WAYLAND_DISPLAY=wayland-0 XDG_RUNTIME_DIR=/run/kiosk wlr-randr
|
||||
#
|
||||
# Wpisz właściwe nazwy poniżej:
|
||||
|
||||
set $OUTPUT_LEFT DP-1
|
||||
set $OUTPUT_RIGHT HDMI-1
|
||||
|
||||
# --- Wyjścia wideo ---
|
||||
output * bg #000000 solid_color
|
||||
|
||||
# Opcjonalnie: rotacja per-wyjście (odkomentuj jeśli wymagana)
|
||||
# output $OUTPUT_LEFT transform 270
|
||||
# output $OUTPUT_RIGHT transform 270
|
||||
|
||||
# Przypisanie workspace do ekranów
|
||||
workspace 1 output $OUTPUT_LEFT
|
||||
workspace 2 output $OUTPUT_RIGHT
|
||||
|
||||
# --- Przypisanie aplikacji do workspaces ---
|
||||
# Chromium (prawy ekran — workspace 2)
|
||||
# --app=URL generuje app_id: "chrome-<hash>-Default" — używamy regex
|
||||
assign [app_id="~^chrome"] workspace 2
|
||||
for_window [app_id="~^chrome"] move to workspace 2, fullscreen enable
|
||||
|
||||
# Prezentacja LibreOffice Impress (lewy ekran — workspace 1)
|
||||
# LO zawsze otwiera się na workspace 1 — assign to potwierdza
|
||||
assign [app_id="soffice"] workspace 1
|
||||
assign [class="libreoffice-impress"] workspace 1
|
||||
for_window [app_id="soffice"] fullscreen enable
|
||||
for_window [class="libreoffice-impress"] fullscreen enable
|
||||
# Jeśli powyższe nie działają, sprawdź rzeczywistą klasę:
|
||||
# WAYLAND_DISPLAY=wayland-0 XDG_RUNTIME_DIR=/run/kiosk swaymsg -t get_tree | grep -E 'app_id|class'
|
||||
|
||||
# --- Wygląd ---
|
||||
default_border none
|
||||
default_floating_border none
|
||||
hide_edge_borders both
|
||||
|
||||
# Ukryj kursor — niewidoczny motyw XCursor (1×1 px, całkowicie przezroczysty)
|
||||
# Działa niezależnie od pozycji kursora i bez dodatkowych pakietów.
|
||||
# Plik binarny XCursor tworzony przez printf przy każdym starcie sway.
|
||||
# Jeśli motyw nie zdąży załadować się przed pierwszym rysowaniem → hide_cursor 1 jako fallback.
|
||||
seat * hide_cursor 1
|
||||
seat * xcursor_theme blank 1
|
||||
exec_always bash -c '
|
||||
D=/home/kiosk/.icons/blank/cursors
|
||||
mkdir -p "$D"
|
||||
# 68-bajtowy XCursor: 1×1 px, hotspot 0,0, ARGB 0x00000000
|
||||
for n in left_ptr default pointer crosshair text watch wait move size_all fleur; do
|
||||
printf "\x58\x63\x75\x72\x10\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x02\x00\xfd\xff\x01\x00\x00\x00\x1c\x00\x00\x00\x24\x00\x00\x00\x02\x00\xfd\xff\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x00\x00\x00\x00\x00\x00\x00" > "$D/$n"
|
||||
done
|
||||
printf "[Icon Theme]\nName=blank\n" > /home/kiosk/.icons/blank/index.theme'
|
||||
|
||||
# Wygaszanie ekranów przy uśpieniu (bez -w: ignoruje inhibitory Chromium)
|
||||
exec swayidle before-sleep "wlopm --off '*'"
|
||||
|
||||
# Uruchom skrypt kiosku
|
||||
exec /home/kiosk/kiosk-manager.sh
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Oczekiwanie na sieć</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #0a0a0a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 48px;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
border: 5px solid rgba(255, 255, 255, 0.08);
|
||||
border-top-color: rgba(255, 255, 255, 0.55);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.text {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
font-size: 2rem;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.04em;
|
||||
animation: pulse 2.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 0.6; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.dots {
|
||||
display: inline-block;
|
||||
width: 2em;
|
||||
text-align: left;
|
||||
animation: dots 1.5s steps(4, end) infinite;
|
||||
}
|
||||
|
||||
@keyframes dots {
|
||||
0% { content: ''; clip-path: none; }
|
||||
}
|
||||
|
||||
.dots::after {
|
||||
content: '';
|
||||
animation: dotcycle 1.5s steps(4, end) infinite;
|
||||
}
|
||||
|
||||
@keyframes dotcycle {
|
||||
0% { content: ''; }
|
||||
25% { content: '.'; }
|
||||
50% { content: '..'; }
|
||||
75% { content: '...'; }
|
||||
100% { content: ''; }
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 90%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="logo"><img src="logo.png" alt="Logo"></div>
|
||||
<div class="spinner"></div>
|
||||
<div class="text">Oczekiwanie na sieć<span class="dots"></span></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Enable Wake on LAN on all ethernet interfaces
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
# Włącza WoL (g = magic packet) na każdym interfejsie sieciowym
|
||||
ExecStart=/bin/bash -c '\
|
||||
for iface in $(ls /sys/class/net | grep -v lo); do \
|
||||
ethtool -s "$iface" wol g 2>/dev/null \
|
||||
&& echo "WoL enabled: $iface" \
|
||||
|| true; \
|
||||
done'
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user