# Meteo Dom — opis wdrożenia i specyfikacja

Wersja dokumentu: 1 (2026-10-11) · status: **projekt, aplikacja jeszcze nie powstaje**

Jeden ekran w stylu aplikacji **Meteo** (v1.8.0): prognoza dla Wrocławia i pomiary z domu
(Netatmo przez Home Assistant oraz Airly). Strona stoi na hostingu deltaeternal.eu, wymaga
logowania, a lokalny Home Assistant (HA) co 5 minut **wysyła** do niej odczyty. HA nie musi być
dostępny z internetu.

Urządzenie docelowe: **iPad 9. generacji w poziomie**, aplikacja z ekranu początkowego (PWA).
Dodatkowo komputer w przeglądarce i telefon w pionie.

---

## 1. Architektura

```
 ┌──────────── dom (LAN) ─────────────┐            ┌──────── hosting deltaeternal.eu ────────┐
 │ Netatmo ×2 (wewn. + zewn.)          │            │  meteo-dom.deltaeternal.eu               │
 │ Airly (integracja HA)               │            │                                          │
 │        │                            │  HTTPS     │  ingest.php  ← token Bearer              │
 │  Home Assistant ── rest_command ────┼──POST────▶ │     │                                    │
 │  (automatyzacja co 5 min)           │  co 5 min  │     ▼                                    │
 └─────────────────────────────────────┘            │  data/home.sqlite (odczyty + agregaty)   │
                                                    │     ▲                                    │
 ┌──── iPad / komputer / telefon ──────┐            │  api.php ── sesja (logowanie)            │
 │  PWA „Meteo Dom”                    │◀──HTTPS───▶│     ├─ src=home, home_hist  (SQLite)     │
 │  odświeża dom co 60 s,              │            │     └─ src=imgw, hybrid, ecmwf, …        │
 │  pogodę jak Meteo                   │            │        (kod z Meteo, cache plikowy)      │
 └─────────────────────────────────────┘            └──────────────────────────────────────────┘
```

- **Nowe prywatne repo** `LbArtJ/Meteo-Dom`, katalog `/Users/lbartj/Claude/meteo-dom`.
- **Część pogodowa skopiowana z Meteo 1.8.0**: `src/{core,imgw,ecmwf,antistorm}.php` i
  `assets/js/{app,charts,wx,sky,solar}.js` razem z CSS. Skrypt `scripts/sync-meteo.sh` dociąga
  zmiany z repo Meteo, a w README zapisujemy, z której wersji Meteo pochodzi kopia. Meteo zostaje
  publiczne i bez zmian.
- **Logowanie wzorem Stodoły 180**: `src/{auth,db,helpers,install}.php`, bcrypt, CSRF, blokada po
  nieudanych próbach, moduły JS wydawane tylko zalogowanym. Cała aplikacja jest za logowaniem,
  łącznie z prognozą.
- **Wymagania hostingu**: PHP 8.1+, `pdo_sqlite`, `curl`, HTTPS. Host ignoruje `.htaccess`, więc
  pliki z danymi chroni strażnik w `.php`, tak jak w innych aplikacjach.

## 2. Dane z domu

### 2.1 Czujniki (do potwierdzenia identyfikatorów encji w HA)

| Klucz w aplikacji | Miejsce | Wielkości | Źródło | Przykładowe encje HA (do sprawdzenia) |
|---|---|---|---|---|
| `sypialnia` | wewnątrz | temperatura, CO₂, wilgotność | Netatmo, moduł wewn. | `sensor.sypialnia_temperature`, `…_co2`, `…_humidity` |
| `salon` | wewnątrz | temperatura, CO₂, wilgotność | Netatmo, moduł wewn. | `sensor.salon_temperature`, `…_co2`, `…_humidity` |
| `taras` | na zewnątrz | temperatura, wilgotność | Netatmo, moduł zewn. | `sensor.taras_temperature`, `…_humidity` |
| `balkon` | na zewnątrz | temperatura, wilgotność | Netatmo, moduł zewn. | `sensor.balkon_temperature`, `…_humidity` |
| `airly` | powietrze | PM2.5, PM10, CAQI | Airly | `sensor.<instalacja>_pm2_5`, `…_pm10`, `…_caqi` |

