-
Notifications
You must be signed in to change notification settings - Fork 11
/
index.js
109 lines (90 loc) · 2.85 KB
/
index.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
"use strict";
const GoogleCastClient = require("castv2-client").Client;
const DefaultMediaReceiver = require("castv2-client").DefaultMediaReceiver;
const mdns = require("mdns");
const browser = mdns.createBrowser(mdns.tcp("googlecast"));
const googleTTS = require("google-tts-api");
const isIp = require("is-ip");
class GoogleHome {
constructor(deviceIdentifier, options = {}) {
this.device = {};
if (isIp(deviceIdentifier)) {
this.device.ip = deviceIdentifier;
} else {
this.device.name = deviceIdentifier;
}
this.device.identifier = deviceIdentifier;
this.options = options;
this.options.language =
this.options.language === undefined ? "en" : options.language;
this.options.speed =
this.options.speed === undefined ? 1 : options.speed;
this.options.timeout =
this.options.timeout === undefined ? 5000 : options.timeout;
}
searchDevice(name = this.device.name) {
return new Promise((resolve, reject) => {
browser.start();
browser.on("serviceUp", (service) => {
browser.stop();
// Only use the first IP address in the array
const address = service.addresses[0];
console.log(
`Device ${service.txtRecord.fn} at ${address}:${service.port} found`
);
if (service.txtRecord.fn.includes(name)) {
resolve(address);
}
});
setTimeout(() => {
reject(`.searchDevice(): Search timeout`);
}, this.options.timeout);
});
}
async speak(message, language) {
if (!message) {
console.error(".speak(): The text to speak cannot be empty");
return false;
}
return new Promise((resolve, reject) => {
googleTTS(message, language ? language : this.options.language, this.options.speed)
.then((url) => {
this.push(url).then(resolve).catch(reject);
})
.catch(reject);
}).catch((reject) => {
console.error(reject);
});
}
push(url) {
return new Promise(async (resolve, reject) => {
if (this.device.ip === undefined || !isIp(this.device.ip)) {
try {
this.device.ip = await this.searchDevice();
} catch (err) {
return reject(err);
}
}
const client = new GoogleCastClient();
client.connect(this.device.ip, () => {
client.launch(DefaultMediaReceiver, (err, player) => {
const media = {
contentId: url,
contentType: "audio/mp3",
streamType: "BUFFERED",
};
player.load(media, { autoplay: true }, (err, status) => {
client.close();
resolve(status);
console.log(`Pushed to device at ${this.device.ip}`);
});
});
});
client.on("error", (err) => {
reject(err);
client.close();
});
});
}
}
module.exports = GoogleHome;