homebridge-ge-ac 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/README.md +4 -0
- package/lib/accessory.js +27 -23
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. This project follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and adheres to
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [1.2.1] - 2026-06-21
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Mode switches could show as generic "Switch 1/2/3" in the Home app after re-pairing. Switched
|
|
11
|
+
to the canonical `ConfiguredName` pattern (declare as optional + set a plain writable value, no
|
|
12
|
+
`onGet` override) so the Home app reliably reads the real names and user renames survive restarts.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- The **Fan** tile now sits right after the thermostat (before the mode switches).
|
|
16
|
+
|
|
17
|
+
## [1.2.0] - 2026-06-21
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- **Dedicated Fan accessory** with an **Auto ⇄ Manual** toggle plus a Low/Med/High speed
|
|
21
|
+
slider, mirroring the GE app's Auto/Low/Medium/High fan settings.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Fan speed moved off the thermostat's rotation-speed slider — Apple's Home app never
|
|
25
|
+
rendered it there — onto its own Fan service on the same accessory (it groups with the AC).
|
|
26
|
+
- Restored-accessory service changes are now persisted via `updatePlatformAccessories`, so
|
|
27
|
+
added services and removed characteristics survive Homebridge restarts.
|
|
28
|
+
|
|
29
|
+
### Removed
|
|
30
|
+
- The unused `RotationSpeed` characteristic on the HeaterCooler (the Home app never showed it).
|
|
31
|
+
|
|
32
|
+
## [1.1.0] - 2026-06-19
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- **Adaptive temperature range** read from the unit (`0x7B06`) instead of a hard-coded
|
|
36
|
+
64–86 °F, falling back to 64–86 °F when the unit doesn't report one.
|
|
37
|
+
- **Experimental heat/cool support**: when a unit reports a heating setpoint (`0x7002`), the
|
|
38
|
+
plugin also exposes a Heat thermostat mode, a heating setpoint, and a Heat switch.
|
|
39
|
+
⚠️ Untested on real heat hardware — please [open an issue](https://github.com/fabricore-eng/homebridge-ge-ac/issues) with results.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- Honest compatibility scoping in the README/description: built and tested only on the
|
|
43
|
+
cooling-only GE Profile **AHTT06BC**; other GE Wi-Fi window ACs are likely but unverified.
|
|
44
|
+
- The per-model "available modes" ERD (`0x7B00`) is deliberately ignored — GE window ACs
|
|
45
|
+
report a value that doesn't match the documented bitmask.
|
|
46
|
+
|
|
47
|
+
## [1.0.0] - 2026-06-19
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
- Initial release: HomeKit control of GE SmartHQ Wi-Fi window air conditioners over GE's
|
|
51
|
+
realtime **WebSocket** channel — setpoint/mode/fan writes the appliance actually honors
|
|
52
|
+
(REST writes are accepted but silently dropped on this AC line).
|
|
53
|
+
- **HeaterCooler** thermostat: on/off, target temperature, current temperature, with the
|
|
54
|
+
slider grid aligned to whole Fahrenheit degrees so both 64 °F and the maximum set cleanly.
|
|
55
|
+
- **Named mode switches**: Cool, Fan Only, Energy Saver, Dry — each sets `ConfiguredName`, so
|
|
56
|
+
HomeKit never shows "Switch 1–5".
|
|
57
|
+
- **Fan speed** control and **live state updates** pushed from the WebSocket subscription, so
|
|
58
|
+
changes made in the GE app or on the unit reflect in HomeKit in real time.
|
|
59
|
+
- Resilience: app-level keepalive, OAuth token refresh ahead of expiry, and
|
|
60
|
+
exponential-backoff auto-reconnect.
|
|
61
|
+
|
|
62
|
+
[1.2.1]: https://github.com/fabricore-eng/homebridge-ge-ac/releases/tag/v1.2.1
|
|
63
|
+
[1.2.0]: https://github.com/fabricore-eng/homebridge-ge-ac/releases/tag/v1.2.0
|
|
64
|
+
[1.1.0]: https://github.com/fabricore-eng/homebridge-ge-ac/releases/tag/v1.1.0
|
|
65
|
+
[1.0.0]: https://github.com/fabricore-eng/homebridge-ge-ac/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -103,6 +103,10 @@ The GE SmartHQ / Brillion protocol details (OAuth flow, WebSocket envelopes, ERD
|
|
|
103
103
|
encodings) were derived from the excellent [`simbaja/gehome`](https://github.com/simbaja/gehome)
|
|
104
104
|
Python library. This plugin is an independent JavaScript implementation.
|
|
105
105
|
|
|
106
|
+
## Changelog
|
|
107
|
+
|
|
108
|
+
See [CHANGELOG.md](CHANGELOG.md) for per-release notes.
|
|
109
|
+
|
|
106
110
|
## License
|
|
107
111
|
|
|
108
112
|
ISC — see [LICENSE](LICENSE).
|
package/lib/accessory.js
CHANGED
|
@@ -84,6 +84,27 @@ class ACAccessory {
|
|
|
84
84
|
hc.getCharacteristic(this.Ch.TemperatureDisplayUnits)
|
|
85
85
|
.onGet(() => (this.client.getState(this.mac, C.ERD.TEMP_UNIT) === '01') ? this.Ch.TemperatureDisplayUnits.CELSIUS : this.Ch.TemperatureDisplayUnits.FAHRENHEIT);
|
|
86
86
|
|
|
87
|
+
// ---- Fan (Fanv2): Auto/Manual toggle + Low/Med/High slider, bound to fan ERD 0x7A00 ----
|
|
88
|
+
// Built right after the thermostat so its tile sits second, before the mode switches.
|
|
89
|
+
// Apple Home renders this as a proper Fan tile (with an Auto switch), unlike a HeaterCooler's RotationSpeed.
|
|
90
|
+
const fan = accessory.getService(this.S.Fanv2) || accessory.addService(this.S.Fanv2, `${name} Fan`, 'GEAC_FANV2');
|
|
91
|
+
this.fan = fan;
|
|
92
|
+
this._configuredName(fan, 'Fan');
|
|
93
|
+
const TFS = this.Ch.TargetFanState, CFS = this.Ch.CurrentFanState, ACT = this.Ch.Active;
|
|
94
|
+
fan.getCharacteristic(ACT)
|
|
95
|
+
.onGet(() => this._power() ? ACT.ACTIVE : ACT.INACTIVE)
|
|
96
|
+
.onSet(this._wrap(async (v) => { await this.client.setErd(this.mac, C.ERD.POWER, v === ACT.ACTIVE ? C.POWER.ON : C.POWER.OFF); }));
|
|
97
|
+
fan.getCharacteristic(CFS)
|
|
98
|
+
.onGet(() => this._power() ? CFS.BLOWING_AIR : CFS.INACTIVE);
|
|
99
|
+
fan.getCharacteristic(TFS)
|
|
100
|
+
.onGet(() => this._fanIsAuto() ? TFS.AUTO : TFS.MANUAL)
|
|
101
|
+
.onSet(this._wrap(async (v) => {
|
|
102
|
+
await this.client.setErd(this.mac, C.ERD.FAN, v === TFS.AUTO ? C.FAN.AUTO : this._fanFromPct(this._fanSpeedPct()));
|
|
103
|
+
}));
|
|
104
|
+
fan.getCharacteristic(this.Ch.RotationSpeed) // continuous slider; onSet maps to Low(<=34)/Med(<=67)/High
|
|
105
|
+
.onGet(() => this._fanSpeedPct())
|
|
106
|
+
.onSet(this._wrap(async (pct) => { await this.client.setErd(this.mac, C.ERD.FAN, this._fanFromPct(pct)); }));
|
|
107
|
+
|
|
87
108
|
// ---- mode switches ----
|
|
88
109
|
const defs = [
|
|
89
110
|
['Cool', 'GEAC_COOL', C.MODE.COOL],
|
|
@@ -106,27 +127,6 @@ class ACAccessory {
|
|
|
106
127
|
return { sw, modeHex };
|
|
107
128
|
});
|
|
108
129
|
|
|
109
|
-
// ---- Fan (Fanv2): Auto/Manual toggle + Low/Med/High slider, bound to fan ERD 0x7A00 ----
|
|
110
|
-
// Apple Home renders this as a proper Fan tile (with an Auto switch), unlike a HeaterCooler's
|
|
111
|
-
// RotationSpeed. Same accessory, so it groups with the thermostat + mode switches.
|
|
112
|
-
const fan = accessory.getService(this.S.Fanv2) || accessory.addService(this.S.Fanv2, `${name} Fan`, 'GEAC_FANV2');
|
|
113
|
-
this.fan = fan;
|
|
114
|
-
this._configuredName(fan, 'Fan');
|
|
115
|
-
const TFS = this.Ch.TargetFanState, CFS = this.Ch.CurrentFanState, ACT = this.Ch.Active;
|
|
116
|
-
fan.getCharacteristic(ACT)
|
|
117
|
-
.onGet(() => this._power() ? ACT.ACTIVE : ACT.INACTIVE)
|
|
118
|
-
.onSet(this._wrap(async (v) => { await this.client.setErd(this.mac, C.ERD.POWER, v === ACT.ACTIVE ? C.POWER.ON : C.POWER.OFF); }));
|
|
119
|
-
fan.getCharacteristic(CFS)
|
|
120
|
-
.onGet(() => this._power() ? CFS.BLOWING_AIR : CFS.INACTIVE);
|
|
121
|
-
fan.getCharacteristic(TFS)
|
|
122
|
-
.onGet(() => this._fanIsAuto() ? TFS.AUTO : TFS.MANUAL)
|
|
123
|
-
.onSet(this._wrap(async (v) => {
|
|
124
|
-
await this.client.setErd(this.mac, C.ERD.FAN, v === TFS.AUTO ? C.FAN.AUTO : this._fanFromPct(this._fanSpeedPct()));
|
|
125
|
-
}));
|
|
126
|
-
fan.getCharacteristic(this.Ch.RotationSpeed) // continuous slider; onSet maps to Low(<=34)/Med(<=67)/High
|
|
127
|
-
.onGet(() => this._fanSpeedPct())
|
|
128
|
-
.onSet(this._wrap(async (pct) => { await this.client.setErd(this.mac, C.ERD.FAN, this._fanFromPct(pct)); }));
|
|
129
|
-
|
|
130
130
|
// live updates
|
|
131
131
|
this._onErd = (m) => { if (m === this.mac) this._pushAll(); };
|
|
132
132
|
client.on('erd', this._onErd);
|
|
@@ -134,9 +134,13 @@ class ACAccessory {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
_configuredName(svc, name) {
|
|
137
|
+
// Canonical pattern for naming multiple same-type services so the Home app shows real names
|
|
138
|
+
// (not "Switch 1/2/3"): declare ConfiguredName as optional and set it as a plain writable value.
|
|
139
|
+
// No onGet override — that both confuses some Home clients and would clobber a user rename.
|
|
140
|
+
// Seed our default only when empty so a user's rename survives restarts.
|
|
141
|
+
svc.addOptionalCharacteristic(this.Ch.ConfiguredName);
|
|
142
|
+
if (!svc.getCharacteristic(this.Ch.ConfiguredName).value) svc.setCharacteristic(this.Ch.ConfiguredName, name);
|
|
137
143
|
svc.setCharacteristic(this.Ch.Name, name);
|
|
138
|
-
if (!svc.testCharacteristic(this.Ch.ConfiguredName)) svc.addCharacteristic(this.Ch.ConfiguredName);
|
|
139
|
-
svc.getCharacteristic(this.Ch.ConfiguredName).onGet(() => name).updateValue(name);
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
// ---- state helpers ----
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-ge-ac",
|
|
3
3
|
"displayName": "GE Profile AC (SmartHQ WebSocket)",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.1",
|
|
5
5
|
"description": "Homebridge plugin for GE SmartHQ Wi-Fi window air conditioners over GE's realtime WebSocket channel (reliable setpoint/mode/fan control). Built and tested on the cooling-only GE Profile AHTT06BC; likely works on similar GE Wi-Fi window ACs (unverified).",
|
|
6
6
|
"author": "Fabricore",
|
|
7
7
|
"license": "ISC",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"files": [
|
|
31
31
|
"index.js",
|
|
32
32
|
"lib/",
|
|
33
|
-
"config.schema.json"
|
|
33
|
+
"config.schema.json",
|
|
34
|
+
"CHANGELOG.md"
|
|
34
35
|
],
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"axios": "^1.7.0",
|