Razem 13 wartości. Listę encji spisujemy w HA (Narzędzia deweloperskie → Stany). Mapowanie
encji na pomieszczenia i wielkości trzymamy w **konfiguracji serwera**, a encje spoza tej listy
serwer ignoruje.

Częstotliwość źródeł: Netatmo odświeża się mniej więcej co 10 minut, a Airly w HA zwykle co
kilkanaście minut lub rzadziej (limit darmowego API). Wysyłka co 5 minut czasem powtórzy tę samą
wartość. To nie przeszkadza, a pozwala szybko zauważyć, że HA przestał wysyłać.

### 2.2 Konfiguracja HA (wklejamy w `configuration.yaml` i `secrets.yaml`)

`secrets.yaml`:

```yaml
meteo_dom_auth: "Bearer <losowy token 64 znaki — wygeneruję przy wdrożeniu>"
```

`configuration.yaml`:

```yaml
rest_command:
  meteo_dom_push:
    url: "https://meteo-dom.deltaeternal.eu/ingest.php"
    method: POST
    timeout: 20
    headers:
      Authorization: !secret meteo_dom_auth
    content_type: "application/json"
    payload: >-
      {% set ids = [
        'sensor.sypialnia_temperature', 'sensor.sypialnia_co2', 'sensor.sypialnia_humidity',
        'sensor.salon_temperature', 'sensor.salon_co2', 'sensor.salon_humidity',
        'sensor.taras_temperature', 'sensor.taras_humidity',
        'sensor.balkon_temperature', 'sensor.balkon_humidity',
        'sensor.airly_pm2_5', 'sensor.airly_pm10', 'sensor.airly_caqi'
      ] %}
      {"v": 1, "ts": {{ now().timestamp() | int }}, "states": {
      {%- for e in ids %}"{{ e }}": {{ states(e) | tojson }}{{ "," if not loop.last }}{% endfor -%}
      }}
```

Automatyzacja (`automations.yaml` lub edytor UI):

```yaml
- alias: "Meteo Dom — wysyłka odczytów"
  triggers:
    - trigger: time_pattern
      minutes: "/5"
  actions:
    - action: rest_command.meteo_dom_push
  mode: single
```

Wartości `unavailable` i `unknown` serwer zapisuje jako brak odczytu. Na samym początku
aplikacji przygotuję gotowy plik YAML z prawdziwymi nazwami encji i tokenem.

### 2.3 Przyjmowanie danych: `POST /ingest.php`

- Nagłówek `Authorization: Bearer <token>`. Porównanie przez `hash_equals` ze skrótem SHA-256
  tokenu zapisanym w `data/config.php`, więc na serwerze nie leży sam token.
- Tylko `POST` z `application/json`, ciało najwyżej 64 KB, pole `v` = 1.
- Sprawdzenie zegara: `ts` może się różnić od czasu serwera najwyżej o ±15 min, inaczej żądanie
  jest odrzucane. Odczyt zapisujemy pod czasem zaokrąglonym do 5 min, więc ponowna wysyłka nie
  tworzy duplikatu.
- Ograniczenie: najwyżej 30 żądań na 10 min z jednego IP. Każde żądanie trafia do dziennika
  `ingest_log`.
- Odpowiedź `{"ok":true,"stored":13,"ignored":0}`. Błędy: 401 (token), 400 (format),
  409 (czas), 429 (limit).

### 2.4 Baza `data/home.sqlite`

```sql
CREATE TABLE sensor  (id TEXT PRIMARY KEY, room TEXT, kind TEXT, unit TEXT, entity TEXT UNIQUE, sort INT);
CREATE TABLE reading (sensor_id TEXT, ts INT, value REAL, PRIMARY KEY (sensor_id, ts)) WITHOUT ROWID;
CREATE TABLE hourly  (sensor_id TEXT, ts INT, vmin REAL, vmax REAL, vavg REAL, n INT, PRIMARY KEY (sensor_id, ts)) WITHOUT ROWID;
CREATE TABLE ingest_log (ts INT, ip TEXT, status INT, stored INT);
```

- **Retencja**: odczyty 5-minutowe przez 35 dni, agregaty godzinowe bez limitu (ok. 115 tys.
  wierszy rocznie). Hosting nie ma crona, więc agregację i sprzątanie wykonuje `ingest.php`
  raz na godzinę.
