feat(hardware): ESPHome Gree IR blaster (Wemos D1 Mini + Grove IR)

Native ESPHome gree climate component over the API, no MQTT/Broadlink/Tuya.
HA on piha runs as a plain Docker container (not HAOS), so ESPHome is a
manual docker compose run --rm invocation, not a managed service — device
is deliberately not registered in hosts/piha/services.yaml.
This commit is contained in:
oskar 2026-07-17 15:05:03 +02:00
parent 4bfd6c4429
commit 423f871486
6 changed files with 162 additions and 0 deletions

4
.gitignore vendored
View file

@ -3,6 +3,10 @@
*.env *.env
!*.env.example !*.env.example
# ESPHome secrets
secrets.yaml
!secrets.yaml.example
# IDE artifacts # IDE artifacts
.idea/ .idea/
.vscode/ .vscode/

View file

@ -0,0 +1,87 @@
# Gree IR Blaster
ESPHome firmware for a Wemos D1 Mini (ESP8266) driving a Gree air conditioner
over IR, exposed to Home Assistant via the native ESPHome API (no MQTT, no
Broadlink, no Tuya).
## Hardware
- Wemos D1 Mini (ESP8266)
- Grove IR Emitter
- Grove IR Receiver
### Wiring
| Grove module | Pin | Wemos D1 Mini |
|---|---|---|
| IR Emitter | SIG | D5 |
| IR Emitter | VCC | 5V |
| IR Emitter | GND | GND |
| IR Receiver | SIG | D6 |
| IR Receiver | VCC | **3V3** — not 5V, ESP8266 GPIO is not 5V-tolerant |
| IR Receiver | GND | GND |
## Home Assistant / deployment model
HA on piha runs as the `home-assistant:stable` Docker container, not HAOS, so
ESPHome is **not** installed as an add-on. It runs as a one-off container via
`docker compose run --rm` — there is no ESPHome daemon on piha. Compile/flash
is a manual, operator-triggered action; this device is intentionally **not**
registered in `hosts/piha/services.yaml`.
Once flashed, the device advertises itself via mDNS and shows up as a
discoverable ESPHome device in Home Assistant (Settings → Devices & Services
→ Add Integration → ESPHome).
## First flash (USB)
1. Copy `secrets.yaml.example` to `secrets.yaml` and fill in `wifi_ssid`,
`wifi_password`, `fallback_password`.
2. Wire the board as above and plug it into piha via USB.
3. Run:
```
./deploy.sh --usb
```
This flashes over `/dev/ttyUSB0`.
## Subsequent flashes (OTA)
Once the device is on WiFi, redeploy without `--usb`:
```
./deploy.sh
```
This runs `docker compose run --rm esphome run gree-ir-blaster.yaml`, which
flashes over the network via the ESPHome OTA protocol.
## Identifying the Gree protocol variant
The `climate: platform: gree` component needs a `model:` matching your AC's
remote protocol. `gree-ir-blaster.yaml` currently ships with `model: yan` as
a starting guess — this is **not verified** and must be confirmed against the
actual remote.
To identify the correct variant:
1. Flash the firmware and let the device boot (WiFi connected).
2. Tail the logs:
```
docker compose run --rm esphome logs gree-ir-blaster.yaml
```
3. Point the physical Gree remote at the Grove IR Receiver and press a button
(e.g. power on, or change temperature). `dump: all` on `remote_receiver`
causes ESPHome to log the raw/decoded IR data it captured.
4. Compare the decoded output against the known Gree variants supported by
ESPHome and pick the closest match:
- `generic`
- `yan`
- `yaa`
- `yac`
- `yac1fb9`
- `yx1ff`
- `yag`
5. Update `model:` in `gree-ir-blaster.yaml` to the matching variant, then
redeploy (`./deploy.sh`) and verify the AC responds correctly to commands
sent from Home Assistant (power, mode, temperature, fan speed).
If none of the variants behave correctly, capture the raw IR dumps and check
the ESPHome `gree` component issue tracker / docs for newer variants.

View file

@ -0,0 +1,28 @@
#!/bin/bash
set -e
# Manual deploy only — this device is not managed via hosts/piha/services.yaml.
# Run by hand on piha after wiring the board.
cd "$(dirname "$0")"
if [ ! -f secrets.yaml ]; then
echo "ERROR: secrets.yaml missing. Copy secrets.yaml.example to secrets.yaml and fill in wifi_ssid/wifi_password/fallback_password." >&2
exit 1
fi
USB=false
if [ "$1" = "--usb" ]; then
USB=true
fi
if [ "$USB" = true ]; then
if [ ! -e /dev/ttyUSB0 ]; then
echo "ERROR: /dev/ttyUSB0 not found. Plug in the board via USB for the first flash." >&2
exit 1
fi
echo ">>> First flash over USB (/dev/ttyUSB0)..."
docker compose run --rm --device /dev/ttyUSB0 esphome run gree-ir-blaster.yaml --device /dev/ttyUSB0
else
echo ">>> OTA flash over WiFi..."
docker compose run --rm esphome run gree-ir-blaster.yaml
fi

View file

@ -0,0 +1,7 @@
# Not a daemon — no `up -d`. ESPHome compiles/flashes and exits.
# Invoke via deploy.sh, which wraps `docker compose run --rm esphome ...`.
services:
esphome:
image: ghcr.io/esphome/esphome:stable
volumes:
- .:/config

View file

@ -0,0 +1,31 @@
esphome:
name: gree-ir-blaster
friendly_name: Gree IR Blaster
esp8266:
board: d1_mini
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Gree-IR Fallback"
password: !secret fallback_password
logger:
api:
ota:
platform: esphome
remote_transmitter:
pin: D5
carrier_duty_percent: 50%
remote_receiver:
pin:
number: D6
inverted: true
mode:
input: true
pullup: true
dump: all
climate:
- platform: gree
name: "Klimatyzacja"
id: gree_ac
model: yan

View file

@ -0,0 +1,5 @@
# Copy to secrets.yaml and fill in real values. secrets.yaml is gitignored —
# never commit it. Filled in manually on piha.
wifi_ssid: "your-wifi-ssid"
wifi_password: "your-wifi-password"
fallback_password: "your-fallback-ap-password"