47 KiB
Tak — i to jest bardzo sensowny projekt, szczególnie że nie musimy wymyślać protokołu od zera. GREE/EWPE ma lokalny protokół UDP, a obecna integracja Home Assistant również komunikuje się lokalnie. Oficjalna integracja HA jest typu Local Polling i obsługuje m.in. tryb HVAC, temperaturę, wentylator, swing i presety.
Co ważniejsze, są już implementacje pokazujące, że protokół można obsługiwać niezależnie od Home Assistanta: UDP/7000, szyfrowanie AES, discovery/bind/status/command. Nowsze implementacje obsługują nawet AES-128-ECB i AES-128-GCM.
Ja zrobiłbym to trochę inaczej niż zwykły custom component
Zaprojektowałbym własny lokalny serwer GREE + integrację HA, np.:
┌──────────────────────────┐
│ Home Assistant │
│ │
│ climate.gree_salon │
│ sensor.gree_temperature │
│ switch.gree_quiet │
│ ... │
└────────────┬─────────────┘
│
REST / WebSocket
│
┌────────────▼─────────────┐
│ Gree Controller │
│ │
│ Device Manager │
│ State Manager │
│ Automation Engine │
│ Heating Manager │
│ Scheduler │
│ Web UI │
└────────────┬─────────────┘
│
GREE UDP / AES
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ GREE AC │ │ GREE AC │ │ GREE AC │
│ salon │ │ sypial. │ │ biuro │
└─────────┘ └─────────┘ └─────────┘
Dzięki temu HA nie jest miejscem, w którym znajduje się cała logika. HA staje się klientem naszego kontrolera.
Najważniejsze: kompatybilność 1:1
Chciałbym zachować praktycznie ten sam model urządzenia, który HA już zna:
Climate
HVAC_MODE_OFFHVAC_MODE_AUTOHVAC_MODE_COOLHVAC_MODE_HEATHVAC_MODE_DRYHVAC_MODE_FAN_ONLY- temperatura zadana
- temperatura pomieszczenia
- prędkość wentylatora
- swing pionowy
- swing poziomy
- preset
- power
Obecna integracja GREE obsługuje już te podstawowe funkcje.
Switch
Np.:
- panel light
- quiet
- X-Fan
- turbo
- health
- sleep
- child lock
- display
- eco
Oczywiście tylko te, które faktycznie obsługuje konkretny model.
Dodatkowe sensory
I tutaj możemy zrobić znacznie więcej:
sensor.gree_salon_temperature
sensor.gree_salon_humidity
sensor.gree_salon_power
sensor.gree_salon_mode
sensor.gree_salon_fan
sensor.gree_salon_connection
sensor.gree_salon_last_update
sensor.gree_salon_energy
oraz diagnostykę:
sensor.gree_salon_response_time
sensor.gree_salon_packets
sensor.gree_salon_errors
sensor.gree_salon_uptime
Discovery
To też możemy zrobić porządnie.
Standardowo GREE wykorzystuje UDP/7000. Discovery może działać przez broadcast, a dla VLAN-ów możemy zrobić dodatkowo aktywne wykrywanie po podsieciach. Istniejące implementacje już stosują unicast UDP/7000 właśnie do urządzeń znajdujących się w innych VLAN-ach.
W naszym UI:
GREE Controller
────────────────────────────────
Devices
✓ GREE Salon
192.168.10.51
AA:BB:CC:DD:EE:01
Online
22.4°C
✓ GREE Sypialnia
192.168.10.52
AA:BB:CC:DD:EE:02
Online
20.8°C
[ Scan network ]
Network:
192.168.10.0/24
[ Scan ]
A po znalezieniu:
Found GREE device
Model: GREE ...
MAC: xx:xx:xx:xx:xx:xx
IP: 192.168.10.51
Protocol: GREE / EWPE
Encryption: AES-128-GCM
Firmware: ...
[ Add device ]
I tutaj widzę bardzo ważną rzecz
Nie opierałbym projektu bezpośrednio na obecnym kodzie integracji HA.
Mamy już kilka projektów, które pokazują różne implementacje protokołu:
- Home Assistant GreeClimateComponent
gree-remote- implementacje EWPE
- implementacje Rust
- lokalne serwery GREE
Nawet istniejący projekt Rust ma już architekturę bardzo zbliżoną do tego, co chcemy osiągnąć: daemon rozmawia z klimatyzatorem przez UDP/7000, a frontend dostaje normalne dane JSON i aktualizacje na żywo.
Ale nasz projekt powinien mieć własną warstwę protokołu.
Czyli:
gree_protocol/
discovery
encryption
packet
bind
status
command
device_capabilities
nad tym:
gree_core/
Device
DeviceManager
StateManager
Scheduler
AutomationEngine
HeatingManager
nad tym:
api/
REST
WebSocket
oraz:
web/
dashboard
devices
automations
heating
schedules
diagnostics
i osobno:
homeassistant/
config_flow
climate
sensor
switch
binary_sensor
Najciekawsza część: inteligentne ogrzewanie
Tutaj nasza aplikacja może być dużo bardziej użyteczna niż zwykła integracja GREE.
Przykład:
Strefa: salon
Heating zone: Salon
Target:
21.5°C
Comfort:
21.5°C
Night:
19.0°C
Away:
17.0°C
Minimum:
16.0°C
Źródło temperatury:
○ GREE
● Xiaomi BLE sensor
○ Home Assistant sensor
○ średnia z kilku czujników
I wtedy kontroler decyduje:
22:00
↓
Night mode
↓
target = 19°C
06:30
↓
Morning
↓
target = 21°C
08:30
↓
Nobody home
↓
target = 18°C
16:00
↓
Somebody home
↓
target = 21°C
Ale możemy zrobić jeszcze lepiej.
Histereza
Nie chcemy:
21.0 → ON
21.1 → OFF
21.0 → ON
21.1 → OFF
tylko:
target = 21°C
hysteresis = 0.4°C
ON < 20.6°C
OFF > 21.4°C
A dodatkowo:
minimum ON time
minimum OFF time
minimum interval between commands
żeby nie katować klimatyzatora.
Predykcyjne ogrzewanie
To jest funkcja, którą naprawdę warto zrobić.
Jeżeli system zauważy:
18:00 19.2°C
18:15 19.7°C
18:30 20.1°C
18:45 20.5°C
19:00 20.8°C
może policzyć:
Heating rate:
+0.53°C / hour
i wiedzieć, że dojście do 21°C zajmie około:
23 min
Możemy więc ustawić:
„O 19:00 chcę mieć 21°C”
i rozpocząć ogrzewanie odpowiednio wcześniej.
Możemy też sterować wieloma klimatyzatorami
Przykładowo:
Heating Zone
│
┌─────────┴─────────┐
│ │
GREE Salon GREE Kuchnia
21°C 21°C
│ │
└─────────┬─────────┘
│
Temperature
21.2°C
System może zdecydować:
Salon:
HEAT 21°C
Kuchnia:
OFF
albo:
Salon:
HEAT 20.5°C
Kuchnia:
HEAT 20.5°C
Automatyzacje
Zamiast pisać YAML:
trigger:
...
condition:
...
action:
...
robimy prosty GUI:
Automation
WHEN
[ Temperature ]
[ Salon ]
[ falls below ]
[ 20°C ]
AND
[ Time ]
[ 06:00 - 22:00 ]
THEN
[ Climate ]
[ Salon ]
[ Heat ]
[ 21°C ]
Albo:
WHEN
Outside temperature < 5°C
AND
Time = 22:00
THEN
Set heating zone "Salon"
Target = 19°C
Fan = Auto
Live state
Web UI zrobiłbym na WebSocketach/SSE.
Na dashboardzie:
┌──────────────────────────────────────────┐
│ SALON │
│ │
│ 21.3 °C │
│ │
│ Target 21.0 °C │
│ │
│ ● HEATING │
│ │
│ Mode HEAT │
│ Fan AUTO │
│ Swing AUTO │
│ │
│ Power ███████████░ │
│ │
│ [ − ] 21.0°C [ + ] │
└──────────────────────────────────────────┘
I bez odświeżania strony:
AC → Controller → WebSocket → Browser
Historia
Możemy przechowywać:
temperature
target temperature
mode
fan
power
connection
commands
errors
i zrobić wykres:
22°C ┤ ╭────────
21°C ┤ ╭──────╯
20°C ┤ ╭────╯
19°C ┤───────╯
└────────────────────────────
12 14 16 18 20 22
Do tego:
Heating time today: 3h 42m
Commands: 27
Communication errors: 0
Estimated consumption: ...
Bardzo ważna rzecz — odporność
To jest właśnie coś, co może być lepsze od obecnej integracji HA.
Nie chcemy:
HA
│
├── request
│
├── timeout
│
├── retry
│
└── error
tylko:
Controller
│
persistent state
│
┌─────────────┴─────────────┐
│ │
GREE AC Home Assistant
Controller cały czas monitoruje urządzenia.
Jeżeli AC zniknie:
ONLINE
↓
TIMEOUT
↓
RETRY 1
↓
RETRY 2
↓
OFFLINE
Po powrocie:
OFFLINE
↓
DISCOVER/RECONNECT
↓
GET STATE
↓
ONLINE
HA dostaje już tylko poprawny stan.
I jest jeszcze jedna bardzo istotna kwestia
Nowsze firmware GREE faktycznie może być problemem.
Znalazłem świeże zgłoszenie z lipca 2026 dotyczące GREE Clivia, gdzie autor raportuje, że na firmware 2.12+ urządzenie pozostaje pingowalne, ale nie odpowiada na UDP/7000, przez co standardowa integracja HA nie może wykonać discovery/bind.
To oznacza, że zanim zaczniemy pisać GUI, zrobiłbym reverse engineering konkretnego dongla/klimatyzatora, którego masz.
I to jest najlepszy pierwszy etap.
Etap 1 — „GREE Protocol Lab”
Napiszemy mały program:
gree-probe
który:
1. nasłuchuje UDP
2. wyszukuje GREE
3. identyfikuje urządzenie
4. wykonuje discovery
5. próbuje bind
6. odczytuje capabilities
7. odczytuje status
8. wykonuje pojedyncze komendy
9. loguje wszystkie pakiety
10. zapisuje PCAP
Np.:
$ gree-probe scan
Found 2 devices
192.168.10.51
MAC: ...
Model: ...
Protocol: GREE
Encryption: AES-GCM
UDP: 7000
Status: OK
192.168.10.52
MAC: ...
Model: ...
Protocol: GREE
Encryption: AES-GCM
UDP: 7000
Status: OK
Potem:
gree-probe monitor 192.168.10.51
i dostajemy:
14:32:01 temp=21.4 target=21.0 mode=heat fan=auto
14:32:02 temp=21.4 target=21.0 mode=heat fan=auto
14:32:03 temp=21.5 target=21.0 mode=heat fan=auto
Dopiero na tym fundamencie budowałbym resztę.
I zdecydowanie nie robiłbym tego jako kolejnego prostego custom componentu HA. Zrobiłbym własny daemon/controller + oficjalny custom integration HA. Wtedy możesz mieć jednocześnie pełną kompatybilność encji z HA, własny panel WWW, własny scheduler, inteligentne ogrzewanie, historię i automatyzacje, a protokół GREE jest całkowicie odseparowany od Home Assistanta.
Jeżeli chcesz, możemy teraz przejść do konkretnej architektury projektu i zacząć od reverse-engineeringu protokołu GREE — pliki, moduły, Python/Rust, API, baza danych i później gotowy custom integration dla HA.
Plan jest na to absyntów było w rust z interfejsem i będzie to na osobnym hoście/ kontenerze lxc lub w integracji homeassistant i jakoś trzeba pogodzić przekazywanie encji, generalnie osobny kontener i środowisko to must have
Tak — w takim przypadku zdecydowanie wybrałbym osobny kontener z usługą w Rust, a integrację Home Assistant potraktowałbym wyłącznie jako cienkiego klienta. To daje nam izolację, własny lifecycle i możliwość rozwijania całego systemu niezależnie od HA.
Najważniejsze jest tylko dobre rozwiązanie kwestii encji.
Docelowa architektura
┌─────────────────────────────┐
│ HOME ASSISTANT │
│ │
│ climate.gree_salon │
│ sensor.gree_salon_temp │
│ sensor.gree_salon_humidity │
│ switch.gree_salon_turbo │
│ ... │
└──────────────┬──────────────┘
│
Custom Integration
│
WebSocket + REST
│
┌──────────────▼──────────────┐
│ GREE CONTROLLER │
│ │
│ Rust │
│ │
│ ┌───────────────────────┐ │
│ │ GREE Protocol │ │
│ │ UDP / AES / discovery │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ Device Manager │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ Automation Engine │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ Heating Manager │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ REST API │ │
│ │ WebSocket │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ Web UI │ │
│ └───────────────────────┘ │
└──────────────┬──────────────┘
│
LAN / VLAN
│
┌───────────────────┼───────────────────┐
│ │ │
GREE #1 GREE #2 GREE #3
Kontener
Ja bym zrobił:
LXC
└── gree-controller
├── gree-controller
├── gree.db
└── config/
albo Docker/Podman, jeżeli później będziesz chciał łatwo przenosić usługę.
Rust + jeden binarny executable jest tutaj bardzo dobrym rozwiązaniem.
Encje HA
Nie przekazywałbym encji z kontenera bezpośrednio.
To znaczy controller nie powinien próbować udawać Home Assistanta.
Zamiast tego:
GREE Controller
│
│ API
▼
HA Custom Integration
│
▼
HA Entity Registry
│
├── climate
├── sensor
├── switch
├── binary_sensor
└── number
Czyli:
Rust zarządza urządzeniem, HA zarządza encją.
To jest bardzo ważne rozdzielenie odpowiedzialności.
Jak będzie wyglądała komunikacja
Najlepiej zrobić WebSocket jako kanał realtime, a REST jako konfigurację/command API.
REST
GET /api/v1/devices
GET /api/v1/devices/{id}
GET /api/v1/devices/{id}/state
POST /api/v1/devices/{id}/commands
GET /api/v1/zones
GET /api/v1/automations
POST /api/v1/automations
GET /api/v1/history
WebSocket
WS /api/v1/events
Controller wysyła:
{
"event": "device_state",
"device_id": "gree-salon",
"state": {
"power": true,
"mode": "heat",
"temperature": 21.4,
"target_temperature": 21.0,
"fan": "auto"
}
}
HA dostaje to natychmiast.
Co z komendami?
HA:
climate.set_temperature
↓
Custom integration:
POST /api/v1/devices/gree-salon/commands
↓
Rust:
Command::SetTemperature(21.0)
↓
GREE UDP
↓
odpowiedź
↓
Rust aktualizuje stan
↓
WebSocket
↓
HA
I wtedy HA nie musi samodzielnie rozmawiać z GREE.
Ale zrobiłbym jeszcze jedną rzecz
Stan powinien być przechowywany w controllerze.
Czyli jeśli HA się zrestartuje:
HA
↓
restart
↓
integration connects
↓
GET /api/v1/devices
↓
GET current state
i natychmiast odtwarza encje.
A nie:
HA restart
↓
czekamy aż GREE odpowie
↓
discovery
↓
bind
↓
state
Controller już wie:
GREE Salon
last_state
last_seen
capabilities
configuration
Discovery HA
Custom integration może działać bardzo elegancko.
Po instalacji:
Settings
→ Devices & services
→ Add integration
→ GREE Controller
Podajesz:
Host:
192.168.1.20
Port:
8765
Integration robi:
GET /api/v1/info
i:
GET /api/v1/devices
Dostaje:
{
"devices": [
{
"id": "gree-salon",
"name": "Salon",
"type": "air_conditioner",
"capabilities": [
"heat",
"cool",
"dry",
"fan",
"swing",
"turbo"
]
}
]
}
I tworzy encje.
Co daje nam osobny Rust?
Ogromnie dużo.
1. HA nie musi znać protokołu GREE
Jeżeli GREE zmieni:
AES
UDP
bind
discovery
packet format
aktualizujemy controller.
HA integration pozostaje praktycznie bez zmian.
2. Możemy mieć własny Web UI
I to będzie pełnoprawny panel, nie dodatek do HA.
Np.:
Dashboard
┌───────────────────────────────────────────────┐
│ GREE CONTROLLER │
│ │
│ 3 devices 3 online 0 errors │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ SALON │ │ SYPIALNIA │ │
│ │ │ │ │ │
│ │ 21.4°C │ │ 20.1°C │ │
│ │ → 21.0°C │ │ → 19.0°C │ │
│ │ │ │ │ │
│ │ HEAT │ │ HEAT │ │
│ └──────────────┘ └──────────────┘ │
└───────────────────────────────────────────────┘
3. Automatyzacje nie muszą zależeć od HA
I to jest moim zdaniem najciekawsza rzecz.
Możemy zrobić:
GREE Controller
│
├── automation engine
│
├── heating engine
│
├── scheduler
│
└── HA integration
Czyli np. ogrzewanie działa nawet kiedy HA jest wyłączony.
Ale wtedy potrzebujemy integracji z HA także w drugą stronę
To znaczy Rust może potrzebować informacji z HA:
temperatura z czujnika
obecność
otwarte okno
temperatura zewnętrzna
tryb domu
Nie robiłbym jednak bezpośredniego dostępu Rust → HA API jako podstawowej architektury.
Lepiej:
HA
│
│ WebSocket/API
▼
GREE Integration
│
▼
Rust Controller
Integracja może opcjonalnie przekazywać do controllera wybrane encje HA.
Na przykład:
External sensors
Outdoor temperature
→ sensor.outdoor_temperature
Living room temperature
→ sensor.living_room_temperature
Presence
→ binary_sensor.home_occupied
Controller może wtedy używać ich w automatyzacjach.
Strefy ogrzewania
Wtedy możemy zrobić coś znacznie bardziej zaawansowanego.
Heating
│
├── Zone: Salon
│ ├── GREE Salon
│ ├── temperature sensor
│ └── schedule
│
├── Zone: Sypialnia
│ ├── GREE Sypialnia
│ └── temperature sensor
│
└── Zone: Biuro
├── GREE Biuro
└── temperature sensor
I każda strefa ma:
Comfort: 21.5°C
Night: 19°C
Away: 17°C
Frost protect: 10°C
Schedule:
06:00 → Comfort
08:30 → Away
16:00 → Comfort
23:00 → Night
Technologia
Ja bym poszedł w:
Rust
├── tokio
├── axum
├── serde
├── serde_json
├── sqlx
├── SQLite
├── tracing
├── tower
└── tokio-tungstenite / axum WebSocket
Frontend:
React / TypeScript
albo, jeśli chcemy maksymalnie ograniczyć zasoby:
Leptos
Ale tutaj nie komplikowałbym pierwszej wersji. Rust backend + lekki frontend będzie rozsądniejszy.
SQLite
Na początek:
gree.db
z tabelami mniej więcej:
devices
device_capabilities
device_state
device_history
zones
zone_devices
zone_sensors
automations
automation_conditions
automation_actions
schedules
settings
Bez PostgreSQL.
To będzie jedna usługa na jednym LXC, więc SQLite jest idealny.
I jeszcze jedna decyzja architektoniczna
Nie robiłbym:
Rust
└── web server
└── GREE protocol
jako jednego wielkiego modułu.
Tylko:
src/
├── main.rs
│
├── api/
│ ├── rest.rs
│ ├── websocket.rs
│ └── auth.rs
│
├── gree/
│ ├── protocol.rs
│ ├── crypto.rs
│ ├── discovery.rs
│ ├── device.rs
│ ├── commands.rs
│ └── state.rs
│
├── devices/
│ ├── manager.rs
│ ├── capabilities.rs
│ └── registry.rs
│
├── automation/
│ ├── engine.rs
│ ├── conditions.rs
│ └── actions.rs
│
├── heating/
│ ├── controller.rs
│ ├── zones.rs
│ ├── hysteresis.rs
│ └── prediction.rs
│
├── scheduler/
│
├── database/
│
└── events/
To pozwoli nam później rozwijać projekt bez robienia spaghetti.
Moim zdaniem docelowo powinno to wyglądać tak
┌────────────────────────────┐
│ HOME ASSISTANT │
│ │
│ Native HA entities │
│ │
│ GREE custom integration │
└─────────────┬──────────────┘
│
REST + WebSocket
│
┌─────────────▼──────────────┐
│ GREE CONTROLLER │
│ │
│ RUST │
│ │
│ ┌────────────────────────┐ │
│ │ GREE protocol │ │
│ ├────────────────────────┤ │
│ │ Device manager │ │
│ ├────────────────────────┤ │
│ │ State engine │ │
│ ├────────────────────────┤ │
│ │ Automation engine │ │
│ ├────────────────────────┤ │
│ │ Heating engine │ │
│ ├────────────────────────┤ │
│ │ Scheduler │ │
│ ├────────────────────────┤ │
│ │ SQLite │ │
│ └────────────────────────┘ │
│ │
│ Web UI │
└─────────────┬──────────────┘
│
UDP / 7000
│
┌─────────────┼──────────────┐
▼ ▼ ▼
GREE GREE GREE
To jest architektura, którą bym przyjął. Kontener/LXC jest niezależnym, autonomicznym serwisem, a HA dostaje normalne, natywne encje przez custom integration. Dzięki temu nawet całkowite wyłączenie HA nie zabija automatyki ogrzewania.
Następny krok zrobiłbym już praktycznie: ustalić dokładnie protokół GREE/EWPE dla obecnych dongli, wybrać Rust crate/implementację jako punkt startowy i zaprojektować v1 API + model encji HA, zanim zaczniemy pisać właściwy kod.
I jako dodatek do odczytu temperatur i lepsze odczyty jako opcja dodatkowa odczyt z api homeassistant zewnętrznego czujnika temperatury w pokoju z api homeassistant ale nie jako główne zrodlo informacji tylko jako opcja dodatkowa żeby wspomóc algorytm, zrób takamspecyfikacje uniezależnij to Dodatkowo interfejs musi być napełni kompatybilny z komórek bo to będzie główne miejsce sterowania, zastanawiam się na tailwind css z trybem ciemnym / jasnym Zrób takamspecyfikaje z tym co proponowałeś
Tak. W tej wersji zrobiłbym z tego całkowicie niezależny kontroler GREE, a Home Assistant byłby tylko jednym z możliwych źródeł danych i odbiorcą encji. Szczególnie ważne jest rozdzielenie temperatury zmierzonej przez klimatyzator, temperatury z zewnętrznego sensora HA oraz temperatury używanej przez algorytm sterowania.
Poniżej specyfikacja, którą można potraktować jako bazę projektu.
Specyfikacja GREE Controller
1. Cel projektu
Samodzielna aplikacja działająca w osobnym środowisku:
- Rust
- LXC / kontener
- własny backend
- własna baza danych
- własny interfejs WWW
- komunikacja lokalna z klimatyzatorami GREE
- REST API
- WebSocket
- opcjonalna integracja z Home Assistant
- natywne encje Home Assistant
- własny silnik automatyzacji
- własny silnik sterowania ogrzewaniem/chłodzeniem
- obsługa zewnętrznych czujników temperatury
Home Assistant nie jest wymagany do działania podstawowych funkcji systemu.
2. Zasada nadrzędna
Architektura ma być HA-independent.
┌──────────────────────┐
│ GREE Controller │
│ │
│ Rust │
│ │
│ GREE protocol │
│ State engine │
│ Heating engine │
│ Automation engine │
│ Scheduler │
│ Web UI │
│ Database │
└──────────┬───────────┘
│
┌─────────────┴──────────────┐
│ │
GREE AC Home Assistant
│ │
│ Custom Integration
│ │
│ Entities / sensors
HA jest integracją z kontrolerem, a nie jego fundamentem.
3. Źródła temperatury
To będzie jeden z najważniejszych elementów projektu.
Każda strefa może mieć kilka źródeł temperatury.
Źródło 1 — temperatura GREE
Podstawowe:
GREE internal temperature
np.
21.7°C
To jest temperatura raportowana przez klimatyzator.
Źródło 2 — zewnętrzny sensor
Opcjonalnie:
Home Assistant
↓
REST API / WebSocket
↓
GREE Controller
↓
external temperature
Przykład:
sensor.salon_temperature
Controller może cyklicznie pobierać:
21.2°C
ale nie traktuje tego automatycznie jako zamiennika temperatury GREE.
Źródło 3 — temperatura obliczona
Najważniejsze:
CONTROL TEMPERATURE
czyli temperatura, którą faktycznie wykorzystuje algorytm.
Przykładowo:
GREE:
21.7°C
External:
21.2°C
Control:
21.4°C
Algorytm może korzystać z:
control_temperature =
weighted_average(
gree_temperature,
external_temperature
)
albo:
control_temperature =
external_temperature
jeżeli użytkownik jawnie tak skonfiguruje.
4. Konfiguracja źródła temperatury
W UI:
Temperature source
○ GREE internal sensor
○ External Home Assistant sensor
● Combined
GREE weight: 40%
External weight: 60%
External sensor:
sensor.salon_temperature
Dodatkowo:
Maximum allowed difference:
3.0°C
Jeżeli:
GREE = 21°C
External = 26°C
system nie powinien bezwarunkowo przyjąć 26°C.
Generuje:
Temperature sensor discrepancy
i może automatycznie przejść na GREE.
5. Confidence / jakość pomiaru
Każdy pomiar powinien mieć metadane:
temperature
timestamp
source
age
quality
Przykład:
External sensor
Temperature: 21.3°C
Age: 4 sec
Quality: 100%
Jeżeli HA przestanie odpowiadać:
Age: 83 sec
Quality: 20%
Po przekroczeniu timeoutu:
External sensor:
UNAVAILABLE
i system automatycznie korzysta z GREE.
To jest bardzo ważne dla niezależności.
6. Algorytm sterowania
Nie robimy prostego:
if temp < target:
heat()
tylko warstwę kontrolną.
Sensors
↓
Sensor validation
↓
Temperature estimator
↓
Target temperature
↓
Heating/Cooling controller
↓
Safety limits
↓
GREE command
7. Target temperature
Temperatura docelowa może wynikać z:
Manual
Schedule
Night
Away
Presence
External temperature
Automation
Heating zone
Przykład:
23:00
Night profile
↓
19°C
06:00
Morning
↓
21°C
08:30
Away
↓
17°C
16:00
Home
↓
21°C
8. Histereza
Konfigurowalna:
Target: 21°C
Hysteresis: 0.4°C
czyli:
< 20.6°C → HEAT
20.6–21.4°C → maintain
> 21.4°C → STOP
Dodatkowo:
Minimum ON time
Minimum OFF time
Minimum command interval
Maximum commands/hour
9. Inteligentne ogrzewanie
System powinien opcjonalnie analizować:
temperature history
target history
heating state
outside temperature
time
heating rate
i obliczać:
temperature change/hour
Przykład:
19:00 19.4°C
19:15 19.8°C
19:30 20.2°C
19:45 20.6°C
System:
Heating rate ≈ 1.6°C/hour
Może więc przewidzieć:
Target 21°C
ETA ≈ 15 min
W kolejnej wersji można dodać predykcję rozpoczęcia ogrzewania.
10. Strefy
Klimatyzator nie musi być bezpośrednio jednostką sterowania.
Tworzymy:
Zone
np.
Salon
która posiada:
Devices:
GREE Salon
Temperature sources:
GREE
sensor.salon_temperature
Target:
21°C
Schedule:
Salon schedule
Control:
Intelligent heating
Dzięki temu później można mieć:
Salon
├── GREE
├── Xiaomi temperature sensor
└── window sensor
Sypialnia
├── GREE
└── temperature sensor
11. Home Assistant jako opcjonalne źródło danych
Controller posiada moduł:
home_assistant/
który jest opcjonalny.
Konfiguracja:
Home Assistant integration
Enabled: YES
URL:
http://homeassistant:8123
Token:
************
Poll interval:
10 sec
Możemy pobierać:
sensor.*
binary_sensor.*
input_boolean.*
input_number.*
ale użytkownik wskazuje konkretne encje.
Np.:
External temperature:
HA entity:
sensor.salon_temperature
Nie robimy automatycznego pobierania całego HA.
12. HA nie może być wymaganiem
Jeżeli:
HA DOWN
system nadal:
- steruje GREE
- wykonuje harmonogram
- wykonuje automatyzacje lokalne
- używa temperatury GREE
- działa przez Web UI
- przechowuje historię
Jedynie:
External HA sensors
stają się niedostępne.
13. Integracja Home Assistant
Po stronie HA:
GREE Controller
↓
Custom Integration
↓
Device
↓
Entities
Dla klimatyzatora:
climate.gree_salon
oraz np.:
sensor.gree_salon_temperature
sensor.gree_salon_target_temperature
sensor.gree_salon_power
sensor.gree_salon_connection
sensor.gree_salon_fan
14. Encja Climate
Powinna być maksymalnie kompatybilna z natywnym HA.
Obsługa:
OFF
HEAT
COOL
AUTO
DRY
FAN_ONLY
oraz:
target temperature
fan mode
preset mode
swing
15. Dodatkowe encje
W zależności od capabilities urządzenia:
switch.gree_salon_turbo
switch.gree_salon_quiet
switch.gree_salon_sleep
switch.gree_salon_light
switch.gree_salon_xfan
oraz:
sensor.gree_salon_temperature
sensor.gree_salon_humidity
sensor.gree_salon_power
sensor.gree_salon_signal
Nie tworzymy encji dla funkcji, których konkretna jednostka nie obsługuje.
16. Web UI — bardzo ważne
Ponieważ telefon będzie głównym sposobem obsługi, projektujemy UI mobile-first, a nie desktop-first.
Technologia:
Tailwind CSS
z:
Dark mode
Light mode
System mode
czyli:
Appearance
● System
○ Dark
○ Light
17. Mobile UI
Na telefonie dashboard:
┌────────────────────────┐
│ GREE Controller ☰ │
├────────────────────────┤
│ │
│ SALON │
│ │
│ 21.4°C │
│ │
│ Target 21°C │
│ │
│ 🔥 HEATING │
│ │
│ − 21°C + │
│ │
│ HEAT AUTO │
│ │
│ ────────────────────── │
│ │
│ Fan Auto │
│ Swing Auto │
│ │
│ Turbo ○ │
│ Quiet ● │
│ Sleep ○ │
│ │
└────────────────────────┘
Bez mikroskopijnych przycisków.
Minimalny rozmiar interaktywnych elementów powinien być około:
44 × 44 px
18. Mobile navigation
Dolny pasek:
┌────────────────────────┐
│ │
│ CONTENT │
│ │
├────────────────────────┤
│ 🏠 🌡 ⚙ │
│ Home Zones More │
└────────────────────────┘
Na desktopie może przełączać się w sidebar.
19. Dashboard
Główne widoki:
Dashboard
Devices
Zones
Heating
Automations
Schedules
History
Diagnostics
Settings
20. Automatyzacje
GUI:
WHEN
Temperature
[ Salon ]
[ < ]
[ 20°C ]
AND
Time
[ 06:00 - 22:00 ]
THEN
Climate
[ Salon ]
Mode:
[ HEAT ]
Target:
[ 21°C ]
Ale silnik jest w Rust.
HA nie jest potrzebny.
21. WebSocket
Frontend nie powinien wykonywać ciągłego:
GET /state
GET /state
GET /state
Tylko:
Browser
│
│ WebSocket
▼
Rust
│
▼
Event stream
Przykładowo:
device_state_changed
temperature_changed
device_online
device_offline
automation_triggered
heating_state_changed
Dzięki temu UI będzie faktycznie „live”.
22. API
REST:
/api/v1/system
/api/v1/devices
/api/v1/devices/{id}
/api/v1/devices/{id}/state
/api/v1/devices/{id}/commands
/api/v1/zones
/api/v1/zones/{id}
/api/v1/automations
/api/v1/schedules
/api/v1/sensors
/api/v1/history
/api/v1/ha
WebSocket:
/api/v1/ws
23. Authentication
Ponieważ będzie to osobny host, od początku robimy:
API authentication
np.:
Bearer token
oraz osobne konto dla Web UI.
W przyszłości:
OIDC
ale nie jest potrzebne w v1.
24. GREE Protocol Layer
Cały protokół izolujemy:
gree/
├── discovery.rs
├── protocol.rs
├── crypto.rs
├── packet.rs
├── bind.rs
├── commands.rs
├── state.rs
└── capabilities.rs
Dzięki temu reszta programu nie wie, że pod spodem jest GREE.
To pozwoli kiedyś potencjalnie dodać:
gree/
haier/
midea/
bez przebudowy całego systemu.
25. Model urządzenia
Device
├── id
├── name
├── ip
├── mac
├── model
├── firmware
├── protocol
├── capabilities
├── state
├── last_seen
└── availability
26. Stan urządzenia
DeviceState
├── power
├── mode
├── target_temperature
├── room_temperature
├── humidity
├── fan_mode
├── swing_vertical
├── swing_horizontal
├── preset
├── turbo
├── quiet
└── ...
Nie zakładamy, że każde GREE ma wszystkie pola.
27. Capability discovery
Po wykryciu urządzenia controller określa:
supports_heat
supports_cool
supports_dry
supports_fan
supports_turbo
supports_quiet
supports_swing
supports_humidity
...
Frontend oraz HA integration korzystają z capabilities.
28. Baza
Na początek:
SQLite
devices
device_capabilities
device_state
temperature_history
events
zones
zone_devices
zone_sensors
automations
automation_conditions
automation_actions
schedules
ha_connections
ha_entities
settings
Bez zewnętrznego PostgreSQL.
29. Historia
Zapisywane:
temperature
target
mode
power
fan
heating state
source temperature
Dzięki temu UI może pokazać:
Temperature
22°C ┤ ╭──────
21°C ┤ ──────╯
20°C ┤
└────────────────
oraz:
GREE: 21.7°C
External: 21.2°C
Control: 21.4°C
To ostatnie jest szczególnie istotne diagnostycznie.
30. Diagnostics
Każdy GREE:
Status: ONLINE
IP:
192.168.x.x
Last seen:
1.2 sec ago
Latency:
12 ms
Packets:
12342
Errors:
0
Last error:
None
Możliwość:
[ Ping ]
[ Refresh state ]
[ Rediscover ]
[ Rebind ]
31. Kontener
Docelowo:
LXC
└── Debian
└── gree-controller
├── /usr/bin/gree-controller
├── /etc/gree-controller/
└── /var/lib/gree-controller/
└── gree.db
Service:
systemd
czyli:
gree-controller.service
Nie potrzebujemy Dockera.
32. Aktualizacja
Rust daje nam prosty model:
binary
+
database migrations
Możemy później zrobić:
v0.1
v0.2
v0.3
...
z migracjami SQLite.
33. Struktura projektu
Docelowo:
gree-controller/
│
├── Cargo.toml
│
├── crates/
│ ├── gree-protocol/
│ ├── gree-core/
│ ├── gree-api/
│ └── gree-ha/
│
├── backend/
│ └── src/
│
├── frontend/
│ ├── src/
│ ├── public/
│ └── ...
│
├── ha-integration/
│ └── custom_components/
│ └── gree_controller/
│
├── migrations/
│
├── packaging/
│ ├── systemd/
│ └── debian/
│
└── README.md
Przy większym projekcie podział na Cargo workspace będzie bardzo wygodny.
34. Najważniejsza zasada dotycząca HA
Nie kopiujemy logiki między Rust i HA.
Nie:
HA heating logic
+
Rust heating logic
Tylko:
Rust Controller
│
┌─────────────┴──────────────┐
│ │
heating engine automation engine
│ │
└─────────────┬──────────────┘
│
Controller API
│
Home Assistant
│
Entities
HA pokazuje i steruje.
Rust podejmuje decyzje.
35. Kolejność implementacji
Nie zaczynałbym od GUI.
Faza 1 — GREE protocol
[ ] discovery
[ ] bind
[ ] encryption
[ ] status
[ ] commands
[ ] capabilities
[ ] reconnect
Faza 2 — Core
[ ] Device Manager
[ ] State Manager
[ ] event system
[ ] SQLite
[ ] configuration
Faza 3 — API
[ ] REST
[ ] WebSocket
[ ] authentication
Faza 4 — Web UI
[ ] Tailwind
[ ] dark/light
[ ] mobile-first
[ ] dashboard
[ ] devices
[ ] zones
[ ] history
[ ] diagnostics
Faza 5 — Heating Engine
[ ] target
[ ] schedules
[ ] hysteresis
[ ] minimum run time
[ ] sensor weighting
[ ] sensor fallback
[ ] heating zones
[ ] prediction
Faza 6 — Automations
[ ] triggers
[ ] conditions
[ ] actions
[ ] scheduler
[ ] GUI builder
Faza 7 — Home Assistant
[ ] config flow
[ ] device discovery
[ ] climate
[ ] sensors
[ ] switches
[ ] diagnostics
[ ] external HA sensors
Jedna rzecz, którą zmieniłbym względem pierwotnego pomysłu
Nie nazywałbym tego nawet wewnętrznie „integracją GREE do Home Assistant”.
To powinien być samodzielny GREE Controller, a Home Assistant będzie jednym z klientów.
Wtedy mamy:
GREE Controller
/ | \
/ | \
▼ ▼ ▼
Web UI HA REST API
│
HA entities
I dokładnie spełniamy Twój warunek:
osobne środowisko jest obowiązkowe, HA nie jest wymagane do działania, zewnętrzny czujnik HA jest tylko opcjonalnym źródłem wspomagającym algorytm, a użytkownik może praktycznie całe sterowanie wykonywać z telefonu przez responsywny UI.
Tailwind + dark/light + mobile-first jest tutaj bardzo dobrym wyborem. Zrobiłbym nawet projekt UI od początku z założeniem „telefon jako primary, desktop jako secondary”, zamiast później próbować dopasowywać desktopowy panel do telefonu.