Chromecast <-> nodered <-> harmony hub remote integration.


  • Admin

    As I have mentioned elsewhere, I have been working on re-implementing a lot of my automation stuff, which now runs entirely in node-red, with a couple of companion hang-arounds to make the system complete.

    The last addition is that I now can control my chromecast with my harmony hub remote (I have a Harmony Elite). Normally this remote can't control chromecasts directly, but with the help of an extra python script, I now have an emulated roku device on my network (which the Harmony is happy to control over WiFI), that emits the "remote" button presses it receives as MQTT topics. This means that I can make node-red flows, that act upon button presses on my harmony remote 🙂

    In addition I have my python chromecast control script that expose my chromecasts as MQTT devices, so that they emit a MQTT message when status changes, and I can send MQTT messages to the chromecast, such as pause / play etc.

    I have chosen to have node-red as a central hub, so I can manipulate message that I receive from the roku, this is because it does not have a separate "pause" functionality, the pause button simply emits "play", and so does the play button. In nodered I keep track on states of the chromecast, if it's in PLAYING state I send pause, otherwise I send play

    the roku implementation can be found on github here, and the chromecastcontrol is likewise on github here

    Control flow that handles play / pause propagation from roku to av center

    [
        {
            "id": "bfa30dc8.1e214",
            "type": "mqtt out",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "topic": "avctrl/in/control",
            "qos": "2",
            "retain": "false",
            "broker": "4798f2b0.5d747c",
            "x": 1120,
            "y": 280,
            "wires": []
        },
        {
            "id": "d40036e7.baedd8",
            "type": "mqtt in",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "topic": "roku/keypress",
            "qos": "2",
            "broker": "4798f2b0.5d747c",
            "x": 770,
            "y": 280,
            "wires": [
                [
                    "e7726249.7e6c"
                ]
            ]
        },
        {
            "id": "e7726249.7e6c",
            "type": "function",
            "z": "d2be3a2a.67d4b8",
            "name": "translate roku",
            "func": "state = global.get('chromestate');\nmsg.payload = msg.payload.toLowerCase();\nif (state == 'PLAYING' && msg.payload == 'play') {\n    msg.payload = 'pause';\n} \nif (msg.payload == 'back') {\n    msg.payload = 'stop';\n}\nreturn msg;",
            "outputs": 1,
            "noerr": 0,
            "x": 940,
            "y": 280,
            "wires": [
                [
                    "bfa30dc8.1e214",
                    "fcfb9705.c45cf8"
                ]
            ]
        },
        {
            "id": "fcfb9705.c45cf8",
            "type": "debug",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "false",
            "x": 1110,
            "y": 240,
            "wires": []
        },
        {
            "id": "cc3b35dc.759cb8",
            "type": "mqtt in",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "topic": "chromecast/+/state",
            "qos": "2",
            "broker": "4798f2b0.5d747c",
            "x": 750,
            "y": 340,
            "wires": [
                [
                    "76b34013.ca6b5"
                ]
            ]
        },
        {
            "id": "76b34013.ca6b5",
            "type": "change",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "rules": [
                {
                    "t": "set",
                    "p": "chromestate",
                    "pt": "global",
                    "to": "payload",
                    "tot": "msg"
                }
            ],
            "action": "",
            "property": "",
            "from": "",
            "to": "",
            "reg": false,
            "x": 960,
            "y": 340,
            "wires": [
                [
                    "f1bbbf89.9581d"
                ]
            ]
        },
        {
            "id": "f1bbbf89.9581d",
            "type": "debug",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "active": false,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "false",
            "x": 1150,
            "y": 340,
            "wires": []
        },
        {
            "id": "4798f2b0.5d747c",
            "type": "mqtt-broker",
            "z": "",
            "broker": "mosquitto",
            "port": "1883",
            "clientid": "nodered-mysensors",
            "usetls": false,
            "compatmode": true,
            "keepalive": "60",
            "cleansession": true,
            "willTopic": "",
            "willQos": "0",
            "willPayload": "",
            "birthTopic": "",
            "birthQos": "0",
            "birthPayload": ""
        }
    ]
    

    And the AV center control flow

    [
        {
            "id": "2c73477.9c149b8",
            "type": "switch",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "property": "payload",
            "propertyType": "msg",
            "rules": [
                {
                    "t": "eq",
                    "v": "volumeup",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "volumedown",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "mute",
                    "vt": "str"
                },
                {
                    "t": "else"
                }
            ],
            "checkall": "false",
            "repair": false,
            "outputs": 4,
            "x": 290,
            "y": 480,
            "wires": [
                [
                    "f5568b5f.898cc8"
                ],
                [
                    "367a93b4.65ee8c"
                ],
                [
                    "c70cb7be.595738"
                ],
                [
                    "fc2bd7be.c40148"
                ]
            ]
        },
        {
            "id": "f5568b5f.898cc8",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Volume UP",
            "server": "56b003cf.93c9bc",
            "activity": "21395657",
            "label": "Chromecast Audio",
            "command": "%7B%22command%22::%22VolumeUp%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008441%22%7D",
            "repeat": "1",
            "x": 490,
            "y": 400,
            "wires": [
                []
            ]
        },
        {
            "id": "367a93b4.65ee8c",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Volume DOWN",
            "server": "56b003cf.93c9bc",
            "activity": "21395657",
            "label": "Chromecast Audio",
            "command": "%7B%22command%22::%22VolumeDown%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008441%22%7D",
            "repeat": "1",
            "x": 500,
            "y": 440,
            "wires": [
                []
            ]
        },
        {
            "id": "1bb38ed7.f57a81",
            "type": "mqtt in",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "topic": "avctrl/in/control",
            "qos": "2",
            "broker": "4798f2b0.5d747c",
            "x": 120,
            "y": 480,
            "wires": [
                [
                    "2c73477.9c149b8",
                    "9b166d59.19dab"
                ]
            ]
        },
        {
            "id": "c70cb7be.595738",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Mute",
            "server": "56b003cf.93c9bc",
            "activity": "21395657",
            "label": "Chromecast TV",
            "command": "%7B%22command%22::%22Mute%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008441%22%7D",
            "repeat": "1",
            "x": 470,
            "y": 480,
            "wires": [
                []
            ]
        },
        {
            "id": "fc2bd7be.c40148",
            "type": "switch",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "property": "avctrl",
            "propertyType": "global",
            "rules": [
                {
                    "t": "eq",
                    "v": "dvd",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "cd",
                    "vt": "str"
                },
                {
                    "t": "cont",
                    "v": "audio",
                    "vt": "str"
                },
                {
                    "t": "cont",
                    "v": "video",
                    "vt": "str"
                }
            ],
            "checkall": "false",
            "repair": false,
            "outputs": 4,
            "x": 470,
            "y": 540,
            "wires": [
                [
                    "25273a45.75e776"
                ],
                [
                    "25273a45.75e776"
                ],
                [
                    "e0cb35b0.2bf4a8"
                ],
                [
                    "fef6e906.107c58"
                ]
            ]
        },
        {
            "id": "e0cb35b0.2bf4a8",
            "type": "change",
            "z": "d2be3a2a.67d4b8",
            "name": "audio",
            "rules": [
                {
                    "t": "change",
                    "p": "topic",
                    "pt": "msg",
                    "from": "avctrl/in",
                    "fromt": "str",
                    "to": "chromecast/audio",
                    "tot": "str"
                }
            ],
            "action": "",
            "property": "",
            "from": "",
            "to": "",
            "reg": false,
            "x": 610,
            "y": 560,
            "wires": [
                [
                    "15cbe8a1.e953e7",
                    "2aadd645.74b1ba"
                ]
            ]
        },
        {
            "id": "fef6e906.107c58",
            "type": "change",
            "z": "d2be3a2a.67d4b8",
            "name": "video",
            "rules": [
                {
                    "t": "change",
                    "p": "topic",
                    "pt": "msg",
                    "from": "avctrl/in",
                    "fromt": "str",
                    "to": "chromecast/cast",
                    "tot": "str"
                }
            ],
            "action": "",
            "property": "",
            "from": "",
            "to": "",
            "reg": false,
            "x": 610,
            "y": 600,
            "wires": [
                [
                    "15cbe8a1.e953e7",
                    "2aadd645.74b1ba"
                ]
            ]
        },
        {
            "id": "15cbe8a1.e953e7",
            "type": "mqtt out",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "topic": "",
            "qos": "2",
            "retain": "false",
            "broker": "4798f2b0.5d747c",
            "x": 770,
            "y": 620,
            "wires": []
        },
        {
            "id": "25273a45.75e776",
            "type": "switch",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "property": "payload",
            "propertyType": "msg",
            "rules": [
                {
                    "t": "eq",
                    "v": "pause",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "play",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "fwd",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "rev",
                    "vt": "str"
                },
                {
                    "t": "eq",
                    "v": "stop",
                    "vt": "str"
                }
            ],
            "checkall": "false",
            "repair": false,
            "outputs": 5,
            "x": 610,
            "y": 500,
            "wires": [
                [
                    "c29005a6.029498"
                ],
                [
                    "aa76e025.eb137"
                ],
                [
                    "b3ccceab.07286"
                ],
                [
                    "a0ecd37f.01d88"
                ],
                [
                    "a73cb364.f49ab"
                ]
            ]
        },
        {
            "id": "c29005a6.029498",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Pause",
            "server": "56b003cf.93c9bc",
            "activity": "20800253",
            "label": "DVD",
            "command": "%7B%22command%22::%22Pause%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008443%22%7D",
            "repeat": "1",
            "x": 770,
            "y": 420,
            "wires": [
                []
            ]
        },
        {
            "id": "aa76e025.eb137",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Play",
            "server": "56b003cf.93c9bc",
            "activity": "20800253",
            "label": "DVD",
            "command": "%7B%22command%22::%22Play%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008443%22%7D",
            "repeat": "1",
            "x": 770,
            "y": 460,
            "wires": [
                []
            ]
        },
        {
            "id": "a73cb364.f49ab",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Stop",
            "server": "56b003cf.93c9bc",
            "activity": "20800253",
            "label": "DVD",
            "command": "%7B%22command%22::%22Stop%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008443%22%7D",
            "repeat": "1",
            "x": 770,
            "y": 580,
            "wires": [
                []
            ]
        },
        {
            "id": "9b166d59.19dab",
            "type": "debug",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "active": false,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "true",
            "x": 290,
            "y": 420,
            "wires": []
        },
        {
            "id": "ff1c1d34.07702",
            "type": "comment",
            "z": "d2be3a2a.67d4b8",
            "name": "MQTT -> control media endpoint",
            "info": "",
            "x": 170,
            "y": 380,
            "wires": []
        },
        {
            "id": "b3ccceab.07286",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Skip fwd",
            "server": "56b003cf.93c9bc",
            "activity": "20800253",
            "label": "DVD",
            "command": "%7B%22command%22::%22ChapterNext%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008443%22%7D",
            "repeat": "1",
            "x": 780,
            "y": 500,
            "wires": [
                []
            ]
        },
        {
            "id": "a0ecd37f.01d88",
            "type": "H command",
            "z": "d2be3a2a.67d4b8",
            "name": "Skip back",
            "server": "56b003cf.93c9bc",
            "activity": "20800253",
            "label": "DVD",
            "command": "%7B%22command%22::%22ChapterPrev%22,%22type%22::%22IRCommand%22,%22deviceId%22::%2237008443%22%7D",
            "repeat": "1",
            "x": 780,
            "y": 540,
            "wires": [
                []
            ]
        },
        {
            "id": "2aadd645.74b1ba",
            "type": "debug",
            "z": "d2be3a2a.67d4b8",
            "name": "",
            "active": true,
            "tosidebar": true,
            "console": false,
            "tostatus": false,
            "complete": "true",
            "x": 980,
            "y": 620,
            "wires": []
        },
        {
            "id": "56b003cf.93c9bc",
            "type": "harmony-server",
            "z": "",
            "name": "Stuen",
            "ip": "192.168.0.66"
        },
        {
            "id": "4798f2b0.5d747c",
            "type": "mqtt-broker",
            "z": "",
            "broker": "mosquitto",
            "port": "1883",
            "clientid": "nodered-mysensors",
            "usetls": false,
            "compatmode": true,
            "keepalive": "60",
            "cleansession": true,
            "willTopic": "",
            "willQos": "0",
            "willPayload": "",
            "birthTopic": "",
            "birthQos": "0",
            "birthPayload": ""
        }
    ]
    

 

383
Online

7.6k
Users

8.5k
Topics

91.2k
Posts