- `kind` przyjmuje wartości `temp`, `hum`, `co2`, `pm25`, `pm10`, `caqi`, a `room` to klucz z tabeli 2.1.
- Tryb WAL i `busy_timeout`. Plik bazy leży w `data/` i nigdy nie jest nadpisywany przy wdrożeniu.

### 2.5 Uzupełnienie historii wstecz (opcjonalnie)

HA przechowuje zwykle 10 dni historii (ustawienie `recorder`). Jednorazowy skrypt
`scripts/backfill.py`, uruchomiony na Macu w sieci domowej, pobierze `/api/history/period`
z HA (token długoterminowy, tylko lokalnie) i wyśle te dane partiami do `ingest.php` w trybie
`backfill` (ten sam token, bez sprawdzania zegara). Dzięki temu wykresy 7-dniowe są pełne od
pierwszego dnia.

## 3. API dla aplikacji (wymaga sesji)

| Zapytanie | Zwraca |
|---|---|
| `api.php?src=home` | dla każdego pomieszczenia: ostatnie wartości, czas odczytu, min./maks. dziś, seria 24 h (co 5 min) do mini-wykresów; do tego `age` (wiek ostatniej wysyłki z HA) |
| `api.php?src=home_hist&room=salon&range=24h\|7d\|30d` | serie do paneli (24 h surowe, 7 dni i 30 dni z agregatów godzinowych z min./maks.) |
| `api.php?src=imgw\|hybrid\|warnings\|station\|ecmwf\|antistorm` | bez zmian względem Meteo |
| `api.php?act=me\|login\|logout\|password\|admin_*` | logowanie i zarządzanie użytkownikami, jak w Stodole |

Format odpowiedzi jak w Meteo: `{ok, src, fetched, stale, now, data}`.

## 4. Interfejs

### 4.1 iPad 9 w poziomie (priorytet)

Viewport CSS iPada 9 to **1080 × 810 pt**. Jako aplikacja z ekranu początkowego, z paskiem stanu
w stylu „black”, zostaje ok. **1080 × 790**. Pierwszy ekran ma się zmieścić **bez przewijania**.
Rozkład bazuje na karcie „Teraz” z Meteo, a pod nią dochodzi rząd „Dom”.

```
┌──────────────────────────────────────────────────────────────────────────────────┐
│ ◐ Meteo Dom · Wrocław          niedz. 11 października   11:43         ● 2 min  v1.0│ ~44
├───────────────────────┬──────────────────────────────────────────────────────────┤
│ ☁  13°C               │  Wiatr i porywy │  Słońce        │  Wilgotność           │
│ Duże zachmurzenie  >  │  17 km/h  ↗     │  31° nad hor.  │  68 %                 │
│ Odczuwalna 9° · …     ├─────────────────┼────────────────┼───────────────────────┤ ~300
│ ⤒07:08 ⤓18:07 11h ☾   │  Ciśnienie      │  Zachmurzenie  │  Opad · IMGW          │
├───────────────────────┼─────────────────┴────────────────┴───────────────────────┤
│ Prognoza 7 dni · IMGW │  10–12  13–15  16–18  19–21  22–24 │JUTRO 0–3  4–6  7–9  │ ~170
│ (trend maks./min.)    │   13°    14°    13°     9°     9°  │      9°   7°   8°    │
├───────────────────────┴──────────────────────────────────────────────────────────┤
│ ⌂ DOM                                                                             │
│ ┌ Sypialnia ──┐ ┌ Salon ──────┐ ┌ Taras ──────┐ ┌ Balkon ─────┐ ┌ Powietrze ───┐ │
│ │ 21,4 °C     │ │ 23,2 °C     │ │ 14,3 °C     │ │ 15,6 °C     │ │ PM2.5  5 µg  │ │ ~200
│ │ CO₂ 462 ● · │ │ CO₂ 823 ● · │ │ 62 % · dziś │ │ 58 % · dziś │ │ PM10 9 · CAQI│ │
│ │ 48 %        │ │ 45 %        │ │ 9,8–15,1°   │ │ 10,2–15,9°  │ │ ● dobra      │ │
│ │ ╱╲__╱‾‾╲_   │ │ ‾╲__╱‾‾╲_   │ │ ╲__╱‾‾╲_╱   │ │ ╲__╱‾‾╲_╱   │ │ _╱╲_╱╲__     │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────┘
   ↓ niżej (przewijanie): IMGW 60 h · ICM 60 h · ECMWF + ENS · AntiStorm — jak w Meteo
```

