(Last Updated: November 3, 2020)
For those who registered but didn't received the confirmation email, please send an email to support@smarthome.community with the email you used

node-red Alexa OpenLuup/Vera voice integration


  • Here is a simple integration of OpenLuup/vera device to Alexa via Node-red.

    The speed is fast sub 1 second responses.

    Requirements -
    node-red.
    alexa.
    node-red-contrib-amazon-echo(local Hue devices).
    openluup or Vera (or any controller via http requests).

    Capabilities-
    Binary switch.
    dimming switch.
    rgb switch.
    Run scenes.

    Each alexa device node is configured in the topic of the amazon-echo device node -
    (device number#type of switch)
    bnary - 123#binary.
    dimming - 123#dimming.
    rgb - 123#colour (W/D is default 310 to adjust colour temp add value to end e.g. 123#colour#300
    scene - 123#scene#124 (123 on 124 off. 124 can be omitted).

    Enter the ip of your controller in the http request block.
    Just copy code and import into Node-red

    [
        {
            "id": "de7838ac.ebead",
            "type": "amazon-echo-hub",
            "z": "8659fc6b.981b4",
            "port": "8980",
            "processinput": "0",
            "discovery": true,
            "x": 150,
            "y": 840,
            "wires": [
                [
                    "cd0ae070.e98378",
                    "a605448.899d8b8",
                    "21ca89ff.b0f6ce"
                ]
            ]
        },
        {
            "id": "a605448.899d8b8",
            "type": "amazon-echo-device",
            "z": "8659fc6b.981b4",
            "name": "bedroom four",
            "topic": "199#colour",
            "x": 410,
            "y": 860,
            "wires": [
                [
                    "688830f.c57775"
                ]
            ]
        },
        {
            "id": "21ca89ff.b0f6ce",
            "type": "amazon-echo-device",
            "z": "8659fc6b.981b4",
            "name": "app safe",
            "topic": "164#binary",
            "x": 390,
            "y": 900,
            "wires": [
                [
                    "688830f.c57775"
                ]
            ]
        },
        {
            "id": "cd0ae070.e98378",
            "type": "amazon-echo-device",
            "z": "8659fc6b.981b4",
            "name": "lounge 1",
            "topic": "8#dimming",
            "x": 390,
            "y": 940,
            "wires": [
                [
                    "688830f.c57775"
                ]
            ]
        },
        {
            "id": "688830f.c57775",
            "type": "function",
            "z": "8659fc6b.981b4",
            "name": "",
            "func": "let types = {\n    \"dimming\":[\"urn:upnp-org:serviceId:Dimming1\",\"SetLoadLevelTarget\",\"newLoadlevelTarget\"],\n    \"binary\":[\"urn:upnp-org:serviceId:SwitchPower1\",\"SetTarget\",\"newTargetValue\"],\n    \"scene\":[\"urn:micasaverde-com:serviceId:HomeAutomationGateway1\",\"RunScene\",\"SceneNum\"],\n    \"colour\":[\"urn:micasaverde-com:serviceId:Color1\",{\"tt\":\"SetColor\",\"hs\":\"SetColorRGB\",\"ct\":\"SetColorTemp\"},{\"tt\":\"newColorTarget\",\"hs\":\"newColorRGBTarget\",\"ct\":\"newColorTempTarget\"}] \t\n}\nfunction binaryPayload(device, type, turnOn, payload) {\n    payload.id = \"action\";\n    payload.serviceId = type[0];\n    payload.DeviceNum = device;\n    payload.action = type[1];\n    payload[type[2]] = (turnOn === true ? 1 : 0);\n    payload.message = payload[type[2]];\nreturn payload;\n}\n\nfunction dimmingPayload(device, type, level, payload) {\n    payload.id = \"action\";\n    payload.serviceId = type[0];\n    payload.DeviceNum = device;\n    payload.action = type[1];\n    payload[type[2]] = level;\n    payload.message = level;\nreturn payload;\n}\nfunction scenePayload(device, type, turnOn, payload) {\n    payload.id = \"action\";\n    payload.serviceId = type[0];\n    payload.action = type[1];\n    payload[type[2]] = (turnOn === true ? device[0] : (device[2] || device[0]));\n    payload.message =\"Run Scene \" + payload[type[2]];\nreturn payload;\n}\n\nfunction rgbPayload(device, types, msg, payload) { \n    if(msg.on === true && msg.meta.changes.on === false && msg.meta[\"input\"].on === true){\n        payload =  binaryPayload(device[0], types[\"binary\"], msg.on, {});\n    }else if (msg.meta.changes.percentage && msg.on === true){\n        payload = dimmingPayload(device[0], types[\"dimming\"], msg.percentage, {});\n    }else if (msg.on === true && msg.colormode === \"hs\"){\n        payload.id = \"action\";\n        payload.serviceId = types[\"colour\"][0];\n        payload.DeviceNum = device[0];\n        payload.action = types[\"colour\"][1][\"hs\"];\n        payload[types[\"colour\"][2][\"hs\"]] =  msg.rgb.join(\",\");\n        payload.message = msg.rgb.join(\",\");\n    }else if (msg.on === true && msg.colormode === \"ct\"){\n        let diff = msg.ct - (Number(device[2]) || 310);\n        msg.ct = (diff < 0) ? \"D\" + Math.min(Math.abs(diff * 1.7),255).toFixed() : \"W\" + Math.abs(Math.min((diff * 1.7),255) - 255).toFixed();\n        payload.id = \"action\";\n        payload.serviceId = types[\"colour\"][0];\n        payload.DeviceNum = device[0];\n        payload.action = types[\"colour\"][1][\"ct\"];\n        payload[types[\"colour\"][2][\"ct\"]] = msg.ct;\n        payload.message = msg.ct;\n    }\nreturn payload;\n}\n\nmsg.topic = msg.topic.split(\"#\").map(Function.prototype.call, String.prototype.trim);\nmsg.hold = msg.payload;\nmsg.payload = {};\nlet type = msg.topic[1] || \"binary\";\nif(msg.topic[1] === \"scene\"){\n    msg.payload = scenePayload(msg.topic, types[\"scene\"], msg.on, {});\n}else if (msg.topic[1] === \"binary\" || msg.percentage === 0 || msg.on === false){\n    msg.payload =  binaryPayload(msg.topic[0], types[\"binary\"], msg.on, {});\n}else if(msg.topic[1] ===\"dimming\"){\n    msg.payload = dimmingPayload(msg.topic[0], types[\"dimming\"], msg.percentage, {});\n}else if (msg.topic[1] === \"colour\"){\n    msg.payload = rgbPayload(msg.topic, types, msg, {});\n}\nlet  error = [\"green\", msg.topic[1] + \" | \" + msg.topic[0], msg.payload.message];\ndelete msg.payload.message;\nif (Object.keys(msg.payload).length < 1){\n    error[0] =\"red\";\n    error[2] =\"failed to create payload\";\n}\nnode.status({\"fill\": error[0],\"shape\":\"ring\",\"text\": error[1] + \" | \" + error[2]});\n\nreturn msg;\n",
            "outputs": 1,
            "noerr": 0,
            "initialize": "",
            "finalize": "",
            "x": 590,
            "y": 940,
            "wires": [
                [
                    "680d28ae.8a163"
                ]
            ]
        },
        {
            "id": "680d28ae.8a163",
            "type": "http request",
            "z": "8659fc6b.981b4",
            "name": "Get request",
            "method": "GET",
            "ret": "txt",
            "paytoqs": "query",
            "url": "http://192.168.1.11:3480/data_request",
            "tls": "",
            "persist": false,
            "proxy": "",
            "authType": "",
            "x": 760,
            "y": 1000,
            "wires": [
                [
                    "cb471442.5d60c8"
                ]
            ]
        }
    ]