Bose SoundTouch dashboard remote control

This dashboard flow implements much of the SoundTouch control API. It sends GET and POST requests to your SoundTouch systems. It does not implement the WebSockets interface, but was specifically designed to work well without it.

Features:

  • Uses a discovery node to automatically add SoundTouch systems.
  • Three volume settings (low, medium, and high) which can be configured per system.
  • Max volume level which can be configured per system.
  • System selection drop-down list.
  • Six preset buttons.
  • Mute, volume down, volume up, and three preset volume level buttons.
  • Previous track, next track, pause, play, and power buttons.
  • Shuffle settings.
  • Repeat settings.
  • Multi-room (zone) settings (very easy to setup).
  • Now playing (and other information) dialog.
  • Input link node to accept commands from other flows.

I've been using these controls for a while, and find it so much faster and easier to use than the Bose app. Obviously, you still need the Bose app to do some things such as setup your presets.

Multi-room notes:

Select a system to add from the multi-room drop-down list and press the add button. Then press the save button. The minus button can be used to remove some systems prior to saving. To disable the multi-room feature, press save without adding any systems first. Press the information button to verify the multi-room setup.

There is a "bose function" input link that you can link to from other flows. I use this to do my Google Assistant automation. You must send an array of json objects to the link because there is a split node downstream. In general, the format follows what you read in the SoundTouch API reference. The main addition is support for a delay object that delays the command by a specified number of milliseconds.

Sample json that could be sent to the link -

[
    {
        "name": "Bose master bedroom",
        "method": "POST",
        "function": "volume",
        "option": "set",
        "volume": "25"
    },
    {
        "name": "Bose master bedroom",
        "method": "POST",
        "function": "key",
        "keyState": "release",
        "key": "PRESET_1"
    },
    {
        "name": "Bose master bedroom",
        "method": "POST",
        "function": "key",
        "keyState": "press",
        "key": "PLAY"
    },
    {
        "name": "Bose master bedroom",
        "method": "POST",
        "function": "key",
        "key": "SHUFFLE_ON",
        "keyState": "press",
        "delay": "15000"
    },
    {
        "name": "Bose basement",
        "method": "POST",
        "function": "volume",
        "option": "set",
        "volume": "25"
    },
    {
        "name": "Bose basement",
        "method": "POST",
        "function": "key",
        "keyState": "release",
        "key": "PRESET_1"
    },
    {
        "name": "Bose basement",
        "method": "POST",
        "function": "key",
        "keyState": "press",
        "key": "PLAY"
    },
    {
        "name": "Bose basement",
        "method": "POST",
        "function": "key",
        "key": "SHUFFLE_ON",
        "keyState": "press",
        "delay": "15000"
    }
]

Seasonal preset node:

I have a custom "seasonal preset" node that allows me to send in commands from other flows without specifying a specific preset number. I can just pass in "PRESET", and this node converts that to either "PRESET_1" or "PRESET_2". You can leave this node as is and it won't do anything bad, or you can remove it, or you can modify it to suit your own purpose.

Future work:

No plans at the moment, but who knows what I'll think of. It would be great to get some user feedback.

