Encode and decode Gree air-conditioner IR remote control signals
Project description
gree-rc-encoder
Python library to encode and decode Gree air-conditioner IR remote-control signals (pulse timings ↔ high-level state).
- GitHub: https://github.com/ClusterM/gree-rc-encoder
- PyPI: https://pypi.org/project/gree-rc-encoder/
- License: GPLv3
Install
From PyPI:
pip install gree-rc-encoder
From a local checkout (editable, with test deps):
pip install -e ".[dev]"
Quick start
from gree_rc import (
GreeState,
Mode,
FanSpeed,
encode_control,
encode_temperature,
decode,
to_ir_ctl,
)
state = GreeState(
is_on=True,
mode=Mode.COOL,
temperature=24,
fan_speed=FanSpeed.AUTO,
light_on=True,
)
timings = encode_control(state) # list[int] durations in microseconds
print(to_ir_ctl(timings)) # "+9000 -4500 +655 ..." for ir-ctl
result = decode(timings)
assert result.state.temperature == 24
# I Feel: remote sensor reading (sent periodically while ifeel_mode is on)
temp_frame = encode_temperature(27)
assert decode(temp_frame).temperature == 27
API overview
| Function | Purpose |
|---|---|
encode_control(state) |
GreeState → 559 timing values |
decode_control(timings) |
timings / ir-ctl string → GreeState |
encode_temperature(temp) |
I Feel ambient °C (0–255) → 35 timing values |
decode_temperature(timings) |
→ int °C |
decode(timings) |
auto-detect control / temperature / combined → DecodeResult |
to_ir_ctl / from_ir_ctl |
convert to/from ir-ctl pulse strings |
encode_gree / parse_gree |
nibble-level frame without IR timings |
The library performs no I/O and does not print; raise GreeEncodeError,
GreeDecodeError, or GreeValidationError on failure.
GreeState fields
Fields marked model-dependent exist only on some units (the remote protocol
still carries the bits; unsupported hardware ignores them). Per the manual:
wifi_on / wifi_reset, cold_plasma, uvc_lamp, soft_sound, fast_cool,
start_auto_clean, fresh_air.
| Field | Meaning |
|---|---|
is_on |
Unit power on/off |
mode |
cool / dry / fan_only / heat / auto |
temperature |
Setpoint, 16–31.5 in 0.5 steps |
units |
"C" or "F" |
fan_speed |
auto, speed_1…speed_5, silent, turbo |
x_fan |
X-FAN: after off in Cool/Dry, indoor fan keeps running briefly to dry the evaporator. Not available in Auto/Fan/Heat. Defaults off after the unit is powered. |
cold_plasma |
Model-dependent. Cold Plasma health function. Requires is_on. |
uvc_lamp |
Model-dependent. UVC lamp health function. Requires is_on. Both may be on together. |
humidity_level_set |
Manual humidity control via the Humidity button (Cool/Dry only). |
humidity_level |
Target humidity % when set manually (None if unused). Cool: 40–80; Dry: 30–70; multiples of 5. |
humidity_level_auto |
Humidity button “auto” mode — meaning depends on mode: in Cool, smart dehumidification (Ao); in Dry, continuous dehumidification (Co). Mutually exclusive with humidity_level_set. |
vertical_swing_mode |
Vertical louvre: off, full swing, or fixed positions 1–5 |
horizontal_swing_mode |
Horizontal louvre: off, full/double swing, positions, or pos_1_5 |
swing_started |
Poorly understood (empirical). Changes when automatic movement of vertical or horizontal swing is turned on or off (louvre moving, not fixed). Value is the result of that last toggle: True ≈ some swing was started, False ≈ some swing was stopped. |
ifeel_mode |
I Feel: remote sends ambient-temperature frames from its built-in sensor (see Protocol notes). |
timer_set |
Timer armed (True iff timer_mode is not disabled) |
timer_mode |
disabled / off (turn off later) / on (turn on later) |
timer_hours_set |
Timer duration in hours (0.5 steps) |
timer_off_left_mins / timer_on_left_mins |
Remaining minutes for off/on timers (wire fields) |
wifi_on |
Model-dependent. Wi-Fi module enabled |
wifi_reset |
Model-dependent. One-shot: True only in a single frame; clears Wi-Fi settings so the network can be reconfigured |
soft_sound |
Model-dependent. Manual name: Volume control of IDU Buzzer — quieter indoor-unit beeps |
power_down_level |
Power limiting: 0 = off, 1 = level 1, 2 = level 2 (stricter than 1). Cleared when the remote turns the unit off. With two indoor units, the outdoor unit follows the stricter limit. Independent of energy_saving. |
energy_saving |
Energy-saving (SE on the remote): Cool only; requires fan_speed=auto and sleep_mode_level=0. The unit applies a factory energy-saving setpoint — the encoded temperature is still sent but ignored. Independent of power_down_level. |
light_on / light_auto |
Display light on; auto dimming (light_auto requires light_on) |
fresh_air |
Model-dependent. Manual name: two-way ventilation; fan speed follows the AC / fan button |
sleep_mode_level |
0 = cancel; 1/2 = preset sleep curves; 3 = DIY hourly schedule (see Protocol notes; schedule payload not fully implemented) |
display_indoor_temperature / display_indoor_humidity |
What the indoor display shows (mutually exclusive) |
reset_clean_reminder |
One-shot: toggle/reset the filter clean-reminder function |
fast_cool |
Model-dependent. Fast cool (Cool only): temporary 25°C or 16°C boost for ~20 minutes, then restore previous state |
start_auto_clean |
Model-dependent. One-shot: start auto clean; unit must be off |
Hardware demo
Real receive/transmit via ir-ctl lives in
examples/ir_ctl_demo.py:
python3 examples/ir_ctl_demo.py receive
python3 examples/ir_ctl_demo.py send --dry-run
python3 examples/ir_ctl_demo.py temperature --dry-run
Tests
pytest
Protocol notes
Control frame
A typical control frame is four subsignals (139 timings each) separated by
~40 ms spaces. Each subsignal carries 16 nibbles (LSB-first bits), a 0,1,0
delimiter with a 20 ms space in the middle, a marker nibble, and a CRC
nibble.
Markers identify the logical signal index (0..4). Captures may include more
than four subsignals and may list them in any order; the decoder places each
subsignal into a fixed 5-slot array by marker before parsing GreeState.
I Feel (ambient temperature)
When I Feel is enabled (GreeState.ifeel_mode), the remote periodically
sends a short 35-sample frame with a different leading pulse. That frame
carries the reading from the remote’s built-in temperature sensor so the
indoor unit can hold the setpoint at the remote’s location rather than only
at the AC.
Sleep mode level 3
sleep_mode_level values 1–2 are fixed sleep curves. Level 3 lets the
user program an automatic temperature change every hour for up to eight
hours. That schedule needs an extra subsignal (logical slot 4 / ~699-sample
capture). This library decodes the level flag and will accept/arrange the
extra subsignal by marker, but encoding and full parsing of the eight
hourly setpoints is not implemented yet.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gree_rc_encoder-0.1.2.tar.gz.
File metadata
- Download URL: gree_rc_encoder-0.1.2.tar.gz
- Upload date:
- Size: 34.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa917ce7609ea9e49d02fe1c99064d3232f9c6dff75ec7017093ebfdc2ed054a
|
|
| MD5 |
47a8529dade73d37bb4f8058d65da59e
|
|
| BLAKE2b-256 |
79055ba1c6bd56ba5bb4250ee9a711280e5e67189b974380d6a21165f2d5a281
|
File details
Details for the file gree_rc_encoder-0.1.2-py3-none-any.whl.
File metadata
- Download URL: gree_rc_encoder-0.1.2-py3-none-any.whl
- Upload date:
- Size: 32.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69553282823edd92d3c9d04034aea1d1283252970cb396f9e5117091fcd8e447
|
|
| MD5 |
280a7d14fc902675c12fd55e165e0d35
|
|
| BLAKE2b-256 |
8dceb76c627c3020305bbbf463bc376d7a6407bc08ab6f849e9366f0066944f2
|