Files
gree-controller/docs/API.md
T
2026-08-23 23:32:26 +02:00

6.4 KiB

API examples

TOKEN is optional when GREE_CONTROLLER_APP_TOKEN is empty.

AUTH='Authorization: Bearer TOKEN'
BASE='http://127.0.0.1:8787'

Home Assistant access tokens

Create and revoke integration tokens from the controller Web UI under Settings -> Home Assistant integration access. The clear-text secret is returned only once and the SQLite database stores only its SHA-256 hash.

Administrator endpoints:

GET    /api/access-tokens
POST   /api/access-tokens
DELETE /api/access-tokens/{id}

The Home Assistant custom integration uses a restricted API surface:

GET    /api/integrations/home-assistant/devices
POST   /api/integrations/home-assistant/devices/{id}/command

These two endpoints always require Authorization: Bearer <generated-token> (or the administrator GREE_CONTROLLER_APP_TOKEN). A generated HA token cannot update settings, run discovery, delete devices, manage tokens, or use the controller WebSocket.

Discovery

curl -X POST "$BASE/api/discovery" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"timeout_ms":6000,"broadcast":"255.255.255.255:7000","protocol_version":0,"passes":3}'

protocol_version is 0 for auto/both, 1 for AES-ECB only, and 2 for AES-GCM only. passes is 1..10. Auto is recommended when different GREE Wi-Fi module generations share the network.

Device command

{
  "power": true,
  "mode": "cool",
  "target_temperature": 22.0,
  "fan_speed": 3,
  "swing_vertical": true,
  "quiet": false,
  "turbo": false,
  "light": true
}

Supported modes: auto, cool, dry, fan, heat. Fan speed: 0..5. Physical GREE Celsius setpoints are normalized to whole degrees in the 8..30°C range.

Smart thermostat / house control

The controller separates the seasonal house mode from per-zone profiles. Normal operation uses setpoint modulation: units remain powered while the controller moves the device target between an active and satisfied setpoint. off is the explicit hard-off house mode.

curl -X POST "$BASE/api/house/control" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"mode":"cool"}'

curl -X POST "$BASE/api/house/preset" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"preset":"sleep"}'

House modes: cool, heat, off. House presets: auto, comfort, sleep, away. A non-auto house preset creates temporary per-zone overrides that expire at each zone's next schedule boundary.

A zone stores separate profile temperatures for both seasons:

{
  "name": "Paweł",
  "device_id": "gree-aabbccddeeff",
  "enabled": true,
  "mode": "cool",
  "inherit_house_mode": true,
  "setpoint": 23.0,
  "cool_comfort_setpoint": 23.0,
  "cool_sleep_setpoint": 24.5,
  "cool_away_setpoint": 27.0,
  "heat_comfort_setpoint": 21.0,
  "heat_sleep_setpoint": 19.0,
  "heat_away_setpoint": 17.0,
  "hysteresis": 0.6,
  "min_adjust_seconds": 120,
  "standby_offset_c": 2.0,
  "smart_fan": true,
  "sensor_source": "combined",
  "ha_entity_id": "sensor.pawel_temperature",
  "external_sensor_weight": 0.4,
  "max_sensor_difference": 3.0
}

Quick control does not directly fight the schedule engine:

# Sleep now until the next schedule boundary
curl -X POST "$BASE/api/zones/ZONE_ID/control" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"preset":"sleep"}'

# Return to automatic schedule
curl -X POST "$BASE/api/zones/ZONE_ID/control" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"preset":"auto"}'

# Temporary custom room target
curl -X POST "$BASE/api/zones/ZONE_ID/control" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"setpoint":22.5}'

mode on the quick zone endpoint accepts house, cool, or heat. Global off always wins over local zone mode overrides.

Ready-made schedule templates

Templates generate normal schedule records and replace the current schedules for the selected zone. Every generated entry remains editable.

curl -X POST "$BASE/api/zones/ZONE_ID/schedule-template" -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{"template":"child"}'

Templates: family, child, bedroom, workday, always.

Schedules use a profile (comfort, sleep, away) or a custom temperature:

{
  "zone_id": "UUID",
  "name": "Sleep",
  "enabled": true,
  "weekdays": [1,2,3,4,5,6,7],
  "start_time": "20:30",
  "end_time": "06:30",
  "preset": "sleep",
  "setpoint": 24.0
}

For non-custom schedules, setpoint is only a compatibility value; the actual target comes from the zone's seasonal profile.

Home Assistant outdoor assist and local HTTPS

Runtime settings can specify home_assistant.outdoor_entity_id and outdoor_assist_enabled. Outdoor temperature never replaces the zone room temperature. It is only used to make active setpoints/fan speed slightly more assertive in extreme weather.

For trusted local Home Assistant servers with self-signed/invalid HTTPS certificates, set:

{
  "home_assistant": {
    "url": "https://10.87.65.2",
    "allow_invalid_tls": true
  }
}

This setting is opt-in and applies only to the controller's outbound Home Assistant sensor client.

WebSocket

Connect to ws://HOST:8787/ws?token=TOKEN. The first message uses event type bootstrap; later events include device.updated, zone.updated, settings.updated and log.created.

Localization assets

Localization endpoints are public because the login dialog also needs translations. Language packs are embedded in the Rust binary at build time.

curl "$BASE/lang/index.json"
curl "$BASE/lang/en.json"

GET /lang/index.json returns the automatically generated language catalog. GET /lang/<code>.json returns the corresponding language pack. Add a valid lang/<code>.json file and rebuild to expose a new language.

GET /api/history

Returns rich per-zone climate history. Query parameters:

  • zone_id=<zone id> for one zone, or zone_id=all for all zones,
  • hours=6|24|168|720,
  • limit up to 20,000 rows.

Each row contains gree_temperature, external_temperature (HA room sensor), control_temperature, target_temperature, device_setpoint, outdoor_temperature, power, mode, fan_speed, demand, control_source, and active_preset.

The endpoint automatically downsamples in SQLite to keep charts responsive: 30-second buckets up to 6 hours, 2-minute buckets up to 24 hours, 10-minute buckets up to 7 days, and 30-minute buckets for longer ranges.