homebridge-multiple-switch 1.6.0 → 1.7.0-beta.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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.7.0-beta.1] - 2026-05-17
4
+
5
+ ### Changed
6
+ - Switch type (Switch / Outlet) is now configured per device instead of per individual switch
7
+ - All switches within a device share the same type, set once in the device settings
8
+ - Switch cards no longer show a type selector — type is shown in the collapsed summary from the device level
9
+
10
+ ### Fixed
11
+ - Automatic migration: existing configs with per-switch `type` are migrated to device-level `switchType` on first UI save (first switch's type is used as the device type)
12
+
3
13
  ## [1.6.0] - 2026-03-22
4
14
 
5
15
  ### Added
package/README.md CHANGED
@@ -1,25 +1,34 @@
1
- # homebridge-multiple-switch
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/azadaydinli/homebridge-multiple-switch/master/banner.png" width="600">
3
+ </p>
2
4
 
3
- ![CI](https://github.com/azadaydinli/homebridge-multiple-switch/actions/workflows/ci.yml/badge.svg)
5
+ <span align="center">
6
+
7
+ # Homebridge Multiple Switch
8
+
9
+ A lightweight Homebridge plugin that lets you create multiple customizable dummy switches in HomeKit. Supports multi-device, master switch, and 14 languages.
10
+
11
+ [![verified-by-homebridge](https://img.shields.io/badge/homebridge-verified-blueviolet?color=%23491F59&style=flat)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
4
12
  [![npm](https://img.shields.io/npm/v/homebridge-multiple-switch)](https://www.npmjs.com/package/homebridge-multiple-switch)
5
- [![GitHub issues](https://img.shields.io/github/issues/azadaydinli/homebridge-multiple-switch)](https://github.com/azadaydinli/homebridge-multiple-switch/issues)
13
+ [![npm](https://img.shields.io/npm/dt/homebridge-multiple-switch)](https://www.npmjs.com/package/homebridge-multiple-switch)
6
14
  [![GitHub license](https://img.shields.io/github/license/azadaydinli/homebridge-multiple-switch)](https://github.com/azadaydinli/homebridge-multiple-switch/blob/master/LICENSE)
7
15
 
8
- A lightweight Homebridge plugin that lets you create multiple customizable dummy switches under a single accessory — configurable as `Switch`, `Outlet`, `Lightbulb`, or `Fan`.
9
- Supports `Independent`, `Master`, and `Single` switch modes.
16
+ </span>
10
17
 
11
18
  ---
12
19
 
13
20
  ## Features
14
21
 
15
- - Grouped multiple switches in one HomeKit tile
16
- - Accessory type: `switch`, `outlet`, `lightbulb`, or `fan`
22
+ - **Multi-device support** create multiple separate HomeKit accessories
23
+ - Accessory type: `switch` or `outlet`
17
24
  - **Independent Mode** – All switches operate separately
18
- - **Master Mode** – One switch controls all others
19
25
  - **Single Mode** – Only one switch can be active at a time
26
+ - **Master Switch** (Independent mode) — one switch controls all others
20
27
  - Per-switch config support (type, auto-off delay, default state)
21
- - Switch states preserved across Homebridge restarts via cached accessories
22
- - Automatic cleanup of stale accessories on config change
28
+ - Collapsible config UI with dark mode support
29
+ - i18n localization (14 languages)
30
+ - Homebridge v2 compatible
31
+ - Switch states preserved across restarts via cached accessories
23
32
  - Compatible with HomeKit and Siri
24
33
 
25
34
  ---
@@ -47,23 +56,40 @@ Configure from Homebridge UI or manually edit `config.json`:
47
56
  ```json
48
57
  {
49
58
  "platform": "MultipleSwitchPlatform",
50
- "name": "Multiple Switches",
51
- "switchBehavior": "single",
52
- "switches": [
59
+ "name": "Multiple Switch Platform",
60
+ "devices": [
53
61
  {
54
- "name": "Heater",
55
- "type": "outlet",
56
- "defaultState": true,
57
- "delayOff": 10000
62
+ "name": "Living Room",
63
+ "switchBehavior": "independent",
64
+ "masterSwitch": true,
65
+ "masterSwitchType": "switch",
66
+ "switches": [
67
+ {
68
+ "name": "Lamp",
69
+ "type": "outlet",
70
+ "defaultState": false,
71
+ "delayOff": 0
72
+ },
73
+ {
74
+ "name": "Heater",
75
+ "type": "switch",
76
+ "delayOff": 10000
77
+ }
78
+ ]
58
79
  },
59
80
  {
60
- "name": "Fan",
61
- "type": "fan"
62
- },
63
- {
64
- "name": "Light",
65
- "type": "lightbulb",
66
- "delayOff": 5000
81
+ "name": "Bedroom",
82
+ "switchBehavior": "single",
83
+ "switches": [
84
+ {
85
+ "name": "Scene 1",
86
+ "type": "switch"
87
+ },
88
+ {
89
+ "name": "Scene 2",
90
+ "type": "switch"
91
+ }
92
+ ]
67
93
  }
68
94
  ]
69
95
  }
@@ -73,19 +99,28 @@ Configure from Homebridge UI or manually edit `config.json`:
73
99
 
74
100
  ### Platform Options
75
101
 
76
- | Field | Type | Required | Description |
77
- |------------------|--------|----------|--------------------------------------|
78
- | `name` | string | Yes | Name of the platform instance |
79
- | `switchBehavior` | string | No | `independent`, `master`, or `single` |
80
- | `switches` | array | Yes | List of switches to create |
102
+ | Field | Type | Required | Description |
103
+ |-----------|--------|----------|-------------------------------|
104
+ | `name` | string | Yes | Name of the platform instance |
105
+ | `devices` | array | Yes | List of devices to create |
106
+
107
+ ### Device Options
108
+
109
+ | Field | Type | Required | Description |
110
+ |--------------------|---------|----------|-------------------------------------------------|
111
+ | `name` | string | Yes | Device name (becomes HomeKit accessory name) |
112
+ | `switchBehavior` | string | No | `independent` or `single` (default: independent) |
113
+ | `masterSwitch` | boolean | No | Enable master switch (Independent mode only) |
114
+ | `masterSwitchType` | string | No | `switch` or `outlet` (default: switch) |
115
+ | `switches` | array | Yes | List of switches for this device |
81
116
 
82
117
  ### Per-Switch Options
83
118
 
84
- | Field | Type | Required | Description |
85
- |----------------|---------|----------|--------------------------------------------------|
86
- | `name` | string | Yes | Name of the switch |
87
- | `type` | string | No | `switch`, `outlet`, `lightbulb`, or `fan` |
88
- | `defaultState` | boolean | No | Initial power state (default: `false`) |
119
+ | Field | Type | Required | Description |
120
+ |----------------|---------|----------|---------------------------------------------------|
121
+ | `name` | string | Yes | Name of the switch |
122
+ | `type` | string | No | `switch` or `outlet` (default: outlet) |
123
+ | `defaultState` | boolean | No | Initial power state (default: `false`) |
89
124
  | `delayOff` | number | No | Auto turn off after N milliseconds (default: `0`) |
90
125
 
91
126
  ---
@@ -95,7 +130,7 @@ Configure from Homebridge UI or manually edit `config.json`:
95
130
  - Simulate smart plugs for automation testing
96
131
  - Trigger HomeKit scenes manually
97
132
  - Create virtual switches for non-HomeKit devices
98
- - Combine several virtual accessories under one tile
133
+ - Group several virtual accessories under one device
99
134
 
100
135
  ---
101
136
 
package/banner.png ADDED
Binary file
@@ -34,6 +34,16 @@
34
34
  { "title": "Single", "enum": ["single"] }
35
35
  ]
36
36
  },
37
+ "switchType": {
38
+ "title": "Switch Type",
39
+ "description": "The HomeKit accessory type for all switches in this device.",
40
+ "type": "string",
41
+ "default": "outlet",
42
+ "oneOf": [
43
+ { "title": "Switch", "enum": ["switch"] },
44
+ { "title": "Outlet", "enum": ["outlet"] }
45
+ ]
46
+ },
37
47
  "masterSwitch": {
38
48
  "title": "Master Switch",
39
49
  "description": "Add a master switch that turns all switches on or off at once. Only available in Single mode.",
@@ -52,16 +62,6 @@
52
62
  "description": "Display name of the switch in HomeKit.",
53
63
  "type": "string"
54
64
  },
55
- "type": {
56
- "title": "Switch Type",
57
- "description": "The HomeKit accessory type for this switch.",
58
- "type": "string",
59
- "default": "outlet",
60
- "oneOf": [
61
- { "title": "Switch", "enum": ["switch"] },
62
- { "title": "Outlet", "enum": ["outlet"] }
63
- ]
64
- },
65
65
  "defaultState": {
66
66
  "title": "Default State",
67
67
  "description": "Initial power state when Homebridge starts.",
@@ -11,7 +11,7 @@
11
11
  "switchName": "اسم المفتاح",
12
12
  "switchNameDesc": "اسم العرض للمفتاح في HomeKit.",
13
13
  "switchType": "نوع المفتاح",
14
- "switchTypeDesc": "نوع ملحق HomeKit لهذا المفتاح.",
14
+ "switchTypeDesc": "نوع ملحق HomeKit لجميع المفاتيح في هذا الجهاز.",
15
15
  "typeSwitch": "مفتاح",
16
16
  "typeOutlet": "مقبس",
17
17
  "defaultState": "الحالة الافتراضية",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Schaltername",
12
12
  "switchNameDesc": "Anzeigename des Schalters in HomeKit.",
13
13
  "switchType": "Schaltertyp",
14
- "switchTypeDesc": "Der HomeKit-Zubehörtyp für diesen Schalter.",
14
+ "switchTypeDesc": "Der HomeKit-Zubehörtyp für alle Schalter in diesem Gerät.",
15
15
  "typeSwitch": "Schalter",
16
16
  "typeOutlet": "Steckdose",
17
17
  "defaultState": "Standardzustand",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Switch Name",
12
12
  "switchNameDesc": "Display name of the switch in HomeKit.",
13
13
  "switchType": "Switch Type",
14
- "switchTypeDesc": "The HomeKit accessory type for this switch.",
14
+ "switchTypeDesc": "The HomeKit accessory type for all switches in this device.",
15
15
  "typeSwitch": "Switch",
16
16
  "typeOutlet": "Outlet",
17
17
  "defaultState": "Default State",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Nombre del interruptor",
12
12
  "switchNameDesc": "Nombre visible del interruptor en HomeKit.",
13
13
  "switchType": "Tipo de interruptor",
14
- "switchTypeDesc": "El tipo de accesorio HomeKit para este interruptor.",
14
+ "switchTypeDesc": "El tipo de accesorio HomeKit para todos los interruptores de este dispositivo.",
15
15
  "typeSwitch": "Interruptor",
16
16
  "typeOutlet": "Enchufe",
17
17
  "defaultState": "Estado predeterminado",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Nom de l'interrupteur",
12
12
  "switchNameDesc": "Nom affiché de l'interrupteur dans HomeKit.",
13
13
  "switchType": "Type d'interrupteur",
14
- "switchTypeDesc": "Le type d'accessoire HomeKit pour cet interrupteur.",
14
+ "switchTypeDesc": "Le type d'accessoire HomeKit pour tous les interrupteurs de cet appareil.",
15
15
  "typeSwitch": "Interrupteur",
16
16
  "typeOutlet": "Prise",
17
17
  "defaultState": "État par défaut",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Nome dell'interruttore",
12
12
  "switchNameDesc": "Nome visualizzato dell'interruttore in HomeKit.",
13
13
  "switchType": "Tipo di interruttore",
14
- "switchTypeDesc": "Il tipo di accessorio HomeKit per questo interruttore.",
14
+ "switchTypeDesc": "Il tipo di accessorio HomeKit per tutti gli interruttori in questo dispositivo.",
15
15
  "typeSwitch": "Interruttore",
16
16
  "typeOutlet": "Presa",
17
17
  "defaultState": "Stato predefinito",
@@ -11,7 +11,7 @@
11
11
  "switchName": "スイッチ名",
12
12
  "switchNameDesc": "HomeKit でのスイッチの表示名。",
13
13
  "switchType": "スイッチタイプ",
14
- "switchTypeDesc": "このスイッチの HomeKit アクセサリタイプ。",
14
+ "switchTypeDesc": "このデバイス内のすべてのスイッチの HomeKit アクセサリタイプ。",
15
15
  "typeSwitch": "スイッチ",
16
16
  "typeOutlet": "コンセント",
17
17
  "defaultState": "デフォルト状態",
@@ -11,7 +11,7 @@
11
11
  "switchName": "스위치 이름",
12
12
  "switchNameDesc": "HomeKit에서 스위치의 표시 이름.",
13
13
  "switchType": "스위치 유형",
14
- "switchTypeDesc": "이 스위치의 HomeKit 액세서리 유형.",
14
+ "switchTypeDesc": "이 장치의 모든 스위치에 적용되는 HomeKit 액세서리 유형.",
15
15
  "typeSwitch": "스위치",
16
16
  "typeOutlet": "콘센트",
17
17
  "defaultState": "기본 상태",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Schakelaarnaam",
12
12
  "switchNameDesc": "Weergavenaam van de schakelaar in HomeKit.",
13
13
  "switchType": "Schakelaartype",
14
- "switchTypeDesc": "Het HomeKit-accessoiretype voor deze schakelaar.",
14
+ "switchTypeDesc": "Het HomeKit-accessoiretype voor alle schakelaars in dit apparaat.",
15
15
  "typeSwitch": "Schakelaar",
16
16
  "typeOutlet": "Stopcontact",
17
17
  "defaultState": "Standaardstatus",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Nazwa przełącznika",
12
12
  "switchNameDesc": "Wyświetlana nazwa przełącznika w HomeKit.",
13
13
  "switchType": "Typ przełącznika",
14
- "switchTypeDesc": "Typ akcesorium HomeKit dla tego przełącznika.",
14
+ "switchTypeDesc": "Typ akcesorium HomeKit dla wszystkich przełączników w tym urządzeniu.",
15
15
  "typeSwitch": "Przełącznik",
16
16
  "typeOutlet": "Gniazdko",
17
17
  "defaultState": "Stan domyślny",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Nome do interruptor",
12
12
  "switchNameDesc": "Nome de exibição do interruptor no HomeKit.",
13
13
  "switchType": "Tipo de interruptor",
14
- "switchTypeDesc": "O tipo de acessório HomeKit para este interruptor.",
14
+ "switchTypeDesc": "O tipo de acessório HomeKit para todos os interruptores deste dispositivo.",
15
15
  "typeSwitch": "Interruptor",
16
16
  "typeOutlet": "Tomada",
17
17
  "defaultState": "Estado padrão",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Название переключателя",
12
12
  "switchNameDesc": "Отображаемое имя переключателя в HomeKit.",
13
13
  "switchType": "Тип переключателя",
14
- "switchTypeDesc": "Тип аксессуара HomeKit для этого переключателя.",
14
+ "switchTypeDesc": "Тип аксессуара HomeKit для всех переключателей в этом устройстве.",
15
15
  "typeSwitch": "Выключатель",
16
16
  "typeOutlet": "Розетка",
17
17
  "defaultState": "Состояние по умолчанию",
@@ -11,7 +11,7 @@
11
11
  "switchName": "Anahtar Adı",
12
12
  "switchNameDesc": "Anahtarın HomeKit'teki görünen adı.",
13
13
  "switchType": "Anahtar Tipi",
14
- "switchTypeDesc": "Bu anahtar için HomeKit aksesuar tipi.",
14
+ "switchTypeDesc": "Bu cihazdaki tüm anahtarlar için HomeKit aksesuar tipi.",
15
15
  "typeSwitch": "Anahtar",
16
16
  "typeOutlet": "Priz",
17
17
  "defaultState": "Varsayılan Durum",
@@ -11,7 +11,7 @@
11
11
  "switchName": "开关名称",
12
12
  "switchNameDesc": "开关在 HomeKit 中的显示名称。",
13
13
  "switchType": "开关类型",
14
- "switchTypeDesc": "此开关的 HomeKit 配件类型。",
14
+ "switchTypeDesc": "此设备中所有开关的 HomeKit 配件类型。",
15
15
  "typeSwitch": "开关",
16
16
  "typeOutlet": "插座",
17
17
  "defaultState": "默认状态",
@@ -181,6 +181,18 @@
181
181
  delete config.switchBehavior;
182
182
  }
183
183
 
184
+ // Migrate per-switch type to device-level switchType
185
+ if (Array.isArray(config.devices)) {
186
+ config.devices.forEach(dev => {
187
+ if (!dev.switchType && Array.isArray(dev.switches) && dev.switches.length > 0) {
188
+ dev.switchType = dev.switches[0].type || 'outlet';
189
+ }
190
+ if (Array.isArray(dev.switches)) {
191
+ dev.switches.forEach(sw => { delete sw.type; });
192
+ }
193
+ });
194
+ }
195
+
184
196
  if (!config.devices) {
185
197
  config.devices = [];
186
198
  }
@@ -387,7 +399,7 @@
387
399
  </div>
388
400
 
389
401
  <div class="device-body ${isOpen ? '' : 'collapsed'}">
390
- <div class="inline-row">
402
+ <div class="inline-row" style="grid-template-columns: 1fr 1fr 1fr">
391
403
  <div class="form-group">
392
404
  <label>${t.deviceName || 'Device Name'}</label>
393
405
  <input type="text" class="dev-field" data-dev="${di}" data-field="name" value="${esc(dev.name || '')}">
@@ -400,6 +412,14 @@
400
412
  </select>
401
413
  <div class="desc" style="margin-top:6px">${behaviorDesc}</div>
402
414
  </div>
415
+ <div class="form-group">
416
+ <label>${t.switchType || 'Switch Type'}</label>
417
+ <div class="desc">${t.switchTypeDesc || ''}</div>
418
+ <select class="dev-field" data-dev="${di}" data-field="switchType">
419
+ <option value="outlet" ${!dev.switchType || dev.switchType === 'outlet' ? 'selected' : ''}>${t.typeOutlet || 'Outlet'}</option>
420
+ <option value="switch" ${dev.switchType === 'switch' ? 'selected' : ''}>${t.typeSwitch || 'Switch'}</option>
421
+ </select>
422
+ </div>
403
423
  </div>
404
424
 
405
425
  ${isIndependent ? `
@@ -424,7 +444,7 @@
424
444
 
425
445
  <div class="section-title" style="margin-top:16px">${t.switches || 'Switches'}</div>
426
446
 
427
- ${switches.map((sw, si) => renderSwitch(sw, di, si)).join('')}
447
+ ${switches.map((sw, si) => renderSwitch(sw, di, si, dev.switchType || 'outlet')).join('')}
428
448
 
429
449
  <button class="btn btn-primary btn-add-switch" data-dev="${di}">+ ${t.addSwitch || 'Add Switch'}</button>
430
450
  </div>
@@ -432,9 +452,10 @@
432
452
  `;
433
453
  }
434
454
 
435
- function renderSwitch(sw, di, si) {
455
+ function renderSwitch(sw, di, si, deviceSwitchType) {
436
456
  const isOpen = expandedSwitches.has(`${di}_${si}`);
437
457
  const swLabel = sw.name || `#${si + 1}`;
458
+ const typeLabel = deviceSwitchType === 'switch' ? (t.typeSwitch || 'Switch') : (t.typeOutlet || 'Outlet');
438
459
 
439
460
  return `
440
461
  <div class="switch-card">
@@ -442,7 +463,7 @@
442
463
  <div class="switch-header-left">
443
464
  <span class="chevron ${isOpen ? 'open' : ''}">&#9654;</span>
444
465
  <strong>${esc(swLabel)}</strong>
445
- ${!isOpen ? `<span class="switch-summary">${sw.type || 'outlet'}${sw.delayOff ? ` / ${sw.delayOff}ms` : ''}</span>` : ''}
466
+ ${!isOpen ? `<span class="switch-summary">${typeLabel}${sw.delayOff ? ` / ${sw.delayOff}ms` : ''}</span>` : ''}
446
467
  </div>
447
468
  <div class="switch-header-right">
448
469
  <button class="btn btn-danger btn-sm btn-remove-switch" data-dev="${di}" data-sw="${si}">${t.removeSwitch || 'Remove'}</button>
@@ -454,25 +475,16 @@
454
475
  <label>${t.switchName || 'Switch Name'}</label>
455
476
  <input type="text" class="sw-field" data-dev="${di}" data-sw="${si}" data-field="name" value="${esc(sw.name || '')}">
456
477
  </div>
457
- <div class="form-group">
458
- <label>${t.switchType || 'Switch Type'}</label>
459
- <select class="sw-field" data-dev="${di}" data-sw="${si}" data-field="type">
460
- <option value="switch" ${sw.type === 'switch' ? 'selected' : ''}>${t.typeSwitch || 'Switch'}</option>
461
- <option value="outlet" ${sw.type === 'outlet' || !sw.type ? 'selected' : ''}>${t.typeOutlet || 'Outlet'}</option>
462
- </select>
463
- </div>
464
- </div>
465
- <div class="inline-row">
466
478
  <div class="form-group">
467
479
  <label>${t.delayOff || 'Auto Turn Off (ms)'}</label>
468
480
  <input type="number" class="sw-field" data-dev="${di}" data-sw="${si}" data-field="delayOff" min="0" value="${sw.delayOff || 0}">
469
481
  </div>
470
- <div class="form-group">
471
- <label>${t.defaultState || 'Default State'}</label>
472
- <div class="toggle-wrap" style="margin-top:6px">
473
- <input type="checkbox" class="sw-field" data-dev="${di}" data-sw="${si}" data-field="defaultState" ${sw.defaultState ? 'checked' : ''}>
474
- <span>${sw.defaultState ? (t.on || 'On') : (t.off || 'Off')}</span>
475
- </div>
482
+ </div>
483
+ <div class="form-group">
484
+ <label>${t.defaultState || 'Default State'}</label>
485
+ <div class="toggle-wrap" style="margin-top:6px">
486
+ <input type="checkbox" class="sw-field" data-dev="${di}" data-sw="${si}" data-field="defaultState" ${sw.defaultState ? 'checked' : ''}>
487
+ <span>${sw.defaultState ? (t.on || 'On') : (t.off || 'Off')}</span>
476
488
  </div>
477
489
  </div>
478
490
  </div>
package/index.js CHANGED
@@ -133,10 +133,11 @@ class MultipleSwitchPlatform {
133
133
  }
134
134
 
135
135
  // Create regular switches
136
+ const switchType = device.switchType || (switches[0] && switches[0].type) || 'outlet';
136
137
  switches.forEach((sw, index) => {
137
138
  const subtype = `switch_${index}`;
138
139
 
139
- const ServiceClass = this.getServiceClass(sw.type);
140
+ const ServiceClass = this.getServiceClass(switchType);
140
141
  const service = accessory.addService(ServiceClass, sw.name, subtype);
141
142
 
142
143
  this.setServiceName(service, sw.name);
package/logo.png ADDED
Binary file
package/logo.svg ADDED
@@ -0,0 +1,102 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#1a1a2e"/>
5
+ <stop offset="50%" style="stop-color:#16213e"/>
6
+ <stop offset="100%" style="stop-color:#0f3460"/>
7
+ </linearGradient>
8
+ <linearGradient id="glowGreen" x1="0%" y1="0%" x2="0%" y2="100%">
9
+ <stop offset="0%" style="stop-color:#00ff88"/>
10
+ <stop offset="100%" style="stop-color:#00cc6a"/>
11
+ </linearGradient>
12
+ <linearGradient id="glowAmber" x1="0%" y1="0%" x2="0%" y2="100%">
13
+ <stop offset="0%" style="stop-color:#ffb347"/>
14
+ <stop offset="100%" style="stop-color:#ff8c00"/>
15
+ </linearGradient>
16
+ <linearGradient id="glowBlue" x1="0%" y1="0%" x2="0%" y2="100%">
17
+ <stop offset="0%" style="stop-color:#00d4ff"/>
18
+ <stop offset="100%" style="stop-color:#0099cc"/>
19
+ </linearGradient>
20
+ <linearGradient id="ringGrad" x1="0%" y1="0%" x2="100%" y2="100%">
21
+ <stop offset="0%" style="stop-color:rgba(255,255,255,0.15)"/>
22
+ <stop offset="100%" style="stop-color:rgba(255,255,255,0.03)"/>
23
+ </linearGradient>
24
+ <filter id="glowFilter1">
25
+ <feGaussianBlur stdDeviation="12" result="blur"/>
26
+ <feMerge>
27
+ <feMergeNode in="blur"/>
28
+ <feMergeNode in="SourceGraphic"/>
29
+ </feMerge>
30
+ </filter>
31
+ <filter id="glowFilter2">
32
+ <feGaussianBlur stdDeviation="8" result="blur"/>
33
+ <feMerge>
34
+ <feMergeNode in="blur"/>
35
+ <feMergeNode in="SourceGraphic"/>
36
+ </feMerge>
37
+ </filter>
38
+ <filter id="softShadow">
39
+ <feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#000" flood-opacity="0.4"/>
40
+ </filter>
41
+ </defs>
42
+
43
+ <!-- Background -->
44
+ <rect width="512" height="512" rx="112" fill="url(#bg)"/>
45
+
46
+ <!-- Subtle grid pattern -->
47
+ <line x1="256" y1="80" x2="256" y2="432" stroke="rgba(255,255,255,0.03)" stroke-width="1"/>
48
+ <line x1="80" y1="256" x2="432" y2="256" stroke="rgba(255,255,255,0.03)" stroke-width="1"/>
49
+
50
+ <!-- Central hub ring -->
51
+ <circle cx="256" cy="256" r="155" fill="none" stroke="url(#ringGrad)" stroke-width="2"/>
52
+ <circle cx="256" cy="256" r="90" fill="none" stroke="rgba(255,255,255,0.06)" stroke-width="1.5"/>
53
+
54
+ <!-- Connection lines from center to switches -->
55
+ <line x1="256" y1="256" x2="160" y2="160" stroke="rgba(0,255,136,0.25)" stroke-width="2" stroke-dasharray="4,4"/>
56
+ <line x1="256" y1="256" x2="352" y2="160" stroke="rgba(0,212,255,0.25)" stroke-width="2" stroke-dasharray="4,4"/>
57
+ <line x1="256" y1="256" x2="160" y2="352" stroke="rgba(255,179,71,0.25)" stroke-width="2" stroke-dasharray="4,4"/>
58
+ <line x1="256" y1="256" x2="352" y2="352" stroke="rgba(255,255,255,0.1)" stroke-width="2" stroke-dasharray="4,4"/>
59
+
60
+ <!-- Switch 1 — Top Left — Green (ON) -->
61
+ <g filter="url(#glowFilter1)">
62
+ <circle cx="160" cy="160" r="8" fill="#00ff88" opacity="0.3"/>
63
+ </g>
64
+ <circle cx="160" cy="160" r="38" fill="rgba(0,255,136,0.08)" stroke="rgba(0,255,136,0.4)" stroke-width="2"/>
65
+ <circle cx="160" cy="160" r="22" fill="rgba(0,255,136,0.12)" stroke="rgba(0,255,136,0.6)" stroke-width="1.5"/>
66
+ <!-- Power icon -->
67
+ <line x1="160" y1="146" x2="160" y2="155" stroke="#00ff88" stroke-width="3" stroke-linecap="round"/>
68
+ <path d="M 149 153 A 14 14 0 1 0 171 153" fill="none" stroke="#00ff88" stroke-width="2.5" stroke-linecap="round"/>
69
+
70
+ <!-- Switch 2 — Top Right — Blue (ON) -->
71
+ <g filter="url(#glowFilter1)">
72
+ <circle cx="352" cy="160" r="8" fill="#00d4ff" opacity="0.3"/>
73
+ </g>
74
+ <circle cx="352" cy="160" r="38" fill="rgba(0,212,255,0.08)" stroke="rgba(0,212,255,0.4)" stroke-width="2"/>
75
+ <circle cx="352" cy="160" r="22" fill="rgba(0,212,255,0.12)" stroke="rgba(0,212,255,0.6)" stroke-width="1.5"/>
76
+ <!-- Power icon -->
77
+ <line x1="352" y1="146" x2="352" y2="155" stroke="#00d4ff" stroke-width="3" stroke-linecap="round"/>
78
+ <path d="M 341 153 A 14 14 0 1 0 363 153" fill="none" stroke="#00d4ff" stroke-width="2.5" stroke-linecap="round"/>
79
+
80
+ <!-- Switch 3 — Bottom Left — Amber (ON) -->
81
+ <g filter="url(#glowFilter1)">
82
+ <circle cx="160" cy="352" r="8" fill="#ffb347" opacity="0.3"/>
83
+ </g>
84
+ <circle cx="160" cy="352" r="38" fill="rgba(255,179,71,0.08)" stroke="rgba(255,179,71,0.4)" stroke-width="2"/>
85
+ <circle cx="160" cy="352" r="22" fill="rgba(255,179,71,0.12)" stroke="rgba(255,179,71,0.6)" stroke-width="1.5"/>
86
+ <!-- Power icon -->
87
+ <line x1="160" y1="338" x2="160" y2="347" stroke="#ffb347" stroke-width="3" stroke-linecap="round"/>
88
+ <path d="M 149 345 A 14 14 0 1 0 171 345" fill="none" stroke="#ffb347" stroke-width="2.5" stroke-linecap="round"/>
89
+
90
+ <!-- Switch 4 — Bottom Right — OFF -->
91
+ <circle cx="352" cy="352" r="38" fill="rgba(255,255,255,0.03)" stroke="rgba(255,255,255,0.12)" stroke-width="2"/>
92
+ <circle cx="352" cy="352" r="22" fill="rgba(255,255,255,0.04)" stroke="rgba(255,255,255,0.15)" stroke-width="1.5"/>
93
+ <!-- Power icon (dimmed) -->
94
+ <line x1="352" y1="338" x2="352" y2="347" stroke="rgba(255,255,255,0.2)" stroke-width="3" stroke-linecap="round"/>
95
+ <path d="M 341 345 A 14 14 0 1 0 363 345" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="2.5" stroke-linecap="round"/>
96
+
97
+ <!-- Center hub -->
98
+ <circle cx="256" cy="256" r="32" fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.15)" stroke-width="2"/>
99
+ <circle cx="256" cy="256" r="18" fill="rgba(255,255,255,0.08)" stroke="rgba(255,255,255,0.2)" stroke-width="1.5"/>
100
+ <!-- HomeKit house icon in center -->
101
+ <path d="M 245 260 L 256 249 L 267 260 L 267 270 L 261 270 L 261 263 L 251 263 L 251 270 L 245 270 Z" fill="rgba(255,255,255,0.7)" filter="url(#softShadow)"/>
102
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-multiple-switch",
3
- "version": "1.6.0",
3
+ "version": "1.7.0-beta.1",
4
4
  "description": "Multiple switch platform for Homebridge",
5
5
  "homepage": "https://github.com/azadaydinli/homebridge-multiple-switch",
6
6
  "main": "index.js",