Initial version

This commit is contained in:
Axel Olsson 2018-08-09 21:20:30 +02:00
parent 8a083b8440
commit b0782184f3
5 changed files with 184 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/node_modules
.DS_Store

32
README.md Normal file
View file

@ -0,0 +1,32 @@
# yamaha-sound-program-by-source
Instead of having to manually change the sound program when you're switching from e.g. TV to Spotify and vice verse, let the computer do it for you.
When the input source of your Yamaha receiver changes, the sound program and clear voice settings are automatically changed.
## Usage
Specify the following env variables before running `index.js`
YAMAHA_IP # The ip address to your receiver
LOCAL_IP # Your local ip address to use, 0.0.0.0 could work in some setups
PORT # Port listening for events from the receiver, defaults to 41100
Example
YAMAHA_IP=192.168.1.216 LOCAL_IP=192.168.1.187 node .
## Misc
Currently the following mappings from source to sound program are hard coded
tv => tv_program with clear_voice enabled
bd_dvd => tv_program with clear_voice enabled
spotify => music with clear_voice disabled
airplay => music with clear_voice disabled
# References
http://habitech.s3.amazonaws.com/PDFs/YAM/MusicCast/Yamaha%20MusicCast%20HTTP%20simplified%20API%20for%20ControlSystems.pdf
https://www.pdf-archive.com/2017/04/21/yxc-api-spec-advanced/yxc-api-spec-advanced.pdf

136
index.js Normal file
View file

@ -0,0 +1,136 @@
const udp = require('dgram');
const server = udp.createSocket('udp4');
const http = require('http');
const YAMAHA_IP = process.env.YAMAHA_IP || '192.168.1.216';
const LOCAL_IP = process.env.LOCAL_IP || '192.168.1.187';
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;
}
};
const send = (path, headers) =>
http
.get(
{
localAddress: LOCAL_IP,
host: YAMAHA_IP,
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(
`/YamahaExtendedControl/v1/main/setSoundProgram?program=${soundProgram}`
);
const sendSetClearVoice = enabled =>
send(
`/YamahaExtendedControl/v1/main/setClearVoice?enabled=${
enabled ? 'true' : 'false'
}`
);
const sendEventServerAddress = port =>
send('/YamahaExtendedControl/v1', {
'X-AppName': 'MusicCast/1',
'X-AppPort': port
});
const handleIncomingEvent = event => {
const isInputChanged = event.main && typeof event.main.input !== 'undefined';
if (isInputChanged) {
const soundProgram = inputSourceToSoundProgam(event.main.input);
const setClearVoice = inputSourceShouldUseClearVoice(event.main.input);
if (soundProgram) {
console.log('Changing sound program to', soundProgram);
sendSetSoundProgram(soundProgram);
}
console.log('Setting clear voice to', setClearVoice);
sendSetClearVoice(setClearVoice);
}
};
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);
});
server.bind(INCOMING_EVENT_SERVER_PORT, LOCAL_IP);

9
package.json Normal file
View file

@ -0,0 +1,9 @@
{
"name": "yamaha-sound-program-by-source",
"version": "1.0.0",
"main": "index.js",
"author": "axelo",
"license": "MIT",
"private": true,
"dependencies": {}
}

4
yarn.lock Normal file
View file

@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1