- **Nagłówek**: nazwa, miasto, duży zegar z sekundami w indeksie górnym (jak w HA), data, kropka
  świeżości danych z domu (zielona do 12 min, żółta do 30 min, czerwona powyżej z napisem
  „brak danych z domu od …”), numer wersji.
- **Karta „Teraz”, kafelki 3×2, bloki 3 h i trend 7 dni** to te same komponenty co w Meteo, ze
  wszystkimi panelami (`sheet`) i kolorowym niebem w tle. Wysokości są dopasowane do 790 pt.
- **Rząd „Dom”** w tym samym szklanym stylu co kafelki Meteo (`tile-btn`), 5 kafelków po równo:
  - **Pomieszczenie wewnątrz**: nazwa i ikona, duża temperatura, wiersz „CO₂ 823 ppm ● · 45 %”,
    mini-wykres temperatury z 24 h z linią północy i jaśniejszym dniem (jak `sparkTime` w Meteo).
    Kolor kropki CO₂: zielony < 800 ppm, żółty 800–1199, pomarańczowy 1200–1499, czerwony
    ≥ 1500 i wtedy plakietka „wywietrz”.
  - **Na zewnątrz**: temperatura, wilgotność, zakres min.–maks. z dziś, mini-wykres z 24 h.
  - **Powietrze · Airly**: PM2.5 jako główna liczba i % normy WHO (15 µg/m³ dla średniej
    24 h), PM10 i CAQI. Kolor według skali CAQI Airly (bardzo dobra … bardzo zła), mini-wykres
    PM2.5 z 24 h.
- **Kliknięcie kafelka** otwiera panel (`sheet`, jak w Meteo) z przełącznikiem 24 h / 7 dni /
  30 dni:
  - wnętrza: temperatura i wilgotność na wspólnym wykresie oraz osobny wykres CO₂ z pasami progów;
  - zewnątrz: pomiar Taras i Balkon na tle prognozy IMGW Hybrid, żeby było widać różnicę;
  - Airly: PM2.5 i PM10 z linią normy.
  Pod wykresem: min./maks./średnia za okres i godzina ostatniego odczytu.
- **Brak danych**: kafelek z szarą wartością i podpisem „ostatni odczyt 14:05”; nigdy pusty.

### 4.2 Telefon w pionie

Jedna kolumna: „Teraz” → **Dom** (kafelki 2×2 i Airly na całą szerokość) → bloki 3 h
(przewijane w poziomie) → kafelki pogodowe 2×3 → trend 7 dni → pozostałe sekcje Meteo.
Zegar w nagłówku jest mniejszy, bez sekund.

### 4.3 Komputer

Układ jak na tablecie, wycentrowany, maks. szerokość ok. 1440 px. Przy szerokości ≥ 1300 px
rząd „Dom” może przejść obok bloków 3 h, jeśli wygląda to lepiej (do decyzji na makiecie).
Działa przewijanie do pozostałych sekcji.

### 4.4 Progi układu

`< 760` telefon · `760–999` tablet w pionie / małe okno (Dom 3+2) · `≥ 1000` tablet w poziomie
i komputer (opisany wyżej) · `≥ 1300` szeroki komputer.

## 5. Zachowanie na tablecie (praca ciągła)

- **Odświeżanie**: dane z domu co 60 s (lekki JSON z SQLite), pogoda według harmonogramu Meteo.
  Po powrocie z uśpienia (`visibilitychange`) wszystko od razu się odświeża.
- **Codzienny przeładunek strony o 3:30** (zabezpieczenie przed wyciekami pamięci przy pracy
  24/7), a także po wykryciu nowej wersji service workera.
- **Wygaszanie ekranu**: Screen Wake Lock API, jeśli system na to pozwala. Pewniejszy sposób to
  ustawienia iPada: Blokada automatyczna → „Nigdy” i iPad stale na ładowarce (krok 9).
- **Tryb nocny** (opcjonalny, w Ustawieniach): między zachodem a wschodem słońca przyciemniony
  motyw i wolniejsze animacje nieba, żeby tablet nie świecił w pokoju.
