Skip to content

Commit

Permalink
Introduce NightMode and SpeechEnhancement calls
Browse files Browse the repository at this point in the history
Recognize subs connected to PLAYBAR
v1.4.0
  • Loading branch information
jishi committed Feb 26, 2017
1 parent 89f0b91 commit 6faedf8
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 33 deletions.
22 changes: 6 additions & 16 deletions lib/SonosSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,18 @@ function SonosSystem(settings) {
}

cache[member.uuid] = new Type(member, listener, _this);

const channelMapSet = member.channelmapset || member.htsatchanmapset;
cache[member.uuid].hasSub = /:SW/.test(channelMapSet);

return cache[member.uuid];
}

function getPlayers(members) {
if (members instanceof Array === false) {
// single item
return [tryGet(playerCache, Player, members)];
const player = tryGet(playerCache, Player, members);
return [player];
}

// Find normal players
Expand All @@ -66,21 +71,6 @@ function SonosSystem(settings) {
return tryGet(playerCache, Player, member);
});

// fix sub and pairs
const invisible = members.filter((member) => {
return !isVisible(member);
})
.forEach((member) => {
if (!member.channelmapset) {
return;
}

const hasSub = /SW,SW/.test(member.channelmapset);
const primaryMatch = /(RINCON_[0-9ABCDEF]+):LF/.exec(member.channelmapset);
let primaryUuid = primaryMatch[1];
playerCache[primaryUuid].hasSub = hasSub;
});

return players;
}

Expand Down
13 changes: 13 additions & 0 deletions lib/prototypes/Player/nightMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
const soap = require('../../helpers/soap');
const TYPE = soap.TYPE;

function nightMode(enable) {
const value = enable ? '1' : '0';
return soap.invoke(
`${this.baseUrl}/MediaRenderer/RenderingControl/Control`,
TYPE.SetEQ,
{ eqType: 'NightMode', value });
};

module.exports = nightMode;
13 changes: 13 additions & 0 deletions lib/prototypes/Player/speechEnhancement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
const soap = require('../../helpers/soap');
const TYPE = soap.TYPE;

function speechEnhancement(enable) {
const value = enable ? '1' : '0';
return soap.invoke(
`${this.baseUrl}/MediaRenderer/RenderingControl/Control`,
TYPE.SetEQ,
{ eqType: 'DialogLevel', value });
};

module.exports = speechEnhancement;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sonos-discovery",
"version": "1.3.2",
"version": "1.4.0",
"description": "A simple node library for managing your Sonos system",
"author": "Jimmy Shimizu <[email protected]>",
"repository": {
Expand Down
18 changes: 18 additions & 0 deletions test/data/topology.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,23 @@
"channelmapset": "RINCON_30000000000101400:LF,LF;RINCON_30000000000201400:RF,RF;RINCON_30000000000301400:SW,SW"
}
]
},
{
"$name": "zonegroup",
"$attrs": {
"coordinator": "RINCON_40000000000101400",
"id": "RINCON_40000000000101400:49"
},
"zonegroupmember": {
"bootseq": "8",
"configuration": "1",
"htsatchanmapset": "RINCON_40000000000101400:LF,RF;RINCON_40000000000201400:RR;RINCON_40000000000301400:LR;RINCON_40000000000401400:SW",
"icon": "x-rincon-roomicon:living",
"location": "http://192.168.1.103:1400/xml/device_description.xml",
"mincompatibleversion": "22.0-00000",
"softwareversion": "24.0-71060",
"uuid": "RINCON_40000000000101400",
"zonename": "Home Theatre"
}
}
]
32 changes: 16 additions & 16 deletions test/unit/SonosSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,33 +170,33 @@ describe('SonosSystem', () => {
});

it('Flags primary player if SUB is connected', () => {
sonos.zones.forEach((zone) => {
let tvRoom = zone.members.find((member) => member.roomName === 'TV Room');
expect(tvRoom).not.undefined;
expect(tvRoom.hasSub).to.be.true;
});
const tvRoom = sonos.getPlayer('TV Room');
expect(tvRoom).not.undefined;
expect(tvRoom.hasSub).to.be.true;
});

