WiiM Player – Einfache Steuerung deines WiiM Pro (Plus)

Was ist der WiiM Pro / Pro Plus?
Der WiiM Pro Plus ist ein sehr kompakter und günstiger Musik-Streamer, den du an aktive Lautsprecher, einen Verstärker oder Bluetooth-Lautsprecher anschließen kannst.
Er ist eine beliebte und deutlich preiswertere Alternative zum Sonos Port und bietet gleichzeitig mehr Anschlussmöglichkeiten (u. a. Optical In, Line In, Coaxial) sowie USB-C-Stromversorgung.

Mit dem WiiM kannst du u. a.:

  • Spotify Connect, Tidal, Qobuz, Deezer, Amazon Music etc. streamen
  • Musik direkt von deinem Handy oder Tablet casten
  • z. B. den Ton von deinem Fernseher/Beamer über deine aktiven Lautsprecher oder Bluetooth-Boxen wiedergeben

Mehr Infos:
www.wiimhome.com

Wozu dient dieser Node-RED-Flow?
Eine einfache, schnelle und zuverlässige Steuerung deines WiiM-Geräts direkt aus dem Node-RED-Dashboard (oder deinem PeKaWay Touch-Display) – ohne dass du jedes Mal die offizielle WiiM Home App öffnen musst.

Was kannst du damit machen?

  • Vorheriger / Nächster Titel
  • Play / Pause
  • Lautstärke regeln (mit Schieberegler)
  • Aktueller Interpret + Titel werden angezeigt
  • Aktuelle Eingangsquelle sehen (Network, Optical, Line In, Bluetooth, …)

Installation – Schritt für Schritt

  1. Schalte deinen WiiM ein
    Schließe deine Lautsprecher an und richte den WiiM komplett über die offizielle WiiM Home App ein. Achte darauf, dass er im selben Netzwerk ist wie dein PeKaWay / Node-RED.

  2. Finde die IP-Adresse deines WiiM
    Öffne die WiiM Home App → gehe zu deinem Gerät → tippe auf das Zahnrad (Einstellungen) → Netzwerkstatus → notiere dir die IP-Adresse (z. B. 192.168.1.123)

  3. Lade den Flow herunter
    Lade die JSON-Datei (wiim-player.json) aus diesem Beitrag / dem Anhang herunter.

  4. Importiere ihn in Node-RED

    • Öffne Node-RED
    • Menü (oben rechts) → Import
    • Klicke auf „Datei zum Import auswählen“
    • Wähle die heruntergeladene .json-Datei aus
    • Bei „Importieren in“ wähle neuer Flow
    • Klicke auf Importieren
  5. Trage deine IP-Adresse ein

    • Es erscheint ein neuer Tab „Player - WiiM“
    • Suche das blaue Knoten-Element „Config WiiM IP“ (meist oben links im Flow)
    • Doppelklicke darauf
    • Im Feld „Funktion“ steht:
      global.set('wiim_ip', '192.168.1.44')

Ersetze ‘192.168.1.44’ durch deine echte IP-Adresse (die Anführungszeichen müssen bleiben!)

Klicke auf Fertig

Deploy

Klicke oben rechts auf Deploy (der rote Knopf)

Fertig! Dein WiiM sollte jetzt im Node-RED-Dashboard erscheinen und lässt sich direkt bedienen.

Hinweise

Kein Album-Cover / Artwork Es wird bewusst kein Cover angezeigt. Das hält die Oberfläche übersichtlich und schnell, verhindert Probleme mit dem lokalen Zertifikat, PeKaWay-Displays und spart Daten.

Kompatibilität Getestet mit WiiM Pro Plus. Es sollte auch mit WiiM Pro, WiiM Mini, WiiM Ultra und WiiM Amp funktionieren – wurde aber noch nicht bei allen ausführlich getestet.

Viel Spaß damit!
Rückmeldungen, Verbesserungsvorschläge sind super willkommen.

Edit: Juhuuu, jetzt geht’s! Ich kann uploaden!

Flow_Wiim_Player_v1_0.json (14.5 KB)

WiiM API

Als neuer User darf ich anscheinend keine Dateien und Links teilen.
Hat jemand eine gute Idee, wie ich die JSON-Datei trotzdem mit euch teilen kann?

Du könntest den Export in die Zwischenahn kopieren, und hier einsetzen

Sorry, du musst auf das Plus klicken und dann auf vorformatierter Text

