homebridge-multiple-switch 1.1.3 → 1.1.5

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.
@@ -0,0 +1,41 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: 📥 Repo-nu klonla
15
+ uses: actions/checkout@v3
16
+
17
+ - name: ⚙️ Node.js qur
18
+ uses: actions/setup-node@v3
19
+ with:
20
+ node-version: '18'
21
+ cache: 'npm'
22
+
23
+ - name: 📦 Asılılıqları qur
24
+ run: npm install
25
+
26
+ - name: ✅ Kod yoxlaması (lint varsa)
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
41
+
@@ -0,0 +1,28 @@
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 }}
package/README.md CHANGED
@@ -1,17 +1,70 @@
1
- # Homebridge Multiple Switch Plugin
2
-
3
- ## Overview
4
- The **Homebridge Multiple Switch** plugin allows you to create and manage multiple virtual switches within the HomeKit environment. This plugin is ideal for users who want to control multiple devices or scenarios using a single accessory with multiple switch options.
5
-
6
- ## Features
7
- - **Multiple Switches**: Add, manage, and control multiple virtual switches under one accessory in HomeKit.
8
- - **Master Switch**: Optionally add a master switch that controls all other switches simultaneously.
9
- - **Customizable**: Easily configure the number of switches and their names through the Homebridge UI.
10
- - **Flexible**: Supports dynamic addition of switches, allowing for easy scaling to your needs.
11
-
12
- ## Installation
13
- 1. Ensure you have [Homebridge](https://homebridge.io) installed and running.
14
- 2. Install the plugin via Homebridge or npm:
15
- ```bash
16
- npm install -g homebridge-multiple-switch
17
- 3. Configure the plugin through the Homebridge UI or manually edit your config.json.
1
+ # homebridge-multiple-switch
2
+
3
+ [![npm](https://img.shields.io/npm/v/homebridge-multiple-switch)](https://www.npmjs.com/package/homebridge-multiple-switch)
4
+ [![GitHub issues](https://img.shields.io/github/issues/azadaydinli/homebridge-multiple-switch)](https://github.com/azadaydinli/homebridge-multiple-switch/issues)
5
+ [![GitHub license](https://img.shields.io/github/license/azadaydinli/homebridge-multiple-switch)](https://github.com/azadaydinli/homebridge-multiple-switch/blob/master/LICENSE)
6
+
7
+ A lightweight Homebridge plugin that lets you create multiple customizable dummy switches (Outlet/Fan/Light/Switch) with different behavior modes including Independent, Master, and Single-Switch Mode.
8
+
9
+ ---
10
+
11
+ ## ✨ Features
12
+
13
+ - Multiple switches in a single accessory
14
+ - Each switch can be `switch`, `outlet`, `lightbulb`, or `fan`
15
+ - **Independent Mode** – all switches work separately
16
+ - **Master Mode** – adds a master switch that controls all other switches
17
+ - **Single Mode** only one switch can be on at any time
18
+ - Auto turn-off (in milliseconds)
19
+ - Works seamlessly with HomeKit and Siri
20
+
21
+ ---
22
+
23
+ ## 📦 Installation
24
+
25
+ Install the plugin via the Homebridge UI:
26
+
27
+ 1. Go to **Plugins**
28
+ 2. Search for `homebridge-multiple-switch`
29
+ 3. Click **Install**
30
+
31
+ Or use the command line:
32
+
33
+ ```bash
34
+ npm install -g homebridge-multiple-switch
35
+ ```
36
+
37
+ ---
38
+
39
+ ## ⚙️ Configuration
40
+
41
+ You can configure the plugin directly via the Homebridge UI, or manually in config.json:
42
+
43
+ ```bash
44
+ {
45
+ "accessory": "MultipleSwitchAccessory",
46
+ "name": "My Multi Switch",
47
+ "switchCount": 3,
48
+ "type": "outlet",
49
+ "mode": "independent",
50
+ "autoTurnOff": 1000,
51
+ "defaultState": false,
52
+ "states": [
53
+ { "type": "switch", "autoTurnOff": 3000 },
54
+ { "type": "fan" },
55
+ { "type": "lightbulb", "defaultState": true }
56
+ ]
57
+ }
58
+ ```
59
+
60
+ ### 🔧 Configuration Options
61
+
62
+ | Field | Type | Required | Description |
63
+ |---------------|---------|----------|-----------------------------------------------------------------------------|
64
+ | `name` | string | ✅ | Name of the accessory |
65
+ | `switchCount` | number | ✅ | Number of switches to create (max depends on HomeKit limits) |
66
+ | `type` | string | ❌ | Default type: `switch`, `outlet`, `lightbulb`, or `fan` |
67
+ | `mode` | string | ❌ | `independent`, `master`, or `single` |
68
+ | `autoTurnOff` | number | ❌ | Global auto-off in milliseconds |
69
+ | `defaultState`| boolean | ❌ | Default on/off state on restart |
70
+ | `states` | array | ❌ | Per-switch custom settings (overrides global config) |
@@ -1,39 +1,23 @@
1
1
  {
2
- "pluginAlias": "MultipleSwitchAccessory",
3
- "pluginType": "accessory",
4
- "singular": false,
5
- "headerDisplay": "Multiple Switch Accessory",
2
+ "pluginAlias": "MultipleSwitchPlatform",
3
+ "pluginType": "platform",
4
+ "headerDisplay": "Multiple Switch Platform",
6
5
  "schema": {
7
6
  "type": "object",
8
7
  "properties": {
9
8
  "name": {
10
- "title": "Accessory Name",
9
+ "title": "Platform Name",
11
10
  "type": "string",
12
- "default": "Multiple Switch"
11
+ "default": "Multiple Switch Platform"
13
12
  },
14
13
  "switchBehavior": {
15
14
  "title": "Switch Behavior Mode",
16
15
  "type": "string",
17
16
  "default": "independent",
18
17
  "oneOf": [
19
- {
20
- "title": "Independent",
21
- "enum": [
22
- "independent"
23
- ]
24
- },
25
- {
26
- "title": "Master",
27
- "enum": [
28
- "master"
29
- ]
30
- },
31
- {
32
- "title": "Single",
33
- "enum": [
34
- "single"
35
- ]
36
- }
18
+ { "title": "Independent", "enum": ["independent"] },
19
+ { "title": "Master", "enum": ["master"] },
20
+ { "title": "Single", "enum": ["single"] }
37
21
  ]
38
22
  },
39
23
  "switches": {
@@ -51,30 +35,10 @@
51
35
  "type": "string",
52
36
  "default": "outlet",
53
37
  "oneOf": [
54
- {
55
- "title": "Switch",
56
- "enum": [
57
- "switch"
58
- ]
59
- },
60
- {
61
- "title": "Outlet",
62
- "enum": [
63
- "outlet"
64
- ]
65
- },
66
- {
67
- "title": "Lightbulb",
68
- "enum": [
69
- "lightbulb"
70
- ]
71
- },
72
- {
73
- "title": "Fan",
74
- "enum": [
75
- "fan"
76
- ]
77
- }
38
+ { "title": "Switch", "enum": ["switch"] },
39
+ { "title": "Outlet", "enum": ["outlet"] },
40
+ { "title": "Lightbulb", "enum": ["lightbulb"] },
41
+ { "title": "Fan", "enum": ["fan"] }
78
42
  ]
79
43
  },
80
44
  "defaultState": {
@@ -89,10 +53,7 @@
89
53
  "minimum": 0
90
54
  }
91
55
  },
92
- "required": [
93
- "name",
94
- "type"
95
- ]
56
+ "required": ["name", "type"]
96
57
  },
97
58
  "default": [
98
59
  {
@@ -104,9 +65,6 @@
104
65
  ]
105
66
  }
106
67
  },
107
- "required": [
108
- "name",
109
- "switches"
110
- ]
68
+ "required": ["name", "switches"]
111
69
  }
112
70
  }
package/index.js CHANGED
@@ -1,78 +1,109 @@
1
- let Accessory, Service, Characteristic;
2
-
3
- module.exports = (homebridge) => {
4
- Accessory = homebridge.platformAccessory || homebridge.hap.Accessory;
5
- Service = homebridge.hap.Service;
6
- Characteristic = homebridge.hap.Characteristic;
7
-
8
- homebridge.registerAccessory(
9
- 'homebridge-multiple-switch',
10
- 'MultipleSwitchAccessory',
11
- MultipleSwitchAccessory
12
- );
1
+ // homebridge-multiple-switch: index.js (Platform plugin, bir Accessory, çox Service)
2
+
3
+ let Service, Characteristic, UUIDGen;
4
+
5
+ module.exports = (api) => {
6
+ Service = api.hap.Service;
7
+ Characteristic = api.hap.Characteristic;
8
+ UUIDGen = api.hap.uuid;
9
+
10
+ api.registerPlatform('MultipleSwitchPlatform', MultipleSwitchPlatform);
13
11
  };
14
12
 
15
- class MultipleSwitchAccessory {
16
- constructor(log, config) {
13
+ class MultipleSwitchPlatform {
14
+ constructor(log, config, api) {
17
15
  this.log = log;
18
16
  this.config = config;
19
- this.name = config.name || 'Multiple Switch';
20
- this.switches = config.switches || [];
21
- this.services = [];
22
-
23
- const infoService = new Service.AccessoryInformation()
24
- .setCharacteristic(Characteristic.Manufacturer, 'Custom')
25
- .setCharacteristic(Characteristic.Model, 'MultipleSwitch')
26
- .setCharacteristic(Characteristic.SerialNumber, 'v1.0.0');
27
-
28
- this.services.push(infoService);
29
-
30
- const serviceTypes = {
31
- switch: Service.Switch,
32
- outlet: Service.Outlet,
33
- lightbulb: Service.Lightbulb,
34
- fan: Service.Fan
35
- };
36
-
37
- this.switches.forEach((conf, index) => {
38
- const switchName = conf.name || `Switch ${index + 1}`;
39
- const type = (conf.type || 'outlet').toLowerCase();
40
- const ServiceClass = serviceTypes[type];
41
-
42
- if (!ServiceClass) {
43
- this.log.warn(`"${switchName}" üçün tanınmayan növ: "${type}". Default olaraq Outlet istifadə olunur.`);
44
- return;
45
- }
46
-
47
- conf.state = conf.defaultState === true;
48
-
49
- const service = new ServiceClass(switchName, `subtype-${index}`);
50
-
51
- service
52
- .getCharacteristic(Characteristic.On)
53
- .on('get', (callback) => {
54
- callback(null, conf.state);
55
- })
56
- .on('set', (value, callback) => {
57
- conf.state = value;
58
- this.log(`"${switchName}" vəziyyəti dəyişdi: ${value}`);
59
-
60
- if (value && conf.delayOff && conf.delayOff > 0) {
17
+ this.api = api;
18
+ this.accessories = [];
19
+
20
+ this.api.on('didFinishLaunching', () => {
21
+ this.log('🔌 MultipleSwitchPlatform başladıldı.');
22
+ this.setupAccessories();
23
+ });
24
+ }
25
+
26
+ setupAccessories() {
27
+ const switches = this.config.switches || [];
28
+ const behavior = this.config.switchBehavior || 'independent';
29
+ const name = this.config.name || 'Multiple Switch Panel';
30
+
31
+ const uuid = UUIDGen.generate(name);
32
+ const accessory = new this.api.platformAccessory(name, uuid);
33
+
34
+ accessory.context.switchStates = {};
35
+ accessory.context.switchServices = {};
36
+ accessory.context.switchBehavior = behavior;
37
+
38
+ switches.forEach((sw, index) => {
39
+ const id = `switch_${index}`;
40
+ const service = this.createSwitchService(accessory, sw, id);
41
+
42
+ accessory.addService(service);
43
+ accessory.context.switchStates[id] = sw.defaultState || false;
44
+ accessory.context.switchServices[id] = service;
45
+ });
46
+
47
+ this.api.registerPlatformAccessories(
48
+ 'homebridge-multiple-switch',
49
+ 'MultipleSwitchPlatform',
50
+ [accessory]
51
+ );
52
+ this.accessories.push(accessory);
53
+ }
54
+
55
+ createSwitchService(accessory, sw, id) {
56
+ const ServiceType = this.getServiceClass(sw.type);
57
+ const service = new ServiceType(sw.name, id);
58
+
59
+ service.getCharacteristic(Characteristic.On)
60
+ .onGet(() => {
61
+ return accessory.context.switchStates[id];
62
+ })
63
+ .onSet((value) => {
64
+ const behavior = accessory.context.switchBehavior;
65
+ accessory.context.switchStates[id] = value;
66
+ this.log(`[${sw.name}] → ${value ? 'ON' : 'OFF'}`);
67
+
68
+ if (behavior === 'single' && value) {
69
+ Object.keys(accessory.context.switchStates).forEach(key => {
70
+ if (key !== id) {
71
+ accessory.context.switchStates[key] = false;
72
+ accessory.context.switchServices[key].updateCharacteristic(Characteristic.On, false);
73
+ }
74
+ });
75
+ }
76
+
77
+ if (behavior === 'master') {
78
+ Object.keys(accessory.context.switchStates).forEach(key => {
79
+ accessory.context.switchStates[key] = value;
80
+ accessory.context.switchServices[key].updateCharacteristic(Characteristic.On, value);
81
+ });
82
+ } else {
83
+ if (value && sw.delayOff > 0) {
61
84
  setTimeout(() => {
62
- conf.state = false;
63
- service.getCharacteristic(Characteristic.On).updateValue(false);
64
- this.log(`"${switchName}" auto turn off tətbiq olundu`);
65
- }, conf.delayOff); // saniyəni ms-ə çeviririk
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);
66
89
  }
90
+ }
91
+ });
67
92
 
68
- callback();
69
- });
93
+ return service;
94
+ }
70
95
 
71
- this.services.push(service);
72
- });
96
+ getServiceClass(type) {
97
+ switch ((type || '').toLowerCase()) {
98
+ case 'switch': return Service.Switch;
99
+ case 'lightbulb': return Service.Lightbulb;
100
+ case 'fan': return Service.Fan;
101
+ case 'outlet':
102
+ default: return Service.Outlet;
103
+ }
73
104
  }
74
105
 
75
- getServices() {
76
- return this.services;
106
+ configureAccessory(accessory) {
107
+ this.accessories.push(accessory);
77
108
  }
78
- }
109
+ }
package/package.json CHANGED
@@ -1,12 +1,25 @@
1
1
  {
2
2
  "name": "homebridge-multiple-switch",
3
- "version": "1.1.3",
4
- "description": "Multiple switch accessory for Homebridge",
3
+ "version": "1.1.5",
4
+ "description": "Multiple switch platform for Homebridge",
5
+ "homepage": "https://github.com/azadaydinli/homebridge-multiple-switch",
5
6
  "main": "index.js",
6
7
  "author": "Azad Aydınlı",
7
8
  "license": "ISC",
9
+ "bugs": {
10
+ "url": "https://github.com/azadaydinli/homebridge-multiple-switch/issues"
11
+ },
8
12
  "keywords": [
9
- "homebridge-plugin"
13
+ "homebridge-plugin",
14
+ "homebridge",
15
+ "homekit",
16
+ "switch",
17
+ "outlet",
18
+ "lightbulb",
19
+ "fan",
20
+ "dummy",
21
+ "multiple",
22
+ "platform"
10
23
  ],
11
24
  "repository": {
12
25
  "type": "git",
@@ -16,4 +29,4 @@
16
29
  "node": ">=14.17.0",
17
30
  "homebridge": ">=1.3.0"
18
31
  }
19
- }
32
+ }