This commit is contained in:
Mateusz Gruszczyński
2026-09-16 09:04:43 +02:00
parent 3d69e74319
commit 0437ef7b6f
28 changed files with 1254 additions and 221 deletions
+71 -16
View File
@@ -2,9 +2,9 @@
"openapi": "3.1.0",
"info": {
"title": "GREE Controller API",
"version": "0.14.4",
"version": "0.14.8",
"summary": "Local HTTP/WebSocket API for GREE HVAC control",
"description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nAdministrator endpoints accept `Authorization: Bearer <APP_TOKEN>` or `x-api-token: <APP_TOKEN>` when configured. Restricted Home Assistant control endpoints also accept generated integration tokens.\n\n### Local and GREE Cloud\nDevices use one API model and one command surface. `connection_type=local` is dispatched only to the existing LAN/UDP provider; `connection_type=gree_cloud` is dispatched only to the GREE Cloud provider. No automatic transport fallback is performed.\n\n### GREE Cloud security\nCloud passwords, REST/MQTT tokens, Authorization values and device cipher keys are never returned in normal API responses or Cloud diagnostics. MQTT uses TLS with certificate and hostname validation.\n\n### Energy\nGREE Cloud `ElcAll` and selected Home Assistant cumulative energy sensors are normalized to kWh and converted to consumption deltas before aggregation. Raw cumulative values are retained only as meter samples/baselines.\n\n### 0.14.4\nHome Assistant connection tests validate only the configured server/API token and require no entity. `outdoor_entity_id` is the global Home Assistant outdoor-temperature sensor; zones can override it with `ha_outdoor_entity_id`. Room-temperature Home Assistant sensors remain configured per zone with `ha_entity_id`. Global/per-zone outdoor sensors are integrated with aliases, metrics/history and Visual Flow entity suggestions.\n\n### 0.14.2\nAdds independent vertical/horizontal swing controls across manual device control, thermostat zones, legacy automations, Visual Flow and Home Assistant zone climates. Swing is treated as an auxiliary one-shot unit setting and does not replace thermostat ownership.\n\n### 0.14.1\nAdds split/multisplit installation groups with shared energy and outdoor-temperature sources, multi-target energy charts with period comparison, cleaner Cloud status/alerts and safe MQTT cleanup after the last Cloud device is removed.\n\n### 0.14.0\nAdds first-class GREE Cloud MQTT status/control, reconnect/resubscribe lifecycle, Cloud diagnostics, per-device capabilities, Cloud/HA energy sources and energy-history aggregation while preserving the LAN transport contract.",
"description": "Self-hosted API used by the GREE Controller Web UI and Home Assistant integration.\n\n### Authentication\nAdministrator endpoints accept `Authorization: Bearer <APP_TOKEN>` or `x-api-token: <APP_TOKEN>` when configured. Restricted Home Assistant control endpoints also accept generated integration tokens.\n\n### Local and GREE Cloud\nDevices use one API model and one command surface. `connection_type=local` is dispatched only to the existing LAN/UDP provider; `connection_type=gree_cloud` is dispatched only to the GREE Cloud provider. No automatic transport fallback is performed.\n\n### GREE Cloud security\nCloud passwords, REST/MQTT tokens, Authorization values and device cipher keys are never returned in normal API responses or Cloud diagnostics. MQTT uses TLS with certificate and hostname validation.\n\n### Energy\nGREE Cloud `ElcAll` and selected Home Assistant cumulative energy sensors are normalized to kWh and converted to consumption deltas before aggregation. Raw cumulative values are retained only as meter samples/baselines.\n\n### 0.14.8\nRemaining Home Assistant and notification diagnostic errors no longer use device-transport 502 responses. Missing/invalid integration configuration returns 400, configured external dependency failures return 424, and 502 is reserved for Local/LAN GREE device communication.\n\n### 0.14.7\nHome Assistant energy-sensor discovery now returns an empty optional result when HA is not configured, uses 424 for configured external-dependency failures, and custom select popovers use their rendered height when positioning above a field.\n\n\n### 0.14.6\nFixes dynamic custom-select duplication in History → Energy and hides Energy history controls when no energy source is configured.\n\n### 0.14.5\nWeb UI single-choice controls now use one consistent custom dropdown, language packs are loaded on demand, and the dashboard outdoor temperature opens a 24-hour history modal.\n\n### 0.14.4\nHome Assistant connection tests validate only the configured server/API token and require no entity. `outdoor_entity_id` is the global Home Assistant outdoor-temperature sensor; zones can override it with `ha_outdoor_entity_id`. Room-temperature Home Assistant sensors remain configured per zone with `ha_entity_id`. Global/per-zone outdoor sensors are integrated with aliases, metrics/history and Visual Flow entity suggestions.\n\n### 0.14.2\nAdds independent vertical/horizontal swing controls across manual device control, thermostat zones, legacy automations, Visual Flow and Home Assistant zone climates. Swing is treated as an auxiliary one-shot unit setting and does not replace thermostat ownership.\n\n### 0.14.1\nAdds split/multisplit installation groups with shared energy and outdoor-temperature sources, multi-target energy charts with period comparison, cleaner Cloud status/alerts and safe MQTT cleanup after the last Cloud device is removed.\n\n### 0.14.0\nAdds first-class GREE Cloud MQTT status/control, reconnect/resubscribe lifecycle, Cloud diagnostics, per-device capabilities, Cloud/HA energy sources and energy-history aggregation while preserving the LAN transport contract.",
"license": {
"name": "MIT"
}
@@ -782,6 +782,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -1118,6 +1121,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -1623,6 +1629,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -1675,6 +1684,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -1728,6 +1740,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -1781,6 +1796,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3116,11 +3134,11 @@
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"502": {
"$ref": "#/components/responses/BadGateway"
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3178,11 +3196,11 @@
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"502": {
"$ref": "#/components/responses/BadGateway"
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3240,11 +3258,11 @@
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"502": {
"$ref": "#/components/responses/BadGateway"
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3487,6 +3505,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3632,6 +3653,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3684,6 +3708,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3737,6 +3764,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3790,6 +3820,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -3857,6 +3890,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -4979,6 +5015,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -5036,6 +5075,9 @@
},
"409": {
"$ref": "#/components/responses/Conflict"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -5113,8 +5155,8 @@
"400": {
"$ref": "#/components/responses/BadRequest"
},
"502": {
"$ref": "#/components/responses/BadGateway"
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -5180,7 +5222,7 @@
"Energy"
],
"summary": "List compatible Home Assistant energy sensors",
"description": "Lists entities compatible with cumulative energy ingestion: device_class=energy, state_class total/total_increasing and Wh or kWh.",
"description": "Lists entities compatible with cumulative energy ingestion: device_class=energy, state_class total/total_increasing and Wh or kWh. If Home Assistant is not configured, returns configured=false with an empty sensors array.",
"operationId": "listHomeAssistantEnergySensors",
"security": [
{
@@ -5207,6 +5249,9 @@
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"424": {
"$ref": "#/components/responses/FailedDependency"
}
}
}
@@ -5475,7 +5520,7 @@
},
"version": {
"type": "string",
"example": "0.14.4"
"example": "0.14.8"
},
"uptime_seconds": {
"type": "integer",
@@ -9135,7 +9180,7 @@
}
},
"BadGateway": {
"description": "GREE/Home Assistant/integration communication failure",
"description": "Local/LAN GREE device communication failure.",
"content": {
"application/json": {
"schema": {
@@ -9156,6 +9201,16 @@
}
}
}
},
"FailedDependency": {
"description": "A configured external service or integration could not complete the request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}