Node-RED Sonos Plus

Starten von TuneIn mit NDR2 als Sender. Als Button dient ein Fritz Dect 400. Der Taster löst selbst kein Ereignis aus. Stattdessen muss er ständig abgefragt werden. Als auswertbare Information liefert er einen Timestamp zurück, wann seine Taste kurz und wann lang gedrückt wurde.

identifier: "130960008460"
id: "20"
functionbitmask: "32"
fwversion: "04.90"
manufacturer: "AVM"
productname: "FRITZ!DECT 400"
present: "1"
txbusy: "0"
name: "FRITZ!DECT 400 #5"
battery: "100"
batterylow: "0"
button: array[2]
0: object
identifier: "13096 0008460-0"
id: "5000"
name: "FRITZ!DECT 400 #5: kurz"
lastpressedtimestamp: "1607768809"
1: object
identifier: "13096 0008460-9"
id: "5001"
name: "FRITZ!DECT 400 #5: lang"
lastpressedtimestamp: "1607518778"

Die Timestamps haben unterschiedliche Format, der des DECT-Tasters ist im Unix-Format, also Sekunden seit Jan 1st 1970 (UTC). Der Timestamp unter Node-Red ist in Millisekunden!

Beide Timestamps laufen leider auseinander und dass auch noch umso mehr, je länger der Flow läuft.

Der Timestamp lässt sich mit dem aktuellen Timestamp des Systems vergleichen. Wenn der innerhalb der letzte 5 Sekunden lag, gilt die Taster als gerade gedrückt. Anhängig von Zustand vorher wird TuneIn dann gestartet oder gestopot

In einem Function-Node (GetShortPress) wird das ganze ausgewertet:

var taster = context.get('taster')||"off";
var timepressed = parseInt(msg.payload.button[0].lastpressedtimestamp)
var d= new Date();
var actualSeconds = d.getTime()/1000;
var pastSeconds = Math.abs(actualSeconds- timepressed);
if (pastSeconds < 3 && taster === "off"){
   taster = "on"
}
else if (pastSeconds < 2 && taster === "on"){
   taster = "off"
}
context.set('taster',taster);  
msg.payload=taster;
return msg;

Den Sonos-Node befüllt man mit dem Speaker und der ID des Radiosenders. Die Radio ID findet man in der URL auf TuneIn:

https://tunein.com/radio/NDR-2-Niedersachsen-962-s56857/

Hier also s56857.

Der Flow dazu sieht folgendermaßen aus:

node

[
    {
        "id": "f387a91f.d86ea",
        "type": "tab",
        "label": "Starte Sonos TuneIn mit DECT400",
        "disabled": false,
        "info": ""
    },
    {
        "id": "98fc6ef0.8d9fa",
        "type": "sonos-universal",
        "z": "f387a91f.d86ea",
        "confignode": "efde0521.42073",
        "compatibilityMode": false,
        "command": "group.play.tunein",
        "state": "s56857",
        "stateType": "str",
        "name": "",
        "x": 950,
        "y": 660,
        "wires": [
            []
        ]
    },
    {
        "id": "85c2ca66.423348",
        "type": "fritz-thermostat",
        "z": "f387a91f.d86ea",
        "connection": "88740b7e.825fe",
        "name": "Get Device ",
        "action": "getDevice",
        "x": 510,
        "y": 560,
        "wires": [
            [
                "198ebc92.735d7b",
                "7550a250.78c2bc"
            ]
        ]
    },
    {
        "id": "cba470ac.4e0ae8",
        "type": "inject",
        "z": "f387a91f.d86ea",
        "name": "5 seconds timer",
        "topic": "130960008460",
        "payload": "",
        "payloadType": "date",
        "repeat": "5",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 230,
        "y": 560,
        "wires": [
            [
                "85c2ca66.423348"
            ]
        ]
    },
    {
        "id": "198ebc92.735d7b",
        "type": "function",
        "z": "f387a91f.d86ea",
        "name": "GetShortPress",
        "func": "var taster = context.get('taster')||\"off\";\nvar timepressed = parseInt(msg.payload.button[0].lastpressedtimestamp)\nvar d= new Date();\nvar actualSeconds = d.getTime()/1000;\nvar pastSeconds = Math.abs(actualSeconds- timepressed);\nif (pastSeconds < 3 && taster === \"off\"){\n   taster = \"on\"\n}\nelse if (pastSeconds < 2 && taster === \"on\"){\n   taster = \"off\"\n}\ncontext.set('taster',taster);  \nmsg.payload=taster;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 800,
        "y": 560,
        "wires": [
            [
                "ec3dd1e9.3e9508"
            ]
        ]
    },
    {
        "id": "ec3dd1e9.3e9508",
        "type": "rbe",
        "z": "f387a91f.d86ea",
        "name": "",
        "func": "rbe",
        "gap": "",
        "start": "",
        "inout": "out",
        "property": "payload",
        "x": 530,
        "y": 660,
        "wires": [
            [
                "a97623e0.79d288",
                "a83b4cbe.41e178",
                "b7ffd426.9a41e"
            ]
        ]
    },
    {
        "id": "a97623e0.79d288",
        "type": "debug",
        "z": "f387a91f.d86ea",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 820,
        "y": 860,
        "wires": []
    },
    {
        "id": "de82a84f.0b7958",
        "type": "sonos-universal",
        "z": "f387a91f.d86ea",
        "confignode": "efde0521.42073",
        "compatibilityMode": false,
        "command": "group.stop",
        "state": "",
        "stateType": "str",
        "name": "",
        "x": 950,
        "y": 760,
        "wires": [
            []
        ]
    },
    {
        "id": "a83b4cbe.41e178",
        "type": "switch",
        "z": "f387a91f.d86ea",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "on",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 710,
        "y": 660,
        "wires": [
            [
                "98fc6ef0.8d9fa"
            ]
        ]
    },
    {
        "id": "b7ffd426.9a41e",
        "type": "switch",
        "z": "f387a91f.d86ea",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "off",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 760,
        "y": 760,
        "wires": [
            [
                "de82a84f.0b7958"
            ]
        ]
    },
    {
        "id": "7550a250.78c2bc",
        "type": "debug",
        "z": "f387a91f.d86ea",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 680,
        "y": 480,
        "wires": []
    },
    {
        "id": "efde0521.42073",
        "type": "sonos-config",
        "z": "",
        "name": "Sonos1",
        "serialnum": "",
        "ipaddress": "192.168.2.121"
    },
    {
        "id": "88740b7e.825fe",
        "type": "fritz-api",
        "z": "",
        "name": "Fritzbox",
        "host": "192.168.2.1",
        "strictSSL": false
    }
]