This commit is contained in:
Mateusz Gruszczyński
2026-09-18 11:21:48 +02:00
parent 3ffb02595e
commit 8d96ad2d38
29 changed files with 758 additions and 256 deletions
+46 -17
View File
@@ -1,6 +1,6 @@
# GREE Controller API reference
HTTP and WebSocket API for GREE Controller **0.15.4**.
HTTP and WebSocket API for GREE Controller **0.15.6**.
[← Main documentation](../README.md)
@@ -132,7 +132,8 @@ Common statuses:
| Method | Endpoint | Description |
| --- | --- | --- |
| POST | `/api/discovery` | Discover/bind GREE devices. |
| POST | `/api/discovery/scan` | Scan for local GREE devices without adding them. |
| POST | `/api/discovery/add` | Add and bind selected scan results. |
| GET | `/api/devices` | List devices. |
| POST | `/api/devices` | Add a device manually. |
| GET | `/api/devices/{id}` | Read a device. |
@@ -240,7 +241,7 @@ Response:
{
"status": "ok",
"name": "gree-controller",
"version": "0.15.4",
"version": "0.15.6",
"uptime_seconds": 1234,
"control_ready": true,
"time": "2026-08-30T06:54:00Z"
@@ -303,7 +304,7 @@ Returns the initial Web UI snapshot:
"control_plan": {"generated_at": "2026-09-04T08:00:00Z", "zones": [], "rules": []},
"control_plan_revision": 42,
"system": {
"version": "0.15.4",
"version": "0.15.6",
"uptime_seconds": 1234,
"auth_required": false,
"control_ready": true,
@@ -374,9 +375,9 @@ A device response contains:
| `communication_failures` | integer | Consecutive/recorded communication failure counter. |
| `created_at`, `updated_at` | ISO-8601 | Resource timestamps. |
### `POST /api/discovery`
### `POST /api/discovery/scan`
Request body, all fields optional:
Scans without adding or binding anything. Request body fields are optional:
```json
{
@@ -387,23 +388,51 @@ Request body, all fields optional:
}
```
Rules:
`protocol_version` accepts `0` (auto/both), `1` (AES-ECB only) or `2` (AES-GCM only). Explicit V1/V2 selection rejects replies from the other protocol generation before decryption. The UDP scan packet itself is common to both generations.
- `timeout_ms`: effective range `500..30000` ms.
- `protocol_version`: `0` auto/both, `1` AES-ECB only, `2` AES-GCM only.
- `passes`: `1..10`.
- Missing values use runtime GREE settings.
Successful discovery merges known devices, tries binding devices that do not have a key, persists results and returns:
The response contains candidates with MAC, IP, detected protocol and an `already_added` flag:
```json
{
"count": 1,
"devices": [],
"new_device_ids": ["gree-aabbccddeeff"]
"devices": [
{
"name": "GREE EEFF",
"mac": "AABBCCDDEEFF",
"ip": "192.168.50.30",
"port": 7000,
"protocol_version": 1,
"model": "GREE",
"firmware": "",
"already_added": false
}
]
}
```
### `POST /api/discovery/add`
Add only selected candidates returned by `/api/discovery/scan`:
```json
{
"devices": [
{
"name": "Living room",
"mac": "AABBCCDDEEFF",
"ip": "192.168.50.30",
"port": 7000,
"protocol_version": 1,
"model": "GREE",
"firmware": "",
"already_added": false
}
]
}
```
Each selected candidate is bound strictly with its detected `protocol_version`. Existing MAC addresses are skipped.
### `GET /api/devices`
Returns `Device[]`.
@@ -1599,10 +1628,10 @@ BASE='http://127.0.0.1:8787'
AUTH='Authorization: Bearer APP_TOKEN'
```
Discover devices:
Scan local devices:
```bash
curl -X POST "$BASE/api/discovery" -H "$AUTH" -H 'Content-Type: application/json' \
curl -X POST "$BASE/api/discovery/scan" -H "$AUTH" -H 'Content-Type: application/json' \
-d '{"protocol_version":0,"passes":3}'
```
+195 -39
View File
@@ -2,7 +2,7 @@
"openapi": "3.1.0",
"info": {
"title": "GREE Controller API",
"version": "0.15.4",
"version": "0.15.6",
"summary": "Local HTTP/WebSocket API for GREE Controller",
"description": "Local API used by the GREE Controller Web UI and Home Assistant integration.",
"license": {
@@ -198,14 +198,14 @@
}
}
},
"/api/discovery": {
"/api/discovery/scan": {
"post": {
"tags": [
"Devices"
],
"summary": "Discover GREE devices",
"description": "Broadcasts GREE discovery, merges known devices, attempts binding for devices without a key, persists results and reports newly discovered controller IDs.",
"operationId": "discoverDevices",
"summary": "Scan for local GREE devices",
"description": "Broadcasts GREE discovery and returns local device candidates without persisting or binding them. protocol_version=1 or 2 strictly accepts only that protocol; protocol_version=0 accepts both.",
"operationId": "scanDiscoveredDevices",
"requestBody": {
"required": true,
"content": {
@@ -232,11 +232,77 @@
],
"responses": {
"200": {
"description": "Discovery result",
"description": "Discovery candidates; no devices are added automatically",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DiscoveryResponse"
"$ref": "#/components/schemas/DiscoveryScanResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"502": {
"$ref": "#/components/responses/BadGateway"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}
},
"/api/discovery/add": {
"post": {
"tags": [
"Devices"
],
"summary": "Add selected discovered devices",
"description": "Persists and binds only the local discovery candidates selected by the caller. Each selected unit is bound strictly with the protocol version detected during the scan.",
"operationId": "addDiscoveredDevices",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddDiscoveredDevicesRequest"
},
"example": {
"devices": [
{
"name": "Living room",
"mac": "AABBCCDDEEFF",
"ip": "192.168.50.30",
"port": 7000,
"protocol_version": 1,
"model": "GREE",
"firmware": "",
"already_added": false
}
]
}
}
}
},
"security": [
{
"BearerToken": []
},
{
"ApiTokenHeader": []
}
],
"responses": {
"200": {
"description": "Selected devices added",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddDiscoveredDevicesResponse"
}
}
}
@@ -5900,7 +5966,7 @@
},
"version": {
"type": "string",
"example": "0.15.4"
"example": "0.15.6"
},
"uptime_seconds": {
"type": "integer",
@@ -6633,37 +6699,6 @@
}
}
},
"DiscoveryResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"minimum": 0,
"example": 1
},
"devices": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Device"
}
},
"new_device_ids": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"gree-aabbccddeeff"
]
}
},
"required": [
"count",
"devices",
"new_device_ids"
],
"additionalProperties": false
},
"TemporaryQuickThermostatRequest": {
"type": "object",
"description": "Persisted temporary thermostat session with delayed/absolute start and several finish rules.",
@@ -9602,6 +9637,127 @@
"source"
],
"additionalProperties": false
},
"LocalDiscoveryCandidate": {
"type": "object",
"description": "Local GREE unit returned by discovery. No device is persisted until it is submitted to /api/discovery/add.",
"properties": {
"name": {
"type": "string",
"example": "Living room"
},
"mac": {
"type": "string",
"example": "AABBCCDDEEFF"
},
"ip": {
"type": "string",
"example": "192.168.50.30"
},
"port": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"default": 7000
},
"protocol_version": {
"type": "integer",
"enum": [
1,
2
],
"description": "Detected protocol generation"
},
"model": {
"type": "string",
"example": "GREE"
},
"firmware": {
"type": "string",
"example": "1.0"
},
"already_added": {
"type": "boolean",
"description": "True when this MAC already exists in the controller"
}
},
"required": [
"name",
"mac",
"ip",
"port",
"protocol_version",
"model",
"firmware",
"already_added"
],
"additionalProperties": false
},
"AddDiscoveredDevicesRequest": {
"type": "object",
"properties": {
"devices": {
"type": "array",
"minItems": 1,
"maxItems": 64,
"items": {
"$ref": "#/components/schemas/LocalDiscoveryCandidate"
}
}
},
"required": [
"devices"
],
"additionalProperties": false
},
"AddDiscoveredDevicesResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"minimum": 0
},
"devices": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Device"
}
},
"skipped_macs": {
"type": "array",
"items": {
"type": "string"
},
"description": "MAC addresses skipped because they were already registered"
}
},
"required": [
"count",
"devices",
"skipped_macs"
],
"additionalProperties": false
},
"DiscoveryScanResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"minimum": 0,
"example": 1
},
"devices": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LocalDiscoveryCandidate"
}
}
},
"required": [
"count",
"devices"
],
"additionalProperties": false
}
},
"responses": {