From 423f871486f6aaca5823bb5ad5694227b15f67f1 Mon Sep 17 00:00:00 2001 From: oskar Date: Fri, 17 Jul 2026 15:05:03 +0200 Subject: [PATCH] feat(hardware): ESPHome Gree IR blaster (Wemos D1 Mini + Grove IR) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .gitignore | 4 + hardware/esp/ir-ac-ha-integration/README.md | 87 +++++++++++++++++++ hardware/esp/ir-ac-ha-integration/deploy.sh | 28 ++++++ .../ir-ac-ha-integration/docker-compose.yml | 7 ++ .../ir-ac-ha-integration/gree-ir-blaster.yaml | 31 +++++++ .../ir-ac-ha-integration/secrets.yaml.example | 5 ++ 6 files changed, 162 insertions(+) create mode 100644 hardware/esp/ir-ac-ha-integration/README.md create mode 100755 hardware/esp/ir-ac-ha-integration/deploy.sh create mode 100644 hardware/esp/ir-ac-ha-integration/docker-compose.yml create mode 100644 hardware/esp/ir-ac-ha-integration/gree-ir-blaster.yaml create mode 100644 hardware/esp/ir-ac-ha-integration/secrets.yaml.example diff --git a/.gitignore b/.gitignore index d839d11..2a6a877 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,10 @@ *.env !*.env.example +# ESPHome secrets +secrets.yaml +!secrets.yaml.example + # IDE artifacts .idea/ .vscode/ diff --git a/hardware/esp/ir-ac-ha-integration/README.md b/hardware/esp/ir-ac-ha-integration/README.md new file mode 100644 index 0000000..f6e4744 --- /dev/null +++ b/hardware/esp/ir-ac-ha-integration/README.md @@ -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. diff --git a/hardware/esp/ir-ac-ha-integration/deploy.sh b/hardware/esp/ir-ac-ha-integration/deploy.sh new file mode 100755 index 0000000..cc6ac96 --- /dev/null +++ b/hardware/esp/ir-ac-ha-integration/deploy.sh @@ -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 diff --git a/hardware/esp/ir-ac-ha-integration/docker-compose.yml b/hardware/esp/ir-ac-ha-integration/docker-compose.yml new file mode 100644 index 0000000..513ba9e --- /dev/null +++ b/hardware/esp/ir-ac-ha-integration/docker-compose.yml @@ -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 diff --git a/hardware/esp/ir-ac-ha-integration/gree-ir-blaster.yaml b/hardware/esp/ir-ac-ha-integration/gree-ir-blaster.yaml new file mode 100644 index 0000000..ac89f9a --- /dev/null +++ b/hardware/esp/ir-ac-ha-integration/gree-ir-blaster.yaml @@ -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 diff --git a/hardware/esp/ir-ac-ha-integration/secrets.yaml.example b/hardware/esp/ir-ac-ha-integration/secrets.yaml.example new file mode 100644 index 0000000..38b0bdf --- /dev/null +++ b/hardware/esp/ir-ac-ha-integration/secrets.yaml.example @@ -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"