This node red flow works.
- ESPresense phone sensor
- Change node to only pass room changes that have music capabilities
- Change node to store flow data with old room and new room
- Current state node to check if “follow music” input boolean is on
- Function node to create action payload
- Action code to call change queue service.
Probably going to add a limiter to eliminate quick changes in a row, like going to the kitchen for less than 2 mins
[{"id":"filter","type":"switch","z":"2ace8abbbc7448db","name":"Room Changed?","property":"data.new_state.state","propertyType":"msg","rules":[{"t":"neq","v":"msg.data.old_state.state","vt":"msg"},{"t":"neq","v":"not_home","vt":"str"},{"t":"neq","v":"office","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":250,"y":160,"wires":[["set_vars"],[],[]]},{"id":"trigger","type":"server-state-changed","z":"2ace8abbbc7448db","name":"iPhonePVC","server":"2a12269e.94634a","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["sensor.iphonepvc"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":70,"y":160,"wires":[["filter"]]},{"id":"set_vars","type":"change","z":"2ace8abbbc7448db","name":"Set Locations","rules":[{"t":"set","p":"old_location","pt":"flow","to":"msg.data.old_state.state","tot":"msg"},{"t":"set","p":"new_location","pt":"flow","to":"msg.data.new_state.state","tot":"msg"}],"x":480,"y":160,"wires":[["37ac6641e0135e8c"]]},{"id":"37ac6641e0135e8c","type":"api-current-state","z":"2ace8abbbc7448db","name":"music follow paul","server":"2a12269e.94634a","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_boolean.music_follow_paul","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":670,"y":160,"wires":[["function"]]},{"id":"function","type":"function","z":"2ace8abbbc7448db","name":"Transfer Queue","func":"// =============================================================================\n// MUSIC ASSISTANT QUEUE TRANSFER - Node-RED Function\n// Based on: music_assistant.transfer_queue\n// =============================================================================\n\n// Extract old/new locations from flow context (set by previous change node)\nvar old_location = flow.get('old_location');\nvar new_location = flow.get('new_location');\n\n// VALIDATION: Skip invalid transfers\nif (!old_location || !new_location || old_location === new_location || new_location === 'not_home') {\n node.warn(`❌ Skipping: ${old_location || 'none'} → ${new_location || 'none'}`);\n return null;\n}\n\n// 🎵 BUILD EXACT Home Assistant Service Format\nmsg.payload = {\n // REQUIRED: Action (for Node-RED api-call-service)\n \"action\": \"music_assistant.transfer_queue\",\n \n // REQUIRED: Target entity (matches your HA example)\n \"target\": {\n \"entity_id\": \"media_player.ma_\" + new_location\n },\n \n // REQUIRED: Music Assistant data (matches your HA example)\n \"data\": {\n \"source_player\": \"media_player.ma_\" + old_location\n //\"target_player\": \"media_player.ma_\" + new_location\n }\n};\n\n// DEBUG INFO\nnode.log(`🎵 Transferring: ${old_location} → ${new_location}`);\nmsg.debugInfo = {\n from: old_location,\n to: new_location,\n source: \"media_player.ma_\" + old_location,\n target: \"media_player.ma_\" + new_location,\n timestamp: new Date().toISOString()\n};\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":860,"y":160,"wires":[["service"]]},{"id":"service","type":"api-call-service","z":"2ace8abbbc7448db","name":"Music Assistant","server":"2a12269e.94634a","version":7,"debugenabled":true,"action":"music_assistant.transfer_queue","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"$payload","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":false,"domain":"music_assistant","service":"transfer_queue","x":1040,"y":160,"wires":[["debug"]]},{"id":"debug","type":"debug","z":"2ace8abbbc7448db","name":"Transfer Details","tosidebar":true,"complete":"debugInfo","statusVal":"","statusType":"auto","x":1220,"y":160,"wires":[]},{"id":"2a12269e.94634a","type":"server","name":"Hingham Home","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":true,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]