2018-08-09 21:20:30 +02:00
|
|
|
const udp = require('dgram');
|
|
|
|
const server = udp.createSocket('udp4');
|
|
|
|
const http = require('http');
|
|
|
|
|
2021-03-24 22:40:49 +01:00
|
|
|
const YAMAHA_IP = process.env.YAMAHA_IP;
|
|
|
|
const SPEAKERS_IP = process.env.SPEAKERS_IP;
|
|
|
|
const LOCAL_IP = process.env.LOCAL_IP || "0.0.0.0";
|
2018-08-09 21:20:30 +02:00
|
|
|
const INCOMING_EVENT_SERVER_PORT = parseInt(process.env.PORT) || 41100;
|
|
|
|
|
|
|
|
const inputSourceToSoundProgam = inputSource => {
|
|
|
|
switch (inputSource) {
|
|
|
|
case 'airplay':
|
|
|
|
case 'spotify':
|
|
|
|
return 'music';
|
|
|
|
|
|
|
|
case 'tv':
|
|
|
|
case 'bd_dvd':
|
|
|
|
return 'tv_program';
|
|
|
|
|
|
|
|
default:
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const inputSourceShouldUseClearVoice = inputSource => {
|
|
|
|
switch (inputSource) {
|
|
|
|
case 'tv':
|
|
|
|
case 'bd_dvd':
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-24 22:40:49 +01:00
|
|
|
const send = (host, path, headers) =>
|
2018-08-09 21:20:30 +02:00
|
|
|
http
|
|
|
|
.get(
|
|
|
|
{
|
|
|
|
localAddress: LOCAL_IP,
|
2021-03-24 22:40:49 +01:00
|
|
|
host: host,
|
2018-08-09 21:20:30 +02:00
|
|
|
path,
|
|
|
|
timeout: 3000,
|
|
|
|
headers: {
|
|
|
|
'User-Agent': 'yamaha-sound-program-by-source',
|
|
|
|
Accept: 'application/vnd.musiccast.v1+json',
|
|
|
|
...headers
|
|
|
|
}
|
|
|
|
},
|
|
|
|
resp => {
|
|
|
|
let data = '';
|
|
|
|
|
|
|
|
resp.on('data', chunk => {
|
|
|
|
data += chunk;
|
|
|
|
});
|
|
|
|
|
|
|
|
resp.on('end', () => {
|
|
|
|
// console.log(data);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
)
|
|
|
|
.on('error', err => {
|
|
|
|
console.error('Error', err.message);
|
|
|
|
});
|
|
|
|
|
|
|
|
const sendSetSoundProgram = soundProgram =>
|
|
|
|
send(
|
2021-03-24 22:40:49 +01:00
|
|
|
YAMAHA_IP,
|
2018-08-09 21:20:30 +02:00
|
|
|
`/YamahaExtendedControl/v1/main/setSoundProgram?program=${soundProgram}`
|
|
|
|
);
|
|
|
|
|
|
|
|
const sendSetClearVoice = enabled =>
|
|
|
|
send(
|
2021-03-24 22:40:49 +01:00
|
|
|
YAMAHA_IP,
|
2018-08-09 21:20:30 +02:00
|
|
|
`/YamahaExtendedControl/v1/main/setClearVoice?enabled=${
|
|
|
|
enabled ? 'true' : 'false'
|
|
|
|
}`
|
|
|
|
);
|
|
|
|
|
2021-03-24 22:40:49 +01:00
|
|
|
const setVolume = (host,volume) =>
|
|
|
|
send(host,'/YamahaExtendedControl/v1/main/setVolume?volume='+volume);
|
|
|
|
|
2018-08-09 21:20:30 +02:00
|
|
|
const sendEventServerAddress = port =>
|
2021-03-24 22:40:49 +01:00
|
|
|
send(YAMAHA_IP,
|
|
|
|
'/YamahaExtendedControl/v1', {
|
2018-08-09 21:20:30 +02:00
|
|
|
'X-AppName': 'MusicCast/1',
|
|
|
|
'X-AppPort': port
|
|
|
|
});
|
|
|
|
|
|
|
|
const handleIncomingEvent = event => {
|
2021-03-24 22:40:49 +01:00
|
|
|
console.log(event)
|
2018-08-09 21:20:30 +02:00
|
|
|
const isInputChanged = event.main && typeof event.main.input !== 'undefined';
|
|
|
|
|
2021-03-24 22:40:49 +01:00
|
|
|
// e.g. { main: { volume: 47 }, device_id: 'AC44F2852577' }
|
|
|
|
if ( event.main && typeof event.main.volume !== 'undefined' ) {
|
|
|
|
setVolume(SPEAKERS_IP,event.main.volume);
|
|
|
|
}
|
|
|
|
|
2018-08-09 21:20:30 +02:00
|
|
|
if (isInputChanged) {
|
|
|
|
const soundProgram = inputSourceToSoundProgam(event.main.input);
|
|
|
|
const setClearVoice = inputSourceShouldUseClearVoice(event.main.input);
|
|
|
|
|
|
|
|
if (soundProgram) {
|
|
|
|
console.log('Changing sound program to', soundProgram);
|
2021-03-24 22:40:49 +01:00
|
|
|
//sendSetSoundProgram(soundProgram);
|
2018-08-09 21:20:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
console.log('Setting clear voice to', setClearVoice);
|
2021-03-24 22:40:49 +01:00
|
|
|
// sendSetClearVoice(setClearVoice);
|
2018-08-09 21:20:30 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
server.on('close', () => {
|
|
|
|
console.log('Server is closed!');
|
|
|
|
});
|
|
|
|
|
|
|
|
server.on('error', error => {
|
|
|
|
console.error('Error', error);
|
|
|
|
server.close();
|
|
|
|
});
|
|
|
|
|
|
|
|
server.on('message', (msg, _info) => {
|
|
|
|
let body = '';
|
|
|
|
|
|
|
|
try {
|
|
|
|
body = JSON.parse(msg.toString('utf8'));
|
|
|
|
} catch (err) {
|
|
|
|
console.warn('Could not parse event', msg.toString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// console.log(body);
|
|
|
|
handleIncomingEvent(body);
|
|
|
|
});
|
|
|
|
|
|
|
|
server.on('listening', () => {
|
|
|
|
const address = server.address();
|
|
|
|
const port = address.port;
|
|
|
|
const ipaddr = address.address;
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
'Incoming event server is listening at port',
|
|
|
|
ipaddr + ':' + port
|
|
|
|
);
|
|
|
|
|
|
|
|
sendEventServerAddress(port);
|
2018-08-09 21:33:30 +02:00
|
|
|
|
|
|
|
// After 10 minutes the receiver will drop this server to be notified unless we
|
|
|
|
// say hi again, so to be on the safe side, ask again every 5 minutes.
|
|
|
|
setInterval(() => sendEventServerAddress(port), 5 * 60 * 1000);
|
2018-08-09 21:20:30 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
server.bind(INCOMING_EVENT_SERVER_PORT, LOCAL_IP);
|