1 Like
[
    {
        "id": "1985ea40c1c7a8f6",
        "type": "tab",
        "label": "Player - WiiM",
        "disabled": false,
        "info": "WiiM Pro Plus Control via HTTP API\nPolling every 5s for artist/title/volume/state\nCommands: prev, play/resume, pause, next, vol:<0-100>\nNo artwork/cover"
    },
    {
        "id": "95a4155f5eb7883e",
        "type": "comment",
        "z": "1985ea40c1c7a8f6",
        "name": "WiiM Pro Plus",
        "info": "Base URL: https://{wiim_ip}/httpapi.asp?command=\nStatus: getPlayerStatus (JSON)\nMetadata: getMetaInfo (JSON)\nCommands: setPlayerCmd:prev / pause / resume / next / vol:<0-100>\n\nMore api information: https://www.wiimhome.com/pdf/HTTP%20API%20for%20WiiM%20Products.pdf\n\nIP address is configurable via the 'Config WiiM IP' node.\n\n📱 Quick Setup:\n1. Find WiiM IP in your network (e.g., via WiiM app).\n2. Edit \"Config WiiM IP\" node → On Start: global.set('wiim_ip', '192.168.x.x');\n3. Deploy → Done! Works with WiiM Pro/Pro Plus.\n\nWiim Player V1.0 - 01.02.2026 - Run",
        "x": 130,
        "y": 40,
        "wires": []
    },
    {
        "id": "6f931c0d16d8ef05",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Config WiiM IP",
        "func": "global.set('wiim_ip', '192.168.1.44');",
        "outputs": 0,
        "timeout": "",
        "noerr": 0,
        "initialize": "global.set('wiim_ip', '192.168.1.44');",
        "finalize": "",
        "libs": [],
        "x": 140,
        "y": 100,
        "wires": []
    },
    {
        "id": "4eadc4c3841cf2ca",
        "type": "ui_button",
        "z": "1985ea40c1c7a8f6",
        "name": "Previous",
        "group": "f9be0acd304ba0c2",
        "order": 1,
        "width": "1",
        "height": "1",
        "passthru": false,
        "label": "",
        "tooltip": "Previous",
        "color": "#ffffff",
        "bgcolor": "#3ececd",
        "className": "",
        "icon": "skip_previous",
        "payload": "prev",
        "payloadType": "str",
        "topic": "wiim/command",
        "topicType": "str",
        "x": 1200,
        "y": 60,
        "wires": [
            [
                "85af84ac2c3cc02f"
            ]
        ]
    },
    {
        "id": "a980e5c0b2185d91",
        "type": "ui_button",
        "z": "1985ea40c1c7a8f6",
        "name": "Play",
        "group": "f9be0acd304ba0c2",
        "order": 2,
        "width": "2",
        "height": "1",
        "passthru": false,
        "label": "",
        "tooltip": "Play",
        "color": "#ffffff",
        "bgcolor": "#3ececd",
        "className": "",
        "icon": "play_arrow",
        "payload": "resume",
        "payloadType": "str",
        "topic": "wiim/command",
        "topicType": "str",
        "x": 1210,
        "y": 120,
        "wires": [
            [
                "85af84ac2c3cc02f"
            ]
        ]
    },
    {
        "id": "d840a1130a8e78b6",
        "type": "ui_button",
        "z": "1985ea40c1c7a8f6",
        "name": "Pause",
        "group": "f9be0acd304ba0c2",
        "order": 3,
        "width": "2",
        "height": "1",
        "passthru": false,
        "label": "",
        "tooltip": "Pause",
        "color": "#ffffff",
        "bgcolor": "#3ececd",
        "className": "",
        "icon": "pause",
        "payload": "pause",
        "payloadType": "str",
        "topic": "wiim/command",
        "topicType": "str",
        "x": 1210,
        "y": 180,
        "wires": [
            [
                "85af84ac2c3cc02f"
            ]
        ]
    },
    {
        "id": "50c442f711a7aaba",
        "type": "ui_button",
        "z": "1985ea40c1c7a8f6",
        "name": "Next",
        "group": "f9be0acd304ba0c2",
        "order": 4,
        "width": "1",
        "height": "1",
        "passthru": false,
        "label": "",
        "tooltip": "Next",
        "color": "#ffffff",
        "bgcolor": "#3ececd",
        "className": "",
        "icon": "skip_next",
        "payload": "next",
        "payloadType": "str",
        "topic": "wiim/command",
        "topicType": "str",
        "x": 1210,
        "y": 240,
        "wires": [
            [
                "85af84ac2c3cc02f"
            ]
        ]
    },
    {
        "id": "e305d64b4dbccc78",
        "type": "ui_slider",
        "z": "1985ea40c1c7a8f6",
        "name": "Volume",
        "label": "Volume",
        "tooltip": "",
        "group": "f9be0acd304ba0c2",
        "order": 5,
        "width": 0,
        "height": 0,
        "passthru": true,
        "outs": "all",
        "topic": "wiim/volume",
        "topicType": "str",
        "min": 0,
        "max": 100,
        "step": 1,
        "className": "",
        "x": 1200,
        "y": 300,
        "wires": [
            [
                "74dec51c9138c2e2"
            ]
        ]
    },
    {
        "id": "662fff739f796ada",
        "type": "ui_text",
        "z": "1985ea40c1c7a8f6",
        "group": "f9be0acd304ba0c2",
        "order": 6,
        "width": 0,
        "height": 0,
        "name": "Artist",
        "label": "Artist",
        "format": "{{msg.payload.artist || '–'}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 1210,
        "y": 420,
        "wires": []
    },
    {
        "id": "9eb5c7cf506f74f7",
        "type": "ui_text",
        "z": "1985ea40c1c7a8f6",
        "group": "f9be0acd304ba0c2",
        "order": 7,
        "width": 0,
        "height": 0,
        "name": "Song Title",
        "label": "Song",
        "format": "{{msg.payload.title || '–'}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": "",
        "color": "#000000",
        "x": 1200,
        "y": 480,
        "wires": []
    },
    {
        "id": "85af84ac2c3cc02f",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Build WiiM Command",
        "func": "let cmd = '';\n\nswitch (msg.payload) {\n case 'prev':\n cmd = 'setPlayerCmd:prev';\n break;\n case 'resume':\n cmd = 'setPlayerCmd:resume';\n break;\n case 'pause':\n cmd = 'setPlayerCmd:pause';\n break;\n case 'next':\n cmd = 'setPlayerCmd:next';\n break;\n}\n\nif (cmd) {\n msg.url = 'https://' + global.get('wiim_ip') + '/httpapi.asp?command=' + cmd;\n msg.method = 'GET';\n}\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1460,
        "y": 160,
        "wires": [
            [
                "f3473ee8facb06ea"
            ]
        ]
    },
    {
        "id": "74dec51c9138c2e2",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Build Volume Command",
        "func": "let vol = Math.round(msg.payload);\n\n// Send volume to WiiM\nmsg.url = 'https://' + global.get('wiim_ip') + '/httpapi.asp?command=setPlayerCmd:vol:' + vol;\nmsg.method = 'GET';\n\n// Mark the time of last user change (debounce flag)\nglobal.set('wiim_last_vol_change', Date.now());\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1450,
        "y": 300,
        "wires": [
            [
                "f3473ee8facb06ea"
            ]
        ]
    },
    {
        "id": "f3473ee8facb06ea",
        "type": "http request",
        "z": "1985ea40c1c7a8f6",
        "name": "WiiM API Call",
        "method": "GET",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "",
        "tls": "wiim_tls_config",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 1720,
        "y": 300,
        "wires": [
            []
        ]
    },
    {
        "id": "81dea50b7152fedc",
        "type": "inject",
        "z": "1985ea40c1c7a8f6",
        "name": "Poll every 5s",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": true,
        "onceDelay": 0.5,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 140,
        "y": 360,
        "wires": [
            [
                "da321590d20aab72",
                "cff59d37f7dcdf07"
            ]
        ]
    },
    {
        "id": "e4ac843a6f7d99f6",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Update Status (Volume)",
        "func": "let vol = msg.payload.volume || 20;\nlet state = msg.payload.state || 'stopped';\n\n// Ignore poll if user changed volume <15s ago\nif (global.get('wiim_last_vol_change') > Date.now() - 15000) {\n return [null, msg]; // No slider update, but keep other logic\n}\n\n// Sync WiiM → slider\nlet sliderMsg = { payload: vol };\n\nglobal.set('wiim_volume', vol);\nglobal.set('wiim_state', state);\n\nreturn [sliderMsg, msg];",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 930,
        "y": 300,
        "wires": [
            [
                "e305d64b4dbccc78"
            ]
        ]
    },
    {
        "id": "74a5bb1213ae8608",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Update Artist & Song",
        "func": "let artist = msg.payload.metaData.artist || '–';\nlet title = msg.payload.metaData.title || '–';\n\nmsg.payload = { artist: artist, title: title };\n\nreturn [msg, msg]; // first to Artist text, second to Song Title text",
        "outputs": 2,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 920,
        "y": 420,
        "wires": [
            [
                "662fff739f796ada"
            ],
            [
                "9eb5c7cf506f74f7"
            ]
        ]
    },
    {
        "id": "b219fe2c9c4e993c",
        "type": "http request",
        "z": "1985ea40c1c7a8f6",
        "name": "Get Player Status",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "",
        "tls": "wiim_tls_config",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 630,
        "y": 360,
        "wires": [
            [
                "e4ac843a6f7d99f6",
                "e6428184121f1cc0"
            ]
        ]
    },
    {
        "id": "a9aa0ffe297fda80",
        "type": "http request",
        "z": "1985ea40c1c7a8f6",
        "name": "Get Meta Info",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "",
        "tls": "wiim_tls_config",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 640,
        "y": 420,
        "wires": [
            [
                "74a5bb1213ae8608"
            ]
        ]
    },
    {
        "id": "da321590d20aab72",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Build Status URL",
        "func": "msg.url = 'https://' + global.get('wiim_ip') + '/httpapi.asp?command=getPlayerStatus';\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 400,
        "y": 360,
        "wires": [
            [
                "b219fe2c9c4e993c"
            ]
        ]
    },
    {
        "id": "cff59d37f7dcdf07",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Build Metadata URL",
        "func": "msg.url = 'https://' + global.get('wiim_ip') + '/httpapi.asp?command=getMetaInfo';\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 400,
        "y": 420,
        "wires": [
            [
                "a9aa0ffe297fda80"
            ]
        ]
    },
    {
        "id": "e6428184121f1cc0",
        "type": "function",
        "z": "1985ea40c1c7a8f6",
        "name": "Map Current Input",
        "func": "let mode = parseInt(msg.payload.mode || 0);\nlet activeInput = 'Unbekannt';\n\nswitch (mode) {\n case 0:\n activeInput = 'Network / Streaming';\n break;\n case 1:\n activeInput = 'Optical In';\n break;\n case 2:\n activeInput = 'Line In / Coaxial';\n break;\n case 3:\n activeInput = 'Bluetooth';\n break;\n case 31:\n activeInput = 'Ethernet / Network';\n break;\n case 40:\n activeInput = 'Line In';\n break;\n case 41:\n activeInput = 'Bluetooth';\n break;\n case 43:\n activeInput = 'Optical In';\n break;\n default:\n activeInput = 'Unbekannt (Mode ' + mode + ')';\n}\n\nglobal.set('wiim_active_input', activeInput);\n\nmsg.payload = { currentInput: activeInput };\n\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 910,
        "y": 360,
        "wires": [
            [
                "d4334a88d3030ead"
            ]
        ]
    },
    {
        "id": "d4334a88d3030ead",
        "type": "ui_text",
        "z": "1985ea40c1c7a8f6",
        "group": "f9be0acd304ba0c2",
        "order": 11,
        "width": "6",
        "height": "1",
        "name": "Current Input",
        "label": "Current Input",
        "format": "{{msg.payload.currentInput || 'Unbekannt'}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1190,
        "y": 360,
        "wires": []
    },
    {
        "id": "f9be0acd304ba0c2",
        "type": "ui_group",
        "name": "Wiim",
        "tab": "2c8e194fe4fc498b",
        "order": 1,
        "disp": true,
        "width": 6,
        "collapse": false,
        "className": ""
    },
    {
        "id": "wiim_tls_config",
        "type": "tls-config",
        "name": "WiiM Ignore Self-Signed",
        "cert": "",
        "key": "",
        "ca": "",
        "certname": "",
        "keyname": "",
        "caname": "",
        "servername": "",
        "verifyservercert": false,
        "alpnprotocol": ""
    },
    {
        "id": "2c8e194fe4fc498b",
        "type": "ui_tab",
        "name": "Player",
        "icon": "my_library_music",
        "disabled": false,
        "hidden": false
    },
    {
        "id": "f8a167f87891f9f3",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-dashboard": "3.6.6"
        }
    }
]