feat: testowanie nastrojów za pomocą rest api

This commit is contained in:
2026-06-05 23:08:31 +02:00
parent 856990f232
commit a7ed8f6cdd
3 changed files with 212 additions and 42 deletions
+98 -18
View File
@@ -1,6 +1,6 @@
# ESP32-C6 Desk Buddy
Animowany "biurkowy przyjaciel" na Seeed XIAO ESP32-C6 z czujnikiem gestów PAJ7620 i wyświetlaczem OLED 128×64. Reaguje na gesty emocjami, wykonuje webhooki HTTP, wyświetla informacje na żądanie i symuluje potrzeby w stylu Tamagotchi. Konfigurowany przez przeglądarkę.
Animowany "biurkowy przyjaciel" na Seeed XIAO ESP32-C6 z czujnikiem gestów PAJ7620 i wyświetlaczem OLED 128×64. Reaguje na gesty emocjami, wykonuje webhooki HTTP, wyświetla informacje na żądanie, symuluje potrzeby w stylu Tamagotchi i pokazuje pogodę z Open-Meteo. Konfigurowany przez przeglądarkę.
---
@@ -73,6 +73,21 @@ Buddy ma trzy potrzeby narastające z czasem:
Gdy potrzeba przekroczy próg, Buddy automatycznie zmienia nastrój. W lewym dolnym rogu ekranu pojawiają się litery: **G** (głód), **Z** (zabawa), **M** (mycie).
### Pogoda (Open-Meteo)
Co jakiś czas (konfigurowalny interwał) wyświetlany jest ekran pogodowy — zamiast oczu pojawia się ikona pogodowa, a zamiast ust — temperatura i ciśnienie:
| Ikona | Warunki |
|-------|---------|
| Słońce | Bezchmurnie (WMO 0) |
| Chmura + słońce | Częściowe zachmurzenie (WMO 12) |
| Chmura | Zachmurzenie, mgła (WMO 348) |
| Deszcz | Mżawka, deszcz, przelotny deszcz (WMO 5182) |
| Śnieg | Śnieg i opady śnieżne (WMO 7186) |
| Burza | Burza z piorunami (WMO 9599) |
Dane z [Open-Meteo](https://open-meteo.com/) — **darmowe, bez klucza API**. Dwuetapowe pobieranie: geocoding (nazwa miasta → współrzędne) + aktualna prognoza.
### Gesty (PAJ7620)
Czujnik rozpoznaje 9 gestów ręką:
@@ -132,27 +147,56 @@ Po uruchomieniu wejdź przeglądarką na adres IP wypisany w Serial (lub na OLED
http://<IP>/
```
Dla każdego gestu można ustawić:
- **URL webhoka** — endpoint HTTP POST (pusty = wyłączony)
- **Nastrój** — jaki nastrój ustawić po geście (0 = bez zmiany)
- **Akcja** — co zrobić/wyświetlić na OLED
- **ON** — czy gest jest aktywny
Panel zawiera cztery sekcje:
#### Gesty
Dla każdego gestu można ustawić URL webhoka, nastrój, akcję i czy gest jest aktywny.
#### Tamagotchi
Podgląd aktualnych potrzeb (głód, szczęście, higiena) z paskami postępu oraz przyciski: **Nakarm**, **Pobaw się**, **Umyj**.
#### Pogoda
Aktualny stan pogody (ikona, temperatura, ciśnienie) oraz ustawienia:
- **Miasto** — nazwa w języku polskim lub angielskim (np. `Warszawa`, `Kraków`)
- **Co ile sekund** — interwał wyświetlania ekranu pogodowego (0 = wyłączony)
- **Pokazuj przez (s)** — czas trwania ekranu pogodowego
#### Test nastroju
12 przycisków do ręcznego ustawienia dowolnego nastroju na **10 sekund** — do testowania wyglądu oczu bez czujnika gestów.
### JSON API
```bash
# Odczyt konfiguracji gestów
GET http://<IP>/api/config
# Odczyt / zapis konfiguracji gestów
GET http://<IP>/api/config
POST http://<IP>/api/config (Content-Type: application/json)
# Zapis konfiguracji gestów
POST http://<IP>/api/config
Content-Type: application/json
# Stan Tamagotchi
GET http://<IP>/api/tama
# Akcje Tamagotchi
POST http://<IP>/api/tama/feed
POST http://<IP>/api/tama/play
POST http://<IP>/api/tama/clean
# Aktualna pogoda + konfiguracja
GET http://<IP>/api/weather
# Zapis konfiguracji pogody (form POST)
POST http://<IP>/weather/save
# Test nastroju (011) na 10 sekund
POST http://<IP>/api/mood/test?m=1
```
Przykład zapisu gestów:
```json
{
"wave": {
"url": "http://homeassistant.local:8123/api/webhook/my_hook",
"mood": 6,
"action": 4,
"action": 0,
"enabled": true
},
"up": {
@@ -215,6 +259,10 @@ Plik `data/config.json` zawiera wyłącznie konfigurację gestów (bez danych Wi
}
```
### Konfiguracja pogody
Konfiguracja przechowywana w `/weather.json` na LittleFS — zapisywana przez panel webowy, persystuje przez restarty. Nie wymaga reflashowania.
---
## Instalacja i build
@@ -243,7 +291,7 @@ task flash-monitor # uploadfs + upload + monitor
|---------|------|
| `task build` | Tylko kompilacja |
| `task flash` | Wgraj filesystem + firmware |
| `task upload` | Wgraj tylko firmware |
| `task upload` | Wgraj tylko firmware (zachowuje LittleFS) |
| `task uploadfs` | Wgraj `data/wifi.json` + `data/config.json` |
| `task monitor` | Monitor portu szeregowego |
| `task flash-monitor` | Pełne wgranie + monitor |
@@ -251,8 +299,11 @@ task flash-monitor # uploadfs + upload + monitor
| `task gestures` | Edytuj gesty (`data/config.json`) + wgraj FS |
| `task config-download` | Pobierz konfigurację gestów z urządzenia |
| `task erase-flash` | Skasuj flash i wgraj od nowa |
| `task test` | Uruchom testy jednostkowe (native, na Mac) |
| `task` | Lista wszystkich zadań |
> **Uwaga:** `task uploadfs` nadpisuje LittleFS — konfiguracja pogody zapisana przez panel webowy zostanie utracona. Użyj `task upload` do aktualizacji samego firmware'u.
### Zmiana WiFi bez rekompilacji
```bash
@@ -272,13 +323,31 @@ mathieucarbou/ESPAsyncWebServer@^3.3.12
## Architektura kodu
Cały projekt mieści się w jednym pliku `src/main.cpp`.
Logika domenowa wydzielona do bibliotek w `lib/` — zero zależności od Arduino, kompilowalne natywnie.
```
src/main.cpp — hardware + HTTP server + WiFi + FreeRTOS (~1100 linii)
lib/
BuddyDomain/ — BuddyTypes.h, BuddyLogic.h/.cpp (nastroje, mruganie, źrenice)
TamaLogic/ — TamaLogic.h/.cpp (potrzeby, ticki, override nastroju)
GestureConfig/ — GestureConfig.h/.cpp (struct, enums, tablice stringów)
test/native/
test_buddy/ — ~21 testów Unity (initBuddy, mruganie, saccady)
test_tama/ — ~19 testów Unity (ticki, progi, tamaFeed/Play/Clean)
data/
wifi.json — dane WiFi (nie commitowane)
config.json — konfiguracja gestów
partitions.csv — własna tablica partycji (app 1.75 MB, LittleFS 2.19 MB)
```
### Przepływ inicjalizacji
```
setup()
loadAllConfig()
/wifi.json → WIFI_SSID/PASS (nigdy nie serwowane)
/config.json → gConfig[] (gesty)
/weather.json → weatherCfg (miasto, interwał)
initBuddy() + initTama()
Wire.begin(22, 23) ← I2C0 HP dla obu urządzeń
u8g2.begin() ← SSD1306 HW I2C
@@ -286,15 +355,16 @@ setup()
connectWiFi() → NTP sync
setupHttpServer() ← AsyncWebServer port 80
loop() ← polling
loop()
sensor.readGesture() ← co 500 ms
handleGesture()
executeAction() ← tama efekt + overlay OLED
executeAction() ← efekt tama + overlay OLED
setBuddyMood() ← skonfigurowany lub domyślny
fireWebhook() ← FreeRTOS task (async)
updateTama() ← co 10 s (potrzeby + mood override)
updateBuddyAnim() ← co 50 ms (mruganie, saccady, ZZZ)
showBuddyScreen() ← co 50 ms (~20 fps)
drawWeatherFace() ← priorytet gdy weatherShowUntil aktywny
```
### Kluczowe decyzje techniczne
@@ -306,13 +376,23 @@ loop() ← polling
| `Wire1` (LP I2C) zablokowany na GPIO6/7 (niedostępne na XIAO) | Jeden `Wire` (HP I2C) dla SSD1306 + PAJ7620 |
| `setContrast()` ma zbyt wąski zakres wizualny na SSD1306 | `setPowerSave(1/0)` — komenda 0xAE/0xAF wyłącza panel |
| Hasło WiFi dostępne przez HTTP | Oddzielny `/wifi.json` — nigdy nie serwowany; `/config.json` zawiera tylko gesty |
| Firmware nie mieścił się w partycji OTA (1.28 MB) | Własna `partitions.csv`: app0 1.75 MB, LittleFS 2.19 MB |
| Domena logiki — testy natywne bez sprzętu | Biblioteki w `lib/` bez zależności Arduino; `pio test -e native` |
### Testy
```bash
task test # pio test -e native — 40 testów na Mac, bez urządzenia
```
Testy pokrywają: inicjalizację stanu, cykl mrugania (OPEN→CLOSING→CLOSED→OPENING), saccady źrenic, ticki tamagotchi, progi nastrojów, tamaFeed/Play/Clean z wartościami brzegowymi.
---
## Dodawanie nowych akcji
1. Dodaj wartość do `enum Action` w `main.cpp`
2. Zaktualizuj `NUM_ACTIONS` i `ACTION_LABELS[]`
1. Dodaj wartość do `enum Action` w `GestureConfig.h`
2. Zaktualizuj `NUM_ACTIONS` i `ACTION_LABELS[]` w `GestureConfig.cpp`
3. Napisz funkcję `showXxxScreen()`
4. Dodaj `case ACTION_XXX:` w `showBuddyScreen()` (sekcja overlay)
5. Opcjonalnie: dodaj efekt tama w `executeAction()` (np. zmiana potrzeby)