homebridge-ac-freedom 2.3.5 → 2.3.7
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 +8 -0
- package/README.md +18 -19
- package/homebridge-ui/public/index.html +26 -28
- package/package.json +1 -1
- package/src/ac-accessory.js +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.3.7
|
|
4
|
+
|
|
5
|
+
- **Fix inverted swing mode on local connection** (#1) — local Broadlink protocol uses fixation `0` = swinging and `7` = fixed; the plugin had it reversed, so the HomeKit swing toggle showed the opposite of the actual louvre state. Cloud connection was unaffected.
|
|
6
|
+
|
|
7
|
+
## 2.3.6
|
|
8
|
+
|
|
9
|
+
- **Config UI: feature toggles redesigned** — checkboxes removed; each feature is now a colour-coded pill: bright green when enabled, muted grey when disabled
|
|
10
|
+
|
|
3
11
|
## 2.3.5
|
|
4
12
|
|
|
5
13
|
- **Fix double beep on power-on** — `TargetHeaterCoolerState` command is suppressed when fired within 200 ms of a power command; mode is already included in `sendPower`
|
package/README.md
CHANGED
|
@@ -31,13 +31,13 @@ A [Homebridge](https://homebridge.io) plugin for controlling **AUX-based air con
|
|
|
31
31
|
- Self Clean
|
|
32
32
|
- Comfortable Wind
|
|
33
33
|
- **Display** switch — LED display on/off
|
|
34
|
-
- **Auto-reset** — fan
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
34
|
+
- **Auto-reset** — fan resets to Auto and Sleep turns off when the AC is powered off
|
|
35
|
+
- **Consistent tile order** — Fan is always first, followed by Sleep, Display, Health, Clean, Eco, Comf. Wind
|
|
36
|
+
- **Hybrid** — single cloud login at platform level; optional IP + MAC per device for direct local Broadlink UDP (local preferred, cloud fallback)
|
|
37
|
+
- **Local** — direct Broadlink UDP only, no internet required
|
|
37
38
|
- **Multi-device** — configure as many ACs as needed
|
|
38
39
|
- **Custom config UI** — built-in Homebridge UI with Fetch Devices button
|
|
39
40
|
- Homebridge v1 & v2 compatible
|
|
40
|
-
- English UI
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
@@ -196,8 +196,6 @@ Required for Hybrid mode. Configured once, shared by all hybrid devices.
|
|
|
196
196
|
| `name` | string | Yes | — | Device name in HomeKit |
|
|
197
197
|
| `connection` | string | No | `"hybrid"` | `"hybrid"` or `"local"` |
|
|
198
198
|
| `endpointId` | string | No | — | Cloud device ID (auto-detected if empty) |
|
|
199
|
-
| `pollInterval` | integer | No | `30` | Polling interval in seconds (5–300) |
|
|
200
|
-
| `tempStep` | number | No | `0.5` | Temperature step: `0.5` or `1` |
|
|
201
199
|
|
|
202
200
|
### Local Settings (`local` object, per device)
|
|
203
201
|
|
|
@@ -218,7 +216,7 @@ Required for Hybrid mode. Configured once, shared by all hybrid devices.
|
|
|
218
216
|
| `showComfWind` | boolean | `false` | Comfortable Wind switch |
|
|
219
217
|
| `showDisplay` | boolean | `false` | Display (LED) switch |
|
|
220
218
|
|
|
221
|
-
> **Tip:** For a clean HomeKit appearance, enable **Fan** and
|
|
219
|
+
> **Tip:** For a clean HomeKit appearance, enable only the features you use. **Fan** and **Sleep** are enabled by default — most users need nothing else.
|
|
222
220
|
|
|
223
221
|
---
|
|
224
222
|
|
|
@@ -226,13 +224,11 @@ Required for Hybrid mode. Configured once, shared by all hybrid devices.
|
|
|
226
224
|
|
|
227
225
|
Once configured, the AC appears as a **HeaterCooler** tile. Tapping it reveals:
|
|
228
226
|
|
|
229
|
-
- Temperature control
|
|
227
|
+
- Temperature control (1 °C steps, 16–32 °C)
|
|
230
228
|
- Mode selector — Auto / Heat / Cool
|
|
231
229
|
- Fan speed slider — 0% Auto · 25% Low · 50% Medium · 75% High · 100% Turbo
|
|
232
230
|
- Swing toggle
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
All linked services appear as tiles inside the climate card.
|
|
231
|
+
- Linked service tiles in a fixed order: Fan → Sleep → Display → Health → Clean → Eco → Comf. Wind
|
|
236
232
|
|
|
237
233
|
---
|
|
238
234
|
|
|
@@ -246,7 +242,7 @@ All linked services appear as tiles inside the climate card.
|
|
|
246
242
|
| Works remotely | Yes | No |
|
|
247
243
|
| Local fallback | Yes (when IP + MAC configured) | — |
|
|
248
244
|
|
|
249
|
-
> ¹ **Hybrid + IP/MAC:** if internet is unavailable at startup, the device starts in local-only mode automatically. Full hybrid resumes on the next restart when internet is available.
|
|
245
|
+
> ¹ **Hybrid + IP/MAC:** if internet is unavailable at Homebridge startup, the device starts in local-only mode automatically. Full hybrid resumes on the next restart when internet is available.
|
|
250
246
|
|
|
251
247
|
---
|
|
252
248
|
|
|
@@ -258,19 +254,22 @@ All linked services appear as tiles inside the climate card.
|
|
|
258
254
|
- Check the `region` matches your account region
|
|
259
255
|
- Logging into the AC Freedom app may invalidate the plugin session — restart Homebridge after using the app
|
|
260
256
|
|
|
261
|
-
**Device not found**
|
|
257
|
+
**Device not found after Fetch**
|
|
262
258
|
- Leave `endpointId` empty for auto-detection (first discovered device is used)
|
|
263
259
|
- Use the **Fetch** button in the Homebridge UI to discover and auto-fill your device IDs
|
|
260
|
+
- If the device is missing from the cloud list, power cycle the AC and try again
|
|
264
261
|
|
|
265
|
-
**"
|
|
266
|
-
- These are transient and automatically suppressed
|
|
267
|
-
- If persistent, increase `pollInterval` to 60 or higher
|
|
268
|
-
|
|
269
|
-
**AC not responding**
|
|
262
|
+
**AC not responding / "Service Communication Failure" in HomeKit**
|
|
270
263
|
- Check the AC is powered on and connected to Wi-Fi
|
|
271
|
-
- Local mode: Homebridge and AC must be on the same network
|
|
264
|
+
- Local mode: Homebridge and the AC must be on the same network
|
|
272
265
|
- Try restarting Homebridge
|
|
273
266
|
|
|
267
|
+
**"Server busy" errors in logs**
|
|
268
|
+
- These are transient cloud API errors and are automatically suppressed — no action needed
|
|
269
|
+
|
|
270
|
+
**Tile order is wrong in HomeKit**
|
|
271
|
+
- Remove the accessory from the Home app (the individual tile, not the whole bridge), then restart Homebridge — it will re-appear with the correct order
|
|
272
|
+
|
|
274
273
|
---
|
|
275
274
|
|
|
276
275
|
## Support
|
|
@@ -154,17 +154,17 @@
|
|
|
154
154
|
.toggle-row { display: flex; gap: 6px; }
|
|
155
155
|
.toggle-item {
|
|
156
156
|
flex: 1; min-width: 0;
|
|
157
|
-
display: flex; align-items: center; justify-content: center;
|
|
157
|
+
display: flex; align-items: center; justify-content: center;
|
|
158
158
|
padding: 7px 4px; border-radius: 7px;
|
|
159
159
|
border: 1px solid var(--border); background: var(--card-bg);
|
|
160
|
-
cursor: pointer; font-size: 11px; font-weight: 500; color: var(--text);
|
|
161
|
-
white-space: nowrap; transition: border-color .15s, background .15s;
|
|
160
|
+
cursor: pointer; font-size: 11px; font-weight: 500; color: var(--text-muted);
|
|
161
|
+
white-space: nowrap; transition: border-color .15s, background .15s, color .15s;
|
|
162
|
+
user-select: none;
|
|
162
163
|
}
|
|
163
|
-
.toggle-item:hover { border-color:
|
|
164
|
-
.toggle-item
|
|
165
|
-
|
|
164
|
+
.toggle-item:not(.on):hover { border-color: #9ca3af; }
|
|
165
|
+
.toggle-item.on {
|
|
166
|
+
background: #16a34a; border-color: #16a34a; color: #fff; font-weight: 600;
|
|
166
167
|
}
|
|
167
|
-
.toggle-item.checked { border-color: var(--accent-border); background: var(--accent-light); }
|
|
168
168
|
|
|
169
169
|
/* ── Fieldset ── */
|
|
170
170
|
.fieldset {
|
|
@@ -253,23 +253,22 @@
|
|
|
253
253
|
function featToggles(d, i) {
|
|
254
254
|
const presets = d.presets || {};
|
|
255
255
|
const feats = [
|
|
256
|
-
{ key: 'showFan', label: t.fan||'Fan',
|
|
257
|
-
{ key: 'sleep', label: t.sleep||'Sleep',
|
|
258
|
-
{ key: 'showDisplay', label: t.display||'Display',
|
|
259
|
-
{ key: 'health', label: t.health||'Health',
|
|
260
|
-
{ key: 'clean', label: t.clean||'Clean',
|
|
261
|
-
{ key: 'eco', label: t.eco||'Eco',
|
|
262
|
-
{ key: 'showComfWind', label: t.comfWind||'Comf. Wind',
|
|
256
|
+
{ key: 'showFan', label: t.fan||'Fan', val: bool(d.showFan) },
|
|
257
|
+
{ key: 'sleep', label: t.sleep||'Sleep', val: bool(presets.sleep), preset: true },
|
|
258
|
+
{ key: 'showDisplay', label: t.display||'Display', val: bool(d.showDisplay) },
|
|
259
|
+
{ key: 'health', label: t.health||'Health', val: bool(presets.health), preset: true },
|
|
260
|
+
{ key: 'clean', label: t.clean||'Clean', val: bool(presets.clean), preset: true },
|
|
261
|
+
{ key: 'eco', label: t.eco||'Eco', val: bool(presets.eco), preset: true },
|
|
262
|
+
{ key: 'showComfWind', label: t.comfWind||'Comf. Wind', val: bool(d.showComfWind) },
|
|
263
263
|
];
|
|
264
|
+
|
|
264
265
|
return `
|
|
265
266
|
<div class="toggle-row">
|
|
266
267
|
${feats.map(f => `
|
|
267
|
-
<
|
|
268
|
-
|
|
269
|
-
data-i="${i}" data-k="${f.key}" data-preset="${f.preset||false}"
|
|
270
|
-
${f.val ? 'checked' : ''}>
|
|
268
|
+
<div class="toggle-item ${f.val ? 'on' : ''}"
|
|
269
|
+
data-i="${i}" data-k="${f.key}" data-preset="${f.preset||false}">
|
|
271
270
|
${f.label}
|
|
272
|
-
</
|
|
271
|
+
</div>
|
|
273
272
|
`).join('')}
|
|
274
273
|
</div>
|
|
275
274
|
`;
|
|
@@ -624,19 +623,18 @@
|
|
|
624
623
|
});
|
|
625
624
|
});
|
|
626
625
|
|
|
627
|
-
/* Feature
|
|
628
|
-
document.querySelectorAll('.
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
const i = +
|
|
632
|
-
const isPreset =
|
|
626
|
+
/* Feature toggles */
|
|
627
|
+
document.querySelectorAll('.toggle-item').forEach(el => {
|
|
628
|
+
el.addEventListener('click', () => {
|
|
629
|
+
const isOn = el.classList.toggle('on');
|
|
630
|
+
const i = +el.dataset.i, k = el.dataset.k;
|
|
631
|
+
const isPreset = el.dataset.preset === 'true';
|
|
633
632
|
if (isPreset) {
|
|
634
633
|
if (!config.devices[i].presets) config.devices[i].presets = {};
|
|
635
|
-
config.devices[i].presets[k] =
|
|
634
|
+
config.devices[i].presets[k] = isOn;
|
|
636
635
|
} else {
|
|
637
|
-
config.devices[i][k] =
|
|
636
|
+
config.devices[i][k] = isOn;
|
|
638
637
|
}
|
|
639
|
-
cb.closest('.toggle-item').classList.toggle('checked', cb.checked);
|
|
640
638
|
save();
|
|
641
639
|
});
|
|
642
640
|
});
|
package/package.json
CHANGED
package/src/ac-accessory.js
CHANGED
|
@@ -462,8 +462,9 @@ class AcFreedomAccessory {
|
|
|
462
462
|
this.state.currentTemp = s.ambientTemp;
|
|
463
463
|
// Normalise local fan speed → canonical cloud numbering
|
|
464
464
|
this.state.fanSpeed = FAN_REMAP[s.fanSpeed] ?? FAN_SPEED.AUTO;
|
|
465
|
-
|
|
466
|
-
this.state.
|
|
465
|
+
// Local fixation: 0 = swinging, 7 = fixed
|
|
466
|
+
this.state.swingV = s.verticalFixation === 0;
|
|
467
|
+
this.state.swingH = s.horizontalFixation === 0;
|
|
467
468
|
this.state.sleep = !!s.sleep;
|
|
468
469
|
this.state.health = !!s.health;
|
|
469
470
|
this.state.eco = !!s.mildew;
|
|
@@ -613,8 +614,9 @@ class AcFreedomAccessory {
|
|
|
613
614
|
return this._send(
|
|
614
615
|
() => {
|
|
615
616
|
const a = this._localApi;
|
|
616
|
-
|
|
617
|
-
a.state.
|
|
617
|
+
// Local fixation: 0 = swinging, 7 = fixed
|
|
618
|
+
a.state.verticalFixation = v ? 0 : 7;
|
|
619
|
+
a.state.horizontalFixation = h ? 0 : 7;
|
|
618
620
|
return a.setState();
|
|
619
621
|
},
|
|
620
622
|
() => this.cloudSet({ [CLOUD.SWING_V]: v ? 1 : 0, [CLOUD.SWING_H]: h ? 1 : 0 }),
|