• Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. Jan Teunis
    3. Best
    J
    • Profile
    • Following 0
    • Followers 0
    • Topics 6
    • Posts 14
    • Best 1
    • Controversial 0
    • Groups 0

    Best posts made by Jan Teunis

    • Node-RED flow -- EVOK to MQTT to EVOK

      Hey all,

      The following Node-RED flow might be useful to people who like to tinker with home automation and use different systems or multiple Unipi Neuron devices in unison.

      What it does, is take specific data from an MQTT stream of topics and translates it to the EVOK JSON API. This way you can control all the relays of your Unipi Neuron with the MQTT protocol.
      It also announces all changes to the specified MQTT topics for all relay states (when changed) and announces press / long press for all digital inputs on the Unipi Neuron.

      These topics are used:

      • /home/--name-of-neuron--/relay/--number-of-relay--/set [0/1]
      • /home/--name-of-neuron--/relay/--number-of-relay--/state [0/1]
      • /home/--name-of-neuron--/input/--number-of-input--/short/set [0/1]
      • /home/--name-of-neuron--/input/--number-of-input--/short/state [0/1]
      • /home/--name-of-neuron--/input/--number-of-input--/long/set [0/1]
      • /home/--name-of-neuron--/input/--number-of-input--/long/state [0/1]

      I'm currently using 2 Unipi Neuron L203 devices in the same network (this setup could even be used over the internet!) and needed a way for them to talk and listen to commands from my home automation system, which is currently Pimatic.
      In a few weeks I want to expand even more, but with some homemade arduino based setup for outside use, which also communicates over MQTT ;-)

      Anyway, here is a look at my current Node-RED flow, running on the same RaspberryPi as my MQTT broker and Pimatic system.

      0_1536491730161_a3e9c68a-413e-4a81-a369-76a7eb781b6a-image.png

      Here is the code for the flow, just change the settings that are commented.

      [
          {
              "id": "49e50089.02aeb",
              "type": "tab",
              "label": "Flow 1",
              "disabled": false,
              "info": ""
          },
          {
              "id": "21946c18.8d5ba4",
              "type": "websocket in",
              "z": "49e50089.02aeb",
              "name": "EVOK - Neuron 2",
              "server": "",
              "client": "c9e778d4.219068",
              "x": 160,
              "y": 400,
              "wires": [
                  [
                      "d67a87db.929288"
                  ]
              ]
          },
          {
              "id": "d67a87db.929288",
              "type": "json",
              "z": "49e50089.02aeb",
              "name": "",
              "x": 310,
              "y": 400,
              "wires": [
                  [
                      "58898526.d520cc"
                  ]
              ]
          },
          {
              "id": "58898526.d520cc",
              "type": "split",
              "z": "49e50089.02aeb",
              "name": "",
              "splt": "\\n",
              "x": 430,
              "y": 400,
              "wires": [
                  [
                      "c78bc1eb.6df81"
                  ]
              ]
          },
          {
              "id": "2b2f8289.2fdc6e",
              "type": "switch",
              "z": "49e50089.02aeb",
              "name": "",
              "property": "payload.dev",
              "propertyType": "msg",
              "rules": [
                  {
                      "t": "eq",
                      "v": "input",
                      "vt": "str"
                  },
                  {
                      "t": "eq",
                      "v": "relay",
                      "vt": "str"
                  },
                  {
                      "t": "neq",
                      "v": "ai",
                      "vt": "str"
                  }
              ],
              "checkall": "true",
              "repair": false,
              "outputs": 3,
              "x": 750,
              "y": 360,
              "wires": [
                  [
                      "e173eb6.0b37118",
                      "46c95350.2e22fc"
                  ],
                  [
                      "d54243ad.10aad",
                      "43e533dc.c7c6bc"
                  ],
                  []
              ]
          },
          {
              "id": "d54243ad.10aad",
              "type": "debug",
              "z": "49e50089.02aeb",
              "name": "",
              "active": false,
              "tosidebar": true,
              "console": false,
              "tostatus": false,
              "complete": "false",
              "x": 950,
              "y": 400,
              "wires": []
          },
          {
              "id": "43e533dc.c7c6bc",
              "type": "function",
              "z": "49e50089.02aeb",
              "name": "Relay Status to MQTT",
              "func": "newMsg = {};\n\nrelayName = msg.payload.device+\"_relay_\"+msg.payload.circuit;\npreviousRelayState = flow.get(relayName)||0;\nrelayState = msg.payload.value;\nflow.set(relayName,msg.payload.value);\n\nif (relayState != previousRelayState) {\n    newMsg.topic = \"/home/\"+msg.payload.device+\"/relay/\"+msg.payload.circuit+\"/state\";\n    newMsg.payload = msg.payload.value;\n    return [newMsg];\n} else {\n}",
              "outputs": 1,
              "noerr": 0,
              "x": 980,
              "y": 360,
              "wires": [
                  [
                      "bf555b66.8c8698",
                      "547a9c49.66a784"
                  ]
              ]
          },
          {
              "id": "bf555b66.8c8698",
              "type": "debug",
              "z": "49e50089.02aeb",
              "name": "",
              "active": false,
              "tosidebar": true,
              "console": false,
              "tostatus": false,
              "complete": "payload",
              "x": 1230,
              "y": 420,
              "wires": []
          },
          {
              "id": "547a9c49.66a784",
              "type": "mqtt out",
              "z": "49e50089.02aeb",
              "name": "MQTT",
              "topic": "",
              "qos": "",
              "retain": "",
              "broker": "2090ed8f.9d8142",
              "x": 1210,
              "y": 360,
              "wires": []
          },
          {
              "id": "46c95350.2e22fc",
              "type": "debug",
              "z": "49e50089.02aeb",
              "name": "",
              "active": false,
              "tosidebar": true,
              "console": false,
              "tostatus": false,
              "complete": "false",
              "x": 950,
              "y": 280,
              "wires": []
          },
          {
              "id": "e173eb6.0b37118",
              "type": "function",
              "z": "49e50089.02aeb",
              "name": "Input Status to MQTT",
              "func": "newMsg = {};\n\ninputState = msg.payload.value;\ninputPort = msg.payload.device+\"_input_\"+msg.payload.circuit;\n\ninputPressed = inputPort+\"_pressed\";\ntimerLast = inputPort+\"_time\";\ninputTimer = inputPort+\"_timer\"\ninputLongName = inputPort+\"_long\";\ninputShortName = inputPort+\"_short\";\n\nnewMsg.topic = \"/home/\"+msg.payload.device+\"/input/\"+msg.payload.circuit;\n\nprevLongValue = flow.get(inputLongName)||0;\nprevShortValue = flow.get(inputShortName)||0;\n\nvar interval = (750*1); // minimum interval between messages (ms)\nflow.inputTimer = flow.inputTimer || 0;\n\nif (inputState === 1) {\n    var now = Date.now();\n    flow.set(inputTimer,now);\n    flow.set(inputPressed,1);\n}    \n\nif (inputState === 0) {\n\n    if (flow.get(inputPressed) === 1) {\n\n        var now = Date.now();\n        \n        if (now-flow.get(inputTimer) > interval) { // do something on long press\n            flow.set(inputTimer,0); // reset timer\n            \n            if (prevLongValue === 0) {\n                newLongValue = 1;\n                newMsg.topic += \"/long/state\";\n                newMsg.payload = 1;\n            } else {\n                newLongValue = 0;\n                newMsg.topic += \"/long/state\";\n                newMsg.payload = 0;\n            }\n            flow.set(inputLongName, newLongValue);\n            flow.set(inputPressed,0);\n            return [newMsg];\n        } else {\n            flow.set(inputTimer,0);\n            // do something on short press\n            if (prevShortValue === 0) {\n                newShortValue = 1;\n                newMsg.topic += \"/short/state\";\n                newMsg.payload = 1;\n            } else {\n                newShortValue = 0;\n                newMsg.topic += \"/short/state\";\n                newMsg.payload = 0;\n            }\n            flow.set(inputShortName, newShortValue);\n            flow.set(inputPressed,0);\n            return [newMsg];\n        }\n\n    }\n\n    flow.set(inputPressed,0);\n        \n}\n\n\n",
              "outputs": 1,
              "noerr": 0,
              "x": 980,
              "y": 320,
              "wires": [
                  [
                      "b1b92233.807b7",
                      "547a9c49.66a784"
                  ]
              ]
          },
          {
              "id": "b1b92233.807b7",
              "type": "debug",
              "z": "49e50089.02aeb",
              "name": "",
              "active": false,
              "tosidebar": true,
              "console": false,
              "tostatus": false,
              "complete": "false",
              "x": 1230,
              "y": 280,
              "wires": []
          },
          {
              "id": "9965b21f.00a7f",
              "type": "websocket in",
              "z": "49e50089.02aeb",
              "name": "EVOK - Neuron 1",
              "server": "",
              "client": "2e0f8aa6.859726",
              "x": 160,
              "y": 320,
              "wires": [
                  [
                      "5dbca402.a7e41c"
                  ]
              ]
          },
          {
              "id": "57b3c796.390058",
              "type": "mqtt in",
              "z": "49e50089.02aeb",
              "name": "MQTT",
              "topic": "/home/#",
              "qos": "2",
              "broker": "2090ed8f.9d8142",
              "x": 130,
              "y": 160,
              "wires": [
                  [
                      "a8619cff.4b222"
                  ]
              ]
          },
          {
              "id": "a8619cff.4b222",
              "type": "function",
              "z": "49e50089.02aeb",
              "name": "Populate Variables",
              "func": "var output = msg.topic.split(\"/\");\n \nvar device = output[2];\nvar type = output[3];\n\nif (output[3] == \"relay\") {\n\n    var relay = output[4];\n    var mode = output[5];\n    var value = msg.payload;\n\n    node.debug(\"Relay Detected\");\n    return { device, type, relay, mode, value };\n\n} else if (output[3] == \"input\") {\n\n    var input = output[4];\n    var timing = output[5];\n    var mode = output[6];\n    var value = msg.payload;\n\n    node.debug(\"Input Detected\");\n    return { device, type, input, timing, mode, value };\n\n} else {\n    \n    node.debug(\"Nothing Detected\");\n\n}\n\n",
              "outputs": 1,
              "noerr": 0,
              "x": 310,
              "y": 160,
              "wires": [
                  [
                      "688b4e69.f85ea"
                  ]
              ]
          },
          {
              "id": "688b4e69.f85ea",
              "type": "switch",
              "z": "49e50089.02aeb",
              "name": "input / relay",
              "property": "type",
              "propertyType": "msg",
              "rules": [
                  {
                      "t": "eq",
                      "v": "input",
                      "vt": "str"
                  },
                  {
                      "t": "eq",
                      "v": "relay",
                      "vt": "str"
                  }
              ],
              "checkall": "false",
              "repair": false,
              "outputs": 2,
              "x": 510,
              "y": 160,
              "wires": [
                  [
                      "8e08aecc.268c5"
                  ],
                  [
                      "c5b81807.5f0178"
                  ]
              ]
          },
          {
              "id": "c5b81807.5f0178",
              "type": "function",
              "z": "49e50089.02aeb",
              "name": "MQTT to EVOK",
              "func": "newMsg = {};\n\nif (msg.mode == \"set\") {\n\n    relayName = msg.device+\"_relay_\"+msg.relay;\n    previousRelayState = flow.get(relayName)||0;\n    relayState = msg.value;\n    flow.set(relayName,relayState);\n    \n    if (relayState != previousRelayState) {\n        newMsg.relay = msg.relay;\n        newMsg.ip = flow.get(msg.device+\"_IP\");\n        newMsg.value = relayState;\n        newMsg.payload = '{\"value\":\"'+relayState+'\"}';\n        return [newMsg];\n    } else {\n\n    }\n    \n} else if (msg.mode == \"state\") {\n    \n}\n",
              "outputs": 1,
              "noerr": 0,
              "x": 700,
              "y": 180,
              "wires": [
                  [
                      "98ebefac.a9b81"
                  ]
              ]
          },
          {
              "id": "98ebefac.a9b81",
              "type": "http request",
              "z": "49e50089.02aeb",
              "name": "Neuron JSON",
              "method": "POST",
              "ret": "txt",
              "url": "http://{{ip}}:8080/json/relay/{{relay}}",
              "tls": "",
              "x": 900,
              "y": 180,
              "wires": [
                  []
              ],
              "icon": "node-red/bridge.png"
          },
          {
              "id": "7a340aca.03f074",
              "type": "function",
              "z": "49e50089.02aeb",
              "name": "Flow Settings",
              "func": "// -------------------------------------------------------\n//\n//  Every Device needs to be setup with an IP and TYPE\n// \n//  flow.set(\"[DEVICENAME]_IP\",\"[IP]\");\n//  sets the type of the device (EVOK,arduino,...)\n//\n//  flow.set(\"[DEVICENAME]_TYPE\",\"[TYPE]\");\n//  sets the IP number of the device\n//\n// -------------------------------------------------------\n\nflow.set(\"neuron1_IP\",\"10.10.1.6\");\nflow.set(\"neuron1_TYPE\",\"EVOK\");\n\nflow.set(\"neuron2_IP\",\"10.10.1.7\");\nflow.set(\"neuron2_TYPE\",\"EVOK\");\n\nflow.set(\"neuron3_IP\",\"10.10.1.8\");\nflow.set(\"neuron3_TYPE\",\"EVOK\");\n",
              "outputs": 1,
              "noerr": 0,
              "x": 320,
              "y": 120,
              "wires": [
                  []
              ],
              "icon": "node-red/file.png"
          },
          {
              "id": "4ea4bedc.9766d",
              "type": "inject",
              "z": "49e50089.02aeb",
              "name": "Startup",
              "topic": "",
              "payload": "",
              "payloadType": "str",
              "repeat": "",
              "crontab": "",
              "once": true,
              "onceDelay": "0",
              "x": 140,
              "y": 120,
              "wires": [
                  [
                      "7a340aca.03f074"
                  ]
              ]
          },
          {
              "id": "8e08aecc.268c5",
              "type": "function",
              "z": "49e50089.02aeb",
              "name": "INPUT update",
              "func": "if (msg.mode == \"set\") {\n    \n    // generate name for storage\n    inputName = msg.device+\"_input_\"+msg.input+\"_\"+msg.timing;\n    \n    // get new value\n    inputState = msg.value;\n    \n    // store new value\n    flow.set(inputName,inputState);\n    \n}",
              "outputs": 1,
              "noerr": 0,
              "x": 700,
              "y": 140,
              "wires": [
                  []
              ]
          },
          {
              "id": "c78bc1eb.6df81",
              "type": "change",
              "z": "49e50089.02aeb",
              "name": "Set DEVICE",
              "rules": [
                  {
                      "t": "set",
                      "p": "payload.device",
                      "pt": "msg",
                      "to": "neuron2",
                      "tot": "str"
                  }
              ],
              "action": "",
              "property": "",
              "from": "",
              "to": "",
              "reg": false,
              "x": 570,
              "y": 400,
              "wires": [
                  [
                      "2b2f8289.2fdc6e"
                  ]
              ]
          },
          {
              "id": "5dbca402.a7e41c",
              "type": "json",
              "z": "49e50089.02aeb",
              "name": "",
              "x": 310,
              "y": 320,
              "wires": [
                  [
                      "d05e8eb9.6822f"
                  ]
              ]
          },
          {
              "id": "d05e8eb9.6822f",
              "type": "split",
              "z": "49e50089.02aeb",
              "name": "",
              "splt": "\\n",
              "x": 430,
              "y": 320,
              "wires": [
                  [
                      "6f0eebff.be9c74"
                  ]
              ]
          },
          {
              "id": "6f0eebff.be9c74",
              "type": "change",
              "z": "49e50089.02aeb",
              "name": "Set DEVICE",
              "rules": [
                  {
                      "t": "set",
                      "p": "payload.device",
                      "pt": "msg",
                      "to": "neuron1",
                      "tot": "str"
                  }
              ],
              "action": "",
              "property": "",
              "from": "",
              "to": "",
              "reg": false,
              "x": 570,
              "y": 320,
              "wires": [
                  [
                      "2b2f8289.2fdc6e"
                  ]
              ]
          },
          {
              "id": "ab98e297.393d",
              "type": "comment",
              "z": "49e50089.02aeb",
              "name": "List all devices",
              "info": "",
              "x": 320,
              "y": 80,
              "wires": []
          },
          {
              "id": "c24e5aa8.cbe8d8",
              "type": "comment",
              "z": "49e50089.02aeb",
              "name": "Change IP",
              "info": "",
              "x": 140,
              "y": 280,
              "wires": []
          },
          {
              "id": "1ffa1591.b7a49a",
              "type": "comment",
              "z": "49e50089.02aeb",
              "name": "Change DEVICE name",
              "info": "",
              "x": 600,
              "y": 280,
              "wires": []
          },
          {
              "id": "c9e778d4.219068",
              "type": "websocket-client",
              "z": "",
              "path": "ws://--IP-NEURON2--::80/ws",
              "tls": "",
              "wholemsg": "false"
          },
          {
              "id": "2090ed8f.9d8142",
              "type": "mqtt-broker",
              "z": "",
              "name": "",
              "broker": "127.0.0.1",
              "port": "1883",
              "clientid": "node-red",
              "usetls": false,
              "compatmode": true,
              "keepalive": "60",
              "cleansession": true,
              "birthTopic": "home/neuron2",
              "birthQos": "0",
              "birthRetain": "false",
              "birthPayload": "online",
              "closeTopic": "",
              "closePayload": "",
              "willTopic": "",
              "willQos": "0",
              "willPayload": ""
          },
          {
              "id": "2e0f8aa6.859726",
              "type": "websocket-client",
              "z": "",
              "path": "ws://--IP-NEURON1--:80/ws",
              "tls": "",
              "wholemsg": "false"
          }
      ]
      

      Hope someone can do something with this code... or give some hints on how to improve on this?

      posted in Official API - Evok
      J
      Jan Teunis