it('should flag stereo pair if SUB is connected', () => {
sonos.zones.forEach((zone) => {
let livingRoom = zone.members.find((member) => member.roomName === 'Living Room');
expect(livingRoom).not.undefined;
expect(livingRoom.hasSub).to.be.true;
});
const livingRoom = sonos.getPlayer('Living Room');
expect(livingRoom).not.undefined;
expect(livingRoom.hasSub).to.be.true;
});

it('should flag PLAYBAR if SUB is connected', () => {
const playbar = sonos.getPlayer('Home Theatre');
expect(playbar).not.undefined;
expect(playbar.hasSub).to.be.true;
});

it('should not flag player if SUB is not connected', () => {
sonos.zones.forEach((zone) => {
let livingRoom = zone.members.find((member) => member.roomName === 'Kitchen');
expect(livingRoom).not.undefined;
expect(livingRoom.hasSub).to.be.false;
});
const kitchen = sonos.getPlayer('Kitchen');
expect(kitchen).not.undefined;
expect(kitchen.hasSub).to.be.false;
});

it('Only creates player once', () => {
let topology = require('../data/topology.json');
listener.on.withArgs('topology').yield('', topology);
expect(Player).callCount(6);
expect(Player).callCount(7);
});

it('Links coordinator property on all players', () => {
Expand Down
123 changes: 123 additions & 0 deletions test/unit/prototypes/Player/nightMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
'use strict';
const expect = require('chai').expect;
const sinon = require('sinon');
const proxyquire = require('proxyquire');
require('chai').use(require('sinon-chai'));

const soap = require('../../../../lib/helpers/soap');
const TYPE = soap.TYPE;

describe('Player.nightMode()', () => {
let zoneMemberData;
let request;
let Player;
let player;
let Subscriber;
let subscriber;
let listener;
let system;
let musicServices;

beforeEach(() => {
sinon.stub(soap, 'invoke').resolves();
sinon.stub(soap, 'parse');
});

afterEach(() => {
if (soap.invoke.restore)
soap.invoke.restore();
if (soap.parse.restore)
soap.parse.restore();
});

beforeEach(() => {
zoneMemberData = {
uuid: 'RINCON_00000000000001400',
location: 'http://192.168.1.151:1400/xml/device_description.xml',
zonename: 'Kitchen',
icon: 'x-rincon-roomicon:kitchen',
configuration: '1',
softwareversion: '31.8-24090',
mincompatibleversion: '29.0-00000',
legacycompatibleversion: '24.0-00000',
bootseq: '114',
wirelessmode: '0',
hasconfiguredssid: '0',
channelfreq: '2412',
behindwifiextender: '0',
wifienabled: '1',
orientation: '0',
sonarstate: '4'
};

subscriber = {
dispose: sinon.spy()
};

Subscriber = sinon.stub().returns(subscriber);

musicServices = {
tryGetHighResArt: sinon.stub()
};

musicServices.tryGetHighResArt.onCall(0).resolves('http://example.org/image1');
musicServices.tryGetHighResArt.onCall(1).resolves('http://example.org/image2');

Player = proxyquire('../../../../lib/models/Player', {
'../Subscriber': Subscriber,
'../musicservices': musicServices
});

listener = {
endpoint: sinon.stub().returns('http://127.0.0.2/'),
on: sinon.spy()
};

system = {
zones: [
{
uuid: zoneMemberData.uuid,
members: []
}
],
on: sinon.stub(),
emit: sinon.spy()
};

player = new Player(zoneMemberData, listener, system);
player.coordinator = player;
system.zones[0].coordinator = player;
system.zones[0].members.push(player);
});

it('should call correct soap call when enabling', () => {
return player.nightMode(true)
.then(() => {
expect(soap.invoke).calledOnce;
expect(soap.invoke.firstCall.args).eql([
'http://192.168.1.151:1400/MediaRenderer/RenderingControl/Control',
TYPE.SetEQ,
{
eqType: 'NightMode',
value: '1'
}
]);
});
});

it('should call correct soap call when disabling', () => {
return player.nightMode(false)
.then(() => {
expect(soap.invoke).calledOnce;
expect(soap.invoke.firstCall.args).eql([
'http://192.168.1.151:1400/MediaRenderer/RenderingControl/Control',
TYPE.SetEQ,
{
eqType: 'NightMode',
value: '0'
}
]);
});
});

});
Loading

0 comments on commit 6faedf8

Please sign in to comment.