From 0605c5ff86dfbfed23fdf67eb2f59de228d20955 Mon Sep 17 00:00:00 2001 From: bezzers Date: Thu, 23 Jul 2015 09:27:58 -0400 Subject: [PATCH 1/5] Create Sonos.js --- platforms/Sonos.js | 154 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 platforms/Sonos.js diff --git a/platforms/Sonos.js b/platforms/Sonos.js new file mode 100644 index 0000000..47a078a --- /dev/null +++ b/platforms/Sonos.js @@ -0,0 +1,154 @@ +var types = require("HAP-NodeJS/accessories/types.js"); +var sonos = require('sonos'); + +function SonosPlatform(log, config){ + this.log = log; + this.name = config["name"]; + this.playVolume = config["play_volume"]; +} + +SonosPlatform.prototype = { + accessories: function(callback) { + this.log("Fetching Sonos devices."); + var that = this; + + sonos.search(function (device) { + that.log("Found device at " + device.host); + + device.deviceDescription(function (err, description) { + if (description["zoneType"] != '11') { + that.log("Found playable device - " + description["roomName"]); + // device is an instance of sonos.Sonos + var accessory = new SonosAccessory(that.log, device, description); + callback([accessory]); + } + }); + }); + } +}; + +function SonosAccessory(log, device, description) { + this.log = log; + this.description = description; + this.name = description["roomName"] + " Sonos"; + this.playVolume = 25; +} + +SonosAccessory.prototype = { + + setPlaying: function(playing) { + + if (!this.device) { + this.log("No device found (yet?)"); + return; + } + + var that = this; + + if (playing) { + this.device.play(function(err, success) { + that.log("Playback attempt with success: " + success); + }); + + if (this.playVolume) { + this.device.setVolume(this.playVolume, function(err, success) { + if (!err) { + that.log("Set volume to " + that.playVolume); + } + else { + that.log("Problem setting volume: " + err); + } + }); + } + } + else { + this.device.stop(function(err, success) { + that.log("Stop attempt with success: " + success); + }); + } + }, + + getServices: function() { + var that = this; + return [{ + sType: types.ACCESSORY_INFORMATION_STYPE, + characteristics: [{ + cType: types.NAME_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.name, + supportEvents: false, + supportBonjour: false, + manfDescription: "Name of the accessory", + designedMaxLength: 255 + },{ + cType: types.MANUFACTURER_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: "Sonos", + supportEvents: false, + supportBonjour: false, + manfDescription: "Manufacturer", + designedMaxLength: 255 + },{ + cType: types.MODEL_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: "Rev-1", + supportEvents: false, + supportBonjour: false, + manfDescription: "Model", + designedMaxLength: 255 + },{ + cType: types.SERIAL_NUMBER_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: "A1S2NASF88EW", + supportEvents: false, + supportBonjour: false, + manfDescription: "SN", + designedMaxLength: 255 + },{ + cType: types.IDENTIFY_CTYPE, + onUpdate: null, + perms: ["pw"], + format: "bool", + initialValue: false, + supportEvents: false, + supportBonjour: false, + manfDescription: "Identify Accessory", + designedMaxLength: 1 + }] + },{ + sType: types.SWITCH_STYPE, + characteristics: [{ + cType: types.NAME_CTYPE, + onUpdate: null, + perms: ["pr"], + format: "string", + initialValue: this.description["roomName"] + " Speakers", + supportEvents: false, + supportBonjour: false, + manfDescription: "Name of service", + designedMaxLength: 255 + },{ + cType: types.POWER_STATE_CTYPE, + onUpdate: function(value) { that.setPlaying(value); }, + perms: ["pw","pr","ev"], + format: "bool", + initialValue: false, + supportEvents: false, + supportBonjour: false, + manfDescription: "Change the playback state of the sonos", + designedMaxLength: 1 + }] + }]; + } +}; + +module.exports.accessory = SonosAccessory; +module.exports.platform = SonosPlatform; From 0b457f9b7f0c361ca58939ab83df7a9fdb27cfb1 Mon Sep 17 00:00:00 2001 From: bezzers Date: Thu, 23 Jul 2015 09:36:37 -0400 Subject: [PATCH 2/5] Create a Sonos Platform handler - first version Creates a platform for Sonos that scans for all Sonos boxes and adds any that are not bridges (type 11) as accessories. Reads the names of each box from the Sonos configuration and creates device names based on the Sonos room names. --- platforms/Sonos.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/platforms/Sonos.js b/platforms/Sonos.js index 47a078a..91bd04d 100644 --- a/platforms/Sonos.js +++ b/platforms/Sonos.js @@ -19,7 +19,7 @@ SonosPlatform.prototype = { if (description["zoneType"] != '11') { that.log("Found playable device - " + description["roomName"]); // device is an instance of sonos.Sonos - var accessory = new SonosAccessory(that.log, device, description); + var accessory = new SonosAccessory(that.log, that.config, device, description); callback([accessory]); } }); @@ -27,11 +27,15 @@ SonosPlatform.prototype = { } }; -function SonosAccessory(log, device, description) { +function SonosAccessory(log, config, device, description) { this.log = log; + this.config = config; + this.device = device; this.description = description; - this.name = description["roomName"] + " Sonos"; - this.playVolume = 25; + + this.name = this.description["roomName"] + " " + this.config["name"]; + this.serviceName = this.description["roomName"] + " Speakers"; + this.playVolume = this.config["play_volume"]; } SonosAccessory.prototype = { @@ -130,7 +134,7 @@ SonosAccessory.prototype = { onUpdate: null, perms: ["pr"], format: "string", - initialValue: this.description["roomName"] + " Speakers", + initialValue: this.serviceName, supportEvents: false, supportBonjour: false, manfDescription: "Name of service", From 9325b154375436ddd0790a9be1cca1e613a2e3c6 Mon Sep 17 00:00:00 2001 From: bezzers Date: Thu, 23 Jul 2015 09:39:10 -0400 Subject: [PATCH 3/5] Moving Sonos configuration example from accessories to platform --- config-sample.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/config-sample.json b/config-sample.json index 125d632..7c29a75 100644 --- a/config-sample.json +++ b/config-sample.json @@ -52,6 +52,11 @@ { "platform": "LogitechHarmony", "name": "Living Room Harmony Hub" + }, + { + "platform": "Sonos", + "name": "Sonos", + "play_volume": 25 } ], @@ -70,12 +75,6 @@ "username": "your-liftmaster-username", "password" : "your-liftmaster-password" }, - { - "accessory": "Sonos", - "name": "Speakers", - "description": "This shim supports Sonos devices on the same network as this server. It acts as a simple switch that calls play() or pause() on the Sonos, so it's only useful for pausing and resuming tracks or radio stations that are already in the queue. When 'play_volume' is nonzero, the volume will be reset to that value when it turns the Sonos on.", - "play_volume": 25 - }, { "accessory": "Lockitron", "name": "Front Door", From 8b81001647eca45816c625ff1be5406aa4849837 Mon Sep 17 00:00:00 2001 From: bezzers Date: Thu, 23 Jul 2015 09:41:29 -0400 Subject: [PATCH 4/5] Delete Sonos as an accessory Replaced by new Sonos platform module --- accessories/Sonos.js | 146 ------------------------------------------- 1 file changed, 146 deletions(-) delete mode 100644 accessories/Sonos.js diff --git a/accessories/Sonos.js b/accessories/Sonos.js deleted file mode 100644 index 5757b0c..0000000 --- a/accessories/Sonos.js +++ /dev/null @@ -1,146 +0,0 @@ -var types = require("HAP-NodeJS/accessories/types.js"); -var sonos = require('sonos'); - -function SonosAccessory(log, config) { - this.log = log; - this.name = config["name"]; - this.playVolume = config["play_volume"]; - this.device = null; - this.search(); -} - -SonosAccessory.prototype = { - - search: function() { - var that = this; - - sonos.search(function(device) { - that.log("Found device at " + device.host); - - device.deviceDescription(function (err, description) { - - if (description["zoneType"] == '3') { - that.log("Found playable device"); - // device is an instance of sonos.Sonos - that.device = device; - } - - }); - }); - }, - - setPlaying: function(playing) { - - if (!this.device) { - this.log("No device found (yet?)"); - return; - } - - var that = this; - - if (playing) { - this.device.play(function(err, success) { - that.log("Playback attempt with success: " + success); - }); - - if (this.playVolume) { - this.device.setVolume(this.playVolume, function(err, success) { - if (!err) { - that.log("Set volume to " + that.playVolume); - } - else { - that.log("Problem setting volume: " + err); - } - }); - } - } - else { - this.device.stop(function(err, success) { - that.log("Stop attempt with success: " + success); - }); - } - }, - - getServices: function() { - var that = this; - return [{ - sType: types.ACCESSORY_INFORMATION_STYPE, - characteristics: [{ - cType: types.NAME_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: this.name, - supportEvents: false, - supportBonjour: false, - manfDescription: "Name of the accessory", - designedMaxLength: 255 - },{ - cType: types.MANUFACTURER_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: "Sonos", - supportEvents: false, - supportBonjour: false, - manfDescription: "Manufacturer", - designedMaxLength: 255 - },{ - cType: types.MODEL_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: "Rev-1", - supportEvents: false, - supportBonjour: false, - manfDescription: "Model", - designedMaxLength: 255 - },{ - cType: types.SERIAL_NUMBER_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: "A1S2NASF88EW", - supportEvents: false, - supportBonjour: false, - manfDescription: "SN", - designedMaxLength: 255 - },{ - cType: types.IDENTIFY_CTYPE, - onUpdate: null, - perms: ["pw"], - format: "bool", - initialValue: false, - supportEvents: false, - supportBonjour: false, - manfDescription: "Identify Accessory", - designedMaxLength: 1 - }] - },{ - sType: types.SWITCH_STYPE, - characteristics: [{ - cType: types.NAME_CTYPE, - onUpdate: null, - perms: ["pr"], - format: "string", - initialValue: "Speakers", - supportEvents: false, - supportBonjour: false, - manfDescription: "Name of service", - designedMaxLength: 255 - },{ - cType: types.POWER_STATE_CTYPE, - onUpdate: function(value) { that.setPlaying(value); }, - perms: ["pw","pr","ev"], - format: "bool", - initialValue: false, - supportEvents: false, - supportBonjour: false, - manfDescription: "Change the playback state of the sonos", - designedMaxLength: 1 - }] - }]; - } -}; - -module.exports.accessory = SonosAccessory; From 443f77196a8073e17e6f64be8c7e7dee19605dd6 Mon Sep 17 00:00:00 2001 From: bezzers Date: Fri, 24 Jul 2015 08:22:24 -0400 Subject: [PATCH 5/5] Add missing connection to config parameter --- platforms/Sonos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/platforms/Sonos.js b/platforms/Sonos.js index 91bd04d..15523c6 100644 --- a/platforms/Sonos.js +++ b/platforms/Sonos.js @@ -3,6 +3,7 @@ var sonos = require('sonos'); function SonosPlatform(log, config){ this.log = log; + this.config = config; this.name = config["name"]; this.playVolume = config["play_volume"]; }