-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathadapter.js
130 lines (117 loc) · 3.92 KB
/
adapter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'use strict';
const { Adapter } = require('gateway-addon');
const { Explorer } = require("@harmonyhub/discover");
const HarmonyHub = require("./hub");
//TODO hue bulbs?
class HarmonyAdapter extends Adapter {
constructor(addonManager, packageName) {
super(addonManager, 'HarmonyAdapter', packageName);
addonManager.addAdapter(this);
this.startPairing(30);
}
/**
* @param {HarmonyHub} device Sonos device to add.
* @return {Promise} which resolves to the device added.
*/
async addDevice(device) {
if(device.uuid in this.devices) {
throw 'Device: ' + device.uuid + ' already exists.';
}
else {
const hub = new HarmonyHub(this, device.uuid, device);
await hub.ready;
}
}
async removeDevice(device, force = false) {
const isHub = device instanceof HarmonyHub;
let devicesForHub = 0;
if(isHub) {
for(const dev of Object.values(this.devices)) {
if(dev.id !== device.id && !(dev instanceof HarmonyHub) && dev.hub.id === device.id) {
if(force) {
await this.removeThing(dev);
}
else {
++devicesForHub;
}
}
}
this.handleDeviceRemoved(device);
// Only unload hub when it's the last device depending on itself.
if(devicesForHub === 0) {
device.unload();
}
}
else {
this.handleDeviceRemoved(device);
for(const dev of Object.values(this.devices)) {
if(dev.id !== device.hub.id && !(dev instanceof HarmonyHub) && device.hub.id === dev.hub.id) {
++devicesForHub;
}
}
if(devicesForHub === 0 && this.getDevice(device.hub.id)) {
await this.removeDevice(this.getDevice(device.hub.id));
}
else {
device.hub.unload();
}
}
}
/**
* Start the pairing/discovery process.
*
* @param {Number} timeoutSeconds Number of seconds to run before timeout
*/
startPairing(_timeoutSeconds) {
if(!this.discover) {
this.discover = new Explorer(61991);
this.discover.on('online', (hub) => {
this.addDevice(hub).catch(console.error);
});
this.discover.on('offline', (hub) => {
this.removeDevice(this.getDevice(hub.uuid), true).catch(console.error);
});
this.discover.start();
setTimeout(() => this.cancelPairing(), _timeoutSeconds * 1000);
}
}
/**
* Cancel the pairing/discovery process.
*/
cancelPairing() {
if(this.discover) {
this.discover.stop();
this.discover.removeAllListeners();
this.discover = undefined;
}
}
/**
* Unpair the provided the device from the adapter.
*
* @param {Object} device Device to unpair with.
* @param {boolean} [force=false] If all child devices should also be removed.
*/
removeThing(device, force = false) {
this.removeDevice(device, force).then(() => {
console.log('HarmonyAdapter: device:', device.id, 'was unpaired.');
}).catch((err) => {
console.error('HarmonyAdapter: unpairing', device.id, 'failed');
console.error(err);
});
}
async unload() {
for(const device of Object.values(this.devices)) {
if(device instanceof HarmonyHub) {
device.unload();
}
else {
device.hub.unload();
}
}
return super.unload();
}
}
function loadAdapter(addonManager, manifest, _errorCallback) {
const adapter = new HarmonyAdapter(addonManager, manifest.name);
}
module.exports = loadAdapter;