homebridge-multiple-switch 1.2.0 → 1.3.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/.github/workflows/ci.yml +9 -20
- package/.github/workflows/release.yml +7 -7
- package/CHANGELOG.md +40 -0
- package/README.md +30 -30
- package/config.schema.json +8 -1
- package/i18n/ar.json +46 -0
- package/i18n/de.json +46 -0
- package/i18n/en.json +46 -0
- package/i18n/es.json +46 -0
- package/i18n/fr.json +46 -0
- package/i18n/it.json +46 -0
- package/i18n/ja.json +46 -0
- package/i18n/ko.json +46 -0
- package/i18n/nl.json +46 -0
- package/i18n/pl.json +46 -0
- package/i18n/pt.json +46 -0
- package/i18n/ru.json +46 -0
- package/i18n/tr.json +46 -0
- package/i18n/zh-CN.json +46 -0
- package/index.js +116 -65
- package/package.json +6 -2
- package/.github/workflows/release.yml.save +0 -28
- package/.github/workflows/release.yml.save.1 +0 -28
- package/.github/workflows/release.yml.save.2 +0 -28
package/.github/workflows/ci.yml
CHANGED
|
@@ -11,31 +11,20 @@ jobs:
|
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
|
|
13
13
|
steps:
|
|
14
|
-
- name:
|
|
15
|
-
uses: actions/checkout@
|
|
14
|
+
- name: Checkout
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
16
|
|
|
17
|
-
- name:
|
|
18
|
-
uses: actions/setup-node@
|
|
17
|
+
- name: Setup Node.js
|
|
18
|
+
uses: actions/setup-node@v4
|
|
19
19
|
with:
|
|
20
20
|
node-version: '18'
|
|
21
21
|
cache: 'npm'
|
|
22
22
|
|
|
23
|
-
- name:
|
|
23
|
+
- name: Install dependencies
|
|
24
24
|
run: npm install
|
|
25
25
|
|
|
26
|
-
- name:
|
|
27
|
-
run:
|
|
28
|
-
if [ -f .eslintrc.js ] || [ -f .eslintrc.json ]; then
|
|
29
|
-
npm run lint
|
|
30
|
-
else
|
|
31
|
-
echo "Lint skripti tapılmadı, keçilir..."
|
|
32
|
-
fi
|
|
33
|
-
|
|
34
|
-
- name: 🧪 Testləri icra et (əgər varsa)
|
|
35
|
-
run: |
|
|
36
|
-
if [ -f package.json ] && grep -q '\"test\"' package.json; then
|
|
37
|
-
npm test
|
|
38
|
-
else
|
|
39
|
-
echo "Test skripti yoxdur, keçilir..."
|
|
40
|
-
fi
|
|
26
|
+
- name: Lint
|
|
27
|
+
run: npm run lint
|
|
41
28
|
|
|
29
|
+
- name: Test
|
|
30
|
+
run: npm test
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: Publish to npm
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -10,19 +10,19 @@ jobs:
|
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
|
|
12
12
|
steps:
|
|
13
|
-
- name:
|
|
14
|
-
uses: actions/checkout@
|
|
13
|
+
- name: Checkout
|
|
14
|
+
uses: actions/checkout@v4
|
|
15
15
|
|
|
16
|
-
- name:
|
|
17
|
-
uses: actions/setup-node@
|
|
16
|
+
- name: Setup Node.js
|
|
17
|
+
uses: actions/setup-node@v4
|
|
18
18
|
with:
|
|
19
19
|
node-version: '18'
|
|
20
20
|
registry-url: 'https://registry.npmjs.org/'
|
|
21
21
|
|
|
22
|
-
- name:
|
|
22
|
+
- name: Install dependencies
|
|
23
23
|
run: npm install
|
|
24
24
|
|
|
25
|
-
- name:
|
|
25
|
+
- name: Publish to npm
|
|
26
26
|
run: npm publish
|
|
27
27
|
env:
|
|
28
28
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.3.1] - 2026-03-21
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- i18n localization support for Homebridge UI config with 14 languages:
|
|
7
|
+
English, Turkish, German, French, Spanish, Portuguese, Italian, Russian,
|
|
8
|
+
Chinese (Simplified), Japanese, Korean, Polish, Dutch, Arabic
|
|
9
|
+
- Descriptions added to all config.schema.json fields
|
|
10
|
+
|
|
11
|
+
## [1.3.0] - 2026-03-21
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Replaced global mutable variables with instance properties
|
|
15
|
+
- Refactored accessory setup to reuse cached accessories instead of creating duplicates on restart
|
|
16
|
+
- Extracted switch behavior logic into dedicated methods (`turnOffOthers`, `setAll`, `scheduleAutoOff`)
|
|
17
|
+
- Used `Map` for service and accessory tracking instead of plain objects
|
|
18
|
+
- Service type lookup uses a constant map instead of a switch statement
|
|
19
|
+
- Auto-off now checks current state before turning off (prevents stale timeouts)
|
|
20
|
+
- Updated minimum Node.js version from 14 to 18
|
|
21
|
+
- Updated GitHub Actions from v3 to v4
|
|
22
|
+
- Cleaned up CI workflow
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- `delayOff` not working in `master` mode due to if/else logic bug
|
|
26
|
+
- Cached accessories not being restored on Homebridge restart (caused duplicate accessories)
|
|
27
|
+
- Services stored in `accessory.context` which is not serializable
|
|
28
|
+
- README field names (`autoTurnOff`, `mode`) now match actual config schema (`delayOff`, `switchBehavior`)
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- Automatic removal of stale cached accessories when config changes
|
|
32
|
+
- Service reconciliation: adds new services and removes old ones on config update
|
|
33
|
+
- Validation for empty or missing switches array
|
|
34
|
+
|
|
35
|
+
## [1.2.0] - 2025-01-01
|
|
36
|
+
|
|
37
|
+
- Initial published version with independent, master, and single switch modes
|
|
38
|
+
- Support for switch, outlet, lightbulb, and fan accessory types
|
|
39
|
+
- Per-switch config: type, defaultState, delayOff
|
|
40
|
+
- Homebridge UI config schema
|
package/README.md
CHANGED
|
@@ -5,26 +5,26 @@
|
|
|
5
5
|
[](https://github.com/azadaydinli/homebridge-multiple-switch/issues)
|
|
6
6
|
[](https://github.com/azadaydinli/homebridge-multiple-switch/blob/master/LICENSE)
|
|
7
7
|
|
|
8
|
-
A lightweight Homebridge plugin that lets you create multiple customizable dummy switches under a single accessory — configurable as `Switch`, `Outlet`, `Lightbulb`, or `Fan`.
|
|
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
9
|
Supports `Independent`, `Master`, and `Single` switch modes.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Features
|
|
14
14
|
|
|
15
15
|
- Grouped multiple switches in one HomeKit tile
|
|
16
16
|
- Accessory type: `switch`, `outlet`, `lightbulb`, or `fan`
|
|
17
17
|
- **Independent Mode** – All switches operate separately
|
|
18
|
-
- **Master Mode** – One
|
|
18
|
+
- **Master Mode** – One switch controls all others
|
|
19
19
|
- **Single Mode** – Only one switch can be active at a time
|
|
20
|
-
- Per-switch config support (type, auto-off, default state)
|
|
21
|
-
- Switch states
|
|
22
|
-
-
|
|
20
|
+
- 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
|
|
23
23
|
- Compatible with HomeKit and Siri
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
##
|
|
27
|
+
## Installation
|
|
28
28
|
|
|
29
29
|
Install via Homebridge UI:
|
|
30
30
|
|
|
@@ -40,20 +40,21 @@ npm install -g homebridge-multiple-switch
|
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## Configuration
|
|
44
44
|
|
|
45
|
-
Configure from Homebridge UI or manually edit `config.json
|
|
45
|
+
Configure from Homebridge UI or manually edit `config.json`:
|
|
46
46
|
|
|
47
47
|
```json
|
|
48
48
|
{
|
|
49
49
|
"platform": "MultipleSwitchPlatform",
|
|
50
50
|
"name": "Multiple Switches",
|
|
51
|
+
"switchBehavior": "single",
|
|
51
52
|
"switches": [
|
|
52
53
|
{
|
|
53
54
|
"name": "Heater",
|
|
54
55
|
"type": "outlet",
|
|
55
56
|
"defaultState": true,
|
|
56
|
-
"
|
|
57
|
+
"delayOff": 10000
|
|
57
58
|
},
|
|
58
59
|
{
|
|
59
60
|
"name": "Fan",
|
|
@@ -62,35 +63,34 @@ Configure from Homebridge UI or manually edit `config.json` like below:
|
|
|
62
63
|
{
|
|
63
64
|
"name": "Light",
|
|
64
65
|
"type": "lightbulb",
|
|
65
|
-
"
|
|
66
|
+
"delayOff": 5000
|
|
66
67
|
}
|
|
67
|
-
]
|
|
68
|
-
"mode": "single"
|
|
68
|
+
]
|
|
69
69
|
}
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
74
|
-
###
|
|
74
|
+
### Platform Options
|
|
75
75
|
|
|
76
|
-
| Field
|
|
77
|
-
|
|
78
|
-
| `name`
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `type` | string | ❌ | Switch type: `switch`, `outlet`, `lightbulb`, `fan` (overridden per switch) |
|
|
82
|
-
| `autoTurnOff` | number | ❌ | Global auto-off (ms) – can be overridden per switch |
|
|
83
|
-
| `defaultState` | boolean | ❌ | Default power state on restart – can be overridden per switch |
|
|
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 |
|
|
84
81
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
### Per-Switch Options
|
|
83
|
+
|
|
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`) |
|
|
89
|
+
| `delayOff` | number | No | Auto turn off after N milliseconds (default: `0`) |
|
|
90
90
|
|
|
91
91
|
---
|
|
92
92
|
|
|
93
|
-
##
|
|
93
|
+
## Example Use Cases
|
|
94
94
|
|
|
95
95
|
- Simulate smart plugs for automation testing
|
|
96
96
|
- Trigger HomeKit scenes manually
|
|
@@ -99,7 +99,7 @@ Each object inside `switches[]` can include:
|
|
|
99
99
|
|
|
100
100
|
---
|
|
101
101
|
|
|
102
|
-
##
|
|
102
|
+
## Links
|
|
103
103
|
|
|
104
104
|
- [NPM Package](https://www.npmjs.com/package/homebridge-multiple-switch)
|
|
105
105
|
- [Homebridge](https://homebridge.io/)
|
|
@@ -107,6 +107,6 @@ Each object inside `switches[]` can include:
|
|
|
107
107
|
|
|
108
108
|
---
|
|
109
109
|
|
|
110
|
-
##
|
|
110
|
+
## License
|
|
111
111
|
|
|
112
112
|
MIT © [Azad Aydınlı](https://github.com/azadaydinli)
|
package/config.schema.json
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
"properties": {
|
|
8
8
|
"name": {
|
|
9
9
|
"title": "Platform Name",
|
|
10
|
+
"description": "The name of this platform instance in HomeKit.",
|
|
10
11
|
"type": "string",
|
|
11
12
|
"default": "Multiple Switch Platform"
|
|
12
13
|
},
|
|
13
14
|
"switchBehavior": {
|
|
14
15
|
"title": "Switch Behavior Mode",
|
|
16
|
+
"description": "Controls how switches interact with each other.",
|
|
15
17
|
"type": "string",
|
|
16
18
|
"default": "independent",
|
|
17
19
|
"oneOf": [
|
|
@@ -22,16 +24,19 @@
|
|
|
22
24
|
},
|
|
23
25
|
"switches": {
|
|
24
26
|
"title": "Switches",
|
|
27
|
+
"description": "List of virtual switches to create.",
|
|
25
28
|
"type": "array",
|
|
26
29
|
"items": {
|
|
27
30
|
"type": "object",
|
|
28
31
|
"properties": {
|
|
29
32
|
"name": {
|
|
30
33
|
"title": "Switch Name",
|
|
34
|
+
"description": "Display name of the switch in HomeKit.",
|
|
31
35
|
"type": "string"
|
|
32
36
|
},
|
|
33
37
|
"type": {
|
|
34
38
|
"title": "Switch Type",
|
|
39
|
+
"description": "The HomeKit accessory type for this switch.",
|
|
35
40
|
"type": "string",
|
|
36
41
|
"default": "outlet",
|
|
37
42
|
"oneOf": [
|
|
@@ -43,11 +48,13 @@
|
|
|
43
48
|
},
|
|
44
49
|
"defaultState": {
|
|
45
50
|
"title": "Default State",
|
|
51
|
+
"description": "Initial power state when Homebridge starts.",
|
|
46
52
|
"type": "boolean",
|
|
47
53
|
"default": false
|
|
48
54
|
},
|
|
49
55
|
"delayOff": {
|
|
50
56
|
"title": "Auto Turn Off (ms)",
|
|
57
|
+
"description": "Automatically turn off after this many milliseconds. Set to 0 to disable.",
|
|
51
58
|
"type": "number",
|
|
52
59
|
"default": 0,
|
|
53
60
|
"minimum": 0
|
|
@@ -67,4 +74,4 @@
|
|
|
67
74
|
},
|
|
68
75
|
"required": ["name", "switches"]
|
|
69
76
|
}
|
|
70
|
-
}
|
|
77
|
+
}
|
package/i18n/ar.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "منصة المفاتيح المتعددة",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "اسم المنصة",
|
|
6
|
+
"description": "اسم هذا المثيل من المنصة في HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "وضع سلوك المفتاح",
|
|
10
|
+
"description": "يتحكم في كيفية تفاعل المفاتيح مع بعضها البعض.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "مستقل" },
|
|
13
|
+
{ "title": "رئيسي" },
|
|
14
|
+
{ "title": "فردي" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "المفاتيح",
|
|
19
|
+
"description": "قائمة المفاتيح الافتراضية المراد إنشاؤها.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "اسم المفتاح",
|
|
23
|
+
"description": "اسم العرض للمفتاح في HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "نوع المفتاح",
|
|
27
|
+
"description": "نوع ملحق HomeKit لهذا المفتاح.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "مفتاح" },
|
|
30
|
+
{ "title": "مقبس" },
|
|
31
|
+
{ "title": "مصباح" },
|
|
32
|
+
{ "title": "مروحة" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "الحالة الافتراضية",
|
|
37
|
+
"description": "حالة الطاقة الأولية عند بدء تشغيل Homebridge."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "إيقاف تلقائي (مللي ثانية)",
|
|
41
|
+
"description": "يتم الإيقاف تلقائيًا بعد هذا العدد من المللي ثانية. اضبط على 0 للتعطيل."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/de.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Mehrfachschalter-Plattform",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Plattformname",
|
|
6
|
+
"description": "Der Name dieser Plattforminstanz in HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Schaltverhalten",
|
|
10
|
+
"description": "Steuert, wie die Schalter miteinander interagieren.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Unabhängig" },
|
|
13
|
+
{ "title": "Master" },
|
|
14
|
+
{ "title": "Einzeln" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Schalter",
|
|
19
|
+
"description": "Liste der zu erstellenden virtuellen Schalter.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Schaltername",
|
|
23
|
+
"description": "Anzeigename des Schalters in HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Schaltertyp",
|
|
27
|
+
"description": "Der HomeKit-Zubehörtyp für diesen Schalter.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Schalter" },
|
|
30
|
+
{ "title": "Steckdose" },
|
|
31
|
+
{ "title": "Glühbirne" },
|
|
32
|
+
{ "title": "Ventilator" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Standardzustand",
|
|
37
|
+
"description": "Anfänglicher Energiezustand beim Start von Homebridge."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Automatisch ausschalten (ms)",
|
|
41
|
+
"description": "Schaltet nach dieser Anzahl von Millisekunden automatisch aus. Zum Deaktivieren auf 0 setzen."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/en.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Multiple Switch Platform",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Platform Name",
|
|
6
|
+
"description": "The name of this platform instance in HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Switch Behavior Mode",
|
|
10
|
+
"description": "Controls how switches interact with each other.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Independent" },
|
|
13
|
+
{ "title": "Master" },
|
|
14
|
+
{ "title": "Single" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Switches",
|
|
19
|
+
"description": "List of virtual switches to create.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Switch Name",
|
|
23
|
+
"description": "Display name of the switch in HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Switch Type",
|
|
27
|
+
"description": "The HomeKit accessory type for this switch.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Switch" },
|
|
30
|
+
{ "title": "Outlet" },
|
|
31
|
+
{ "title": "Lightbulb" },
|
|
32
|
+
{ "title": "Fan" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Default State",
|
|
37
|
+
"description": "Initial power state when Homebridge starts."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Auto Turn Off (ms)",
|
|
41
|
+
"description": "Automatically turn off after this many milliseconds. Set to 0 to disable."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/es.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Plataforma de Múltiples Interruptores",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Nombre de la plataforma",
|
|
6
|
+
"description": "El nombre de esta instancia de plataforma en HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Modo de comportamiento",
|
|
10
|
+
"description": "Controla cómo interactúan los interruptores entre sí.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Independiente" },
|
|
13
|
+
{ "title": "Maestro" },
|
|
14
|
+
{ "title": "Único" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Interruptores",
|
|
19
|
+
"description": "Lista de interruptores virtuales a crear.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Nombre del interruptor",
|
|
23
|
+
"description": "Nombre visible del interruptor en HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Tipo de interruptor",
|
|
27
|
+
"description": "El tipo de accesorio HomeKit para este interruptor.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Interruptor" },
|
|
30
|
+
{ "title": "Enchufe" },
|
|
31
|
+
{ "title": "Bombilla" },
|
|
32
|
+
{ "title": "Ventilador" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Estado predeterminado",
|
|
37
|
+
"description": "Estado de energía inicial cuando Homebridge se inicia."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Apagado automático (ms)",
|
|
41
|
+
"description": "Se apaga automáticamente después de estos milisegundos. Establecer en 0 para desactivar."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/fr.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Plateforme Multi-Interrupteurs",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Nom de la plateforme",
|
|
6
|
+
"description": "Le nom de cette instance de plateforme dans HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Mode de comportement",
|
|
10
|
+
"description": "Contrôle la façon dont les interrupteurs interagissent entre eux.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Indépendant" },
|
|
13
|
+
{ "title": "Maître" },
|
|
14
|
+
{ "title": "Unique" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Interrupteurs",
|
|
19
|
+
"description": "Liste des interrupteurs virtuels à créer.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Nom de l'interrupteur",
|
|
23
|
+
"description": "Nom affiché de l'interrupteur dans HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Type d'interrupteur",
|
|
27
|
+
"description": "Le type d'accessoire HomeKit pour cet interrupteur.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Interrupteur" },
|
|
30
|
+
{ "title": "Prise" },
|
|
31
|
+
{ "title": "Ampoule" },
|
|
32
|
+
{ "title": "Ventilateur" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "État par défaut",
|
|
37
|
+
"description": "État d'alimentation initial au démarrage de Homebridge."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Arrêt automatique (ms)",
|
|
41
|
+
"description": "S'éteint automatiquement après ce nombre de millisecondes. Mettre à 0 pour désactiver."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/it.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Piattaforma Multi-Interruttore",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Nome della piattaforma",
|
|
6
|
+
"description": "Il nome di questa istanza della piattaforma in HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Modalità di comportamento",
|
|
10
|
+
"description": "Controlla come gli interruttori interagiscono tra loro.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Indipendente" },
|
|
13
|
+
{ "title": "Master" },
|
|
14
|
+
{ "title": "Singolo" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Interruttori",
|
|
19
|
+
"description": "Elenco degli interruttori virtuali da creare.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Nome dell'interruttore",
|
|
23
|
+
"description": "Nome visualizzato dell'interruttore in HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Tipo di interruttore",
|
|
27
|
+
"description": "Il tipo di accessorio HomeKit per questo interruttore.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Interruttore" },
|
|
30
|
+
{ "title": "Presa" },
|
|
31
|
+
{ "title": "Lampadina" },
|
|
32
|
+
{ "title": "Ventilatore" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Stato predefinito",
|
|
37
|
+
"description": "Stato di alimentazione iniziale all'avvio di Homebridge."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Spegnimento automatico (ms)",
|
|
41
|
+
"description": "Si spegne automaticamente dopo questi millisecondi. Impostare a 0 per disattivare."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/ja.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "マルチスイッチプラットフォーム",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "プラットフォーム名",
|
|
6
|
+
"description": "HomeKit でのこのプラットフォームインスタンスの名前。"
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "スイッチ動作モード",
|
|
10
|
+
"description": "スイッチ同士の相互作用を制御します。",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "独立" },
|
|
13
|
+
{ "title": "マスター" },
|
|
14
|
+
{ "title": "シングル" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "スイッチ",
|
|
19
|
+
"description": "作成する仮想スイッチのリスト。",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "スイッチ名",
|
|
23
|
+
"description": "HomeKit でのスイッチの表示名。"
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "スイッチタイプ",
|
|
27
|
+
"description": "このスイッチの HomeKit アクセサリタイプ。",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "スイッチ" },
|
|
30
|
+
{ "title": "コンセント" },
|
|
31
|
+
{ "title": "電球" },
|
|
32
|
+
{ "title": "ファン" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "デフォルト状態",
|
|
37
|
+
"description": "Homebridge 起動時の初期電源状態。"
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "自動オフ(ミリ秒)",
|
|
41
|
+
"description": "指定したミリ秒後に自動的にオフになります。無効にするには 0 に設定してください。"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/ko.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "멀티 스위치 플랫폼",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "플랫폼 이름",
|
|
6
|
+
"description": "HomeKit에서 이 플랫폼 인스턴스의 이름."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "스위치 동작 모드",
|
|
10
|
+
"description": "스위치 간의 상호 작용 방식을 제어합니다.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "독립" },
|
|
13
|
+
{ "title": "마스터" },
|
|
14
|
+
{ "title": "단일" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "스위치",
|
|
19
|
+
"description": "생성할 가상 스위치 목록.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "스위치 이름",
|
|
23
|
+
"description": "HomeKit에서 스위치의 표시 이름."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "스위치 유형",
|
|
27
|
+
"description": "이 스위치의 HomeKit 액세서리 유형.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "스위치" },
|
|
30
|
+
{ "title": "콘센트" },
|
|
31
|
+
{ "title": "전구" },
|
|
32
|
+
{ "title": "팬" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "기본 상태",
|
|
37
|
+
"description": "Homebridge 시작 시 초기 전원 상태."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "자동 꺼짐 (ms)",
|
|
41
|
+
"description": "지정된 밀리초 후 자동으로 꺼집니다. 비활성화하려면 0으로 설정하세요."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/nl.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Meervoudige schakelaar platform",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Platformnaam",
|
|
6
|
+
"description": "De naam van dit platformexemplaar in HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Schakelaargedrag",
|
|
10
|
+
"description": "Bepaalt hoe de schakelaars met elkaar omgaan.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Onafhankelijk" },
|
|
13
|
+
{ "title": "Master" },
|
|
14
|
+
{ "title": "Enkelvoudig" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Schakelaars",
|
|
19
|
+
"description": "Lijst van virtuele schakelaars om aan te maken.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Schakelaarnaam",
|
|
23
|
+
"description": "Weergavenaam van de schakelaar in HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Schakelaartype",
|
|
27
|
+
"description": "Het HomeKit-accessoiretype voor deze schakelaar.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Schakelaar" },
|
|
30
|
+
{ "title": "Stopcontact" },
|
|
31
|
+
{ "title": "Gloeilamp" },
|
|
32
|
+
{ "title": "Ventilator" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Standaardstatus",
|
|
37
|
+
"description": "Initiële voedingsstatus wanneer Homebridge opstart."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Automatisch uitschakelen (ms)",
|
|
41
|
+
"description": "Schakelt automatisch uit na dit aantal milliseconden. Stel in op 0 om uit te schakelen."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/pl.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Platforma wielu przełączników",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Nazwa platformy",
|
|
6
|
+
"description": "Nazwa tej instancji platformy w HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Tryb zachowania przełączników",
|
|
10
|
+
"description": "Kontroluje sposób interakcji przełączników ze sobą.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Niezależny" },
|
|
13
|
+
{ "title": "Główny" },
|
|
14
|
+
{ "title": "Pojedynczy" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Przełączniki",
|
|
19
|
+
"description": "Lista wirtualnych przełączników do utworzenia.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Nazwa przełącznika",
|
|
23
|
+
"description": "Wyświetlana nazwa przełącznika w HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Typ przełącznika",
|
|
27
|
+
"description": "Typ akcesorium HomeKit dla tego przełącznika.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Przełącznik" },
|
|
30
|
+
{ "title": "Gniazdko" },
|
|
31
|
+
{ "title": "Żarówka" },
|
|
32
|
+
{ "title": "Wentylator" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Stan domyślny",
|
|
37
|
+
"description": "Początkowy stan zasilania przy uruchomieniu Homebridge."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Automatyczne wyłączenie (ms)",
|
|
41
|
+
"description": "Automatycznie wyłącza się po podanej liczbie milisekund. Ustaw 0, aby wyłączyć."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/pt.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Plataforma de Múltiplos Interruptores",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Nome da plataforma",
|
|
6
|
+
"description": "O nome desta instância de plataforma no HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Modo de comportamento",
|
|
10
|
+
"description": "Controla como os interruptores interagem entre si.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Independente" },
|
|
13
|
+
{ "title": "Mestre" },
|
|
14
|
+
{ "title": "Único" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Interruptores",
|
|
19
|
+
"description": "Lista de interruptores virtuais a criar.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Nome do interruptor",
|
|
23
|
+
"description": "Nome de exibição do interruptor no HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Tipo de interruptor",
|
|
27
|
+
"description": "O tipo de acessório HomeKit para este interruptor.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Interruptor" },
|
|
30
|
+
{ "title": "Tomada" },
|
|
31
|
+
{ "title": "Lâmpada" },
|
|
32
|
+
{ "title": "Ventilador" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Estado padrão",
|
|
37
|
+
"description": "Estado de energia inicial quando o Homebridge inicia."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Desligamento automático (ms)",
|
|
41
|
+
"description": "Desliga automaticamente após estes milissegundos. Defina como 0 para desativar."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/ru.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Платформа мультипереключателей",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Название платформы",
|
|
6
|
+
"description": "Название этого экземпляра платформы в HomeKit."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Режим поведения",
|
|
10
|
+
"description": "Управляет взаимодействием переключателей друг с другом.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Независимый" },
|
|
13
|
+
{ "title": "Мастер" },
|
|
14
|
+
{ "title": "Одиночный" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Переключатели",
|
|
19
|
+
"description": "Список виртуальных переключателей для создания.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Название переключателя",
|
|
23
|
+
"description": "Отображаемое имя переключателя в HomeKit."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Тип переключателя",
|
|
27
|
+
"description": "Тип аксессуара HomeKit для этого переключателя.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Выключатель" },
|
|
30
|
+
{ "title": "Розетка" },
|
|
31
|
+
{ "title": "Лампочка" },
|
|
32
|
+
{ "title": "Вентилятор" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Состояние по умолчанию",
|
|
37
|
+
"description": "Начальное состояние питания при запуске Homebridge."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Автоматическое выключение (мс)",
|
|
41
|
+
"description": "Автоматически выключается через указанное количество миллисекунд. Установите 0 для отключения."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/tr.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "Çoklu Anahtar Platformu",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "Platform Adı",
|
|
6
|
+
"description": "Bu platform örneğinin HomeKit'teki adı."
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "Anahtar Davranış Modu",
|
|
10
|
+
"description": "Anahtarların birbirleriyle nasıl etkileşime gireceğini kontrol eder.",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "Bağımsız" },
|
|
13
|
+
{ "title": "Ana Kontrol" },
|
|
14
|
+
{ "title": "Tekli" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "Anahtarlar",
|
|
19
|
+
"description": "Oluşturulacak sanal anahtarların listesi.",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "Anahtar Adı",
|
|
23
|
+
"description": "Anahtarın HomeKit'teki görünen adı."
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "Anahtar Tipi",
|
|
27
|
+
"description": "Bu anahtar için HomeKit aksesuar tipi.",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "Anahtar" },
|
|
30
|
+
{ "title": "Priz" },
|
|
31
|
+
{ "title": "Ampul" },
|
|
32
|
+
{ "title": "Vantilatör" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "Varsayılan Durum",
|
|
37
|
+
"description": "Homebridge başladığında başlangıç güç durumu."
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "Otomatik Kapanma (ms)",
|
|
41
|
+
"description": "Belirtilen milisaniye sonra otomatik kapanır. Devre dışı bırakmak için 0 yazın."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/i18n/zh-CN.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDisplay": "多开关平台",
|
|
3
|
+
"schema": {
|
|
4
|
+
"name": {
|
|
5
|
+
"title": "平台名称",
|
|
6
|
+
"description": "此平台实例在 HomeKit 中的名称。"
|
|
7
|
+
},
|
|
8
|
+
"switchBehavior": {
|
|
9
|
+
"title": "开关行为模式",
|
|
10
|
+
"description": "控制开关之间的交互方式。",
|
|
11
|
+
"oneOf": [
|
|
12
|
+
{ "title": "独立" },
|
|
13
|
+
{ "title": "主控" },
|
|
14
|
+
{ "title": "单选" }
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"switches": {
|
|
18
|
+
"title": "开关",
|
|
19
|
+
"description": "要创建的虚拟开关列表。",
|
|
20
|
+
"items": {
|
|
21
|
+
"name": {
|
|
22
|
+
"title": "开关名称",
|
|
23
|
+
"description": "开关在 HomeKit 中的显示名称。"
|
|
24
|
+
},
|
|
25
|
+
"type": {
|
|
26
|
+
"title": "开关类型",
|
|
27
|
+
"description": "此开关的 HomeKit 配件类型。",
|
|
28
|
+
"oneOf": [
|
|
29
|
+
{ "title": "开关" },
|
|
30
|
+
{ "title": "插座" },
|
|
31
|
+
{ "title": "灯泡" },
|
|
32
|
+
{ "title": "风扇" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"defaultState": {
|
|
36
|
+
"title": "默认状态",
|
|
37
|
+
"description": "Homebridge 启动时的初始电源状态。"
|
|
38
|
+
},
|
|
39
|
+
"delayOff": {
|
|
40
|
+
"title": "自动关闭(毫秒)",
|
|
41
|
+
"description": "在指定的毫秒数后自动关闭。设置为 0 以禁用。"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
package/index.js
CHANGED
|
@@ -1,109 +1,160 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const PLUGIN_NAME = 'homebridge-multiple-switch';
|
|
4
|
+
const PLATFORM_NAME = 'MultipleSwitchPlatform';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const SERVICE_TYPES = {
|
|
7
|
+
switch: 'Switch',
|
|
8
|
+
lightbulb: 'Lightbulb',
|
|
9
|
+
fan: 'Fan',
|
|
10
|
+
outlet: 'Outlet',
|
|
11
|
+
};
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
module.exports = (api) => {
|
|
14
|
+
api.registerPlatform(PLATFORM_NAME, MultipleSwitchPlatform);
|
|
11
15
|
};
|
|
12
16
|
|
|
13
17
|
class MultipleSwitchPlatform {
|
|
14
18
|
constructor(log, config, api) {
|
|
15
19
|
this.log = log;
|
|
16
|
-
this.config = config;
|
|
20
|
+
this.config = config || {};
|
|
17
21
|
this.api = api;
|
|
18
|
-
this.
|
|
22
|
+
this.Service = api.hap.Service;
|
|
23
|
+
this.Characteristic = api.hap.Characteristic;
|
|
24
|
+
this.cachedAccessories = new Map();
|
|
25
|
+
this.switchServices = new Map();
|
|
19
26
|
|
|
20
27
|
this.api.on('didFinishLaunching', () => {
|
|
21
|
-
this.log('
|
|
28
|
+
this.log.info('MultipleSwitchPlatform started.');
|
|
22
29
|
this.setupAccessories();
|
|
23
30
|
});
|
|
24
31
|
}
|
|
25
32
|
|
|
33
|
+
configureAccessory(accessory) {
|
|
34
|
+
this.cachedAccessories.set(accessory.UUID, accessory);
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
setupAccessories() {
|
|
27
|
-
const switches = this.config.switches
|
|
28
|
-
|
|
38
|
+
const switches = this.config.switches;
|
|
39
|
+
if (!Array.isArray(switches) || switches.length === 0) {
|
|
40
|
+
this.log.warn('No switches configured. Removing stale accessories.');
|
|
41
|
+
this.removeStaleCachedAccessories();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
29
45
|
const name = this.config.name || 'Multiple Switch Panel';
|
|
46
|
+
const behavior = this.config.switchBehavior || 'independent';
|
|
47
|
+
const uuid = this.api.hap.uuid.generate(name);
|
|
48
|
+
|
|
49
|
+
let accessory = this.cachedAccessories.get(uuid);
|
|
50
|
+
const isNew = !accessory;
|
|
30
51
|
|
|
31
|
-
|
|
32
|
-
|
|
52
|
+
if (isNew) {
|
|
53
|
+
accessory = new this.api.platformAccessory(name, uuid);
|
|
54
|
+
}
|
|
33
55
|
|
|
34
|
-
accessory.context.switchStates = {};
|
|
35
|
-
accessory.context.switchServices = {};
|
|
36
56
|
accessory.context.switchBehavior = behavior;
|
|
57
|
+
accessory.context.switchStates = accessory.context.switchStates || {};
|
|
58
|
+
|
|
59
|
+
this.reconcileServices(accessory, switches);
|
|
60
|
+
|
|
61
|
+
if (isNew) {
|
|
62
|
+
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.cachedAccessories.delete(uuid);
|
|
66
|
+
this.removeStaleCachedAccessories();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
reconcileServices(accessory, switches) {
|
|
70
|
+
const activeSubtypes = new Set();
|
|
37
71
|
|
|
38
72
|
switches.forEach((sw, index) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
73
|
+
const subtype = `switch_${index}`;
|
|
74
|
+
activeSubtypes.add(subtype);
|
|
41
75
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
76
|
+
const ServiceClass = this.getServiceClass(sw.type);
|
|
77
|
+
let service = accessory.getServiceById(ServiceClass, subtype);
|
|
78
|
+
|
|
79
|
+
if (!service) {
|
|
80
|
+
service = accessory.addService(ServiceClass, sw.name, subtype);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
service.setCharacteristic(this.Characteristic.Name, sw.name);
|
|
84
|
+
this.configureSwitchHandlers(accessory, service, sw, subtype);
|
|
85
|
+
|
|
86
|
+
this.switchServices.set(subtype, service);
|
|
87
|
+
|
|
88
|
+
if (accessory.context.switchStates[subtype] === undefined) {
|
|
89
|
+
accessory.context.switchStates[subtype] = sw.defaultState || false;
|
|
90
|
+
}
|
|
45
91
|
});
|
|
46
92
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
);
|
|
52
|
-
this.accessories.push(accessory);
|
|
93
|
+
const servicesToRemove = accessory.services.filter((s) => {
|
|
94
|
+
return s.subtype && !activeSubtypes.has(s.subtype);
|
|
95
|
+
});
|
|
96
|
+
servicesToRemove.forEach((s) => accessory.removeService(s));
|
|
53
97
|
}
|
|
54
98
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
service.getCharacteristic(Characteristic.On)
|
|
60
|
-
.onGet(() => {
|
|
61
|
-
return accessory.context.switchStates[id];
|
|
62
|
-
})
|
|
99
|
+
configureSwitchHandlers(accessory, service, sw, subtype) {
|
|
100
|
+
service.getCharacteristic(this.Characteristic.On)
|
|
101
|
+
.onGet(() => accessory.context.switchStates[subtype] ?? false)
|
|
63
102
|
.onSet((value) => {
|
|
103
|
+
accessory.context.switchStates[subtype] = value;
|
|
104
|
+
this.log.info(`[${sw.name}] ${value ? 'ON' : 'OFF'}`);
|
|
105
|
+
|
|
64
106
|
const behavior = accessory.context.switchBehavior;
|
|
65
|
-
accessory.context.switchStates[id] = value;
|
|
66
|
-
this.log(`[${sw.name}] → ${value ? 'ON' : 'OFF'}`);
|
|
67
107
|
|
|
68
108
|
if (behavior === 'single' && value) {
|
|
69
|
-
|
|
70
|
-
if (key !== id) {
|
|
71
|
-
accessory.context.switchStates[key] = false;
|
|
72
|
-
accessory.context.switchServices[key].updateCharacteristic(Characteristic.On, false);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
109
|
+
this.turnOffOthers(accessory, subtype);
|
|
75
110
|
}
|
|
76
111
|
|
|
77
112
|
if (behavior === 'master') {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (value && sw.delayOff > 0) {
|
|
84
|
-
setTimeout(() => {
|
|
85
|
-
accessory.context.switchStates[id] = false;
|
|
86
|
-
service.updateCharacteristic(Characteristic.On, false);
|
|
87
|
-
this.log(`[${sw.name}] auto-off after ${sw.delayOff}ms`);
|
|
88
|
-
}, sw.delayOff);
|
|
89
|
-
}
|
|
113
|
+
this.setAll(accessory, value);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (value && sw.delayOff > 0) {
|
|
117
|
+
this.scheduleAutoOff(accessory, service, sw, subtype);
|
|
90
118
|
}
|
|
91
119
|
});
|
|
120
|
+
}
|
|
92
121
|
|
|
93
|
-
|
|
122
|
+
turnOffOthers(accessory, excludeSubtype) {
|
|
123
|
+
for (const [key, svc] of this.switchServices) {
|
|
124
|
+
if (key !== excludeSubtype) {
|
|
125
|
+
accessory.context.switchStates[key] = false;
|
|
126
|
+
svc.updateCharacteristic(this.Characteristic.On, false);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
94
129
|
}
|
|
95
130
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
case 'fan': return Service.Fan;
|
|
101
|
-
case 'outlet':
|
|
102
|
-
default: return Service.Outlet;
|
|
131
|
+
setAll(accessory, value) {
|
|
132
|
+
for (const [key, svc] of this.switchServices) {
|
|
133
|
+
accessory.context.switchStates[key] = value;
|
|
134
|
+
svc.updateCharacteristic(this.Characteristic.On, value);
|
|
103
135
|
}
|
|
104
136
|
}
|
|
105
137
|
|
|
106
|
-
|
|
107
|
-
|
|
138
|
+
scheduleAutoOff(accessory, service, sw, subtype) {
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
if (accessory.context.switchStates[subtype]) {
|
|
141
|
+
accessory.context.switchStates[subtype] = false;
|
|
142
|
+
service.updateCharacteristic(this.Characteristic.On, false);
|
|
143
|
+
this.log.info(`[${sw.name}] auto-off after ${sw.delayOff}ms`);
|
|
144
|
+
}
|
|
145
|
+
}, sw.delayOff);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
getServiceClass(type) {
|
|
149
|
+
const key = (type || 'outlet').toLowerCase();
|
|
150
|
+
const name = SERVICE_TYPES[key] || SERVICE_TYPES.outlet;
|
|
151
|
+
return this.Service[name];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
removeStaleCachedAccessories() {
|
|
155
|
+
if (this.cachedAccessories.size === 0) return;
|
|
156
|
+
const stale = [...this.cachedAccessories.values()];
|
|
157
|
+
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, stale);
|
|
158
|
+
this.cachedAccessories.clear();
|
|
108
159
|
}
|
|
109
160
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-multiple-switch",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Multiple switch platform for Homebridge",
|
|
5
5
|
"homepage": "https://github.com/azadaydinli/homebridge-multiple-switch",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"author": "Azad Aydınlı",
|
|
8
8
|
"license": "ISC",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"lint": "echo \"No linter configured\"",
|
|
11
|
+
"test": "echo \"No tests configured\""
|
|
12
|
+
},
|
|
9
13
|
"bugs": {
|
|
10
14
|
"url": "https://github.com/azadaydinli/homebridge-multiple-switch/issues"
|
|
11
15
|
},
|
|
@@ -26,7 +30,7 @@
|
|
|
26
30
|
"url": "https://github.com/azadaydinli/homebridge-multiple-switch.git"
|
|
27
31
|
},
|
|
28
32
|
"engines": {
|
|
29
|
-
"node": ">=
|
|
33
|
+
"node": ">=18.0.0",
|
|
30
34
|
"homebridge": ">=1.3.0"
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: 📦 Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*.*.*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: 📥 Repo-nu klonla
|
|
14
|
-
uses: actions/checkout@v3
|
|
15
|
-
|
|
16
|
-
- name: ⚙️ Node.js qur
|
|
17
|
-
uses: actions/setup-node@v3
|
|
18
|
-
with:
|
|
19
|
-
node-version: '18'
|
|
20
|
-
registry-url: 'https://registry.npmjs.org/'
|
|
21
|
-
|
|
22
|
-
- name: 📦 Asılılıqları qur
|
|
23
|
-
run: npm install
|
|
24
|
-
|
|
25
|
-
- name: 🚀 NPM-ə yüklə
|
|
26
|
-
run: npm publish
|
|
27
|
-
env:
|
|
28
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: 📦 Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*.*.*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: 📥 Repo-nu klonla
|
|
14
|
-
uses: actions/checkout@v3
|
|
15
|
-
|
|
16
|
-
- name: ⚙️ Node.js qur
|
|
17
|
-
uses: actions/setup-node@v3
|
|
18
|
-
with:
|
|
19
|
-
node-version: '18'
|
|
20
|
-
registry-url: 'https://registry.npmjs.org/'
|
|
21
|
-
|
|
22
|
-
- name: 📦 Asılılıqları qur
|
|
23
|
-
run: npm install
|
|
24
|
-
|
|
25
|
-
- name: 🚀 NPM-ə yüklə
|
|
26
|
-
run: npm publish
|
|
27
|
-
env:
|
|
28
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: 📦 Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*.*.*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: 📥 Repo-nu klonla
|
|
14
|
-
uses: actions/checkout@v3
|
|
15
|
-
|
|
16
|
-
- name: ⚙️ Node.js qur
|
|
17
|
-
uses: actions/setup-node@v3
|
|
18
|
-
with:
|
|
19
|
-
node-version: '18'
|
|
20
|
-
registry-url: 'https://registry.npmjs.org/'
|
|
21
|
-
|
|
22
|
-
- name: 📦 Asılılıqları qur
|
|
23
|
-
run: npm install
|
|
24
|
-
|
|
25
|
-
- name: 🚀 NPM-ə yüklə
|
|
26
|
-
run: npm publish
|
|
27
|
-
env:
|
|
28
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|