- **Wydajność A13**: animacje nieba i kropli na szybie (`sky.js`) mają tryb „oszczędny”
  (mniej klatek, bez kropli). Na tablecie włączam go domyślnie, jeśli testy pokażą przycięcia.
- **Sesja**: „zapamiętaj to urządzenie” na 180 dni, odnawiana przy każdym użyciu, żeby tablet
  się nie wylogowywał.

## 6. PWA, ikony, wersja

- `manifest.webmanifest` (`display: standalone`, orientacja dowolna), ikony i ekran startowy
  w stylu Meteo z dodanym motywem domu. Kafelek **`icons/meteo-dom-300x200.jpg`** do portalu.
- Pasek stanu `black`, bo `black-translucent` w iOS 27 ucina dół widoku.
- Service worker trzyma w pamięci powłokę aplikacji. Odpowiedzi API idą najpierw z sieci,
  a ostatnią kopię pokazujemy offline z plakietką „dane z …”. Pliki prywatne wydaje tylko
  zalogowanym.
- Numer wersji z jednego źródła (`VERSION` = `app.js` = `sw.js` = `?v=` w HTML), widoczny
  w nagłówku, na ekranie logowania i w Ustawieniach. `CHANGELOG.md` i
  `scripts/build-release.sh` (zip i kafelek) jak w Meteo.

## 7. Bezpieczeństwo i prywatność

- Wszystko za logowaniem, łącznie z prognozą i plikami JS z logiką domu.
- Token HA trzymamy tylko w `secrets.yaml` HA. Na serwerze leży jego skrót SHA-256, a w repo
  nic. Token zmienia się w Ustawieniach administratora (generowanie nowego plus instrukcja
  dla HA).
- `ingest.php` przyjmuje wyłącznie mapowane encje i liczby w rozsądnych zakresach
  (np. temp. −50…+60, CO₂ 250…10000, PM 0…1000). Wartości spoza zakresu są odrzucane.
- W publicznych plikach (logowanie, manifest, kafelek, SW) nie ma nazw pomieszczeń, adresu
  ani nazwiska. W UI pojawia się tylko „Wrocław”.
- Konto administratora `lbartj`, w repo tylko skrót bcrypt. Inne konta (np. „tablet”)
  dodaje administrator.

## 8. Kroki wdrożenia

