forked from taeukkang/google-home-push
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
118 lines (100 loc) · 2.98 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
110
111
112
113
114
115
116
117
118
"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.accent =
this.options.accent === undefined ? "en" : options.accent;
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,
1,
3000,
this.options.accent
)
.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();
console.log(`Pushed to device at ${this.device.ip}`);
});
});
}
);
client.on("error", err => {
reject(`Google Cast Client error:\n${err}`);
client.close();
});
});
}
}
module.exports = GoogleHome;