homebridge-ac-freedom 1.0.2 → 1.0.4
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/config.schema.json +0 -9
- package/package.json +1 -1
- package/src/ac-accessory.js +46 -23
package/config.schema.json
CHANGED
|
@@ -83,15 +83,6 @@
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
},
|
|
86
|
-
"hvacModes": {
|
|
87
|
-
"title": "Enabled HVAC Modes",
|
|
88
|
-
"type": "object",
|
|
89
|
-
"properties": {
|
|
90
|
-
"auto": { "title": "Auto", "type": "boolean", "default": true },
|
|
91
|
-
"cool": { "title": "Cool", "type": "boolean", "default": true },
|
|
92
|
-
"heat": { "title": "Heat", "type": "boolean", "default": true }
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
86
|
"presets": {
|
|
96
87
|
"title": "Enabled Preset Modes (shown as switches in climate card)",
|
|
97
88
|
"type": "object",
|
package/package.json
CHANGED
package/src/ac-accessory.js
CHANGED
|
@@ -66,10 +66,11 @@ class AcFreedomAccessory {
|
|
|
66
66
|
|
|
67
67
|
this.setupAccessoryInfo();
|
|
68
68
|
this.setupHeaterCooler();
|
|
69
|
-
this.
|
|
69
|
+
this.purgeLinkedServices();
|
|
70
70
|
this.setupFanService();
|
|
71
71
|
this.setupPresetSwitches();
|
|
72
72
|
this.setupDisplaySwitch();
|
|
73
|
+
this.enforceServiceOrder();
|
|
73
74
|
|
|
74
75
|
// Start polling
|
|
75
76
|
const interval = (config.pollInterval || 30) * 1000;
|
|
@@ -94,7 +95,6 @@ class AcFreedomAccessory {
|
|
|
94
95
|
|| this.accessory.addService(this.Service.HeaterCooler, this.config.name);
|
|
95
96
|
|
|
96
97
|
const C = this.Characteristic;
|
|
97
|
-
const hvac = this.config.hvacModes || { auto: true, cool: true, heat: true };
|
|
98
98
|
|
|
99
99
|
// Active (on/off)
|
|
100
100
|
this.heaterCooler.getCharacteristic(C.Active)
|
|
@@ -115,15 +115,15 @@ class AcFreedomAccessory {
|
|
|
115
115
|
}
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
// Target state (auto/heat/cool)
|
|
119
|
-
const validStates = [];
|
|
120
|
-
if (hvac.auto) validStates.push(C.TargetHeaterCoolerState.AUTO);
|
|
121
|
-
if (hvac.heat) validStates.push(C.TargetHeaterCoolerState.HEAT);
|
|
122
|
-
if (hvac.cool) validStates.push(C.TargetHeaterCoolerState.COOL);
|
|
123
|
-
if (validStates.length === 0) validStates.push(C.TargetHeaterCoolerState.AUTO);
|
|
124
|
-
|
|
118
|
+
// Target state – all HVAC modes always enabled (auto/heat/cool)
|
|
125
119
|
this.heaterCooler.getCharacteristic(C.TargetHeaterCoolerState)
|
|
126
|
-
.setProps({
|
|
120
|
+
.setProps({
|
|
121
|
+
validValues: [
|
|
122
|
+
C.TargetHeaterCoolerState.AUTO,
|
|
123
|
+
C.TargetHeaterCoolerState.HEAT,
|
|
124
|
+
C.TargetHeaterCoolerState.COOL,
|
|
125
|
+
],
|
|
126
|
+
})
|
|
127
127
|
.onGet(() => {
|
|
128
128
|
switch (this.state.mode) {
|
|
129
129
|
case CLOUD_MODE.HEAT: return C.TargetHeaterCoolerState.HEAT;
|
|
@@ -179,24 +179,47 @@ class AcFreedomAccessory {
|
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
// ──
|
|
183
|
-
// Remove cached linked
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
for (const { type, subtype } of ids) {
|
|
182
|
+
// ── Purge linked services ────────────────────────────────────
|
|
183
|
+
// Remove every cached linked service from the accessory AND clear
|
|
184
|
+
// the HeaterCooler's linked list so they are re-created fresh in
|
|
185
|
+
// the correct display order: Fan → Presets → Display.
|
|
186
|
+
purgeLinkedServices() {
|
|
187
|
+
// 1. Clear HeaterCooler's linked services array
|
|
188
|
+
this.heaterCooler.linkedServices = [];
|
|
189
|
+
|
|
190
|
+
// 2. Remove cached services from the accessory
|
|
191
|
+
const subtypes = ['fan', 'sleep', 'health', 'eco', 'clean', 'display'];
|
|
192
|
+
for (const subtype of subtypes) {
|
|
193
|
+
const type = subtype === 'fan' ? this.Service.Fanv2 : this.Service.Switch;
|
|
195
194
|
const svc = this.accessory.getServiceById(type, subtype);
|
|
196
195
|
if (svc) this.accessory.removeService(svc);
|
|
197
196
|
}
|
|
198
197
|
}
|
|
199
198
|
|
|
199
|
+
// ── Enforce service order in accessory ──────────────────────
|
|
200
|
+
// HomeKit reads the services array order from the HAP database to
|
|
201
|
+
// determine tile layout. We sort the array so that Fan always
|
|
202
|
+
// comes right after HeaterCooler, followed by preset switches and
|
|
203
|
+
// the display switch.
|
|
204
|
+
enforceServiceOrder() {
|
|
205
|
+
const S = this.Service;
|
|
206
|
+
const rank = (svc) => {
|
|
207
|
+
if (svc.UUID === S.AccessoryInformation.UUID) return 0;
|
|
208
|
+
if (svc.UUID === S.HeaterCooler.UUID) return 1;
|
|
209
|
+
if (svc.UUID === S.Fanv2.UUID) return 2; // Fan first
|
|
210
|
+
if (svc.UUID === S.Switch.UUID) {
|
|
211
|
+
const sub = svc.subtype;
|
|
212
|
+
if (sub === 'sleep') return 3;
|
|
213
|
+
if (sub === 'health') return 4;
|
|
214
|
+
if (sub === 'eco') return 5;
|
|
215
|
+
if (sub === 'clean') return 6;
|
|
216
|
+
if (sub === 'display') return 7;
|
|
217
|
+
}
|
|
218
|
+
return 99;
|
|
219
|
+
};
|
|
220
|
+
this.accessory.services.sort((a, b) => rank(a) - rank(b));
|
|
221
|
+
}
|
|
222
|
+
|
|
200
223
|
// ── Fan Service (linked to HeaterCooler) ────────────────────────
|
|
201
224
|
setupFanService() {
|
|
202
225
|
const C = this.Characteristic;
|