homebridge-nhc-1 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/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # homebridge-nhc-1
2
+ Homebridge plugin for Niko Home Control 1
3
+
4
+ # Install
5
+ npm install -g homebridge-nhc-1
6
+
7
+ [Configuration example](config.json)
8
+
9
+ # Description
10
+
11
+ This plugin load all your configuration from your local server Niko Home Control
12
+
13
+ It manage `Lights`, `Dimmers` and `Blind`
14
+
15
+ Blinds have a default time of 30s, this can be overridden for each one in config.
16
+
17
+ It is possible to exclude IDs from accessories for scene by example.
18
+
19
+
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const NikoHomeControlPlatform = require('./lib/NikoHomeControlPlatform')
4
+
5
+ module.exports = function (homebridge) {
6
+ homebridge.registerPlatform('homebridge-nhc-1', 'NikoHomeControl', NikoHomeControlPlatform, true)
7
+ }
@@ -0,0 +1,179 @@
1
+ 'use strict';
2
+
3
+ var BLIND_CMD_DOWN = 254;
4
+ var BLIND_CMD_UP = 255;
5
+ var BLIND_CMD_STOP = 253;
6
+
7
+ function NikoHomeControlBlind(platform, action = null) {
8
+ this.platform = platform;
9
+ this.Service = platform.api.hap.Service;
10
+ this.Characteristic = platform.api.hap.Characteristic;
11
+
12
+ var uuid = this.platform.api.hap.uuid.generate(action.name + action.id);
13
+ var foundAccessory = null;
14
+
15
+ this.platform.accessories.forEach((access) => {
16
+ if (access.UUID === uuid) {
17
+ foundAccessory = access;
18
+ }
19
+ });
20
+
21
+ if (foundAccessory === null) {
22
+ this.accessory = this.createAccessory(action);
23
+ } else {
24
+ this.accessory = foundAccessory;
25
+ this.updateAccessory(this.accessory, action);
26
+ }
27
+
28
+ this.accessory._id = action.id;
29
+
30
+ this.accessory.position = action.value1;
31
+ this.accessory.target = action.value1;
32
+ this.accessory.state = 2;
33
+
34
+ this.accessory.time = 30;
35
+
36
+ if (this.platform.config.time) {
37
+ this.platform.config.time.forEach((ActionTime) => {
38
+ if (ActionTime.id === action.id) {
39
+ this.accessory.time = ActionTime.time;
40
+ }
41
+ });
42
+ }
43
+
44
+ this.running = false;
45
+ this.timeout = null;
46
+ }
47
+
48
+ NikoHomeControlBlind.prototype.createAccessory = function(action) {
49
+ var uuid = this.platform.api.hap.uuid.generate(action.name + action.id);
50
+ var PlatformAccessory = this.platform.api.platformAccessory;
51
+
52
+ var accessory = new PlatformAccessory(action.name + action.id, uuid);
53
+
54
+ this.updateAccessory(accessory, action);
55
+
56
+ this.platform.accessories.push(accessory);
57
+ this.platform.api.registerPlatformAccessories("homebridge-nhc-1", "NikoHomeControl", [accessory]);
58
+
59
+ return accessory;
60
+ }
61
+
62
+ NikoHomeControlBlind.prototype.updateAccessory = function(accessory, action) {
63
+ accessory.on('identify', this.identify.bind(this));
64
+
65
+ var service = accessory.getService(accessory.displayName);
66
+
67
+ if (service == undefined) {
68
+ accessory.addService(this.Service.WindowCovering, accessory.displayName)
69
+ }
70
+
71
+ accessory.getService(accessory.displayName)
72
+ .getCharacteristic(this.Characteristic.PositionState)
73
+ .onGet(this.getState.bind(this))
74
+ ;
75
+
76
+ accessory.getService(accessory.displayName)
77
+ .getCharacteristic(this.Characteristic.CurrentPosition)
78
+ .onGet(this.getPosition.bind(this))
79
+ ;
80
+
81
+ accessory.getService(accessory.displayName)
82
+ .getCharacteristic(this.Characteristic.TargetPosition)
83
+ .onGet(this.getTarget.bind(this))
84
+ .onSet(this.setTarget.bind(this))
85
+ .on('change', this.changeTarget.bind(this))
86
+ ;
87
+ }
88
+
89
+ NikoHomeControlBlind.prototype.identify = function(callback) {
90
+ this.platform.log(this.accessory.displayName, "Identify!!!");
91
+ callback();
92
+ }
93
+
94
+ NikoHomeControlBlind.prototype.getState = function() {
95
+ this.platform.log("Get STATE " + this.accessory.displayName + " Blind -> " + this.accessory.state);
96
+ return this.accessory.state;
97
+ }
98
+
99
+ NikoHomeControlBlind.prototype.getPosition = function() {
100
+ this.platform.log("Get Position " + this.accessory.displayName + " Blind -> " + this.accessory.position);
101
+ return this.accessory.position;
102
+ }
103
+
104
+ NikoHomeControlBlind.prototype.getTarget = function() {
105
+ this.platform.log("Get Target " + this.accessory.displayName + " Blind -> " + this.accessory.target);
106
+ return this.accessory.target;
107
+ }
108
+
109
+ NikoHomeControlBlind.prototype.setTarget = function(value) {
110
+ this.accessory.target = value;
111
+
112
+ var cmd = this.accessory.target < this.accessory.position ? BLIND_CMD_DOWN : BLIND_CMD_UP;
113
+
114
+ this.running = true;
115
+ this.platform.niko.executeActions(this.accessory._id, cmd);
116
+ this.platform.log("Set Target " + this.accessory.displayName + " Blind -> " + this.accessory.target);
117
+ }
118
+
119
+ NikoHomeControlBlind.prototype.move = function() {
120
+ var that = this;
121
+ this.platform.log('move position => ', this.accessory.position, this.accessory.target);
122
+ var direction = this.accessory.target > this.accessory.position ? 1 : -1;
123
+
124
+ if (Math.abs(this.accessory.target - this.accessory.position) > 0) {
125
+ that.accessory.position += direction;
126
+ this.timeout = setTimeout(function(){
127
+ that.move();
128
+ }, this.accessory.time * 10);
129
+ } else {
130
+ this.platform.log('DONE');
131
+ this.running = false;
132
+ this.platform.niko.executeActions(this.accessory._id, BLIND_CMD_STOP);
133
+ this.accessory
134
+ .getService(this.accessory.displayName)
135
+ .getCharacteristic(this.Characteristic.CurrentPosition)
136
+ .updateValue(this.accessory.position);
137
+ this.accessory
138
+ .getService(this.accessory.displayName)
139
+ .getCharacteristic(this.Characteristic.PositionState)
140
+ .updateValue(2);
141
+ }
142
+ }
143
+
144
+ NikoHomeControlBlind.prototype.stop = function() {
145
+ if (this.timeout !== null) {
146
+ clearTimeout(this.timeout);
147
+ this.timeout = null;
148
+ }
149
+ this.running = false;
150
+ }
151
+
152
+ NikoHomeControlBlind.prototype.changeTarget = function(oldValue, newValue) {
153
+ this.platform.log('CHANGE Target');
154
+ if (newValue === undefined) {
155
+ return;
156
+ }
157
+
158
+ if (null === oldValue && false === this.running) {
159
+ this.accessory.position = newValue;
160
+ this.accessory.target = newValue;
161
+ this.accessory.state = 2;
162
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.CurrentPosition).updateValue(this.accessory.position);
163
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.TargetPosition).updateValue(this.accessory.target);
164
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.PositionState).updateValue(this.accessory.state);
165
+
166
+ this.platform.log('EVENT');
167
+ return;
168
+ }
169
+
170
+ this.stop();
171
+ this.move();
172
+ }
173
+
174
+ NikoHomeControlBlind.prototype.changeValue = function(oldValue, newValue) {
175
+ this.platform.log('CHANGE VALUE', oldValue, newValue);
176
+ this.changeTarget(oldValue, newValue);
177
+ }
178
+
179
+ module.exports = NikoHomeControlBlind
@@ -0,0 +1,141 @@
1
+ 'use strict';
2
+
3
+ function NikoHomeControlDimmer(platform, action = null) {
4
+ this.platform = platform;
5
+ this.Service = platform.api.hap.Service;
6
+ this.Characteristic = platform.api.hap.Characteristic;
7
+
8
+ var uuid = this.platform.api.hap.uuid.generate(action.name + action.id);
9
+ var foundAccessory = null;
10
+
11
+ this.platform.accessories.forEach((access) => {
12
+ if (access.UUID === uuid) {
13
+ foundAccessory = access;
14
+ }
15
+ });
16
+
17
+ if (foundAccessory === null) {
18
+ this.accessory = this.createAccessory(action);
19
+ } else {
20
+ this.accessory = foundAccessory;
21
+ this.updateAccessory(this.accessory, action);
22
+ }
23
+
24
+ this.accessory._id = action.id;
25
+ this.accessory.value = this.convertValue(action.value1);
26
+ }
27
+
28
+ NikoHomeControlDimmer.prototype.createAccessory = function(action) {
29
+ var uuid = this.platform.api.hap.uuid.generate(action.name + action.id);
30
+ var PlatformAccessory = this.platform.api.platformAccessory;
31
+
32
+ var accessory = new PlatformAccessory(action.name + action.id, uuid);
33
+
34
+ this.updateAccessory(accessory, action);
35
+
36
+ this.platform.accessories.push(accessory);
37
+ this.platform.api.registerPlatformAccessories("homebridge-nhc-1", "NikoHomeControl", [accessory]);
38
+
39
+ return accessory;
40
+ }
41
+
42
+ NikoHomeControlDimmer.prototype.updateAccessory = function(accessory, action) {
43
+ accessory.on('identify', this.identify.bind(this));
44
+
45
+ var service = accessory.getService(accessory.displayName);
46
+
47
+ if (service == undefined) {
48
+ accessory.addService(this.Service.Lightbulb, accessory.displayName)
49
+ }
50
+
51
+ accessory.getService(accessory.displayName)
52
+ .getCharacteristic(this.Characteristic.On)
53
+ .onGet(this.getValue.bind(this))
54
+ .onSet(this.setValue.bind(this))
55
+ .on('change', this.changeValue.bind(this))
56
+ ;
57
+
58
+ accessory.getService(accessory.displayName)
59
+ .getCharacteristic(this.Characteristic.Brightness)
60
+ .onGet(this.getBrightness.bind(this))
61
+ .onSet(this.setBrightness.bind(this))
62
+ .on('change', this.changeValue.bind(this))
63
+ ;
64
+ }
65
+
66
+ NikoHomeControlDimmer.prototype.convertValue = function(value1) {
67
+ if (value1 === true) {
68
+ return 100;
69
+ } else if (value1 === false) {
70
+ return 0;
71
+ }
72
+ return value1;
73
+ }
74
+
75
+ NikoHomeControlDimmer.prototype.identify = function(callback) {
76
+ this.platform.log(this.accessory.displayName, "Identify!!!");
77
+
78
+ var initialValue = this.accessory.value;
79
+ var that = this;
80
+
81
+ if (initialValue > 0) {
82
+ this.platform.niko.executeActions(this.accessory._id, 0);
83
+ } else {
84
+ this.platform.niko.executeActions(this.accessory._id, 100);
85
+ }
86
+
87
+ setTimeout(function() {
88
+ that.platform.niko.executeActions(that.accessory._id, initialValue);
89
+ }, 2000);
90
+
91
+ callback();
92
+ }
93
+
94
+ NikoHomeControlDimmer.prototype.getValue = function() {
95
+ this.platform.log("Get " + this.accessory.displayName + " Dimmer -> " + this.accessory.value);
96
+
97
+ return this.accessory.value > 0;
98
+ }
99
+
100
+ NikoHomeControlDimmer.prototype.setValue = function(value) {
101
+ if (value === true && this.accessory.value === 0) {
102
+ this.platform.niko.executeActions(this.accessory._id, 100);
103
+ } else if (value === false && this.accessory.value > 0) {
104
+ this.platform.niko.executeActions(this.accessory._id, 0);
105
+ }
106
+ }
107
+
108
+ NikoHomeControlDimmer.prototype.getBrightness = function() {
109
+ this.platform.log("Get Brightness " + this.accessory.displayName + " Dimmer -> " + this.accessory.value);
110
+
111
+ return this.accessory.value;
112
+ }
113
+
114
+ NikoHomeControlDimmer.prototype.setBrightness = function(value) {
115
+ this.accessory.value = value;
116
+
117
+ this.platform.niko.executeActions(this.accessory._id, value);
118
+ this.platform.log("Set Brightness " + this.accessory.displayName + " Dimmer -> " + this.accessory.value);
119
+ }
120
+
121
+ NikoHomeControlDimmer.prototype.changeValue = function(oldValue, newValue) {
122
+ if (newValue === undefined) {
123
+ return;
124
+ }
125
+
126
+ var value = this.convertValue(newValue);
127
+
128
+ if (this.accessory.value !== value) {
129
+ this.accessory.value = value;
130
+
131
+ this.platform.log("Change " + this.accessory.displayName + " Dimmer -> " + this.accessory.value);
132
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.Brightness).updateValue(this.accessory.value);
133
+ if (value === 0) {
134
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.On).updateValue(false);
135
+ } else {
136
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.On).updateValue(true);
137
+ }
138
+ }
139
+ }
140
+
141
+ module.exports = NikoHomeControlDimmer
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ function NikoHomeControlLight(platform, action = null) {
4
+ this.platform = platform;
5
+ this.Service = platform.api.hap.Service;
6
+ this.Characteristic = platform.api.hap.Characteristic;
7
+
8
+ var uuid = this.platform.api.hap.uuid.generate(action.name + action.id);
9
+ var foundAccessory = null;
10
+
11
+ this.platform.accessories.forEach((access) => {
12
+ if (access.UUID === uuid) {
13
+ foundAccessory = access;
14
+ }
15
+ });
16
+
17
+ if (foundAccessory === null) {
18
+ this.accessory = this.createAccessory(action);
19
+ } else {
20
+ this.accessory = foundAccessory;
21
+ this.updateAccessory(this.accessory, action);
22
+ }
23
+
24
+ this.accessory._id = action.id;
25
+ this.accessory.value = this.convertValue(action.value1);
26
+ }
27
+
28
+ NikoHomeControlLight.prototype.createAccessory = function(action) {
29
+ var uuid = this.platform.api.hap.uuid.generate(action.name + action.id);
30
+ var PlatformAccessory = this.platform.api.platformAccessory;
31
+
32
+ var accessory = new PlatformAccessory(action.name + action.id, uuid);
33
+
34
+ this.updateAccessory(accessory, action);
35
+
36
+ this.platform.accessories.push(accessory);
37
+ this.platform.api.registerPlatformAccessories("homebridge-nhc-1", "NikoHomeControl", [accessory]);
38
+
39
+ return accessory;
40
+ }
41
+
42
+ NikoHomeControlLight.prototype.updateAccessory = function(accessory, action) {
43
+ accessory.on('identify', this.identify.bind(this));
44
+
45
+ var service = accessory.getService(accessory.displayName);
46
+
47
+ if (service == undefined) {
48
+ accessory.addService(this.Service.Lightbulb, accessory.displayName)
49
+ }
50
+
51
+ accessory.getService(accessory.displayName)
52
+ .getCharacteristic(this.Characteristic.On)
53
+ .onGet(this.getValue.bind(this))
54
+ .onSet(this.setValue.bind(this))
55
+ .on('change', this.changeValue.bind(this))
56
+ ;
57
+ }
58
+
59
+ NikoHomeControlLight.prototype.convertValue = function(value1) {
60
+ return value1 === 100;
61
+ }
62
+
63
+ NikoHomeControlLight.prototype.identify = function(callback) {
64
+ this.platform.log(this.accessory.displayName, "Identify!!!");
65
+
66
+ var that = this;
67
+ var initialValue = this.accessory.value;
68
+
69
+ if (initialValue === true) {
70
+ this.platform.niko.executeActions(this.accessory._id, 0);
71
+ } else {
72
+ this.platform.niko.executeActions(this.accessory._id, 100);
73
+ }
74
+
75
+ setTimeout(function() {
76
+ that.platform.niko.executeActions(that.accessory._id, initialValue ? 100 : 0);
77
+ }, 2000);
78
+
79
+ callback();
80
+ }
81
+
82
+ NikoHomeControlLight.prototype.getValue = function() {
83
+ this.platform.log("Get " + this.accessory.displayName + " Light -> " + this.accessory.value);
84
+
85
+ return this.accessory.value;
86
+ }
87
+
88
+ NikoHomeControlLight.prototype.setValue = function(value) {
89
+ this.accessory.value = value;
90
+
91
+ this.platform.niko.executeActions(this.accessory._id, value ? 100 : 0);
92
+ this.platform.log("Set " + this.accessory.displayName + " Light -> " + this.accessory.value);
93
+ }
94
+
95
+ NikoHomeControlLight.prototype.changeValue = function(oldValue, newValue) {
96
+ if (newValue === undefined) {
97
+ return;
98
+ }
99
+
100
+ var value = this.convertValue(newValue);
101
+
102
+ if (this.accessory.value !== value) {
103
+ this.accessory.value = value;
104
+ this.platform.log("Change " + this.accessory.displayName + " Light -> " + this.accessory.value);
105
+ this.accessory.getService(this.accessory.displayName).getCharacteristic(this.Characteristic.On).updateValue(this.accessory.value);
106
+ }
107
+ }
108
+
109
+ module.exports = NikoHomeControlLight
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ const niko = require('niko-home-control');
4
+
5
+ var NikoHomeControlLight = require('./NikoHomeControlLight');
6
+ var NikoHomeControlDimmer = require('./NikoHomeControlDimmer');
7
+ var NikoHomeControlBlind = require('./NikoHomeControlBlind');
8
+
9
+ module.exports = NikoHomeControlPlatform
10
+
11
+ // Platform constructor
12
+ // config may be null
13
+ // api may be null if launched from old homebridge version
14
+ function NikoHomeControlPlatform(log, config, api) {
15
+ log("NikoHomeControl Init");
16
+
17
+ this.accessories = [];
18
+ this.controllers = [];
19
+ this.niko = niko;
20
+
21
+ this.log = log;
22
+ this.config = config;
23
+
24
+ if (api) {
25
+ // Save the API object as plugin needs to register new accessory via this object
26
+ this.api = api;
27
+
28
+ // Listen to event "didFinishLaunching", this means homebridge already finished loading cached accessories.
29
+ // Platform Plugin should only register new accessory that doesn't exist in homebridge after this event.
30
+ // Or start discover new accessories.
31
+ this.api.on('didFinishLaunching', function() {
32
+ this.log("DidFinishLaunching");
33
+ this.run();
34
+ }.bind(this));
35
+ }
36
+ }
37
+
38
+ // Function invoked when homebridge tries to restore cached accessory.
39
+ // Developer can configure accessory at here (like setup event handler).
40
+ // Update current value.
41
+ NikoHomeControlPlatform.prototype.configureAccessory = function(accessory) {
42
+ this.log(accessory.displayName, "Configure Accessory");
43
+ var platform = this;
44
+
45
+ this.accessories.push(accessory);
46
+ }
47
+
48
+ NikoHomeControlPlatform.prototype.run = function() {
49
+ this.log("Run");
50
+
51
+ if (!this.config.ip) {
52
+ this.log("ERROR: No IP address configured. Please add 'ip' to your config.json.");
53
+ return;
54
+ }
55
+
56
+ this.niko.init({
57
+ ip: this.config.ip,
58
+ port: 8000,
59
+ timeout: 2000,
60
+ events: true
61
+ });
62
+
63
+ niko.events.on('listactions', this.onEventAction.bind(this));
64
+
65
+ niko
66
+ .listActions()
67
+ .then(this.listActions.bind(this))
68
+ .catch((err) => {
69
+ this.log("Error connecting to Niko Home Control: " + err);
70
+ this.log("Retrying in 30 seconds...");
71
+ setTimeout(this.run.bind(this), 30000);
72
+ });
73
+ }
74
+
75
+ NikoHomeControlPlatform.prototype.listActions = function(response) {
76
+ var actions = response.data;
77
+
78
+ actions.forEach((action) => {
79
+ // exclude
80
+ if (this.config.exclude && this.config.exclude.indexOf(action.id) !== -1) {
81
+ return;
82
+ }
83
+
84
+ switch(action.type) {
85
+ case 1:
86
+ this.addAccessory(NikoHomeControlLight, null, action);
87
+ break;
88
+ case 2:
89
+ this.addAccessory(NikoHomeControlDimmer, null, action);
90
+ break;
91
+ case 4:
92
+ this.addAccessory(NikoHomeControlBlind, null, action);
93
+ break;
94
+ default:
95
+ this.log('UNKNOWN ' + action.name + ' type ' + action.type);
96
+ }
97
+ });
98
+ }
99
+
100
+ NikoHomeControlPlatform.prototype.addAccessory = function(className, accessory = null, action = null) {
101
+ this.log("Add " + action.name);
102
+ var controller = new className(this, action);
103
+ this.controllers[action.id] = controller;
104
+ }
105
+
106
+ NikoHomeControlPlatform.prototype.onEventAction = function(event) {
107
+ event.data.forEach((action) => {
108
+ if (this.controllers.hasOwnProperty(action.id)) {
109
+ this.controllers[action.id].changeValue(null, action.value1);
110
+ }
111
+ });
112
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "displayName": "Homebridge NikoHomeControl",
3
+ "name": "homebridge-nhc-1",
4
+ "version": "1.3.1",
5
+ "description": "Homebridge plugin for Niko Home Control",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "homebridge-plugin",
9
+ "Niko",
10
+ "Niko Home",
11
+ "Niko Home Control"
12
+ ],
13
+ "homepage": "https://github.com/hmodateresyc/homebridge-nhc-1#readme",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git://github.com/hmodateresyc/homebridge-nhc-1.git"
17
+ },
18
+ "bugs": {
19
+ "url": "http://github.com/hmodateresyc/homebridge-nhc-1/issues"
20
+ },
21
+ "engines": {
22
+ "node": "^18.20.4 || ^20.15.1 || ^22",
23
+ "homebridge": "^1.6.0 || ^2.0.0"
24
+ },
25
+ "dependencies": {
26
+ "niko-home-control": "0.4.3"
27
+ },
28
+ "peerDependencies": {
29
+ "homebridge": "^1.6.0 || ^2.0.0"
30
+ }
31
+ }