| # | Krok | Kto | Wynik |
|---|---|---|---|
| **0** | **Sprawdzenia wstępne.** (a) **Bramka anty-botowa hostingu** (`/__nodea/`) przepuszcza tylko przeglądarki, więc HA najpewniej dostanie stronę „Weryfikacja” zamiast odpowiedzi API. Trzeba w panelu hostingu wyłączyć bramkę dla subdomeny `meteo-dom` albo dodać wyjątek dla ścieżki `/ingest.php` (ewentualnie zapytać obsługę). Sprawdzamy testowym `curl -X POST` z domu. **Sprawdzone 2026-10-16:** hosting to vh.pl (pakiet Wizytówka, cPanel), a bramka to jego „AntyDDoS L7” dostarczany przez Nodea (nodeaD); na POST też odpowiada stroną „Weryfikacja” z kodem **200**, więc HA uznałby wysyłkę za udaną, choć dane nigdy nie dotrą. Wyjątek ustawia się w cPanel → „NodeaD – AntyDDoS L7” → Ustawienia ochrony → **Zaufane** → typ **Endpoint**, wartość `/ingest.php`. (b) PHP 8.1+ z `pdo_sqlite` na hostingu. (c) Lista encji HA z tabeli 2.1. (d) Nazwa i adres. | Ty + ja | potwierdzone, że POST z domu dociera do PHP |
| 1 | Repo `LbArtJ/Meteo-Dom`, szkielet: kopia Meteo 1.8.0, logowanie ze Stodoły, `VERSION` 0.1.0, `launch.json` (osobny port, np. 8751) | ja | aplikacja startuje lokalnie, logowanie działa |
| 2 | Backend domu: `ingest.php`, schemat SQLite, agregacja i retencja, `src=home` / `home_hist`, testy (`tests/run.sh` + test API) | ja | testy zielone |
| 3 | Symulator HA: `scripts/fake-ha.php` wysyła realistyczne dane co 5 min do lokalnego serwera (oraz wsteczne 30 dni) | ja | lokalnie są dane do budowy UI |
| 4 | **Makieta iPada** (statyczna, 1080×790) z rzędem „Dom”, do Twojej akceptacji, zanim dopracuję szczegóły | ja → Ty | zaakceptowany wygląd |
| 5 | Interfejs: rząd „Dom”, panele 24 h/7 d/30 d, kropka świeżości, zegar, tryb nocny i oszczędny | ja | działa na danych z kroku 3 |
| 6 | Układy telefonu i komputera, PWA, ikony, kafelek 300×200, service worker | ja | — |
| 7 | Testy: Chrome (panel), symulator iPada (viewport 1080×810 i Safari na iPadzie z ekranu początkowego), iPhone 17, offline, wylogowanie, brak danych z HA, błędny token | ja | raport ze zrzutami |
| 8 | Wydanie v1.0.0: PR, Release z zipem i kafelkiem (scalam na Twoje „scal”) | ja | `dist/meteo-dom-1.0.0.zip` |
| 9 | **Hosting**: subdomena `meteo-dom.deltaeternal.eu` z HTTPS, wgranie zipa, pierwsze uruchomienie → hasło administratora i wygenerowanie tokenu HA (pokazany raz) | Ty (z moją instrukcją) | strona działa, logowanie OK |
| 10 | **Home Assistant**: wklejenie YAML z 2.2 i tokenu do `secrets.yaml`, przeładowanie konfiguracji, ręczne uruchomienie automatyzacji, sprawdzenie dziennika HA | Ty (z moją instrukcją) | w aplikacji kropka zielona, dane spływają |
| 11 | (opcjonalnie) `scripts/backfill.py` z Maca w domu: historia z HA (ok. 10 dni) | ja przygotuję, Ty uruchamiasz | pełne wykresy 7 dni |
| 12 | **iPad**: Safari → adres → logowanie z „zapamiętaj” → Udostępnij → „Do ekranu początkowego”. Ustawienia: Ekran i jasność → Blokada automatyczna „Nigdy”; opcjonalnie Dostęp z przewodnikiem (Dostępność), żeby tablet był zamknięty w aplikacji; iPad na stałe na ładowarce | Ty | tablet w trybie kiosku |
| 13 | Portal deltaeternal.eu: kafelek „Meteo Dom” w `apps.php` + krótka ścieżka `/meteo-dom/` | ja | aplikacja w portalu |

## 9. Decyzje do potwierdzenia (domyślne propozycje)

1. **Nazwa i adres**: „Meteo Dom”, `meteo-dom.deltaeternal.eu`.
2. **Temperatura w karcie „Teraz”**: zostaje prognoza/stan IMGW jak w Meteo, a pomiar z Tarasu
   i Balkonu jest w rzędzie „Dom”. Alternatywa: duża liczba z czujnika zewnętrznego, a IMGW
   jako podpis.
3. **Zegar w nagłówku**: tak (z sekundami na tablecie). Mapa z HA: nie, bo mapy opadów są
   w sekcji AntiStorm.
4. **Konta**: administrator plus możliwość dodania kolejnych (np. osobne konto dla tabletu).
5. **Retencja**: 5 min przez 35 dni, godzinowe na zawsze.
6. **Tryb nocny**: automatycznie od zachodu do wschodu, z możliwością wyłączenia.
7. **Uzupełnienie historii z HA (krok 11)**: tak / nie.

## 10. Ryzyka

| Ryzyko | Skutek | Zabezpieczenie |
|---|---|---|
| Bramka anty-botowa blokuje POST z HA | brak danych z domu | krok 0a przed pisaniem kodu; awaryjnie osobna subdomena bez bramki |
| HA lub internet w domu padnie | stare dane | kropka świeżości, czytelny komunikat, kafelki z godziną odczytu |
| Zmiana nazw encji w HA (np. po ponownym dodaniu Netatmo) | brak części wartości | mapowanie w jednym miejscu, `ingest_log` pokazuje encje odrzucone |
| Zmiany w API IMGW / Open-Meteo | brak prognozy | ta sama obsługa co w Meteo (kopia „stale”), poprawki synchronizowane skryptem |
| Wydajność iPada 9 (A13, 3 GB) przy pracy 24/7 | przycięcia, przeładowania | tryb oszczędny animacji, codzienny przeładunek, test w symulatorze i na urządzeniu |