[{"id":"6db31ee6.155d7","type":"tab","label":"Bose","disabled":false,"info":""},{"id":"3a993ccf.013944","type":"function","z":"6db31ee6.155d7","name":"format","func":"var i, miscSettigns, artUrl;\nvar zoneMembers = '';\nvar groupMembers = '';\nvar bose = flow.get('bose_soundtouch_systems', 'memory');\n\nfunction getBoseName(ipaddress) {\n    var j, name;\n    for (j in bose.systems) {\n        if (ipaddress == bose.systems[j].ipAddress) {\n            name = bose.systems[j].name;\n            break;\n        }\n    }\n    return name;\n}\n\n// Misc settings\ntry {\n    miscSettings = msg.payload[0].nowPlaying.shuffleSetting[0] + '<br>' +\n    msg.payload[0].nowPlaying.repeatSetting[0] + '<br>';\n}\ncatch(err) {\n    miscSettings = '';\n}\n\n// Zone members\ntry {\n    for (i in msg.payload[1].zone.member) {\n        zoneMembers = zoneMembers + '&nbsp;&nbsp;' +\n        getBoseName(msg.payload[1].zone.member[i].$.ipaddress) + '<br>';\n    }\n    if (zoneMembers !== '') {\n        groupMembers = 'Group members:<br>' + zoneMembers; \n    } \n}\ncatch(err) { }\n\ntry {\n    artUrl = '<img src=\"' + msg.payload[0].nowPlaying.art[0]._ + '\" width=\"160\" height=\"160\" alt=\"' + msg.payload[0].nowPlaying.album[0] + '\">';\n}\ncatch(err) {\n    artUrl = 'N/A';\n}\n\ntry {\n    message = 'Title: \"' + msg.payload[0].nowPlaying.track[0] + '\"<br>' +\n    'Artist: ' + msg.payload[0].nowPlaying.artist[0] + '<br>' +\n    'Album: ' + msg.payload[0].nowPlaying.album[0] + '<br>' +\n    artUrl + '<br>' +\n    'Playlist: ' + msg.payload[0].nowPlaying.ContentItem[0].itemName[0] + '<br>' +\n    String(msg.payload[0].nowPlaying.$.source).replace(/_/g, ' ') + '<br>' +\n    miscSettings.replace(/_/g, ' ') +\n    String(msg.payload[0].nowPlaying.playStatus[0]).replace(/_/g, ' ') + '<br>' +\n    groupMembers;\n    node.status({fill: 'blue', shape: 'dot', text: String(msg.payload[0].nowPlaying.playStatus[0]).replace(/_/g, ' ')});\n}\ncatch(err) {\n    message = 'Not active...';\n    node.status({fill: 'blue', shape: 'dot', text: message});\n}\nmsg.payload = message;\ndelete msg.topic;\nreturn msg;\n","outputs":1,"noerr":0,"x":2650,"y":600,"wires":[["fea71575.b01da8"]]},{"id":"48650c29.4cee04","type":"function","z":"6db31ee6.155d7","name":"set \"bose_name\"","func":"if (msg.payload !== '') {\n    flow.set('bose_name', msg.payload);\n}\nnode.status({fill: 'blue', shape: 'dot', text: '\"bose_name\" = ' + msg.payload});\nmsg.payload = 'change';\nmsg.name = 'Bose Soundtouch';\nreturn msg;","outputs":1,"noerr":0,"x":1290,"y":160,"wires":[["2f7a60b9.b9611"]]},{"id":"4a934881.039b28","type":"ui_dropdown","z":"6db31ee6.155d7","name":"","label":"","tooltip":"","place":"Select system to control","group":"48a230e.e2f88d","order":1,"width":0,"height":0,"passthru":false,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"","x":1120,"y":180,"wires":[["48650c29.4cee04"]]},{"id":"1d6cbe86.86a0b1","type":"comment","z":"6db31ee6.155d7","name":"buttons","info":"","x":150,"y":140,"wires":[]},{"id":"35958e0c.3b5e02","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"preset 1","order":2,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"PRESET_1\",\n        \"volumeNotification\": \"true\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'><md-tooltip md-direction=\"{{msg.payload.direction}}\">{{msg.payload.tooltip}}</md-tooltip>1</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":140,"wires":[["6c7968a2.618f48"]]},{"id":"da4ff60c.4ff848","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"preset 2","order":3,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"PRESET_2\",\n        \"volumeNotification\": \"true\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'><md-tooltip md-direction=\"{{msg.payload.direction}}\">{{msg.payload.tooltip}}</md-tooltip>2</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":180,"wires":[["6c7968a2.618f48"]]},{"id":"e945bc3.8e13d4","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"preset 3","order":4,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"PRESET_3\",\n        \"volumeNotification\": \"true\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'><md-tooltip md-direction=\"{{msg.payload.direction}}\">{{msg.payload.tooltip}}</md-tooltip>3</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":220,"wires":[["6c7968a2.618f48"]]},{"id":"b8c6d4d8.816018","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"preset 4","order":5,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"PRESET_4\",\n        \"volumeNotification\": \"true\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'><md-tooltip md-direction=\"{{msg.payload.direction}}\">{{msg.payload.tooltip}}</md-tooltip>4</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":260,"wires":[["6c7968a2.618f48"]]},{"id":"f9c54e9f.356fb","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"preset 5","order":6,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"PRESET_5\",\n        \"volumeNotification\": \"true\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'><md-tooltip md-direction=\"{{msg.payload.direction}}\">{{msg.payload.tooltip}}</md-tooltip>5</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":300,"wires":[["6c7968a2.618f48"]]},{"id":"3e8664ff.cd359c","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"preset 6","order":7,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"PRESET_6\",\n        \"volumeNotification\": \"true\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'><md-tooltip md-direction=\"{{msg.payload.direction}}\">{{msg.payload.tooltip}}</md-tooltip>6</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":340,"wires":[["6c7968a2.618f48"]]},{"id":"e92db25c.f4c97","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"volume low","order":10,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"volume\",\n        \"option\": \"set\",\n        \"volume\": \"low\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'>L</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":700,"wires":[["6c7968a2.618f48"]]},{"id":"1690fd83.5ff092","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"volume medium","order":11,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"volume\",\n        \"option\": \"set\",\n        \"volume\": \"medium\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'>M</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":740,"wires":[["6c7968a2.618f48"]]},{"id":"39dc158d.886efa","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"volume high","order":12,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"volume\",\n        \"option\": \"set\",\n        \"volume\": \"high\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'>H</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":780,"wires":[["6c7968a2.618f48"]]},{"id":"d0ed71ff.722f4","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"pause","order":15,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-pause\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PAUSE\",\n        \"notification\": \"Paused\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":330,"y":460,"wires":[["6c7968a2.618f48"]]},{"id":"9745a2fd.521ea","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"previous track","order":14,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-step-backward\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PREV_TRACK\",\n        \"notification\": \"Previous track\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":500,"wires":[["6c7968a2.618f48"]]},{"id":"6c18c457.f4507c","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"next trrack","order":17,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-step-forward\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"NEXT_TRACK\",\n        \"notification\": \"Next track\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":540,"wires":[["6c7968a2.618f48"]]},{"id":"b2200293.48131","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"volume down","order":9,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-volume-down\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GET\",\n        \"function\": \"volume\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"volume\",\n        \"option\": \"offset\",\n        \"volume\": -1,\n        \"delay\": \"300\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":580,"wires":[["6c7968a2.618f48"]]},{"id":"31adb9df.f87296","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"volume up","order":13,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-volume-up\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GET\",\n        \"function\": \"volume\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"volume\",\n        \"option\": \"offset\",\n        \"volume\": 1,\n        \"delay\": \"300\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":620,"wires":[["6c7968a2.618f48"]]},{"id":"6651a5cc.526cec","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"now playing","order":20,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-info-circle\" aria-label=\"Settings\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GET\",\n        \"function\": \"now_playing\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"GET\",\n        \"function\": \"getZone\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":820,"wires":[["6c7968a2.618f48"]]},{"id":"2221f0ec.996c4","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"mute","order":8,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-volume-off\" aria-label=\"Settings\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"MUTE\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":330,"y":660,"wires":[["6c7968a2.618f48"]]},{"id":"fea71575.b01da8","type":"ui_toast","z":"6db31ee6.155d7","position":"dialog","displayTime":"3","highlight":"","outputs":1,"ok":"OK","cancel":"","topic":"","name":"ok notification","x":2800,"y":600,"wires":[[]]},{"id":"9b537490.10ab58","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"play","order":16,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-play\" ng-click='send({\npayload : [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"PLAY\",\n        \"volumeNotification\": \"true\"\n    }\n]\n})'></md-button> ","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":330,"y":380,"wires":[["6c7968a2.618f48"]]},{"id":"70f4ce1e.8a648","type":"function","z":"6db31ee6.155d7","name":"setup http post request","func":"var volume = 0;\n\n// Setup http request parameters\nswitch (msg.bose.function) {\n    case 'key':\n        msg.payload = '<key state=' + msg.bose.keyState + ' sender=Gabbo>' + msg.bose.key + '</key>';\n        node.status({fill: 'blue', shape: 'dot', text: msg.bose.system.name + ' - Function: ' +\n            msg.bose.function + ', Key State: ' + msg.bose.keyState + ', Key: ' + msg.bose.key});\n        break;\n    case 'setZone':\n        msg.payload = msg.bose.option;\n        break;\n    case 'volume':\n        switch(msg.bose.volume) {\n            case 'low':\n                msg.bose.volume = msg.bose.system.lowVolume;\n                break;\n            case 'medium':\n                msg.bose.volume = msg.bose.system.mediumVolume;\n                break;\n            case 'high':\n                msg.bose.volume = msg.bose.system.highVolume;\n        }\n        switch(msg.bose.option) {\n            case 'set':\n                volume = msg.bose.volume;\n                break;\n            case 'offset':\n                volume = flow.get('bose_volume', 'memory') + msg.bose.volume;\n        }\n        if (volume > msg.bose.system.maxVolume) {\n            volume = msg.bose.system.maxVolume;\n        } else if (volume < 0) {\n            volume = 0;\n        }\n        msg.payload = '<volume>' + volume + '</volume>';\n        node.status({fill: 'blue', shape: 'dot', text: msg.bose.system.name + ' - Function.option: ' +\n            msg.bose.function + '.' + msg.bose.option + ', volume: ' + volume});\n}\nmsg.method = msg.bose.method;\nreturn msg;\n","outputs":1,"noerr":0,"x":1860,"y":700,"wires":[["7a20149f.24864c","4d066894.066cc8"]]},{"id":"4d066894.066cc8","type":"http request","z":"6db31ee6.155d7","name":"post request","method":"use","ret":"txt","url":"","tls":"","x":2090,"y":700,"wires":[["7a25a8f6.553298","b5b75da2.32528"]]},{"id":"b5da787c.268ed8","type":"switch","z":"6db31ee6.155d7","name":"method","property":"bose.method","propertyType":"msg","rules":[{"t":"eq","v":"GET","vt":"str"},{"t":"eq","v":"POST","vt":"str"},{"t":"eq","v":"GROUP","vt":"str"},{"t":"eq","v":"VOLUME","vt":"str"}],"checkall":"false","repair":false,"outputs":4,"x":1600,"y":820,"wires":[["407845.ff4297bc"],["70f4ce1e.8a648"],["9cb631a2.6bcff"],["dadd4f28.f925d"]],"outputLabels":["GET","POST","GROUP","VOLUME"]},{"id":"4d14d0d1.c4dc5","type":"function","z":"6db31ee6.155d7","name":"setup bose","func":"if (typeof msg.payload.name === 'string') {\n    var name = msg.payload.name;\n} else {\n    name = 'select';\n}\n\nmsg.bose = {\n    \"method\": msg.payload.method,\n    \"function\": msg.payload.function,\n    \"option\": msg.payload.option,\n    \"key\": msg.payload.key,\n    \"keyState\": msg.payload.keyState,\n    \"volume\": msg.payload.volume,\n    \"delay\": msg.payload.delay,\n    \"notification\": msg.payload.notification,\n    \"volumeNotification\": msg.payload.volumeNotification,\n    \"system\": {}\n}\n\nif (name == 'select') {\n    name = flow.get('bose_name')\n}\n\nmsg.bose.system = flow.get(name.replace(/ /g, '_'));\n\n// Setup node status\nswitch (msg.bose.method) {\n    case 'GET':\n        node.status({fill: 'blue', shape: 'dot', text: name + ' - Function: ' +\n            msg.bose.function});\n        break;\n    case 'POST':\n        if (msg.bose.function == 'volume') {\n            node.status({fill: 'blue', shape: 'dot', text: name + ' - Function.option: ' +\n                msg.bose.function + '.' +  msg.bose.option + ', volume: ' + msg.bose.volume});\n        } else {\n            node.status({fill: 'blue', shape: 'dot', text: name + ' - Function: ' +\n                msg.bose.function + ', Key: ' + msg.bose.key});\n        }\n}\n\n// Setup optional delay\nif (typeof msg.payload.delay  !== 'undefined') {\n    msg.delay = msg.payload.delay;\n} else {\n    msg.delay = 0;\n}\n\n// Set url\nmsg.url = 'http://' + msg.bose.system.ipAddress + ':8090/' + msg.bose.function;\nreturn msg;\n","outputs":1,"noerr":0,"x":1230,"y":820,"wires":[["3ed821c3.7015ae","dd6f7c4f.d7466"]]},{"id":"f3c36470.d265f8","type":"comment","z":"6db31ee6.155d7","name":"post request","info":"","x":1830,"y":660,"wires":[]},{"id":"4f88f155.88436","type":"switch","z":"6db31ee6.155d7","name":"notification?","property":"bose.volumeNotification","propertyType":"msg","rules":[{"t":"eq","v":"true","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":2490,"y":700,"wires":[["852c2080.46d42"]],"outputLabels":["yes"]},{"id":"7a25a8f6.553298","type":"function","z":"6db31ee6.155d7","name":"optional get volume","func":"if (msg.bose.volumeNotification == 'true') {\n    msg.payload = [\n        {\n        \"name\": \"select\",\n        \"method\": \"GET\",\n        \"function\": \"volume\",\n        \"delay\": \"300\",\n        \"volumeNotification\": \"true\"\n        }\n    ] } else {\n        msg.payload = null;\n    }\nreturn msg;","outputs":1,"noerr":0,"x":2310,"y":700,"wires":[["4f88f155.88436"]]},{"id":"7a20149f.24864c","type":"debug","z":"6db31ee6.155d7","name":"http request","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":2110,"y":620,"wires":[]},{"id":"6c7968a2.618f48","type":"split","z":"6db31ee6.155d7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":690,"y":820,"wires":[["32ac04f0.d7a31c","666be9c5.8d30f8"]]},{"id":"32ac04f0.d7a31c","type":"function","z":"6db31ee6.155d7","name":"seasonal preset","func":"if (msg.payload.key == 'PRESET') {\n    if (global.get('christmas_season') === true) {\n        msg.payload.key = 'PRESET_2';\n    } else {\n        msg.payload.key = 'PRESET_1';\n    }\n}\nreturn msg;","outputs":1,"noerr":0,"x":880,"y":820,"wires":[["7b978dfa.14a8e4"]]},{"id":"95216d98.533bd","type":"comment","z":"6db31ee6.155d7","name":"optional input from other flows","info":"","x":220,"y":80,"wires":[]},{"id":"2381bf08.f5895","type":"comment","z":"6db31ee6.155d7","name":"* custom preset function *","info":"","x":890,"y":860,"wires":[],"icon":"node-red/node-error.png"},{"id":"dd6f7c4f.d7466","type":"delay","z":"6db31ee6.155d7","name":"optional delay","pauseType":"delayv","timeout":"0","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":1440,"y":820,"wires":[["b5da787c.268ed8"]]},{"id":"a9b3f48c.c00ac8","type":"http request","z":"6db31ee6.155d7","name":"get request","method":"use","ret":"txt","url":"","tls":"","x":2090,"y":540,"wires":[["7666dbdb.041e94"]]},{"id":"7666dbdb.041e94","type":"xml","z":"6db31ee6.155d7","name":"xml","property":"payload","attr":"","chr":"","x":2230,"y":540,"wires":[["eea0d797.ea1978"]]},{"id":"f91cee4d.9a40e","type":"function","z":"6db31ee6.155d7","name":"format","func":"var i;\nvar presetNames = [];\n\n// Presets\ntry {\n    var presets = msg.payload.presets.preset;\n    for (i in presets) {\n        var tooltipObj = {preset: 'x', direction: 'top',tooltip: 'x'};\n        tooltipObj.preset = i;\n        tooltipObj.tooltip = presets[i].ContentItem[0].itemName[0];\n        presetNames.push(tooltipObj);\n    }\n}\ncatch(err) {}\n//node.warn(presetNames);\nmsg.payload = presetNames;\nreturn msg;\n","outputs":1,"noerr":0,"x":2530,"y":480,"wires":[["3e58f9d7.26d116"]]},{"id":"db2346a8.d74628","type":"comment","z":"6db31ee6.155d7","name":"get request","info":"","x":1820,"y":500,"wires":[]},{"id":"407845.ff4297bc","type":"function","z":"6db31ee6.155d7","name":"setup http get request","func":"msg.method = msg.bose.method;\nnode.status({fill: 'blue', shape: 'dot', text: msg.bose.system.name + ' - Method: ' + msg.method + ', url: ' + msg.url});\nreturn msg;\n","outputs":1,"noerr":0,"x":1860,"y":540,"wires":[["a9b3f48c.c00ac8","7a20149f.24864c"]]},{"id":"d52a7e1c.bd3","type":"switch","z":"6db31ee6.155d7","name":"tooltips","property":"payload.preset","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"2","vt":"str"},{"t":"eq","v":"3","vt":"str"},{"t":"eq","v":"4","vt":"str"},{"t":"eq","v":"5","vt":"str"}],"checkall":"false","repair":false,"outputs":6,"x":140,"y":240,"wires":[["35958e0c.3b5e02"],["da4ff60c.4ff848"],["e945bc3.8e13d4"],["b8c6d4d8.816018"],["f9c54e9f.356fb"],["3e8664ff.cd359c"]]},{"id":"3e58f9d7.26d116","type":"split","z":"6db31ee6.155d7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":2650,"y":480,"wires":[["e10bf946.bf5d68"]]},{"id":"aec466f8.583488","type":"link in","z":"6db31ee6.155d7","name":"bose link 1","links":["e10bf946.bf5d68"],"x":35,"y":240,"wires":[["d52a7e1c.bd3"]]},{"id":"e10bf946.bf5d68","type":"link out","z":"6db31ee6.155d7","name":"bose link 1","links":["aec466f8.583488"],"x":2735,"y":480,"wires":[]},{"id":"eea0d797.ea1978","type":"switch","z":"6db31ee6.155d7","name":"function","property":"bose.function","propertyType":"msg","rules":[{"t":"eq","v":"presets","vt":"str"},{"t":"eq","v":"volume","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":3,"x":2360,"y":540,"wires":[["f91cee4d.9a40e"],["ff5ddb7c.7ade78"],["b3e575e1.be2f68"]],"outputLabels":["presets","volume","notification"]},{"id":"ff5ddb7c.7ade78","type":"function","z":"6db31ee6.155d7","name":"format","func":"var message = 'Update pending...';\ntry {\n    var mute = msg.payload.volume.muteenabled[0];\n    switch (mute) {\n        case 'true':\n            mute = 'On';\n            break;\n        default:\n            mute = 'Off';\n    }\n    message = 'Volume: ' + msg.payload.volume.actualvolume[0] + '%, Mute: ' + mute;\n    flow.set('bose_volume', Number(msg.payload.volume.actualvolume[0]), 'memory');\n}\ncatch(err) {}\nnode.status({fill: 'blue', shape: 'dot', text: message});\nmsg.payload = message;\ndelete msg.topic;\nreturn msg;","outputs":1,"noerr":0,"x":2530,"y":540,"wires":[["bfefb6ea.2e42c8"]]},{"id":"cbc43d51.85954","type":"link in","z":"6db31ee6.155d7","name":"bose function","links":["852c2080.46d42","d4ac1154.4e2c9","19f79bf1.3c0b44","8eea7403.712b48","8f6e9973.5dd968","f08c62fe.c3f5e","7a88c2e7.ad1cec","da26f041.d11b6","a2aa1557.32a5e8","83d5e09f.9241","d324da6f.0a4a88","6342d8b8.086cd8","6650fcc8.47cb04","c8b51082.012ab","7b21b2de.7ed50c"],"x":375,"y":80,"wires":[["6c7968a2.618f48"]]},{"id":"852c2080.46d42","type":"link out","z":"6db31ee6.155d7","name":"bose function","links":["cbc43d51.85954"],"x":2595,"y":700,"wires":[]},{"id":"bfefb6ea.2e42c8","type":"switch","z":"6db31ee6.155d7","name":"notification?","property":"bose.volumeNotification","propertyType":"msg","rules":[{"t":"eq","v":"true","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":2670,"y":540,"wires":[["3a1ceddb.152b12"]],"outputLabels":["yes"]},{"id":"76c27a81.1615c4","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"shuffle control","order":22,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-random\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"N/A\",\n        \"group\": {\n            \"show\": [\n                \"Bose_Soundtouch_Shuffle\"\n            ],\n            \"focus\": \"true\"\n        }\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":860,"wires":[["6c7968a2.618f48"]]},{"id":"27d6075c.d207b8","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"repeat control","order":23,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-repeat\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"N/A\",\n        \"group\": {\n            \"show\": [\n                \"Bose_Soundtouch_Repeat\"\n            ],\n            \"focus\": \"true\"\n        }\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":1020,"wires":[["6c7968a2.618f48"]]},{"id":"b3e575e1.be2f68","type":"join","z":"6db31ee6.155d7","name":"","mode":"auto","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":"false","timeout":"","count":"","reduceRight":false,"x":2530,"y":600,"wires":[["3a993ccf.013944"]]},{"id":"3ed821c3.7015ae","type":"debug","z":"6db31ee6.155d7","name":"post setup","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1430,"y":760,"wires":[]},{"id":"93ff5dc9.ff651","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"button css","order":26,"width":0,"height":0,"format":"<style>\n\n  .md-button.black-text {\n    color: black;\n  }\n\n  /* Metal ------------------------- */\n  \n  .metal {\n    position: relative;\n    margin: auto;\n    \n    text-align: center;\n    color: hsla(0,0%,20%,1);\n    text-shadow:\n      hsla(0,0%,40%,.5) 0 -1px 0,\n      hsla(0,0%,100%,.6) 0 2px 1px;\n    \n    background-color: hsl(0,0%,90%);\n    box-shadow:\n      inset hsla(0,0%,15%,  1) 0  0px 0px 2px, /* border */\n      inset hsla(0,0%,15%, .8) 0 -1px 3px 2px, /* soft SD */\n      inset hsla(0,0%,0%, .25) 0 -1px 0px 3px, /* bottom SD */\n      inset hsla(0,0%,100%,.7) 0  2px 1px 3px, /* top HL */\n      \n      hsla(0,0%, 0%,.15) 0 -2px 3px 2px, /* outer SD */\n      hsla(0,0%,100%,.5) 0  2px 3px 2px; /* outer HL */ \n\n    transition: color .2s;\n  }\n  \n  /* Linear ------------------------- */\n\n  .metal.linear {\n    width: 40px;\n    height: 40px;\n    font-size: 1.2em;\n    border-radius: .5em;\n    background-image:\n      -webkit-repeating-linear-gradient(left, hsla(0,0%,100%,0) 0%, hsla(0,0%,100%,0)   6%, hsla(0,0%,100%, .1) 7.5%),\n      -webkit-repeating-linear-gradient(left, hsla(0,0%,  0%,0) 0%, hsla(0,0%,  0%,0)   4%, hsla(0,0%,  0%,.03) 4.5%),\n      -webkit-repeating-linear-gradient(left, hsla(0,0%,100%,0) 0%, hsla(0,0%,100%,0) 1.2%, hsla(0,0%,100%,.15) 2.2%),\n      \n      linear-gradient(180deg,\n      hsl(0,0%,78%)  0%, \n      hsl(0,0%,90%) 47%, \n      hsl(0,0%,78%) 53%,\n      hsl(0,0%,70%)100%);\n  }\n    \n  /* Wide ------------------------- */\n\n  .metal.wide {\n    width: 90px;\n    height: 40px;\n  }\n\n  /* active ------------------------- */\n\n  .metal:active {\n    color: hsl(210, 100%, 40%);\n    text-shadow:\n      hsla(210,100%,20%,.3) 0 -1px 0,\n      hsl(210,100%,85%) 0 2px 1px,\n      hsla(200,100%,80%,1) 0 0 5px,\n      hsla(210,100%,50%,.6) 0 0 20px;\n    box-shadow: \n      inset hsla(210,100%,30%,  1) 0  0px 0px 2px, /* border */\n      inset hsla(210,100%,15%, .4) 0 -1px 3px 2px, /* soft SD */\n      inset hsla(210,100%,20%,.25) 0 -1px 0px 3px, /* bottom SD */\n      inset hsla(210,100%,100%,.7) 0  2px 1px 3px, /* top HL */\n      \n      hsla(210,100%,75%, .8) 0  0px 3px 2px, /* outer SD */\n      hsla(210,50%,40%, .25) 0 -2px 3px 2px, /* outer SD */\n      hsla(210,80%,95%,   1) 0  2px 3px 2px; /* outer HL */\n  }   \n\n</style>\n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":130,"y":360,"wires":[[]]},{"id":"7bebf6b7.90ef78","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"group control","order":25,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-rss\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GROUP\",\n        \"function\": \"setup\",\n        \"group\": {\n            \"show\": [\n                \"Bose_Soundtouch_Group\"\n            ],\n            \"focus\": \"true\"\n        }\n    }\n]\n})'></md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":1220,"wires":[["6c7968a2.618f48"]]},{"id":"f9337159.3f31c","type":"ui_dropdown","z":"6db31ee6.155d7","name":"group members","label":"","tooltip":"","place":"Select system to add or remove","group":"5fbad2a8.07597c","order":1,"width":"0","height":"0","passthru":false,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"","x":2280,"y":860,"wires":[["55ccf5.cbe4b30c"]]},{"id":"fe7abe93.568f3","type":"ui_template","z":"6db31ee6.155d7","group":"5fbad2a8.07597c","name":"+ group","order":2,"width":"1","height":"1","format":"<md-button ng-disabled=\"msg.payload\" class=\"metal linear black-text fa fa-plus\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GROUP\",\n        \"function\": \"add\",\n    }\n]\n})'></md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":1340,"wires":[["6c7968a2.618f48"]]},{"id":"a0b65db.8ad6ea","type":"ui_template","z":"6db31ee6.155d7","group":"5fbad2a8.07597c","name":"- group","order":3,"width":"1","height":"1","format":"<md-button ng-disabled=\"msg.payload\" class=\"metal linear black-text fa fa-minus\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GROUP\",\n        \"function\": \"remove\"\n    }\n]\n})'></md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":1380,"wires":[["6c7968a2.618f48"]]},{"id":"ebc9f9bf.699818","type":"ui_template","z":"6db31ee6.155d7","group":"5fbad2a8.07597c","name":"cancel group","order":4,"width":"2","height":"1","format":"<md-button class=\"metal linear wide black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"N/A\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Group\"\n            ]\n        }\n    }\n]\n})'>Cancel</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":1260,"wires":[["6c7968a2.618f48"]]},{"id":"2e8c7cd0.41d224","type":"function","z":"6db31ee6.155d7","name":"setup dropdown","func":"var bose = flow.get('bose_soundtouch_systems', 'memory');\nvar name = flow.get('bose_name');\nvar nameArray = ['All'];\n\n// Setup names for dropdown list\nfor (var i in bose.systems) { \n    if (name != bose.systems[i].name) {\n        nameArray.push(bose.systems[i].name);\n    }\n}\n\nflow.set('bose_group_members', [], 'memory');\nflow.set('bose_group_name', '', 'memory');\n\nmsg.options = nameArray;\nmsg.payload = '';\nreturn msg;","outputs":1,"noerr":0,"x":2040,"y":860,"wires":[["f9337159.3f31c","13bbc0aa.714b9f","30ddb518.75ac6a"]]},{"id":"709d53e0.efa15c","type":"comment","z":"6db31ee6.155d7","name":"group request","info":"","x":1830,"y":880,"wires":[]},{"id":"666be9c5.8d30f8","type":"ui_ui_control","z":"6db31ee6.155d7","name":"","x":860,"y":760,"wires":[[]]},{"id":"25d059ef.f01596","type":"ui_template","z":"6db31ee6.155d7","group":"9bb8a452.40e7d8","name":"shuffle on","order":1,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-toggle-on\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"SHUFFLE_ON\",\n        \"notification\": \"Shuffle on\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Shuffle\"\n            ]\n        }\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":900,"wires":[["6c7968a2.618f48"]]},{"id":"f964be73.611c","type":"ui_template","z":"6db31ee6.155d7","group":"9bb8a452.40e7d8","name":"shuffle off","order":2,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-toggle-off\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"SHUFFLE_OFF\",\n        \"notification\": \"Shuffle off\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Shuffle\"\n            ]\n        }\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":940,"wires":[["6c7968a2.618f48"]]},{"id":"a9f584ca.14b3f8","type":"ui_template","z":"6db31ee6.155d7","group":"a3df549a.bdcec8","name":"repeat one","order":1,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text \" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"REPEAT_ONE\",\n        \"notification\": \"Repeat one\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Repeat\"\n            ]\n        }\n    }\n]\n})'>1</md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":1060,"wires":[["6c7968a2.618f48"]]},{"id":"4813e9d0.8dc5c8","type":"ui_template","z":"6db31ee6.155d7","group":"a3df549a.bdcec8","name":"repeat all","order":2,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-toggle-on\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"REPEAT_ALL\",\n        \"notification\": \"Repeat all\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Repeat\"\n            ]\n        }\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":1100,"wires":[["6c7968a2.618f48"]]},{"id":"73bf86ac.d079c8","type":"ui_template","z":"6db31ee6.155d7","group":"a3df549a.bdcec8","name":"repeat off","order":3,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-toggle-off\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"REPEAT_OFF\",\n        \"notification\": \"Repeat off\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Repeat\"\n            ]\n        }\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":340,"y":1140,"wires":[["6c7968a2.618f48"]]},{"id":"391f2288.5746ee","type":"ui_template","z":"6db31ee6.155d7","group":"9bb8a452.40e7d8","name":"cancel shuffle","order":3,"width":"2","height":"1","format":"<md-button class=\"metal linear wide black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"N/A\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Shuffle\"\n            ]\n        }\n    }\n]\n})'>Cancel</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":980,"wires":[["6c7968a2.618f48"]]},{"id":"dacc43b5.dfa9b","type":"ui_template","z":"6db31ee6.155d7","group":"a3df549a.bdcec8","name":"cancel repeat","order":4,"width":"2","height":"1","format":"<md-button class=\"metal linear wide black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"N/A\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Repeat\"\n            ]\n        }\n    }\n]\n})'>Cancel</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":1180,"wires":[["6c7968a2.618f48"]]},{"id":"9cb631a2.6bcff","type":"switch","z":"6db31ee6.155d7","name":"function","property":"bose.function","propertyType":"msg","rules":[{"t":"eq","v":"setup","vt":"str"},{"t":"eq","v":"add","vt":"str"},{"t":"eq","v":"remove","vt":"str"},{"t":"eq","v":"save","vt":"str"}],"checkall":"false","repair":false,"outputs":4,"x":1820,"y":940,"wires":[["2e8c7cd0.41d224"],["f011d861.d6be68"],["4e84de71.ee16d"],["481e68e6.17d348"]],"outputLabels":["setup","add","remove","save"]},{"id":"13bbc0aa.714b9f","type":"ui_text","z":"6db31ee6.155d7","group":"5fbad2a8.07597c","order":3,"width":"6","height":"3","name":"","label":"","format":"{{msg.payload}}","layout":"row-left","x":2250,"y":980,"wires":[]},{"id":"f011d861.d6be68","type":"function","z":"6db31ee6.155d7","name":"add member","func":"var i;\nvar bose = flow.get('bose_soundtouch_systems', 'memory');\nvar name = flow.get('bose_name');\nvar addName = flow.get('bose_group_name', 'memory');\nvar groupMembers = flow.get('bose_group_members', 'memory');\n\nif (addName == 'All') {\n    groupMembers = [];\n    for (i in bose.systems) { \n        if (name != bose.systems[i].name) {\n            groupMembers.push(bose.systems[i].name);\n        }\n    }\n} else if (groupMembers.indexOf(addName) < 0) {\n    groupMembers.push(addName);\n}\n\nflow.set('bose_group_members', groupMembers, 'memory');\n\nmsg.payload = '';\nfor (i in groupMembers) {\n    msg.payload = msg.payload + groupMembers[i] + '<br>';\n}\nreturn msg;","outputs":1,"noerr":0,"x":2030,"y":920,"wires":[["13bbc0aa.714b9f"]]},{"id":"55ccf5.cbe4b30c","type":"function","z":"6db31ee6.155d7","name":"set \"bose_group_name\"","func":"if (msg.payload !== '') {\n    flow.set('bose_group_name', msg.payload, 'memory');\n}\nnode.status({fill: 'blue', shape: 'dot', text: '\"bose_group_name\" = ' + msg.payload});\nmsg.payload = false;\nreturn msg;","outputs":1,"noerr":0,"x":2510,"y":840,"wires":[["75b7b884.3fbcc8"]]},{"id":"4e84de71.ee16d","type":"function","z":"6db31ee6.155d7","name":"remove member","func":"var i;\nvar removeName = flow.get('bose_group_name', 'memory');\nvar groupMembers = flow.get('bose_group_members', 'memory');\n\nif (removeName == 'All') {\n     groupMembers = [];\n} else if (groupMembers.indexOf(removeName) >= 0) {\n    groupMembers.splice(groupMembers.indexOf(removeName), 1);\n}\n\nflow.set('bose_group_members', groupMembers, 'memory');\n\nmsg.payload = '';\nfor (i in groupMembers) {\n    msg.payload = msg.payload + groupMembers[i] + '<br>';\n}\nreturn msg;\n","outputs":1,"noerr":0,"x":2040,"y":980,"wires":[["13bbc0aa.714b9f"]]},{"id":"481e68e6.17d348","type":"function","z":"6db31ee6.155d7","name":"save","func":"var i, j;\nvar bose = flow.get('bose_soundtouch_systems', 'memory');\nvar name = flow.get('bose_name');\nvar groupMembers = flow.get('bose_group_members', 'memory');\n\nmsg.payload = [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"setZone\",\n        \"option\": \"\",\n        \"notification\": \"Group saved\"\n    }\n];\n\nfor (var j in bose.systems) { \n    if (name == bose.systems[j].name) {\n        msg.payload[0].option = '<zone master=\"' + bose.systems[j].deviceID + '\">\\n';\n        break;\n    }\n}\n\nfor (var i in groupMembers) { \n    for (var j in bose.systems) { \n        if (groupMembers[i] == bose.systems[j].name) {\n            msg.payload[0].option = msg.payload[0].option +\n            '  <member ipaddress=\"' + bose.systems[j].ipAddress + '\">' + bose.systems[j].deviceID + '</member>\\n';\n            break;\n        }\n    }\n}\nmsg.payload[0].option = msg.payload[0].option + '</zone>';\n\nreturn msg;","outputs":1,"noerr":0,"x":2010,"y":1040,"wires":[["83d5e09f.9241"]]},{"id":"83d5e09f.9241","type":"link out","z":"6db31ee6.155d7","name":"bose function","links":["cbc43d51.85954"],"x":2095,"y":1040,"wires":[]},{"id":"2ca97efa.e6e882","type":"debug","z":"6db31ee6.155d7","name":"pre setup","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1220,"y":760,"wires":[]},{"id":"2f7a60b9.b9611","type":"function","z":"6db31ee6.155d7","name":"connect/lost/change","func":"switch (msg.payload) {\n    case 'connect':\n    case 'lost':\n        break;\n    case 'change':\n        if (msg.name == 'Bose Soundtouch') {\n            msg.payload = [\n                {\n                    \"name\": \"select\",\n                    \"method\": \"N/A\",\n                    \"function\": 'ui_control',\n                    \"group\": {\n                        \"hide\": [\n                            \"Bose_Soundtouch_Shuffle\",\n                            \"Bose_Soundtouch_Repeat\",\n                            \"Bose_Soundtouch_Volume_presets\",\n                            \"Bose_Soundtouch_Group\"\n                        ]\n                    }\n                },\n                {\n                    \"name\": \"select\",\n                    \"method\": \"GET\",\n                    \"function\": \"presets\"\n                }\n            ]\n        }\n        break;\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":1540,"y":160,"wires":[["7b21b2de.7ed50c"]]},{"id":"cb18c78.2d45938","type":"ui_ui_control","z":"6db31ee6.155d7","name":"","x":1320,"y":100,"wires":[["2f7a60b9.b9611"]]},{"id":"bdd18a65.018f78","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"power","order":19,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-power-off\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"press\",\n        \"key\": \"POWER\"\n    },\n    {\n        \"name\": \"select\",\n        \"method\": \"POST\",\n        \"function\": \"key\",\n        \"keyState\": \"release\",\n        \"key\": \"POWER\",\n        \"notification\": \"Power off\"\n    }\n]\n})'></md-button> \n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":330,"y":420,"wires":[["6c7968a2.618f48"]]},{"id":"f590ce48.2d299","type":"ui_text","z":"6db31ee6.155d7","group":"48a230e.e2f88d","order":27,"width":"6","height":"1","name":"1 s notification","label":"","format":"{{msg.payload}}","layout":"row-left","x":1060,"y":320,"wires":[]},{"id":"bd767cc9.13002","type":"delay","z":"6db31ee6.155d7","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":840,"y":380,"wires":[["36205a4.ae87ea6"]]},{"id":"36205a4.ae87ea6","type":"change","z":"6db31ee6.155d7","name":"clear notification","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1010,"y":380,"wires":[["f590ce48.2d299"]]},{"id":"b5b75da2.32528","type":"function","z":"6db31ee6.155d7","name":"optional notification","func":"if (typeof msg.bose.notification !== 'undefined') {\n    msg.payload = msg.bose.notification;\n    msg.bose.notification = 'true';\n} else {\n    msg.bose.notification = 'false';\n}\ndelete msg.topic;\nreturn msg;","outputs":1,"noerr":0,"x":2310,"y":760,"wires":[["ca58b440.27b968"]]},{"id":"ca58b440.27b968","type":"switch","z":"6db31ee6.155d7","name":"notification?","property":"bose.notification","propertyType":"msg","rules":[{"t":"eq","v":"true","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":2490,"y":760,"wires":[["2fc2d32f.862d2c"]],"outputLabels":["yes"]},{"id":"4e26eb8d.41fff4","type":"ui_template","z":"6db31ee6.155d7","group":"5fbad2a8.07597c","name":"save group","order":5,"width":"2","height":"1","format":"<md-button class=\"metal linear wide black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"GROUP\",\n        \"function\": \"save\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Group\"\n            ]\n        }\n    }\n]\n})'>Save</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":1300,"wires":[["6c7968a2.618f48"]]},{"id":"ececb3c6.21724","type":"link in","z":"6db31ee6.155d7","name":"bose link 3","links":["75b7b884.3fbcc8"],"x":195,"y":1360,"wires":[["fe7abe93.568f3","a0b65db.8ad6ea"]]},{"id":"75b7b884.3fbcc8","type":"link out","z":"6db31ee6.155d7","name":"bose link 3","links":["ececb3c6.21724"],"x":2715,"y":920,"wires":[]},{"id":"30ddb518.75ac6a","type":"function","z":"6db31ee6.155d7","name":"disable add/remove","func":"msg.payload = true;\nreturn msg;","outputs":1,"noerr":0,"x":2290,"y":920,"wires":[["75b7b884.3fbcc8"]]},{"id":"1d38d5b0.29bf5a","type":"discovery","z":"6db31ee6.155d7","name":"discovery","topic":"","service":"_soundtouch._tcp","x":640,"y":180,"wires":[["aa8c184.10dcce8","b6ecb7df.834318"]]},{"id":"aa8c184.10dcce8","type":"delay","z":"6db31ee6.155d7","name":"200 ms","pauseType":"delay","timeout":"200","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":820,"y":180,"wires":[["d61db346.2f18a"]]},{"id":"dfccba07.138078","type":"inject","z":"6db31ee6.155d7","name":"100 ms","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":660,"y":120,"wires":[["dc25e212.a7c04"]]},{"id":"dc25e212.a7c04","type":"function","z":"6db31ee6.155d7","name":"initialize","func":"flow.set('bose_soundtouch_systems', {\"systems\": []}, 'memory');\nreturn msg;","outputs":1,"noerr":0,"x":800,"y":120,"wires":[[]]},{"id":"86d74705.af2e58","type":"comment","z":"6db31ee6.155d7","name":"discovery and initial setup","info":"","x":690,"y":80,"wires":[]},{"id":"654bd3fd.bd172c","type":"ui_template","z":"6db31ee6.155d7","group":"48a230e.e2f88d","name":"volume presets","order":24,"width":"1","height":"1","format":"<md-button class=\"metal linear black-text fa fa-sliders\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"VOLUME\",\n        \"function\": \"setup\",\n        \"group\": {\n            \"show\": [\n                \"Bose_Soundtouch_Volume_presets\"\n            ],\n            \"focus\": \"true\"\n        }\n    }\n]\n})'></md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":1420,"wires":[["6c7968a2.618f48"]]},{"id":"96bd2ef6.39856","type":"ui_template","z":"6db31ee6.155d7","group":"adf6fa3a.e76638","name":"cancel volume","order":6,"width":"2","height":"1","format":"<md-button class=\"metal linear wide black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"N/A\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Volume_presets\"\n            ]\n        }\n    }\n]\n})'>Cancel</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":360,"y":1460,"wires":[["6c7968a2.618f48"]]},{"id":"4cfa98d0.6dfd68","type":"ui_template","z":"6db31ee6.155d7","group":"adf6fa3a.e76638","name":"save volume","order":7,"width":"2","height":"1","format":"<md-button class=\"metal linear wide black-text\" ng-click='send({\npayload: [\n    {\n        \"name\": \"select\",\n        \"method\": \"VOLUME\",\n        \"function\": \"save\",\n        \"group\": {\n            \"hide\": [\n                \"Bose_Soundtouch_Volume_presets\"\n            ]\n        }\n    }\n]\n})'>Save</md-button>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":350,"y":1500,"wires":[["6c7968a2.618f48"]]},{"id":"26e0447e.f67c6c","type":"function","z":"6db31ee6.155d7","name":"save","func":"var name = flow.get('bose_name');\nvar tempSystem = flow.get('temp_system', 'memory');\nvar system = Object.assign({}, tempSystem);\nflow.set(name.replace(/ /g, '_'), system);\nmsg.payload = 'Volume presets saved';\nmsg.bose.notification = 'true';\nreturn msg;","outputs":1,"noerr":0,"x":2010,"y":1200,"wires":[["8ac5bdf7.7e89a"]]},{"id":"adc237be.fd5398","type":"comment","z":"6db31ee6.155d7","name":"volume request","info":"","x":1840,"y":1120,"wires":[]},{"id":"3a1ceddb.152b12","type":"link out","z":"6db31ee6.155d7","name":"bone link 4","links":["ca0d010d.3b7b8"],"x":2775,"y":540,"wires":[]},{"id":"ca0d010d.3b7b8","type":"link in","z":"6db31ee6.155d7","name":"bose link 4","links":["3a1ceddb.152b12","8ac5bdf7.7e89a","2fc2d32f.862d2c"],"x":855,"y":320,"wires":[["bd767cc9.13002","f590ce48.2d299"]]},{"id":"8ac5bdf7.7e89a","type":"link out","z":"6db31ee6.155d7","name":"bone link 4","links":["ca0d010d.3b7b8"],"x":2095,"y":1200,"wires":[]},{"id":"2fc2d32f.862d2c","type":"link out","z":"6db31ee6.155d7","name":"bone link 4","links":["ca0d010d.3b7b8"],"x":2595,"y":760,"wires":[]},{"id":"29ea5455.065e1c","type":"comment","z":"6db31ee6.155d7","name":"1s notification","info":"","x":750,"y":320,"wires":[]},{"id":"dadd4f28.f925d","type":"switch","z":"6db31ee6.155d7","name":"function","property":"bose.function","propertyType":"msg","rules":[{"t":"eq","v":"setup","vt":"str"},{"t":"eq","v":"save","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":1820,"y":1160,"wires":[["59dcacda.7fb654"],["26e0447e.f67c6c"]],"outputLabels":["setup","save"]},{"id":"59dcacda.7fb654","type":"function","z":"6db31ee6.155d7","name":"setup values","func":"var name = flow.get('bose_name');\nvar system = flow.get(name.replace(/ /g, '_'));\nvar tempSystem = Object.assign({}, system);\nflow.set('temp_system', tempSystem, 'memory');\n\nmsg.payload = [\n    {\n       value: system.lowVolume,\n       \"topic\": \"lowVolume\"\n    },\n    {\n       value: system.mediumVolume,\n       \"topic\": \"mediumVolume\"\n    },\n    {\n       value: system.highVolume,\n       \"topic\": \"highVolume\"\n    },\n    {\n       value: system.maxVolume,\n       \"topic\": \"maxVolume\"\n    }\n]\nreturn msg;","outputs":1,"noerr":0,"x":2030,"y":1140,"wires":[["6f8bb1fd.beff2"]]},{"id":"a1576670.559f48","type":"switch","z":"6db31ee6.155d7","name":"topic","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"lowVolume","vt":"str"},{"t":"eq","v":"mediumVolume","vt":"str"},{"t":"eq","v":"highVolume","vt":"str"},{"t":"eq","v":"maxVolume","vt":"str"}],"checkall":"false","repair":false,"outputs":4,"x":2430,"y":1140,"wires":[["8c61509d.0e6fc"],["67a2645c.b4569c"],["7e20d83f.0c82c8"],["e61869ff.4f9a18"]],"outputLabels":["low","medium","high","max"]},{"id":"6f8bb1fd.beff2","type":"split","z":"6db31ee6.155d7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":2170,"y":1140,"wires":[["800bf0f5.340d1"]]},{"id":"800bf0f5.340d1","type":"function","z":"6db31ee6.155d7","name":"set topic","func":"msg.topic = msg.payload.topic;\nmsg.payload = msg.payload.value;\nreturn msg;","outputs":1,"noerr":0,"x":2300,"y":1140,"wires":[["a1576670.559f48"]]},{"id":"f53d7d32.9f6a9","type":"function","z":"6db31ee6.155d7","name":"set context","func":"var tempSystem = flow.get('temp_system', 'memory');\ntempSystem[msg.topic] = msg.payload;\nflow.set('temp_system', tempSystem, 'memory');\nreturn msg;","outputs":1,"noerr":0,"x":2850,"y":1140,"wires":[[]]},{"id":"8c61509d.0e6fc","type":"ui_numeric","z":"6db31ee6.155d7","name":"low volume","label":"Low","tooltip":"","group":"adf6fa3a.e76638","order":1,"width":"3","height":"1","passthru":false,"topic":"lowVolume","format":"{{value}}","min":0,"max":"100","step":1,"x":2630,"y":1060,"wires":[["f53d7d32.9f6a9"]]},{"id":"67a2645c.b4569c","type":"ui_numeric","z":"6db31ee6.155d7","name":"medium volume","label":"Med","tooltip":"","group":"adf6fa3a.e76638","order":3,"width":"3","height":"1","passthru":false,"topic":"mediumVolume","format":"{{value}}","min":0,"max":"100","step":1,"x":2640,"y":1120,"wires":[["f53d7d32.9f6a9"]]},{"id":"7e20d83f.0c82c8","type":"ui_numeric","z":"6db31ee6.155d7","name":"high volume","label":"High","tooltip":"","group":"adf6fa3a.e76638","order":2,"width":"3","height":"1","passthru":false,"topic":"highVolume","format":"{{value}}","min":0,"max":"100","step":1,"x":2630,"y":1180,"wires":[["f53d7d32.9f6a9"]]},{"id":"e61869ff.4f9a18","type":"ui_numeric","z":"6db31ee6.155d7","name":"max volume","label":"Max","tooltip":"","group":"adf6fa3a.e76638","order":4,"width":"3","height":"1","passthru":false,"topic":"maxVolume","format":"{{value}}","min":0,"max":"100","step":1,"x":2630,"y":1240,"wires":[["f53d7d32.9f6a9"]]},{"id":"d61db346.2f18a","type":"function","z":"6db31ee6.155d7","name":"add system","func":"// Uncomment line below to initialize context for named system\n//flow.set(msg.payload.name.replace(/ /g, '_'));\nvar bose = flow.get('bose_soundtouch_systems', 'memory');\nvar system = flow.get(msg.payload.name.replace(/ /g, '_'));\nvar name = flow.get('bose_name');\nvar nameArray = [];\nvar i;\n\nif (typeof name !== 'string') {\n    name = msg.payload.name;\n    flow.set('bose_name', name);\n}\n\nvar newSystem = {\n    \"name\": msg.payload.name,\n    \"ipAddress\": msg.payload.addresses[0],\n    \"deviceID\": msg.payload.txtRecord.MAC\n};\nif (typeof system === 'undefined') {\n    system = newSystem;\n    system.lowVolume = 5;\n    system.mediumVolume = 10;\n    system.highVolume = 15;\n    system.maxVolume = 50;\n} else {\n    system.ipAddress = newSystem.ipAddress;\n    system.deviceID = newSystem.deviceID;\n}\n\nflow.set(system.name.replace(/ /g, '_'), system);\nbose.systems.push(newSystem);\nflow.set('bose_soundtouch_systems', bose, 'memory');\n\n// Setup names for dropdown list\nfor (i in bose.systems) { \n    nameArray.push(bose.systems[i].name);\n}\n\nnode.status({fill: 'blue', shape: 'dot', text: bose.systems.length + ' systems added'});\nmsg.options = nameArray.sort();\nmsg.payload = name;\nreturn msg;\n","outputs":1,"noerr":0,"x":970,"y":180,"wires":[["4a934881.039b28"]]},{"id":"7b21b2de.7ed50c","type":"link out","z":"6db31ee6.155d7","name":"bose function","links":["cbc43d51.85954"],"x":1675,"y":160,"wires":[]},{"id":"793bd500.2f5bdc","type":"comment","z":"6db31ee6.155d7","name":"ui refresh","info":"","x":1320,"y":60,"wires":[]},{"id":"6f9bae60.72a2a","type":"function","z":"6db31ee6.155d7","name":"clear flow context","func":"flow.set('bose_name');\nflow.set('bose_volume', null, 'memory');\nflow.set('bose_group_name', null, 'memory');\nflow.set('bose_group_members', null, 'memory');\nflow.set('bose_soundtouch_systems', null, 'memory');\nflow.set('temp_system', null, 'memory');\nreturn msg;","outputs":1,"noerr":0,"x":930,"y":500,"wires":[[]]},{"id":"3d5e9284.e1436e","type":"inject","z":"6db31ee6.155d7","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":760,"y":500,"wires":[["6f9bae60.72a2a"]]},{"id":"7c8aca9b.9d1bb4","type":"comment","z":"6db31ee6.155d7","name":"manually clear flow context","info":"","x":790,"y":460,"wires":[]},{"id":"b6ecb7df.834318","type":"debug","z":"6db31ee6.155d7","name":"discovery output","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":840,"y":240,"wires":[]},{"id":"7b978dfa.14a8e4","type":"switch","z":"6db31ee6.155d7","name":"continue?","property":"payload.method","propertyType":"msg","rules":[{"t":"neq","v":"N/A","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":1040,"y":820,"wires":[["4d14d0d1.c4dc5","2ca97efa.e6e882"]],"outputLabels":["yes"]},{"id":"48a230e.e2f88d","type":"ui_group","z":"","name":"Soundtouch","tab":"26ae0e63.be0762","order":1,"disp":false,"width":"6","collapse":false},{"id":"5fbad2a8.07597c","type":"ui_group","z":"","name":"Group","tab":"26ae0e63.be0762","order":5,"disp":true,"width":"6","collapse":false},{"id":"9bb8a452.40e7d8","type":"ui_group","z":"","name":"Shuffle","tab":"26ae0e63.be0762","order":2,"disp":true,"width":"4","collapse":false},{"id":"a3df549a.bdcec8","type":"ui_group","z":"","name":"Repeat","tab":"26ae0e63.be0762","order":3,"disp":true,"width":"5","collapse":false},{"id":"adf6fa3a.e76638","type":"ui_group","z":"","name":"Volume presets","tab":"26ae0e63.be0762","order":4,"disp":true,"width":"6","collapse":false},{"id":"26ae0e63.be0762","type":"ui_tab","z":"","name":"Bose Soundtouch","icon":"fa-music","order":1,"disabled":false,"hidden":false}]

Flow Info

Created 9 months, 1 week ago
Updated 9 months ago
Rating: not yet rated

Owner

Node Types

Core
  • change (x1)
  • comment (x11)
  • debug (x4)
  • delay (x3)
  • function (x24)
  • http request (x2)
  • inject (x2)
  • switch (x10)
  • xml (x1)
Other

Tags

  • bose
  • soundtouch
  • musicplayer
  • dashboard
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option