homebridge-multiple-switch 1.6.0-beta.1 → 1.6.0-beta.10
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/.github/workflows/release.yml +11 -1
- package/CHANGELOG.md +46 -0
- package/homebridge-ui/public/i18n/ar.json +2 -1
- package/homebridge-ui/public/i18n/de.json +2 -1
- package/homebridge-ui/public/i18n/en.json +2 -1
- package/homebridge-ui/public/i18n/es.json +2 -1
- package/homebridge-ui/public/i18n/fr.json +2 -1
- package/homebridge-ui/public/i18n/it.json +2 -1
- package/homebridge-ui/public/i18n/ja.json +2 -1
- package/homebridge-ui/public/i18n/ko.json +2 -1
- package/homebridge-ui/public/i18n/nl.json +2 -1
- package/homebridge-ui/public/i18n/pl.json +2 -1
- package/homebridge-ui/public/i18n/pt.json +2 -1
- package/homebridge-ui/public/i18n/ru.json +2 -1
- package/homebridge-ui/public/i18n/tr.json +2 -1
- package/homebridge-ui/public/i18n/zh-CN.json +2 -1
- package/homebridge-ui/public/index.html +35 -17
- package/index.js +46 -36
- package/package.json +2 -2
|
@@ -22,7 +22,17 @@ jobs:
|
|
|
22
22
|
- name: Install dependencies
|
|
23
23
|
run: npm install
|
|
24
24
|
|
|
25
|
+
- name: Determine npm tag
|
|
26
|
+
id: npm-tag
|
|
27
|
+
run: |
|
|
28
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
29
|
+
if echo "$VERSION" | grep -q "beta"; then
|
|
30
|
+
echo "tag=beta" >> $GITHUB_OUTPUT
|
|
31
|
+
else
|
|
32
|
+
echo "tag=latest" >> $GITHUB_OUTPUT
|
|
33
|
+
fi
|
|
34
|
+
|
|
25
35
|
- name: Publish to npm
|
|
26
|
-
run: npm publish
|
|
36
|
+
run: npm publish --tag ${{ steps.npm-tag.outputs.tag }}
|
|
27
37
|
env:
|
|
28
38
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.0-beta.10] - 2026-03-22
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Homebridge v2 compatibility — plugin now shows green checkmark in v2 readiness check
|
|
7
|
+
- Switch ordering in HomeKit now follows config order (services recreated in sequence)
|
|
8
|
+
- Removed ServiceLabel/ServiceLabelIndex that caused outlets to render as toggles
|
|
9
|
+
instead of buttons
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Master switch type now defaults to Switch instead of Outlet (both UI and backend)
|
|
13
|
+
|
|
14
|
+
## [1.6.0-beta.5] - 2026-03-21
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Switch names now correctly appear in HomeKit — services are recreated on each
|
|
18
|
+
start with fresh displayName, Name, and ConfiguredName (cached services kept
|
|
19
|
+
stale names from initial creation)
|
|
20
|
+
- Master switch now always appears first in HomeKit — all subtype services are
|
|
21
|
+
removed and recreated in correct order (master first, then switches)
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- Master switch type selector now inline with the toggle (same row)
|
|
25
|
+
|
|
26
|
+
## [1.6.0-beta.4] - 2026-03-21
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
- Master switch type selection (Switch or Outlet) — appears when master switch is enabled
|
|
30
|
+
- `masterSwitchType` config option
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- All devices and switches now start collapsed when config UI is opened
|
|
34
|
+
- New devices/switches still open expanded when freshly added
|
|
35
|
+
|
|
36
|
+
## [1.6.0-beta.3] - 2026-03-21
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- Switch names now display correctly in HomeKit using `ConfiguredName`
|
|
40
|
+
characteristic (previously all showed the device name)
|
|
41
|
+
- Master switch now always appears first in HomeKit (created before regular switches)
|
|
42
|
+
|
|
43
|
+
## [1.6.0-beta.2] - 2026-03-21
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
- Master Switch now available in Independent mode (was incorrectly in Single mode)
|
|
47
|
+
- Behavior description now appears below the select dropdown instead of above
|
|
48
|
+
|
|
3
49
|
## [1.6.0-beta.1] - 2026-03-21
|
|
4
50
|
|
|
5
51
|
### Removed
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "يمكن تشغيل مفتاح واحد فقط في نفس الوقت. تشغيل واحد يقوم بإيقاف جميع الآخرين تلقائياً.",
|
|
34
34
|
"masterSwitch": "المفتاح الرئيسي",
|
|
35
35
|
"masterSwitchDesc": "يضيف مفتاحاً رئيسياً يقوم بتشغيل أو إيقاف جميع المفاتيح دفعة واحدة.",
|
|
36
|
-
"switchSingular": "مفتاح"
|
|
36
|
+
"switchSingular": "مفتاح",
|
|
37
|
+
"masterSwitchType": "نوع المفتاح الرئيسي"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Es kann nur ein Schalter gleichzeitig eingeschaltet sein. Das Einschalten eines Schalters schaltet alle anderen automatisch aus.",
|
|
34
34
|
"masterSwitch": "Hauptschalter",
|
|
35
35
|
"masterSwitchDesc": "Fügt einen Hauptschalter hinzu, der alle Schalter auf einmal ein- oder ausschaltet.",
|
|
36
|
-
"switchSingular": "Schalter"
|
|
36
|
+
"switchSingular": "Schalter",
|
|
37
|
+
"masterSwitchType": "Hauptschaltertyp"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Only one switch can be on at a time. Turning one on automatically turns off all others.",
|
|
34
34
|
"masterSwitch": "Master Switch",
|
|
35
35
|
"masterSwitchDesc": "Adds a master switch that turns all switches on or off at once.",
|
|
36
|
-
"switchSingular": "switch"
|
|
36
|
+
"switchSingular": "switch",
|
|
37
|
+
"masterSwitchType": "Master Switch Type"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Solo un interruptor puede estar encendido a la vez. Encender uno apaga automáticamente todos los demás.",
|
|
34
34
|
"masterSwitch": "Interruptor maestro",
|
|
35
35
|
"masterSwitchDesc": "Agrega un interruptor maestro que enciende o apaga todos los interruptores a la vez.",
|
|
36
|
-
"switchSingular": "interruptor"
|
|
36
|
+
"switchSingular": "interruptor",
|
|
37
|
+
"masterSwitchType": "Tipo de interruptor maestro"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Un seul interrupteur peut être activé à la fois. En activer un désactive automatiquement tous les autres.",
|
|
34
34
|
"masterSwitch": "Interrupteur principal",
|
|
35
35
|
"masterSwitchDesc": "Ajoute un interrupteur principal qui active ou désactive tous les interrupteurs en une seule fois.",
|
|
36
|
-
"switchSingular": "interrupteur"
|
|
36
|
+
"switchSingular": "interrupteur",
|
|
37
|
+
"masterSwitchType": "Type d'interrupteur principal"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Solo un interruttore può essere acceso alla volta. Accenderne uno spegne automaticamente tutti gli altri.",
|
|
34
34
|
"masterSwitch": "Interruttore principale",
|
|
35
35
|
"masterSwitchDesc": "Aggiunge un interruttore principale che accende o spegne tutti gli interruttori contemporaneamente.",
|
|
36
|
-
"switchSingular": "interruttore"
|
|
36
|
+
"switchSingular": "interruttore",
|
|
37
|
+
"masterSwitchType": "Tipo di interruttore principale"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "同時に1つのスイッチのみオンにできます。1つをオンにすると他はすべて自動的にオフになります。",
|
|
34
34
|
"masterSwitch": "マスタースイッチ",
|
|
35
35
|
"masterSwitchDesc": "すべてのスイッチを一度にオン/オフするマスタースイッチを追加します。",
|
|
36
|
-
"switchSingular": "スイッチ"
|
|
36
|
+
"switchSingular": "スイッチ",
|
|
37
|
+
"masterSwitchType": "マスタースイッチタイプ"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "한 번에 하나의 스위치만 켤 수 있습니다. 하나를 켜면 다른 모든 것이 자동으로 꺼집니다.",
|
|
34
34
|
"masterSwitch": "마스터 스위치",
|
|
35
35
|
"masterSwitchDesc": "모든 스위치를 한 번에 켜거나 끄는 마스터 스위치를 추가합니다.",
|
|
36
|
-
"switchSingular": "스위치"
|
|
36
|
+
"switchSingular": "스위치",
|
|
37
|
+
"masterSwitchType": "마스터 스위치 유형"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Er kan slechts één schakelaar tegelijk aan staan. Het inschakelen van één schakelaar schakelt alle andere automatisch uit.",
|
|
34
34
|
"masterSwitch": "Hoofdschakelaar",
|
|
35
35
|
"masterSwitchDesc": "Voegt een hoofdschakelaar toe die alle schakelaars in één keer in- of uitschakelt.",
|
|
36
|
-
"switchSingular": "schakelaar"
|
|
36
|
+
"switchSingular": "schakelaar",
|
|
37
|
+
"masterSwitchType": "Type hoofdschakelaar"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Tylko jeden przełącznik może być włączony jednocześnie. Włączenie jednego automatycznie wyłącza wszystkie pozostałe.",
|
|
34
34
|
"masterSwitch": "Przełącznik główny",
|
|
35
35
|
"masterSwitchDesc": "Dodaje przełącznik główny, który włącza lub wyłącza wszystkie przełączniki jednocześnie.",
|
|
36
|
-
"switchSingular": "przełącznik"
|
|
36
|
+
"switchSingular": "przełącznik",
|
|
37
|
+
"masterSwitchType": "Typ przełącznika głównego"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Apenas um interruptor pode estar ligado por vez. Ligar um desliga automaticamente todos os outros.",
|
|
34
34
|
"masterSwitch": "Interruptor principal",
|
|
35
35
|
"masterSwitchDesc": "Adiciona um interruptor principal que liga ou desliga todos os interruptores de uma só vez.",
|
|
36
|
-
"switchSingular": "interruptor"
|
|
36
|
+
"switchSingular": "interruptor",
|
|
37
|
+
"masterSwitchType": "Tipo de interruptor principal"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Одновременно может быть включён только один переключатель. Включение одного автоматически выключает все остальные.",
|
|
34
34
|
"masterSwitch": "Главный переключатель",
|
|
35
35
|
"masterSwitchDesc": "Добавляет главный переключатель, который включает или выключает все переключатели одновременно.",
|
|
36
|
-
"switchSingular": "переключатель"
|
|
36
|
+
"switchSingular": "переключатель",
|
|
37
|
+
"masterSwitchType": "Тип главного переключателя"
|
|
37
38
|
}
|
|
@@ -33,5 +33,6 @@
|
|
|
33
33
|
"behaviorSingleDesc": "Aynı anda yalnızca bir anahtar açık olabilir. Birini açmak diğerlerini otomatik kapatır.",
|
|
34
34
|
"masterSwitch": "Ana Anahtar",
|
|
35
35
|
"masterSwitchDesc": "Tüm anahtarları tek seferde açan veya kapatan bir ana anahtar ekler.",
|
|
36
|
-
"switchSingular": "anahtar"
|
|
36
|
+
"switchSingular": "anahtar",
|
|
37
|
+
"masterSwitchType": "Ana Anahtar Tipi"
|
|
37
38
|
}
|
|
@@ -185,14 +185,9 @@
|
|
|
185
185
|
config.devices = [];
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
// Track expand/collapse state
|
|
189
|
-
const expandedDevices = new Set(
|
|
188
|
+
// Track expand/collapse state — all collapsed by default
|
|
189
|
+
const expandedDevices = new Set();
|
|
190
190
|
const expandedSwitches = new Set();
|
|
191
|
-
config.devices.forEach((dev, di) => {
|
|
192
|
-
(dev.switches || []).forEach((_, si) => {
|
|
193
|
-
expandedSwitches.add(`${di}_${si}`);
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
191
|
|
|
197
192
|
const app = document.getElementById('app');
|
|
198
193
|
|
|
@@ -268,8 +263,8 @@
|
|
|
268
263
|
const di = parseInt(input.dataset.dev);
|
|
269
264
|
const field = input.dataset.field;
|
|
270
265
|
config.devices[di][field] = input.value;
|
|
271
|
-
// If switching away from
|
|
272
|
-
if (field === 'switchBehavior' && input.value !== '
|
|
266
|
+
// If switching away from independent, disable masterSwitch
|
|
267
|
+
if (field === 'switchBehavior' && input.value !== 'independent') {
|
|
273
268
|
delete config.devices[di].masterSwitch;
|
|
274
269
|
}
|
|
275
270
|
render();
|
|
@@ -282,6 +277,19 @@
|
|
|
282
277
|
input.addEventListener('change', () => {
|
|
283
278
|
const di = parseInt(input.dataset.dev);
|
|
284
279
|
config.devices[di].masterSwitch = input.checked;
|
|
280
|
+
if (!input.checked) {
|
|
281
|
+
delete config.devices[di].masterSwitchType;
|
|
282
|
+
}
|
|
283
|
+
render();
|
|
284
|
+
save();
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Master switch type
|
|
289
|
+
document.querySelectorAll('.master-type-field').forEach(input => {
|
|
290
|
+
input.addEventListener('change', () => {
|
|
291
|
+
const di = parseInt(input.dataset.dev);
|
|
292
|
+
config.devices[di].masterSwitchType = input.value;
|
|
285
293
|
save();
|
|
286
294
|
});
|
|
287
295
|
});
|
|
@@ -362,6 +370,8 @@
|
|
|
362
370
|
const devLabel = dev.name || `${t.device || 'Device'} #${di + 1}`;
|
|
363
371
|
const switchCount = switches.length;
|
|
364
372
|
const isSingle = dev.switchBehavior === 'single';
|
|
373
|
+
const isIndependent = dev.switchBehavior === 'independent' || !dev.switchBehavior;
|
|
374
|
+
const behaviorDesc = isSingle ? (t.behaviorSingleDesc || '') : (t.behaviorIndependentDesc || '');
|
|
365
375
|
|
|
366
376
|
return `
|
|
367
377
|
<div class="device-card">
|
|
@@ -384,22 +394,30 @@
|
|
|
384
394
|
</div>
|
|
385
395
|
<div class="form-group">
|
|
386
396
|
<label>${t.switchBehavior || 'Switch Behavior Mode'}</label>
|
|
387
|
-
<div class="desc">${isSingle ? (t.behaviorSingleDesc || '') : (t.behaviorIndependentDesc || '')}</div>
|
|
388
397
|
<select class="dev-field" data-dev="${di}" data-field="switchBehavior">
|
|
389
|
-
<option value="independent" ${
|
|
398
|
+
<option value="independent" ${isIndependent ? 'selected' : ''}>${t.behaviorIndependent || 'Independent'}</option>
|
|
390
399
|
<option value="single" ${isSingle ? 'selected' : ''}>${t.behaviorSingle || 'Single'}</option>
|
|
391
400
|
</select>
|
|
401
|
+
<div class="desc" style="margin-top:6px">${behaviorDesc}</div>
|
|
392
402
|
</div>
|
|
393
403
|
</div>
|
|
394
404
|
|
|
395
|
-
${
|
|
405
|
+
${isIndependent ? `
|
|
396
406
|
<div class="master-option">
|
|
397
|
-
<div
|
|
398
|
-
<
|
|
399
|
-
|
|
400
|
-
<
|
|
401
|
-
|
|
407
|
+
<div style="display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap">
|
|
408
|
+
<div class="toggle-wrap" style="flex:1;min-width:0">
|
|
409
|
+
<input type="checkbox" class="master-toggle" data-dev="${di}" ${dev.masterSwitch ? 'checked' : ''}>
|
|
410
|
+
<div>
|
|
411
|
+
<label style="margin-bottom:0">${t.masterSwitch || 'Master Switch'}</label>
|
|
412
|
+
<div class="desc" style="margin-bottom:0">${t.masterSwitchDesc || ''}</div>
|
|
413
|
+
</div>
|
|
402
414
|
</div>
|
|
415
|
+
${dev.masterSwitch ? `
|
|
416
|
+
<select class="master-type-field" data-dev="${di}" style="width:auto;min-width:120px;flex-shrink:0">
|
|
417
|
+
<option value="switch" ${dev.masterSwitchType === 'switch' || !dev.masterSwitchType ? 'selected' : ''}>${t.typeSwitch || 'Switch'}</option>
|
|
418
|
+
<option value="outlet" ${dev.masterSwitchType === 'outlet' ? 'selected' : ''}>${t.typeOutlet || 'Outlet'}</option>
|
|
419
|
+
</select>
|
|
420
|
+
` : ''}
|
|
403
421
|
</div>
|
|
404
422
|
</div>
|
|
405
423
|
` : ''}
|
package/index.js
CHANGED
|
@@ -75,7 +75,7 @@ class MultipleSwitchPlatform {
|
|
|
75
75
|
|
|
76
76
|
const name = device.name || 'Multiple Switch Panel';
|
|
77
77
|
const behavior = device.switchBehavior || 'independent';
|
|
78
|
-
const hasMaster = behavior === '
|
|
78
|
+
const hasMaster = behavior === 'independent' && device.masterSwitch === true;
|
|
79
79
|
const uuid = this.api.hap.uuid.generate(name);
|
|
80
80
|
|
|
81
81
|
let accessory = this.cachedAccessories.get(uuid);
|
|
@@ -92,7 +92,7 @@ class MultipleSwitchPlatform {
|
|
|
92
92
|
const services = new Map();
|
|
93
93
|
this.deviceServices.set(uuid, services);
|
|
94
94
|
|
|
95
|
-
this.reconcileServices(accessory, switches, services, hasMaster);
|
|
95
|
+
this.reconcileServices(accessory, device, switches, services, hasMaster);
|
|
96
96
|
|
|
97
97
|
if (isNew) {
|
|
98
98
|
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
@@ -101,22 +101,51 @@ class MultipleSwitchPlatform {
|
|
|
101
101
|
this.cachedAccessories.delete(uuid);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
setServiceName(service, displayName) {
|
|
105
|
+
service.displayName = displayName;
|
|
106
|
+
service.setCharacteristic(this.Characteristic.Name, displayName);
|
|
107
|
+
if (this.Characteristic.ConfiguredName) {
|
|
108
|
+
if (!service.testCharacteristic(this.Characteristic.ConfiguredName)) {
|
|
109
|
+
service.addOptionalCharacteristic(this.Characteristic.ConfiguredName);
|
|
110
|
+
}
|
|
111
|
+
service.setCharacteristic(this.Characteristic.ConfiguredName, displayName);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
reconcileServices(accessory, device, switches, services, hasMaster) {
|
|
116
|
+
// Remove ALL existing subtype services (ensures fresh names and correct order)
|
|
117
|
+
const subtypeServices = accessory.services.filter((s) => s.subtype);
|
|
118
|
+
subtypeServices.forEach((s) => accessory.removeService(s));
|
|
119
|
+
|
|
120
|
+
// Remove ServiceLabel if left over from previous version
|
|
121
|
+
const existingLabel = accessory.services.find(
|
|
122
|
+
(s) => s.UUID === this.Service.ServiceLabel.UUID
|
|
123
|
+
);
|
|
124
|
+
if (existingLabel) accessory.removeService(existingLabel);
|
|
125
|
+
|
|
126
|
+
// 1. Create master switch FIRST if enabled (appears at top in HomeKit)
|
|
127
|
+
if (hasMaster) {
|
|
128
|
+
const MasterServiceClass = this.getServiceClass(device.masterSwitchType || 'switch');
|
|
129
|
+
const masterService = accessory.addService(MasterServiceClass, 'Master', MASTER_SUBTYPE);
|
|
130
|
+
|
|
131
|
+
this.setServiceName(masterService, 'Master');
|
|
132
|
+
this.configureMasterHandler(accessory, masterService, services);
|
|
133
|
+
|
|
134
|
+
services.set(MASTER_SUBTYPE, masterService);
|
|
135
|
+
|
|
136
|
+
if (accessory.context.switchStates[MASTER_SUBTYPE] === undefined) {
|
|
137
|
+
accessory.context.switchStates[MASTER_SUBTYPE] = false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
106
140
|
|
|
107
|
-
// Create regular switches
|
|
141
|
+
// 2. Create regular switches in config order
|
|
108
142
|
switches.forEach((sw, index) => {
|
|
109
143
|
const subtype = `switch_${index}`;
|
|
110
|
-
activeSubtypes.add(subtype);
|
|
111
144
|
|
|
112
145
|
const ServiceClass = this.getServiceClass(sw.type);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!service) {
|
|
116
|
-
service = accessory.addService(ServiceClass, sw.name, subtype);
|
|
117
|
-
}
|
|
146
|
+
const service = accessory.addService(ServiceClass, sw.name, subtype);
|
|
118
147
|
|
|
119
|
-
|
|
148
|
+
this.setServiceName(service, sw.name);
|
|
120
149
|
this.configureSwitchHandlers(accessory, service, sw, subtype, services);
|
|
121
150
|
|
|
122
151
|
services.set(subtype, service);
|
|
@@ -126,30 +155,13 @@ class MultipleSwitchPlatform {
|
|
|
126
155
|
}
|
|
127
156
|
});
|
|
128
157
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (!masterService) {
|
|
135
|
-
masterService = accessory.addService(this.Service.Switch, 'Master', MASTER_SUBTYPE);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
masterService.setCharacteristic(this.Characteristic.Name, 'Master');
|
|
139
|
-
this.configureMasterHandler(accessory, masterService, services);
|
|
140
|
-
|
|
141
|
-
services.set(MASTER_SUBTYPE, masterService);
|
|
142
|
-
|
|
143
|
-
if (accessory.context.switchStates[MASTER_SUBTYPE] === undefined) {
|
|
144
|
-
accessory.context.switchStates[MASTER_SUBTYPE] = false;
|
|
158
|
+
// Clean up states for removed switches
|
|
159
|
+
const activeKeys = new Set(services.keys());
|
|
160
|
+
for (const key of Object.keys(accessory.context.switchStates)) {
|
|
161
|
+
if (!activeKeys.has(key)) {
|
|
162
|
+
delete accessory.context.switchStates[key];
|
|
145
163
|
}
|
|
146
164
|
}
|
|
147
|
-
|
|
148
|
-
// Remove stale services
|
|
149
|
-
const servicesToRemove = accessory.services.filter((s) => {
|
|
150
|
-
return s.subtype && !activeSubtypes.has(s.subtype);
|
|
151
|
-
});
|
|
152
|
-
servicesToRemove.forEach((s) => accessory.removeService(s));
|
|
153
165
|
}
|
|
154
166
|
|
|
155
167
|
configureSwitchHandlers(accessory, service, sw, subtype, services) {
|
|
@@ -178,8 +190,6 @@ class MultipleSwitchPlatform {
|
|
|
178
190
|
accessory.context.switchStates[MASTER_SUBTYPE] = value;
|
|
179
191
|
this.log.info(`[Master] ${value ? 'ON' : 'OFF'}`);
|
|
180
192
|
|
|
181
|
-
// Master ON → all regular switches ON
|
|
182
|
-
// Master OFF → all regular switches OFF
|
|
183
193
|
for (const [key, svc] of services) {
|
|
184
194
|
if (key !== MASTER_SUBTYPE) {
|
|
185
195
|
accessory.context.switchStates[key] = value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-multiple-switch",
|
|
3
|
-
"version": "1.6.0-beta.
|
|
3
|
+
"version": "1.6.0-beta.10",
|
|
4
4
|
"description": "Multiple switch platform for Homebridge",
|
|
5
5
|
"homepage": "https://github.com/azadaydinli/homebridge-multiple-switch",
|
|
6
6
|
"main": "index.js",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=18.0.0",
|
|
34
|
-
"homebridge": "
|
|
34
|
+
"homebridge": "^1.3.0 || ^2.0.0-beta.0"
|
|
35
35
|
}
|
|
36
36
|
}
|