Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- [
- {
- "id": "715b57c65332b13b",
- "type": "subflow",
- "name": "track info",
- "info": "Gets current and next track BlueSound API",
- "category": "",
- "in": [
- {
- "x": 40,
- "y": 40,
- "wires": [
- {
- "id": "639c5cadda10fd85"
- }
- ]
- }
- ],
- "out": [
- {
- "x": 1100,
- "y": 300,
- "wires": [
- {
- "id": "2fb50bf863ee52f3",
- "port": 0
- }
- ]
- }
- ],
- "env": [
- {
- "name": "info",
- "type": "str",
- "value": "",
- "ui": {
- "label": {
- "en-US": "Home Asisstant Information"
- },
- "type": "none"
- }
- },
- {
- "name": "haAddress",
- "type": "str",
- "value": "127.0.0.1",
- "ui": {
- "label": {
- "en-US": "HA Address"
- },
- "type": "input",
- "opts": {
- "types": [
- "str"
- ]
- }
- }
- },
- {
- "name": "haPort",
- "type": "num",
- "value": "8123",
- "ui": {
- "label": {
- "en-US": "HA Port"
- },
- "type": "input",
- "opts": {
- "types": [
- "num"
- ]
- }
- }
- },
- {
- "name": "haUseHTTPs",
- "type": "bool",
- "value": "false",
- "ui": {
- "label": {
- "en-US": "Use HTTPS"
- },
- "type": "checkbox"
- }
- }
- ],
- "meta": {
- "module": "track info",
- "version": "1.0.0",
- "author": "Me",
- "desc": "Gets current and next track BlueSound API",
- "license": "MIT"
- },
- "color": "#DEBD5C",
- "icon": "font-awesome/fa-list-ol"
- },
- {
- "id": "b2e2a65512769f0f",
- "type": "join",
- "z": "715b57c65332b13b",
- "name": "Join",
- "mode": "custom",
- "build": "merged",
- "property": "payload",
- "propertyType": "msg",
- "key": "topic",
- "joiner": "\\n",
- "joinerType": "str",
- "accumulate": false,
- "timeout": "2",
- "count": "2",
- "reduceRight": false,
- "reduceExp": "",
- "reduceInit": "",
- "reduceInitType": "",
- "reduceFixup": "",
- "x": 170,
- "y": 240,
- "wires": [
- [
- "06c81a105c5371f1"
- ]
- ]
- },
- {
- "id": "0b8cf0cb01cec05e",
- "type": "function",
- "z": "715b57c65332b13b",
- "name": "1 - Format URLs",
- "func": "if (msg.info.ipAddress == \"\") {\n return null;\n}\n\nvar urls = [\n 'Status',\n 'Playlist?length=1',\n]\n\nurls.forEach(url => {\n node.send({\n info: msg.info,\n url: `http://${msg.info.ipAddress}:11000/${url}`,\n });\n})\n\nnode.done();\n",
- "outputs": 1,
- "timeout": "",
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 340,
- "y": 180,
- "wires": [
- [
- "e69f2d4e66f84cdf"
- ]
- ]
- },
- {
- "id": "06c81a105c5371f1",
- "type": "function",
- "z": "715b57c65332b13b",
- "name": "2 - Ensure Playlist",
- "func": "msg.url = undefined;\n\nvar playListLen = -1;\nmsg.info.currentTrack.queuePos = parseInt(msg.payload.status.song[0] || -2);\nmsg.info.currentTrack.queuePos++ // Zero based counter\n\n// Ensure there is a playlist\nif (msg.payload.playlist) {\n msg.info.totalTracks = parseInt(msg.payload.playlist.length[0]);\n\n // Get next track information, if there is one\n if (msg.info.currentTrack.queuePos < msg.info.totalTracks) {\n msg.url = `http://${msg.info.ipAddress}:11000/Playlist?start=${msg.info.currentTrack.queuePos}&end=${msg.info.currentTrack.queuePos}`;\n }\n else {\n msg.info.nextTrack.title = \".\";\n msg.info.nextTrack.artist = \".\";\n msg.info.nextTrack.album = \".\";\n }\n}\n\nif (msg.url != undefined) {\n return [msg, null];\n}\nelse {\n return [null, msg];\n}\n",
- "outputs": 2,
- "timeout": "",
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 350,
- "y": 240,
- "wires": [
- [
- "00f7ba72f2da2b3d"
- ],
- [
- "2fb50bf863ee52f3"
- ]
- ]
- },
- {
- "id": "2fb50bf863ee52f3",
- "type": "function",
- "z": "715b57c65332b13b",
- "name": "3 - NextTrack Info",
- "func": "if (msg.info.currentTrack.queuepos === \".\") {\n msg.info.currentTrack.queuepos = msg.temp.currTrackNo;\n}\n\nif (msg.payload.playlist) {\n if (msg.payload.playlist.song) {\n msg.info.nextTrack.album = msg.payload.playlist.song[0].alb[0];\n msg.info.nextTrack.artist = msg.payload.playlist.song[0].art[0];\n msg.info.nextTrack.title = msg.payload.playlist.song[0].title[0];\n }\n else {\n msg.info.nextTrack.album = \" \";\n msg.info.nextTrack.artist = \"<i>End Of Playlist</i>\";\n msg.info.nextTrack.title = \" \";\n }\n}\n\n//msg.temp = undefined;\nreturn {payload: msg.info};\n",
- "outputs": 1,
- "timeout": "",
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 350,
- "y": 300,
- "wires": [
- []
- ]
- },
- {
- "id": "639c5cadda10fd85",
- "type": "function",
- "z": "715b57c65332b13b",
- "name": "0 - Create Object",
- "func": "var func = global.get(\"func\");\n\nvar emptyPlaylist = \"<i>(playlist empty)</i>\";\nvar emptyAlbumArt = \"\"\nvar haAddress = env.get(\"haAddress\") || \"1.1.1.1\"; \nvar haPort = env.get(\"haPort\") || 8123;\nvar haUseHTTPs = env.get(\"haUseHTTPs\") || false;\nvar urlType = (haUseHTTPs ? \"https\" : \"http\");\n\nif (msg.data) {\n if (msg.data.new_state) {\n msg.data = msg.data.new_state;\n }\n else if ((msg.data) && (msg.data.event.new_state)) {\n msg.data = msg.data.event.new_state;\n }\n}\nelse if ((msg.payload) && (msg.payload.entity_id)) {\n msg.data = msg.payload;\n}\n\nmsg.payload = undefined;\n\nvar info = {\n \"currentTrack\": {\n \"album\": msg.data.attributes.media_album_name || \".\",\n \"artist\": msg.data.attributes.media_artist || \".\",\n \"queuePos\": msg.data.attributes.queue_position || -1,\n \"title\": msg.data.attributes.media_title || emptyPlaylist,\n \"artUri\": `${urlType}://${haAddress}:${haPort}${msg.data.attributes.entity_picture}` || emptyAlbumArt,\n \"length\": parseInt(msg.data.attributes.media_duration) || 0, // Length in seconds\n \"trackPos\": parseInt(msg.data.attributes.media_position) || 0, // Track position in seconds\n \"length2\": func.convertTime(msg.data.attributes.media_duration, \"track\") || \"--:--\", // Length as formatted string\n \"trackPos2\": func.convertTime(msg.data.attributes.media_position, \"track\") || \"--:--\", // Track position as formatted string\n },\n\n \"nextTrack\": {\n \"album\": \".\",\n \"artist\": \".\",\n \"title\": \".\",\n },\n\n \"playbackState\": msg.data.state,\n \"playerName\": msg.data.attributes.friendly_name,\n \"playerId\": msg.data.entity_id,\n \"totalTracks\": -1,\n \"ipAddress\": msg.data.attributes.ip_address || \"\",\n \"volume\": parseInt(msg.data.attributes.volume_level * 100),\n\n}\n\nreturn {info};\n",
- "outputs": 1,
- "timeout": "",
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 130,
- "y": 180,
- "wires": [
- [
- "0b8cf0cb01cec05e"
- ]
- ]
- },
- {
- "id": "e69f2d4e66f84cdf",
- "type": "http request",
- "z": "715b57c65332b13b",
- "name": "Playlist / Status",
- "method": "GET",
- "ret": "txt",
- "paytoqs": "ignore",
- "url": "",
- "tls": "",
- "persist": false,
- "proxy": "",
- "insecureHTTPParser": false,
- "authType": "",
- "senderr": false,
- "headers": [],
- "x": 580,
- "y": 180,
- "wires": [
- [
- "701d5bed666ef95f"
- ]
- ]
- },
- {
- "id": "9f3bf3e37f88796e",
- "type": "xml",
- "z": "715b57c65332b13b",
- "name": "Xml",
- "property": "payload",
- "attr": "",
- "chr": "",
- "x": 930,
- "y": 180,
- "wires": [
- [
- "b2e2a65512769f0f"
- ]
- ]
- },
- {
- "id": "00f7ba72f2da2b3d",
- "type": "http request",
- "z": "715b57c65332b13b",
- "name": "Set Queue Pos",
- "method": "GET",
- "ret": "txt",
- "paytoqs": "ignore",
- "url": "",
- "tls": "",
- "persist": false,
- "proxy": "",
- "insecureHTTPParser": false,
- "authType": "",
- "senderr": false,
- "headers": [],
- "x": 580,
- "y": 240,
- "wires": [
- [
- "40237da30559eb4c"
- ]
- ]
- },
- {
- "id": "09af8be8d4c96ef0",
- "type": "xml",
- "z": "715b57c65332b13b",
- "name": "Xml",
- "property": "payload",
- "attr": "",
- "chr": "",
- "x": 930,
- "y": 240,
- "wires": [
- [
- "2fb50bf863ee52f3"
- ]
- ]
- },
- {
- "id": "f05c7d31ce947fc7",
- "type": "comment",
- "z": "715b57c65332b13b",
- "name": "Stage 1",
- "info": "Forumate URL for playlist length\nForumate URL for currently playing",
- "x": 1090,
- "y": 80,
- "wires": []
- },
- {
- "id": "bfbce7cf8a2daf2a",
- "type": "comment",
- "z": "715b57c65332b13b",
- "name": "Stage 2",
- "info": "Get current track number\nFormulate URL to get next track info",
- "x": 1090,
- "y": 120,
- "wires": []
- },
- {
- "id": "ca34320a5cf428fc",
- "type": "comment",
- "z": "715b57c65332b13b",
- "name": "Stage 3",
- "info": "Tie everything else together",
- "x": 1090,
- "y": 160,
- "wires": []
- },
- {
- "id": "701d5bed666ef95f",
- "type": "switch",
- "z": "715b57c65332b13b",
- "name": "Status Code",
- "property": "statusCode",
- "propertyType": "msg",
- "rules": [
- {
- "t": "eq",
- "v": "200",
- "vt": "num"
- },
- {
- "t": "else"
- }
- ],
- "checkall": "true",
- "repair": false,
- "outputs": 2,
- "x": 770,
- "y": 180,
- "wires": [
- [
- "9f3bf3e37f88796e"
- ],
- []
- ]
- },
- {
- "id": "40237da30559eb4c",
- "type": "switch",
- "z": "715b57c65332b13b",
- "name": "Status Code",
- "property": "statusCode",
- "propertyType": "msg",
- "rules": [
- {
- "t": "eq",
- "v": "200",
- "vt": "num"
- },
- {
- "t": "else"
- }
- ],
- "checkall": "true",
- "repair": false,
- "outputs": 2,
- "x": 770,
- "y": 240,
- "wires": [
- [
- "09af8be8d4c96ef0"
- ],
- []
- ]
- },
- {
- "id": "119ee3c8cec8edfc",
- "type": "comment",
- "z": "715b57c65332b13b",
- "name": "Stage 0",
- "info": "Delays incoming requests: important\nCreates the JS object to manipulate",
- "x": 1090,
- "y": 40,
- "wires": []
- },
- {
- "id": "36a51e882e7c8098",
- "type": "tab",
- "label": "Music Control",
- "disabled": false,
- "info": ""
- },
- {
- "id": "2921e71710bf19f4",
- "type": "group",
- "z": "36a51e882e7c8098",
- "name": "Update Currently Playing Information",
- "style": {
- "label": true,
- "stroke": "#000000",
- "fill": "#bfbfbf",
- "fill-opacity": "0.25",
- "color": "#000000"
- },
- "nodes": [
- "1a9a96b0fcd6a6a6",
- "6e4fa448f739629e",
- "9691d3d8c01a1303",
- "e028a150b4daa738",
- "f00580961c860116",
- "f53e6d14192943b8",
- "699540e3dc5c9caf",
- "51190bea03e13bca",
- "ebecb87c4e391567",
- "28cfc8bc6a861106",
- "d48e9f739bc3a287",
- "0ae94d25f03776f2",
- "56686842eb01ab92",
- "5efd47fae4b678e5"
- ],
- "x": 14,
- "y": 639,
- "w": 1112,
- "h": 182
- },
- {
- "id": "aebdab15ef4ba5d1",
- "type": "group",
- "z": "36a51e882e7c8098",
- "name": "Change Album / Artist",
- "style": {
- "stroke": "#000000",
- "fill": "#bfbfbf",
- "fill-opacity": "0.25",
- "label": true,
- "color": "#000000"
- },
- "nodes": [
- "0a0e8c6f95067f74",
- "1e6dd7fcaab3047c",
- "8a2ba92dfe1002f8",
- "49af760f08bb7064",
- "3b34dba3f4519a53",
- "ca5c6417c40e9323",
- "efbb5469bb8ad08c",
- "da42e5a0c6bd7bf0",
- "ca54ba3ac6aa7b42",
- "845331a79935d27f",
- "b6282e4a9ba743fb",
- "0e6b9ca4662fbe68",
- "d240618aedd55c9c",
- "b0b0840a9f86b853",
- "ee0f42289aef4f48"
- ],
- "x": 14,
- "y": 379,
- "w": 1112,
- "h": 242
- },
- {
- "id": "1a9a96b0fcd6a6a6",
- "type": "ha-get-entities",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Music Players",
- "server": "77c01ee87ceeb243",
- "version": 0,
- "rules": [
- {
- "property": "entity_id",
- "logic": "is",
- "value": "media_player.*",
- "valueType": "re"
- },
- {
- "property": "attributes.media_content_type",
- "logic": "is",
- "value": "music",
- "valueType": "str"
- },
- {
- "property": "state",
- "logic": "is_not",
- "value": "grouped",
- "valueType": "str"
- }
- ],
- "output_type": "split",
- "output_empty_results": false,
- "output_location_type": "msg",
- "output_location": "payload",
- "output_results_count": 1,
- "x": 220,
- "y": 740,
- "wires": [
- [
- "699540e3dc5c9caf"
- ]
- ]
- },
- {
- "id": "6e4fa448f739629e",
- "type": "switch",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Player Select",
- "property": "payload.playerName",
- "propertyType": "msg",
- "rules": [
- {
- "t": "eq",
- "v": "Lounge",
- "vt": "str"
- },
- {
- "t": "eq",
- "v": "Study",
- "vt": "str"
- }
- ],
- "checkall": "false",
- "repair": false,
- "outputs": 2,
- "x": 850,
- "y": 760,
- "wires": [
- [
- "9691d3d8c01a1303"
- ],
- [
- "f00580961c860116"
- ]
- ]
- },
- {
- "id": "9691d3d8c01a1303",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Lounge",
- "mode": "link",
- "links": [
- "209b08538867494f",
- "a83832506dc91f31",
- "fed19dd1434279c9",
- "d2be36990d5d15ae",
- "75bfb14c0c477350"
- ],
- "x": 1040,
- "y": 740,
- "wires": [],
- "icon": "font-awesome/fa-music",
- "l": true
- },
- {
- "id": "c4f3b4349c8ac21f",
- "type": "api-call-service",
- "z": "36a51e882e7c8098",
- "name": "Music Control Service",
- "server": "77c01ee87ceeb243",
- "version": 5,
- "debugenabled": false,
- "domain": "",
- "service": "",
- "areaId": [],
- "deviceId": [],
- "entityId": [],
- "data": "",
- "dataType": "jsonata",
- "mergeContext": "",
- "mustacheAltTags": false,
- "outputProperties": [],
- "queue": "none",
- "x": 360,
- "y": 260,
- "wires": [
- []
- ]
- },
- {
- "id": "acbca54b7a1dbc7b",
- "type": "function",
- "z": "36a51e882e7c8098",
- "name": "Music Control",
- "func": "var action = \"X\";\nvar player = \"X\";\nvar players = global.get(\"musicPlayers\");\nvar currTrack = flow.get(\"currTrack\");\n\nif (typeof msg.payload.slots !== \"undefined\") {\n // From JARVIS\n player = msg.payload.siteId.toLowerCase();\n action = msg.payload.slots.action.toLowerCase();\n}\nelse {\n // From UI CONTROLS\n player = msg.topic.toLowerCase();\n action = msg.payload;\n if (typeof action !== \"number\") {\n action = action.toLowerCase();\n }\n}\n\n// HACK FOR SPEAKER GROUPING ISSUE\nif (player === \"kitchen\") {\n node.warn(\"'KITCHEN' Label Used\");\n player = \"lounge\";\n}\n// HACK FOR SPEAKER GROUPING ISSUE\n\nmsg.payload = {};\nmsg.payload.domain = \"media_player\";\nplayer = player.replace('media_player.', '');\nmsg.payload.data = {\"entity_id\": `media_player.${player}`};\n\nvar skipForward = null;\n\nswitch (action) {\n case \"playpause\": // Toggle play/pause player\n msg.payload.service = \"media_play_pause\";\n break;\n\n case \"play\": // Start playing music\n msg.payload.service = \"media_play\";\n break;\n\n case \"stop\": // Stop playing music\n msg.payload.service = \"media_pause\";\n break;\n\n case \"previous\": // Play previous track\n msg.payload.service = \"media_previous_track\";\n break;\n\n case \"next\": // Play next track\n msg.payload.service = \"media_next_track\";\n break;\n\n case \"album\": // Skip to next album\n msg.payload.service = \"media_pause\";\n skipForward = { skipAction: \"Album\", player: player };\n break;\n\n case \"artist\": // Skip to next artist\n msg.payload.service = \"media_pause\";\n skipForward = { skipAction: \"Artist\", player: player };\n break;\n\n case \"increase\": // Raise volume\n msg.payload.service = \"volume_up\";\n break;\n\n case \"decrease\": // Lower volume\n msg.payload.service = \"volume_down\";\n break;\n\n case \"track\": // Get currently playing track\n var currTrack = flow.get(\"currTrack\")\n msg.payload = `Current track is \"${currTrack[player].title}\" by \"${currTrack[player].artist}\" on \"${currTrack[player].album}\"`;\n msg.siteId = player;\n return [\n msg,\n null,\n null\n ];\n\n default:\n if (typeof action === \"number\") { // Change volume to specific value\n var newVolume = parseFloat(action / 100).toFixed(2);\n\n if (players[player].volume !== newVolume) {\n msg.payload.service = \"volume_set\";\n msg.payload.data.volume_level = newVolume;\n }\n else {\n msg = null;\n }\n }\n}\n\nreturn [\n null,\n skipForward,\n msg\n];\n",
- "outputs": 3,
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 120,
- "y": 220,
- "wires": [
- [
- "a015e856239334be"
- ],
- [
- "069ea68f73053833"
- ],
- [
- "c4f3b4349c8ac21f"
- ]
- ]
- },
- {
- "id": "e028a150b4daa738",
- "type": "trigger-state",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Trigger State",
- "server": "77c01ee87ceeb243",
- "version": 4,
- "inputs": 0,
- "outputs": 2,
- "exposeAsEntityConfig": "",
- "entityId": "media_player",
- "entityIdType": "substring",
- "debugEnabled": false,
- "constraints": [
- {
- "targetType": "this_entity",
- "targetValue": "",
- "propertyType": "property",
- "propertyValue": "new_state.attributes.media_content_type",
- "comparatorType": "is",
- "comparatorValueDatatype": "str",
- "comparatorValue": "music"
- },
- {
- "targetType": "this_entity",
- "targetValue": "",
- "propertyType": "property",
- "propertyValue": "new_state.state",
- "comparatorType": "is_not",
- "comparatorValueDatatype": "str",
- "comparatorValue": "grouped"
- }
- ],
- "customOutputs": [],
- "outputInitially": false,
- "stateType": "str",
- "enableInput": false,
- "exposeToHomeAssistant": false,
- "haConfig": [
- {
- "property": "name",
- "value": ""
- },
- {
- "property": "icon",
- "value": ""
- }
- ],
- "x": 230,
- "y": 680,
- "wires": [
- [
- "5efd47fae4b678e5"
- ],
- []
- ]
- },
- {
- "id": "f00580961c860116",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Study",
- "links": [
- "1c7556be09df24b9",
- "1c979e46c6195e65",
- "6d178decac8c3537",
- "706b7cf43d7c62ce",
- "159319c1082b295c",
- "ccdc6ebc5259862d",
- "11b8bb2e340a07a3",
- "75e879a88b81d8bd",
- "fc4e59a5379d791b",
- "a1bd065a0a8cb6ea"
- ],
- "x": 1030,
- "y": 780,
- "wires": [],
- "icon": "font-awesome/fa-music",
- "l": true
- },
- {
- "id": "b65bf698970b5964",
- "type": "comment",
- "z": "36a51e882e7c8098",
- "name": "Flow Explaination",
- "info": "Music Control Service\n This does all the work to control\n play/pause, next, prev and volume.\n\n\nMusic Player\n Gets all information from all\n `music_player.*` devices\n\n\nTrigger State\n As above, but is trigger by events\n\n",
- "x": 100,
- "y": 80,
- "wires": []
- },
- {
- "id": "87aa0819e57ce109",
- "type": "catch",
- "z": "36a51e882e7c8098",
- "name": "Catch All",
- "scope": null,
- "uncaught": true,
- "x": 1000,
- "y": 40,
- "wires": [
- [
- "67d16d8350936fe6"
- ]
- ]
- },
- {
- "id": "67d16d8350936fe6",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "name": "Error Logging",
- "mode": "link",
- "links": [
- "498db3b5.39bc9c",
- "7495be3477187c7a"
- ],
- "x": 1115,
- "y": 40,
- "wires": [],
- "icon": "font-awesome/fa-exclamation"
- },
- {
- "id": "5157e70bae68b04e",
- "type": "link in",
- "z": "36a51e882e7c8098",
- "name": "Music",
- "links": [
- "983ecb90.e0d3b8",
- "17635279aac1c8b4",
- "d79211d106243437",
- "1549ea7d8f964923",
- "596809fe0d4a7de5",
- "a25cb078df0f4837",
- "c4d3d1f8b171eca8",
- "0b5e1fd28742cf9e",
- "0e975831db7c85c9",
- "bb4ea9df48c90b7b",
- "b6385d7273de2d93",
- "373e7b2e4bd696ba",
- "41dbdd1a9d016910",
- "072ecebf8ddc8049",
- "d4fb5a4216e6e7f9",
- "d2d51e9f5c787f7e"
- ],
- "x": 35,
- "y": 40,
- "wires": [
- [
- "acbca54b7a1dbc7b"
- ]
- ],
- "icon": "node-red/bridge.svg"
- },
- {
- "id": "a015e856239334be",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "name": "Current Track",
- "mode": "link",
- "links": [
- "349a75b9.2668ea"
- ],
- "x": 340,
- "y": 180,
- "wires": [],
- "icon": "node-red/bridge.svg",
- "l": true
- },
- {
- "id": "f53e6d14192943b8",
- "type": "function",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Set currTrack",
- "func": "var currTrack = flow.get(\"currTrack\") || {};\nvar musicPlayers = global.get(\"musicPlayers\") || {};\nvar currPlayer = msg.payload.playerName.toLowerCase();\n\ncurrTrack[currPlayer] = msg.payload.currentTrack;\nmusicPlayers[currPlayer].ipAddress = msg.payload.ipAddress;\n\nflow.set(\"currTrack\", currTrack);\nglobal.set(\"musicPlayers\", musicPlayers);\n",
- "outputs": 1,
- "timeout": "",
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 850,
- "y": 720,
- "wires": [
- []
- ]
- },
- {
- "id": "699540e3dc5c9caf",
- "type": "delay",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Rate 1s",
- "pauseType": "rate",
- "timeout": "1",
- "timeoutUnits": "seconds",
- "rate": "1",
- "nbRateUnits": "1",
- "rateUnits": "second",
- "randomFirst": "1",
- "randomLast": "5",
- "randomUnits": "seconds",
- "drop": false,
- "allowrate": false,
- "outputs": 1,
- "x": 400,
- "y": 740,
- "wires": [
- [
- "d48e9f739bc3a287"
- ]
- ]
- },
- {
- "id": "51190bea03e13bca",
- "type": "function",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Save Volume ",
- "func": "var musicPlayers = global.get(\"musicPlayers\") || {};\nvar currPlayer = msg.topic.replace(\"media_player.\", \"\").toLowerCase();\n\nmusicPlayers[currPlayer] = {};\nmusicPlayers[currPlayer].volume = msg.data.event.new_state.attributes.volume_level;\nglobal.set(\"musicPlayers\", musicPlayers);\n\nreturn msg;\n",
- "outputs": 1,
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 850,
- "y": 680,
- "wires": [
- [
- "ebecb87c4e391567"
- ]
- ]
- },
- {
- "id": "ebecb87c4e391567",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Volume",
- "mode": "link",
- "links": [
- "ac38921646b7142f"
- ],
- "x": 1040,
- "y": 680,
- "wires": [],
- "icon": "font-awesome/fa-volume-up",
- "l": true
- },
- {
- "id": "069ea68f73053833",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "name": "Change Album/Artist",
- "mode": "link",
- "links": [
- "42a03c677f45d9bf",
- "ca5c6417c40e9323"
- ],
- "x": 360,
- "y": 220,
- "wires": [],
- "icon": "node-red-dashboard/ui_dropdown.png",
- "l": true
- },
- {
- "id": "0a0e8c6f95067f74",
- "type": "ha-get-entities",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Music Players",
- "server": "77c01ee87ceeb243",
- "version": 0,
- "rules": [],
- "output_type": "split",
- "output_empty_results": false,
- "output_location_type": "msg",
- "output_location": "payload",
- "output_results_count": 1,
- "x": 520,
- "y": 500,
- "wires": [
- [
- "b0b0840a9f86b853"
- ]
- ]
- },
- {
- "id": "1e6dd7fcaab3047c",
- "type": "http request",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Get Data",
- "method": "GET",
- "ret": "txt",
- "paytoqs": "ignore",
- "url": "",
- "tls": "",
- "persist": false,
- "proxy": "",
- "insecureHTTPParser": false,
- "authType": "",
- "senderr": false,
- "headers": [],
- "x": 360,
- "y": 560,
- "wires": [
- [
- "8a2ba92dfe1002f8"
- ]
- ]
- },
- {
- "id": "8a2ba92dfe1002f8",
- "type": "xml",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "XML",
- "property": "payload",
- "attr": "",
- "chr": "",
- "x": 510,
- "y": 560,
- "wires": [
- [
- "49af760f08bb7064"
- ]
- ]
- },
- {
- "id": "49af760f08bb7064",
- "type": "function",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Get Next",
- "func": "var url = msg.url.split(\"Playlist\")[0];\n\nif (msg.payload.playlist.song === undefined) {\n node.warn(\"msg.payload.playlist.song === undefined\");\n return [\n {\n \"url\": url,\n \"enabled\": true,\n \"player\": msg.player\n },\n null\n ];\n}\n\nvar currAlbum = msg.payload.playlist.song[0].alb[0];\nvar currArtist = msg.payload.playlist.song[0].art[0];\nvar currTrackId = parseInt(msg.payload.playlist.song[0].$.id) || 0;\nvar newTrackId = -1;\n\nfunction matchArtist(newTitle) {\n if ((newTitle.match(currArtist)) || (currArtist.match(newTitle))) {\n return true;\n }\n return false;\n}\n\nif (msg.skipAction === \"Album\") {\n msg.payload.playlist.song.forEach(item => {\n if ((newTrackId === -1) || (newTrackId === currTrackId)) {\n // if ALBUM is different : PLAYTRACK\n if (item.alb[0] != currAlbum) {\n newTrackId = parseInt(item.$.id);\n }\n }\n })\n // End of playlist check\n if (newTrackId === -1) {newTrackId = -2}\n}\n\nelse if (msg.skipAction === \"Artist\") {\n msg.payload.playlist.song.forEach(item => {\n if ((newTrackId === -1) || (newTrackId === currTrackId)) {\n // if ARTIST is different : PLAYTRACK\n if (!matchArtist(item.art[0])) {\n newTrackId = parseInt(item.$.id);\n }\n }\n })\n // End of playlist check\n if (newTrackId === -1) { newTrackId = -2 }\n}\n\nelse {\n node.warn(\"No skipAction specified\");\n return [\n {\n \"url\": null,\n \"enabled\": true,\n \"player\": msg.player\n },\n null\n ]\n}\n\nif ((newTrackId > -1) && (newTrackId > currTrackId)) {\n url = (msg.url.split(\"Playlist\")[0]) + `Play?id=${newTrackId}`\n}\n\nreturn [\n {\n \"url\": url,\n \"enabled\": true,\n \"player\": msg.player\n },\n {\n \"topic\": \"skipchange\",\n \"player\": msg.player,\n \"payload\": {\n \"skipAction\": msg.skipAction,\n \"currAlbum\": currAlbum,\n \"currArtist\": currArtist,\n \"oldId\": currTrackId,\n \"newId\": newTrackId\n }\n }\n];\n",
- "outputs": 2,
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 660,
- "y": 560,
- "wires": [
- [
- "d240618aedd55c9c",
- "3b34dba3f4519a53"
- ],
- [
- "ca54ba3ac6aa7b42"
- ]
- ]
- },
- {
- "id": "3b34dba3f4519a53",
- "type": "http request",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Play Next",
- "method": "POST",
- "ret": "txt",
- "paytoqs": "ignore",
- "url": "",
- "tls": "",
- "persist": false,
- "proxy": "",
- "insecureHTTPParser": false,
- "authType": "",
- "senderr": false,
- "headers": [],
- "x": 840,
- "y": 540,
- "wires": [
- []
- ]
- },
- {
- "id": "ca5c6417c40e9323",
- "type": "link in",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Change Album/Artist",
- "links": [
- "069ea68f73053833"
- ],
- "x": 55,
- "y": 460,
- "wires": [
- [
- "efbb5469bb8ad08c"
- ]
- ],
- "icon": "node-red-dashboard/ui_dropdown.png"
- },
- {
- "id": "efbb5469bb8ad08c",
- "type": "change",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Set Rules",
- "rules": [
- {
- "t": "set",
- "p": "payload",
- "pt": "msg",
- "to": "$join(['{\"rules\":[{\"property\":\"entity_id\",\"logic\":\"is\",\"value\":\"media_player.', player, '\",\"valueType\":\"str\"}]}'], \"\")",
- "tot": "jsonata"
- },
- {
- "t": "set",
- "p": "enabled",
- "pt": "msg",
- "to": "false",
- "tot": "bool"
- }
- ],
- "action": "",
- "property": "",
- "from": "",
- "to": "",
- "reg": false,
- "x": 180,
- "y": 460,
- "wires": [
- [
- "da42e5a0c6bd7bf0",
- "d240618aedd55c9c"
- ]
- ]
- },
- {
- "id": "da42e5a0c6bd7bf0",
- "type": "json",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "JSON",
- "property": "payload",
- "action": "",
- "pretty": false,
- "x": 350,
- "y": 500,
- "wires": [
- [
- "0a0e8c6f95067f74"
- ]
- ]
- },
- {
- "id": "28cfc8bc6a861106",
- "type": "comment",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Ignore \"grouped\" error",
- "info": "This is because it's finding a device that matches the \"is not\" rule.\nIt can be ignored.",
- "x": 600,
- "y": 780,
- "wires": []
- },
- {
- "id": "ca54ba3ac6aa7b42",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Logging",
- "mode": "link",
- "links": [
- "1da60329.1c119d",
- "dff3e2daa88b43f4"
- ],
- "x": 840,
- "y": 580,
- "wires": [],
- "icon": "node-red/debug.svg",
- "l": true
- },
- {
- "id": "d240618aedd55c9c",
- "type": "switch",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Player Select",
- "property": "player",
- "propertyType": "msg",
- "rules": [
- {
- "t": "eq",
- "v": "lounge",
- "vt": "str"
- },
- {
- "t": "eq",
- "v": "study",
- "vt": "str"
- }
- ],
- "checkall": "false",
- "repair": false,
- "outputs": 2,
- "x": 850,
- "y": 460,
- "wires": [
- [
- "845331a79935d27f"
- ],
- [
- "b6282e4a9ba743fb"
- ]
- ]
- },
- {
- "id": "0e6b9ca4662fbe68",
- "type": "change",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Enable",
- "rules": [
- {
- "t": "set",
- "p": "enabled",
- "pt": "msg",
- "to": "true",
- "tot": "bool"
- }
- ],
- "action": "",
- "property": "",
- "from": "",
- "to": "",
- "reg": false,
- "x": 860,
- "y": 420,
- "wires": [
- [
- "845331a79935d27f",
- "b6282e4a9ba743fb"
- ]
- ]
- },
- {
- "id": "b6282e4a9ba743fb",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Study",
- "mode": "link",
- "links": [
- "108d075174f1e5b8",
- "a9c11b3bcd46d87d",
- "68ec3c38f6fd192d",
- "9446b87cc9422610",
- "1d4dde504ee6a9e7",
- "5e2968b3302e7ef5",
- "56fad6f71a3fdc12",
- "e331e98cdc5954f5"
- ],
- "x": 1030,
- "y": 460,
- "wires": [],
- "icon": "font-awesome/fa-toggle-off",
- "l": true
- },
- {
- "id": "845331a79935d27f",
- "type": "link out",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Lounge",
- "mode": "link",
- "links": [
- "1fb4a70acb1e0deb",
- "64cd11a0e798bbc2",
- "d2775ed3c672a3c1",
- "33a8c913445a89a6",
- "ca591f366f53a391",
- "7aab22d735add24e",
- "d041b7987b819a19"
- ],
- "x": 1040,
- "y": 420,
- "wires": [],
- "icon": "font-awesome/fa-toggle-off",
- "l": true
- },
- {
- "id": "b0b0840a9f86b853",
- "type": "function",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Format URL",
- "func": "var currTrack = flow.get(\"currTrack\") || undefined;\n\nif (currTrack === undefined) {\n node.warn(\"currTrack is undefined\")\n return null;\n}\n\nvar player = msg.player;\nvar queuePosS = currTrack[player].queuePos || 0;\nvar queuePosE = currTrack[player].queuePos + 300 || 300;\n\nmsg.url = `http://${msg.payload.attributes.ip_address}:11000/Playlist?start=${queuePosS}&end=${queuePosE}`\n\nreturn msg;\n",
- "outputs": 1,
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "libs": [],
- "x": 190,
- "y": 560,
- "wires": [
- [
- "1e6dd7fcaab3047c"
- ]
- ]
- },
- {
- "id": "ee0f42289aef4f48",
- "type": "link in",
- "z": "36a51e882e7c8098",
- "g": "aebdab15ef4ba5d1",
- "name": "Trigger - Startup",
- "links": [],
- "x": 715,
- "y": 420,
- "wires": [
- [
- "0e6b9ca4662fbe68"
- ]
- ],
- "icon": "font-awesome/fa-thumb-tack"
- },
- {
- "id": "d48e9f739bc3a287",
- "type": "subflow:715b57c65332b13b",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Track Information",
- "env": [
- {
- "name": "haAddress",
- "value": "1.1.1.1",
- "type": "str"
- }
- ],
- "x": 630,
- "y": 740,
- "wires": [
- [
- "f53e6d14192943b8",
- "6e4fa448f739629e"
- ]
- ]
- },
- {
- "id": "0ae94d25f03776f2",
- "type": "link in",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Every 60 Minutes",
- "links": [
- "c3e046d5b1d7cd49"
- ],
- "x": 75,
- "y": 720,
- "wires": [
- [
- "1a9a96b0fcd6a6a6"
- ]
- ]
- },
- {
- "id": "56686842eb01ab92",
- "type": "inject",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Inject",
- "props": [],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "x": 75,
- "y": 760,
- "wires": [
- [
- "1a9a96b0fcd6a6a6"
- ]
- ],
- "l": false
- },
- {
- "id": "5efd47fae4b678e5",
- "type": "delay",
- "z": "36a51e882e7c8098",
- "g": "2921e71710bf19f4",
- "name": "Delay 125ms",
- "pauseType": "delay",
- "timeout": "125",
- "timeoutUnits": "milliseconds",
- "rate": "1",
- "nbRateUnits": "1",
- "rateUnits": "second",
- "randomFirst": "1",
- "randomLast": "5",
- "randomUnits": "seconds",
- "drop": false,
- "allowrate": false,
- "outputs": 1,
- "x": 410,
- "y": 680,
- "wires": [
- [
- "51190bea03e13bca",
- "d48e9f739bc3a287"
- ]
- ]
- },
- {
- "id": "77c01ee87ceeb243",
- "type": "server",
- "name": "Home Assistant",
- "version": 5,
- "addon": false,
- "rejectUnauthorizedCerts": false,
- "ha_boolean": "y|yes|true|on|home|open",
- "connectionDelay": true,
- "cacheJson": true,
- "heartbeat": false,
- "heartbeatInterval": "30",
- "areaSelector": "friendlyName",
- "deviceSelector": "friendlyName",
- "entitySelector": "friendlyName",
- "statusSeparator": "at: ",
- "statusYear": "hidden",
- "statusMonth": "short",
- "statusDay": "numeric",
- "statusHourCycle": "h23",
- "statusTimeFormat": "h:m",
- "enableGlobalContextStore": true
- }
- ]
Add Comment
Please, Sign In to add comment