Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Controllers
  3. Node-RED
  4. Node-Red as Controller

Node-Red as Controller

Scheduled Pinned Locked Moved Node-RED
node-red
54 Posts 17 Posters 48.0k Views 19 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • H humblehacker

    I've used NodeRED for various tasks over the years and it still remains my favorite IOT interface. All the while I've tried at least 5 of the officially supported MS controllers out there and nothing has come close! At present I'm trying Home Assistant but am almost ready to give up and set up my own workflow with NodeRED. There's a blog post at https://crankylinuxuser.net/2015/10/01/idiot-crazy-ways-to-make-iot-simple-and-cheap/ that includes a great example of a MySensors+NodeRED flow along with a spot-on critique of mainstream automation services being marketed at present.

    The only reason I havent just used NodeRED in the past is it would still require other components to truly make a unified home automation service. An ideal scenario IMHO would be something that uses NodeRED as a front-end with something more unified running it.

    crankyC Offline
    crankyC Offline
    cranky
    wrote on last edited by
    #32

    @humblehacker

    Hello! I've not had a chance to update my blog with new updates. I'm busy with converting over my site to a pure node-red backend and being able to push updates via NR on my laptop via clone-flow. But that aside....

    There's currently a regression in the newest serial port node in NR.

    Arduino Nano->SerialGateway->NR->MySensors works with receiving data. However
    Data->MySensors encoder->Serial is currently not working. It's NOT MySensors' fault. If I open up console on Serial gateway and an actuator, I can manually send commands and show that radio does in fact work.

    Where I am at now, is trying to figure out where the node-red-node-serial is in error. I know the recent node.js has caused havoc in the node-red ecosystem, mainly with hardware-to-node modules.

    But I'm glad people are referencing my work thus far :)

    The CrankyLinuxUser (whois for email/phone) if you have any further questions.

    1 Reply Last reply
    0
    • crankyC Offline
      crankyC Offline
      cranky
      wrote on last edited by
      #33

      Ok. I think I finally got to the root of the issue. It's a mixture of "Inject" and mysdecenc errors. Inject mangles "\n" on the string inject node, and mysdecenc doesn't add the proper ending of the payload "\n" to complete the transmission from the gateway to the node.

      I have a flow, and inside it is 2 duplicate paths of the same data. The upper one is a manual MySensors node-red node done with functions, and the lower is using the node-red-contri-mysensors nodes.

      [{"id":"90402c72.682b08","type":"serial-port","z":"ec82138a.7e61d","serialport":"/dev/ttyUSB4","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"cbb9cba0.69cf1","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"500","payloadType":"string","repeat":"","crontab":"","once":false,"x":131,"y":274,"wires":[["7fb75e44.d87738"]]},{"id":"359a983d.9e87d8","type":"debug","z":"ec82138a.7e61d","name":"","active":true,"console":"false","complete":"true","x":800,"y":380,"wires":[]},{"id":"9a892a68.a4d97","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"1000","payloadType":"string","repeat":"","crontab":"","once":false,"x":131,"y":316,"wires":[["7fb75e44.d87738"]]},{"id":"473303a0.d810ec","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"0","payloadType":"string","repeat":"","crontab":"","once":false,"x":129,"y":233,"wires":[["7fb75e44.d87738"]]},{"id":"c84afb59.3425a8","type":"template","z":"ec82138a.7e61d","name":"convert to payload","field":"payload","format":"handlebars","template":"{{nodeId}};{{childSensorId}};{{subType}};{{messageType}};{{ack}};{{payload}}","x":544,"y":270,"wires":[["359a983d.9e87d8","6fc996d1.7babb"]]},{"id":"7fb75e44.d87738","type":"function","z":"ec82138a.7e61d","name":"Manual MySensors","func":"msg.nodeId = 10;\nmsg.childSensorId = 10;\nmsg.subType = 1;\nmsg.messageType = 1;\nmsg.ack = 3;\n\nmsg.payload = msg.payload + \"\\n\" ;\n\nreturn msg;","outputs":1,"noerr":0,"x":332,"y":270,"wires":[["c84afb59.3425a8"]]},{"id":"6fc996d1.7babb","type":"serial out","z":"ec82138a.7e61d","name":"","serial":"90402c72.682b08","x":818,"y":323,"wires":[]},{"id":"98c26eed.2fb63","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"500","payloadType":"string","repeat":"","crontab":"","once":false,"x":136,"y":431,"wires":[["952f68a.e0ff198"]]},{"id":"5d0a69be.2b841","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"1000","payloadType":"string","repeat":"","crontab":"","once":false,"x":136,"y":473,"wires":[["952f68a.e0ff198"]]},{"id":"f32d1e54.bde4b","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"0","payloadType":"string","repeat":"","crontab":"","once":false,"x":134,"y":390,"wires":[["952f68a.e0ff198"]]},{"id":"d3587219.c775c8","type":"mysencap","z":"ec82138a.7e61d","name":"","nodeid":"10","childid":"10","subtype":"3","internal":0,"ack":true,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":478,"y":427,"wires":[["cf568bb2.74a438"]]},{"id":"cf568bb2.74a438","type":"mysdecenc","z":"ec82138a.7e61d","name":"","x":618,"y":427,"wires":[["6fc996d1.7babb","359a983d.9e87d8"]]},{"id":"952f68a.e0ff198","type":"function","z":"ec82138a.7e61d","name":"slash n on payload","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":314,"y":427,"wires":[["d3587219.c775c8"]]}]
      

      You will have to change the nodes to correspond to your actuators as well as your serial port. Aside that, with the appropriate fix, it works well.

      / Off to create my NeoPixel Node

      L 1 Reply Last reply
      0
      • crankyC cranky

        Ok. I think I finally got to the root of the issue. It's a mixture of "Inject" and mysdecenc errors. Inject mangles "\n" on the string inject node, and mysdecenc doesn't add the proper ending of the payload "\n" to complete the transmission from the gateway to the node.

        I have a flow, and inside it is 2 duplicate paths of the same data. The upper one is a manual MySensors node-red node done with functions, and the lower is using the node-red-contri-mysensors nodes.

        [{"id":"90402c72.682b08","type":"serial-port","z":"ec82138a.7e61d","serialport":"/dev/ttyUSB4","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"cbb9cba0.69cf1","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"500","payloadType":"string","repeat":"","crontab":"","once":false,"x":131,"y":274,"wires":[["7fb75e44.d87738"]]},{"id":"359a983d.9e87d8","type":"debug","z":"ec82138a.7e61d","name":"","active":true,"console":"false","complete":"true","x":800,"y":380,"wires":[]},{"id":"9a892a68.a4d97","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"1000","payloadType":"string","repeat":"","crontab":"","once":false,"x":131,"y":316,"wires":[["7fb75e44.d87738"]]},{"id":"473303a0.d810ec","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"0","payloadType":"string","repeat":"","crontab":"","once":false,"x":129,"y":233,"wires":[["7fb75e44.d87738"]]},{"id":"c84afb59.3425a8","type":"template","z":"ec82138a.7e61d","name":"convert to payload","field":"payload","format":"handlebars","template":"{{nodeId}};{{childSensorId}};{{subType}};{{messageType}};{{ack}};{{payload}}","x":544,"y":270,"wires":[["359a983d.9e87d8","6fc996d1.7babb"]]},{"id":"7fb75e44.d87738","type":"function","z":"ec82138a.7e61d","name":"Manual MySensors","func":"msg.nodeId = 10;\nmsg.childSensorId = 10;\nmsg.subType = 1;\nmsg.messageType = 1;\nmsg.ack = 3;\n\nmsg.payload = msg.payload + \"\\n\" ;\n\nreturn msg;","outputs":1,"noerr":0,"x":332,"y":270,"wires":[["c84afb59.3425a8"]]},{"id":"6fc996d1.7babb","type":"serial out","z":"ec82138a.7e61d","name":"","serial":"90402c72.682b08","x":818,"y":323,"wires":[]},{"id":"98c26eed.2fb63","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"500","payloadType":"string","repeat":"","crontab":"","once":false,"x":136,"y":431,"wires":[["952f68a.e0ff198"]]},{"id":"5d0a69be.2b841","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"1000","payloadType":"string","repeat":"","crontab":"","once":false,"x":136,"y":473,"wires":[["952f68a.e0ff198"]]},{"id":"f32d1e54.bde4b","type":"inject","z":"ec82138a.7e61d","name":"","topic":"","payload":"0","payloadType":"string","repeat":"","crontab":"","once":false,"x":134,"y":390,"wires":[["952f68a.e0ff198"]]},{"id":"d3587219.c775c8","type":"mysencap","z":"ec82138a.7e61d","name":"","nodeid":"10","childid":"10","subtype":"3","internal":0,"ack":true,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":478,"y":427,"wires":[["cf568bb2.74a438"]]},{"id":"cf568bb2.74a438","type":"mysdecenc","z":"ec82138a.7e61d","name":"","x":618,"y":427,"wires":[["6fc996d1.7babb","359a983d.9e87d8"]]},{"id":"952f68a.e0ff198","type":"function","z":"ec82138a.7e61d","name":"slash n on payload","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":314,"y":427,"wires":[["d3587219.c775c8"]]}]
        

        You will have to change the nodes to correspond to your actuators as well as your serial port. Aside that, with the appropriate fix, it works well.

        / Off to create my NeoPixel Node

        L Offline
        L Offline
        LeoDesigner
        wrote on last edited by LeoDesigner
        #34

        @cranky
        One small bugfix to your ToString function.

        //msg.payload = msg.payload.toString().replace(/[\n\r]/g, '');
        
        // sometimes we are receiving a several messages in one packet
        // we should spit them and emit one by one
        var outputMsg = [];
        
        msg.payload = msg.payload || '';
        
        msg.payload = msg.payload.toString();
        var parts = msg.payload.split("\n");
        for (var id in parts) {
            var payload = parts[id].replace(/[\n\r]/g, '');
            if (payload.length > 0) {
                outputMsg.push({ 
                    payload: payload, 
                    controller: msg.controller
                });
            }
        }
        
        return [outputMsg];
        
        FotoFieberF 1 Reply Last reply
        0
        • crankyC Offline
          crankyC Offline
          cranky
          wrote on last edited by
          #35

          The flow you are giving feedback on is from @FotoFieber , not I :)

          I was a wee confused, as my flow didn't have a string conversion like that in there. Now, the Router->2d array IP addresses on nodered.org does, but I didn't link that.

          Here's that link: http://flows.nodered.org/flow/9b48db38d8c2bee59367 . If you have a crappy ATT router, you can get a nice list of machines.

          L 1 Reply Last reply
          0
          • crankyC cranky

            The flow you are giving feedback on is from @FotoFieber , not I :)

            I was a wee confused, as my flow didn't have a string conversion like that in there. Now, the Router->2d array IP addresses on nodered.org does, but I didn't link that.

            Here's that link: http://flows.nodered.org/flow/9b48db38d8c2bee59367 . If you have a crappy ATT router, you can get a nice list of machines.

            L Offline
            L Offline
            LeoDesigner
            wrote on last edited by
            #36

            @cranky
            Yep - you are right :)
            Does anybody had a problem with retained messages from mqtt broker?
            Seems to me I am receiving only some retained messages from mosquitto - not all of them :( Looks like it's a bug in nodered mqtt or mosquitto.

            1 Reply Last reply
            0
            • L LeoDesigner

              @cranky
              One small bugfix to your ToString function.

              //msg.payload = msg.payload.toString().replace(/[\n\r]/g, '');
              
              // sometimes we are receiving a several messages in one packet
              // we should spit them and emit one by one
              var outputMsg = [];
              
              msg.payload = msg.payload || '';
              
              msg.payload = msg.payload.toString();
              var parts = msg.payload.split("\n");
              for (var id in parts) {
                  var payload = parts[id].replace(/[\n\r]/g, '');
                  if (payload.length > 0) {
                      outputMsg.push({ 
                          payload: payload, 
                          controller: msg.controller
                      });
                  }
              }
              
              return [outputMsg];
              
              FotoFieberF Offline
              FotoFieberF Offline
              FotoFieber
              Hardware Contributor
              wrote on last edited by
              #37

              @LeoDesigner

              Thx for the bugfix. I have observed this problem on some occations but it didn't hurt too much. :) Glad you found the bug.

              1 Reply Last reply
              0
              • crankyC Offline
                crankyC Offline
                cranky
                wrote on last edited by
                #38

                @hek As a meta-discussion, would you be so kind as to create a Node-Red Controller Subcategory?

                Since Rasberry-Pi's recent addition to Raspbian including NR on all installs, I think we're going to see a lot more questions regarding the nRF and MySensors. And frankly, NR is just amazing :)

                1 Reply Last reply
                1
                • crankyC Offline
                  crankyC Offline
                  cranky
                  wrote on last edited by
                  #39

                  Thank you much, @hek !

                  1 Reply Last reply
                  0
                  • msevM Offline
                    msevM Offline
                    msev
                    wrote on last edited by
                    #40

                    Node-red is great. I'd be interested in entire flows, entire integrations for home automation purposes (ofc with credentials data taken out). So if anyone has something interesting to show please share :D thanks

                    1 Reply Last reply
                    2
                    • F Offline
                      F Offline
                      Fabien
                      wrote on last edited by
                      #41

                      Someone here have a flow working with ACK messages ? And retry feature ? For example 5 retries before failling ?

                      FotoFieberF 1 Reply Last reply
                      0
                      • F Fabien

                        Someone here have a flow working with ACK messages ? And retry feature ? For example 5 retries before failling ?

                        FotoFieberF Offline
                        FotoFieberF Offline
                        FotoFieber
                        Hardware Contributor
                        wrote on last edited by
                        #42

                        @Fabien
                        Please help me understand your requirement.

                        Ack from node to gateway are AFAIK handled by the gateway. So this is not your recquirement.

                        Then you are maybe looking to send messages from node-red to some nodes with the ack flag set and if you don't get the message back within xx seconds you want to have transmitted it again up to n times.

                        Is this your requirement?

                        If yes, what are xx and n?

                        gohanG 1 Reply Last reply
                        0
                        • F Offline
                          F Offline
                          Fabien
                          wrote on last edited by
                          #43

                          Yes my requierement is to send ACK from node-red controller, wait 1s for the message back from the node and send it 5 times. If it's not ok I let the swtich (only example, it can be another actuator) in the last state. For only one message it's quite easy but when you want to handle multiple message (and sometimes the same command), it's more difficult to handle the queue correctly.

                          1 Reply Last reply
                          0
                          • FotoFieberF FotoFieber

                            @Fabien
                            Please help me understand your requirement.

                            Ack from node to gateway are AFAIK handled by the gateway. So this is not your recquirement.

                            Then you are maybe looking to send messages from node-red to some nodes with the ack flag set and if you don't get the message back within xx seconds you want to have transmitted it again up to n times.

                            Is this your requirement?

                            If yes, what are xx and n?

                            gohanG Offline
                            gohanG Offline
                            gohan
                            Mod
                            wrote on last edited by
                            #44

                            @FotoFieber do you have some examples of flows that someone could start from?

                            FotoFieberF 1 Reply Last reply
                            0
                            • gohanG gohan

                              @FotoFieber do you have some examples of flows that someone could start from?

                              FotoFieberF Offline
                              FotoFieberF Offline
                              FotoFieber
                              Hardware Contributor
                              wrote on last edited by
                              #45

                              @gohan
                              Have you seen my controller flow?

                              I have a multi-protocol setup and use sensors from zwave, homegear, netatmo, mysensors, sonoff, mystrom... All the messages are standardised and everything can talk to everything (in theory, wired via node-red). This setup is quite complex but very flexible. If you want to control mysensors-devices only, this may be to complicated.

                              Warning: following code was not intended for general usage by anyone else but me. :smile:

                              Here is a shortened excerpt of my generic mapping code:

                              [{"id":"c912e7c5.0e2cf8","type":"function","z":"9496189e.de6028","name":"Map Messages to Generic Messages (HA/)","func":"var mqtt2mqtt = \n{\n// Netatmo\n// - Indoor, TV\n\"netatmo/dashboard_data/Temperature\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"tv\", \"type\":\"S_TEMP\",\"index\":0, \"unit\":\"V_TEMP\"},\n\"netatmo/dashboard_data/Humidity\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"tv\", \"type\":\"S_HUM\",\"index\":0, \"unit\":\"V_HUM\"},\n// Haustüre\n\"homegear/1234-5678-9abc/plain/45/1/STATE\":\n    {\"destination\":\"\",\"payloadTransformation\":\"OpenClose\",\"floor\":1, \"room\":\"entrance\", \"type\":\"S_DOOR\",\"index\":0, \"unit\":\"V_TRIPPED\"},\n\n// Philio Motion/Door\n// Treppenhaus oben\n// 21.0 C\n\"fhem/ZWave/ZWave_SENSOR_NOTIFICATION_13/temperature\":\n    {\"destination\":\"\",\"payloadTransformation\":\"SplitFirst\",\"floor\":1, \"room\":\"staircase\", \"type\":\"S_TEMP\",\"index\":0, \"unit\":\"V_TEMP\"},\n//4 %\n\"fhem/ZWave/ZWave_SENSOR_NOTIFICATION_13/luminance\":\n    {\"destination\":\"\",\"payloadTransformation\":\"SplitFirst\",\"floor\":1, \"room\":\"staircase\", \"type\":\"S_LIGHT_LEVEL\",\"index\":0, \"unit\":\"V_LIGHT_LEVEL\"},\n// MyStrom\n\n\"myStrom/Switch1/watt\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":0, \"room\":\"laundry\", \"type\":\"S_LIGHT\",\"index\":0, \"unit\":\"V_POWER\"},\n\"myStrom/Switch1/on\":\n    {\"destination\":\"\",\"payloadTransformation\":\"False0True1\",\"floor\":0, \"room\":\"laundry\", \"type\":\"S_LIGHT\",\"index\":1, \"unit\":\"V_STATUS\"},\n\n// Heat Befehle des UI\n\"HEAT/bedroom laura\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"bedroom laura\", \"type\":\"S_HEATER\",\"index\":0, \"unit\":\"V_HEATER_SW\", \"append\":\"/SET\"},\n\n\"HEAT/bedroom parents\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"bedroom parents\", \"type\":\"S_HEATER\",\"index\":0, \"unit\":\"V_HEATER_SW\", \"append\":\"/SET\"},\n\n// Temp/Hum Stube\n\"MYS-NODERED/2/167/1/V_TEMP\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"living room\", \"type\":\"S_TEMP\",\"index\":0, \"unit\":\"V_TEMP\"},\n\"MYS-NODERED/2/167/2/V_HUM\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"living room\", \"type\":\"S_HUM\",\"index\":0, \"unit\":\"V_HUM\"},\n\"MYS-NODERED/2/167/0/V_LEVEL\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"living room\", \"type\":\"S_AIR_QUALITY\",\"index\":0, \"unit\":\"MM_PPM\"},\n // Temp/Hum/CO2 Badezimmer\n\"MYS-NODERED/2/15/1/V_TEMP\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"bathroom\", \"type\":\"S_TEMP\",\"index\":0, \"unit\":\"V_TEMP\"},\n\"MYS-NODERED/2/15/2/V_HUM\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"bathroom\", \"type\":\"S_HUM\",\"index\":0, \"unit\":\"V_HUM\"},\n\"MYS-NODERED/2/15/0/V_LEVEL\":\n    {\"destination\":\"\",\"payloadTransformation\":\"\",\"floor\":1, \"room\":\"bathroom\", \"type\":\"S_AIR_QUALITY\",\"index\":0, \"unit\":\"MM_PPM\"},\n\n};\n\n\nfunction payloadTransformation(payload, transformation) {\n    if (transformation == \"OnOff\") {\n\t\tif (payload === 0) {\n\t\t\tpayload = 'OFF';\n\t\t} \n\t\telse\n\t\t{\n\t\t\tpayload = 'ON';\n\t\t}\n\t} else if  (transformation == \"RemoveBrackets\") {\n\t\tpayload = payload.replace(\"[\",\"\");\n\t\tpayload = payload.replace(\"]\",\"\");\n\t} else if  (transformation == \"NetatmoBatteryIndoor\") {\n\t        /* Battery range: 6000 ... 4200 */\n            // const INDOOR_BATTERY_LEVEL_0 = 5640;/*full*/\n            // const INDOOR_BATTERY_LEVEL_1 = 5280;/*high*/\n            // const INDOOR_BATTERY_LEVEL_2 = 4920;/*medium*/\n            // const INDOOR_BATTERY_LEVEL_3 = 4560;/*low*/\n            /* Below 4560: very low */\n            if (payload >= 5640) {\n                payload = 100;\n            } else if (payload < 4560) {\n                payload = 0;\n            } else {\n                payload = 100.0 * (payload - 4560) / (5640 - 4560);\n            }\n\t} else if  (transformation == \"NetatmoBatteryOutdoor\") {\n             /* Battery range: 6000 ... 3600 */\n            // const BATTERY_LEVEL_0 = 5500;/*full*/\n            // const BATTERY_LEVEL_1 = 5000;/*high*/\n            // const BATTERY_LEVEL_2 = 4500;/*medium*/\n            //const BATTERY_LEVEL_3 = 4000;/*low*/\n            /* below 4000: very low */\n            if (payload >= 5500) {\n                payload = 100;\n            } else if (payload < 4000) {\n                payload = 0;\n            } else {\n                payload = 100.0 * (payload - 4000) / (5500 - 4000);\n            }\n\t}  else if  (transformation == \"HomegearBatteryLOWBAT\") {\n        if (payload == '[false]') {\n            payload = 100;\n        } else {\n            payload = 0;\n        }\n\t}  else if  (transformation == \"SplitFirst\") {\n\t    var tokens = payload.split(\" \");\n        payload = tokens[0];\n\t}  else if  (transformation == \"StringMotion\") {\n\t    upper = payload.toUpperCase();\n\t    if (upper.search(\"MOTION\") > -1) {\n\t        payload = 1;\n\t    }\n\t    else\n\t    {\n\t        payload = 0;\n\t    }\n\t}  else if  (transformation == \"False0True1\") {\n\t    payload = payload.replace(\"[\",\"\");\n\t\tpayload = payload.replace(\"]\",\"\");\n\t    upper = payload.toUpperCase();\n\t    if (upper.search(\"FALSE\") > -1) {\n\t        payload = 0;\n\t    }\n\t    else if (upper.search(\"TRUE\") > -1)\n\t    {\n\t        payload = 1;\n\t    }\n\t}  else if  (transformation == \"False1True0\") {\n\t    payload = payload.replace(\"[\",\"\");\n\t\tpayload = payload.replace(\"]\",\"\");\n\t    upper = payload.toUpperCase();\n\t    if (upper.search(\"FALSE\") > -1) {\n\t        payload = 1;\n\t    }\n\t    else if (upper.search(\"TRUE\") > -1)\n\t    {\n\t        payload = 0;\n\t    } if (upper.search(\"0\") > -1) {\n\t        payload = 1;\n\t    }\n\t    else if (upper.search(\"1\") > -1)\n\t    {\n\t        payload = 0;\n\t    }\n\t}  else if  (transformation == \"Off0On1\") {\n\t    upper = payload.toUpperCase();\n\t    if (upper.search(\"OFF\") > -1) {\n\t        payload = 0;\n\t    }\n\t    else\n\t    {\n\t        payload = 1;\n\t    }\n\t}  else if  (transformation == \"StringClosed\") { // 1 wenn nicht closed (open)\n\t    upper = payload.toUpperCase();\n\t    if (upper.search(\"CLOSED\") > -1) {\n\t        payload = 0;\n\t    }\n\t    else\n\t    {\n\t        payload = 1;\n\t    }\n\t} else \tif (transformation == \"OpenClose\") {\n\t\tif (payload == '[true]') {\n\t\t\tpayload = 1;\n\t\t} \n\t\telse\n\t\t{\n\t\t\tpayload = 0;\n\t\t}\n\t}\n\treturn payload;\n}\n\nmapping =  mqtt2mqtt[msg.topic];\n\nif (mapping === undefined) {\n\treturn;\n}\nelse if (mapping.destination === undefined)\n{\n    var outputMsgs = [];\n    for (var j = 0; j < mapping.length; j++){\n        \n        destination = mapping[j].destination;\n        \n        if (destination === \"\") {\n            destination = \"HA/\" + mapping[j].floor + \"/\" + mapping[j].room + \"/\" +  mapping[j].type + \"/\" + mapping[j].index + \"/\" + mapping[j].unit;\n        }\n        \n        //\"floor\":1, \"room\":\"Bathroom\", \"type\":\"S_HUM\",\"index\":0, \"unit\":\"V_HUM\"\n        //\n        var createmsg = { \n                            topic:  destination, \n                            value:  payloadTransformation(msg.payload,mapping[j].payloadTransformation), \n                            floor:  mapping[j].floor,\n                            room:   mapping[j].room,\n                            type:   mapping[j].type,\n                            index:  mapping[j].index,\n                            unit:   mapping[j].unit,\n                            append: mapping[j].append,\n                            timestamp: Date.now(),\n                            source: msg.topic\n        };\n        \n        \n        if(typeof mapping[j].append !== \"undefined\") {\n            createmsg.topic += mapping[j].append; \n        }\n        \n        outputMsgs.push({       topic: createmsg.topic,\n                                payload: createmsg});\n    }\n\n    return [ outputMsgs ];\n}\nelse\n{\n    var outputMsgs = [];\n    \n    destination = mapping.destination;\n    \n    if (destination === \"\") {\n        destination = \"HA/\" + mapping.floor + \"/\" + mapping.room + \"/\" +  mapping.type + \"/\" + mapping.index + \"/\" + mapping.unit;\n    }\n    \n    var createmsg = { \n                        topic:  destination, \n                        value:  payloadTransformation(msg.payload,mapping.payloadTransformation),\n                        floor:  mapping.floor,\n                        room:   mapping.room,\n                        type:   mapping.type,\n                        index:  mapping.index,\n                        unit:   mapping.unit,\n                        append: mapping.append,\n                        timestamp: Date.now(),\n                        source: msg.topic\n    };\n\n      \n    if(typeof mapping.append !== \"undefined\") {\n            createmsg.topic += mapping.append; \n    }\n    \n \n    outputMsgs.push({       topic: createmsg.topic,\n                            payload: createmsg});\n                            \n    return [ outputMsgs ];\n   \n}","outputs":1,"noerr":0,"x":430.81597900390625,"y":368.27081298828125,"wires":[[]]}]
                              

                              I persist all the current values in a global state and use alasql to get values from it.

                              [{"id":"e4db6599.e95a68","type":"mqtt in","z":"82560a8c.4f93a8","name":"HA Messages","topic":"HA/#","qos":"2","broker":"26224260.2d8dde","x":176,"y":68,"wires":[["6c3867ae.e5a808"]]},{"id":"f8f5de85.ce073","type":"debug","z":"82560a8c.4f93a8","name":"","active":false,"console":"false","complete":"true","x":528,"y":70,"wires":[]},{"id":"5bb12e6f.3a271","type":"function","z":"82560a8c.4f93a8","name":"HA State -> context.global.hastate","func":"var hastate = {};\n\nif (context.global.hastate === undefined)\n{\n    context.global.hastate = hastate;\n}\n\nhc = hashcode(msg.topic);\n\nmsg.payload.topichc = hc;\n\ncontext.global.hastate[msg.topic] = msg.payload;\n\nreturn msg;\n\nfunction hashcode(str) {\n  var hash = 0, i, chr, len;\n  if (str.length === 0) return hash;\n  for (i = 0, len = str.length; i < len; i++) {\n    chr   = str.charCodeAt(i);\n    hash  = ((hash << 5) - hash) + chr;\n    hash |= 0; // Convert to 32bit integer\n  }\n  return hash;\n}","outputs":1,"noerr":0,"x":641,"y":126,"wires":[[]]},{"id":"f6c2ddcb.2d25b","type":"comment","z":"82560a8c.4f93a8","name":"Restore State from Mongo","info":"","x":181,"y":193,"wires":[]},{"id":"1b115bf9.64b9f4","type":"inject","z":"82560a8c.4f93a8","name":"Restore context.global.hastate from Mongo","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"x":266.25,"y":242,"wires":[["eaaa6edf.b5414"]]},{"id":"98fa3c0.77ffec8","type":"function","z":"82560a8c.4f93a8","name":"restore context.global.hastate","func":"context.global.hastate = {};\n\nvar erg = {};\n\nfor (var item in msg.payload) {\n    var payload = msg.payload[item];\n    var topic = payload.topic;\n    //delete payload.topic;\n    delete payload._id;\n    payload.topichc = hashcode(topic);\n    erg[topic] = payload;\n}\n\nmsg.payload = erg;\n\ncontext.global.hastate = msg.payload;\n\nreturn msg;\n\nfunction hashcode(str) {\n  var hash = 0, i, chr, len;\n  if (str.length === 0) return hash;\n  for (i = 0, len = str.length; i < len; i++) {\n    chr   = str.charCodeAt(i);\n    hash  = ((hash << 5) - hash) + chr;\n    hash |= 0; // Convert to 32bit integer\n  }\n  return hash;\n}","outputs":1,"noerr":0,"x":1074.25,"y":240.75,"wires":[["a7df8317.f084b","8172bfbb.14412"]]},{"id":"c2eaa629.552f18","type":"mongodb in","z":"82560a8c.4f93a8","mongodb":"135c13e7.1b136c","name":"Status aus Mongo lesen","collection":"STATE","operation":"find","x":807.5,"y":240.75,"wires":[["98fa3c0.77ffec8","304fc7dd.6070a8"]]},{"id":"a7df8317.f084b","type":"debug","z":"82560a8c.4f93a8","name":"","active":false,"console":"false","complete":"false","x":1170.75,"y":126,"wires":[]},{"id":"46b56401.cc231c","type":"debug","z":"82560a8c.4f93a8","name":"","active":true,"console":"false","complete":"false","x":565,"y":539,"wires":[]},{"id":"fcde162a.b0bfe8","type":"inject","z":"82560a8c.4f93a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":143,"y":540,"wires":[["59bf7cc5.978df4"]]},{"id":"59bf7cc5.978df4","type":"function","z":"82560a8c.4f93a8","name":"context.global.hastate","func":"msg.payload = context.global.hastate;\n\nreturn msg;","outputs":1,"noerr":0,"x":367,"y":542,"wires":[["46b56401.cc231c"]]},{"id":"eaaa6edf.b5414","type":"function","z":"82560a8c.4f93a8","name":"limit und skip setzen","func":"msg.limit = 65000;\nmsg.skip = 0;\n\nreturn msg;","outputs":1,"noerr":0,"x":556,"y":243,"wires":[["c2eaa629.552f18"]]},{"id":"8172bfbb.14412","type":"function","z":"82560a8c.4f93a8","name":"HASTATE bereinigen-> älter als 7 Tage","func":"var i=0;\n\nfor (var erg in context.global.hastate) {\n    payload = context.global.hastate[erg];\n    if ((Date.now() - payload.timestamp)>1000*60*60*24*7) {\n        delete context.global.hastate[erg];       \n        i++;\n    }\n}\n\nmsg.payload = i;\n\nreturn msg;","outputs":1,"noerr":0,"x":448,"y":297,"wires":[["c07188b0.618918"]]},{"id":"1e5a496b.e5cdf7","type":"inject","z":"82560a8c.4f93a8","name":"","topic":"","payload":"","payloadType":"date","repeat":"3600","crontab":"","once":false,"x":151,"y":296,"wires":[["8172bfbb.14412"]]},{"id":"c07188b0.618918","type":"debug","z":"82560a8c.4f93a8","name":"","active":true,"console":"false","complete":"false","x":719,"y":297,"wires":[]},{"id":"6c3867ae.e5a808","type":"json","z":"82560a8c.4f93a8","name":"","x":367.5,"y":130,"wires":[["5bb12e6f.3a271","f8f5de85.ce073"]]},{"id":"304fc7dd.6070a8","type":"debug","z":"82560a8c.4f93a8","name":"","active":true,"console":"false","complete":"false","x":918,"y":377,"wires":[]},{"id":"26224260.2d8dde","type":"mqtt-broker","z":"","broker":"192.168.92.5","port":"1883","clientid":"","usetls":false,"verifyservercert":false,"compatmode":false,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"1","willRetain":"false","willPayload":"","birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":""},{"id":"135c13e7.1b136c","type":"mongodb","z":"","hostname":"192.168.92.5","port":"27017","db":"HASTATE","name":"HASTATE"}]
                              
                              1 Reply Last reply
                              0
                              • FotoFieberF Offline
                                FotoFieberF Offline
                                FotoFieber
                                Hardware Contributor
                                wrote on last edited by
                                #46

                                With this standardisation, I can write simple adapters. Here is one for imperihome:

                                [{"id":"83e8531b.e90b4","type":"debug","z":"a5e97fda.4d467","name":"","active":true,"console":"false","complete":"payload","x":851.2857437133789,"y":251.00000286102295,"wires":[]},{"id":"ab451d5a.6cd2e","type":"http in","z":"a5e97fda.4d467","name":"","url":"/LG53/system","method":"get","swaggerDoc":"","x":190.2857437133789,"y":163.00000286102295,"wires":[["bc40a5db.70b1b8"]]},{"id":"7cd541a2.7f6ba","type":"http in","z":"a5e97fda.4d467","name":"","url":"/LG53/devices","method":"get","swaggerDoc":"","x":178.2857437133789,"y":236.00000286102295,"wires":[["fe9ee011.09dfa"]]},{"id":"247f001b.66de7","type":"http in","z":"a5e97fda.4d467","name":"","url":"/LG53/rooms","method":"get","swaggerDoc":"","x":169.2857437133789,"y":313.00000286102295,"wires":[["2ed87d9a.fe1cd2"]]},{"id":"cfc02ef5.b0a42","type":"http response","z":"a5e97fda.4d467","name":"","x":733.2857437133789,"y":194.00000286102295,"wires":[]},{"id":"bc40a5db.70b1b8","type":"function","z":"a5e97fda.4d467","name":"","func":"msg.payload = { \"id\": \"ISS:LG53:03\", \"apiversion\": 1};\nreturn msg;","outputs":1,"noerr":0,"x":431.2857437133789,"y":160.00000286102295,"wires":[["cfc02ef5.b0a42"]]},{"id":"40424d8c.d0dc34","type":"comment","z":"a5e97fda.4d467","name":"Imperihome","info":"","x":171.2857437133789,"y":119.00000286102295,"wires":[]},{"id":"a77d6fd5.c5549","type":"inject","z":"a5e97fda.4d467","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":157.2857437133789,"y":277.00000286102295,"wires":[["2ed87d9a.fe1cd2"]]},{"id":"2ed87d9a.fe1cd2","type":"function","z":"a5e97fda.4d467","name":"rooms from context.global.hastate","func":"var alasql = global.get('alasql');\n\n\nvar ha = context.global.hastate;\nvar disprooms = [\n        {room:'bedroom parents',disp:'Eltern'}, \n        {room:'bedroom laura', disp:'Laura'},\n        {room:'bedroom baba',disp:'Baba'},\n        {room:'living room',disp:'Wohnzimmer'},\n        {room:'backyard',disp:'Garten hinten'},\n        {room:'basement',disp:'Keller'},\n        {room:'bathroom',disp:'Bad'},\n        {room:'entrance',disp:'Eingang'},\n        {room:'kitchen',disp:'Küche'},\n        {room:'laundry',disp:'Waschküche'},\n        {room:'staircase',disp:'Treppenhaus'},\n        {room:'shower',disp:'Dusche'},\n        {room:'toilet',disp:'Gäste WC'},\n        {room:'tv',disp:'Fernsehraum'}\n        ];\n        \n//var res = alasql('SELECT [1]->payload FROM ? WHERE [1]->payload->room=?',[ha, room]);\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, disp.[1]->disp disp FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room ORDER BY 1',[ha,disprooms]);\n\n\n\nvar rooms = [];\n\nfor (var room in res) {\n    rooms.push( \n        {\n            \"id\"    : 'room_' + hashcode(res[room].room).toString(),\n            \"name\"  : res[room].disp || res[room].room\n        }\n    );\n}\n\nvar resp = { \"rooms\": rooms };\n\nmsg.payload = JSON.stringify(resp);\n\n//msg.payload = JSON.stringify(res);\n\n//msg.payload = {\"rooms\": [{ \"id\": \"roomID1\", \"name\": \"Test Room\" }]};\nreturn msg;\n\n\nfunction hashcode(str) {\n  var hash = 0, i, chr, len;\n  if (str.length === 0) return hash;\n  for (i = 0, len = str.length; i < len; i++) {\n    chr   = str.charCodeAt(i);\n    hash  = ((hash << 5) - hash) + chr;\n    hash |= 0; // Convert to 32bit integer\n  }\n  return hash;\n}","outputs":1,"noerr":0,"x":473.2857437133789,"y":287.00000286102295,"wires":[["83e8531b.e90b4","cfc02ef5.b0a42"]]},{"id":"a6a951b8.fedbf","type":"inject","z":"a5e97fda.4d467","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":166.2857437133789,"y":200.00000286102295,"wires":[["fe9ee011.09dfa"]]},{"id":"15947c1c.319ae4","type":"function","z":"a5e97fda.4d467","name":"","func":"var alasql = global.get('alasql');\n\nvar ha = context.global.hastate;\n\nvar device =  Number(msg.req.params.deviceID);\nvar startdate = Number(msg.req.params.startdate);\nvar enddate = Number(msg.req.params.enddate);\n\n\n//var startdate = 1463992263701;\n//var enddate = 1463992263701;\n\nvar topic = alasql('SELECT VALUE ha.[1]->topic FROM ? ha  WHERE ha.[1]->topichc=?',[ha,device]);\n\nmsg.topic = topic;\nmsg.startdate = startdate;\nmsg.enddate = enddate;\n\nreturn msg;","outputs":1,"noerr":0,"x":511.2857437133789,"y":683.000002861023,"wires":[["e65fbae2.f30598"]]},{"id":"7331dd31.45cae4","type":"http in","z":"a5e97fda.4d467","name":"ISS Rest Actions History","url":"/LG53/devices/:deviceID/:paramKey/histo/:startdate/:enddate","method":"get","swaggerDoc":"","x":159.2857437133789,"y":611.000002861023,"wires":[["15947c1c.319ae4"]]},{"id":"8746e45c.4cd538","type":"http response","z":"a5e97fda.4d467","name":"","x":716.2857437133789,"y":534.000002861023,"wires":[]},{"id":"e6416541.255858","type":"inject","z":"a5e97fda.4d467","name":"","topic":"deviceid","payload":"1897446547","payloadType":"str","repeat":"","crontab":"","once":false,"x":319.2857437133789,"y":696.000002861023,"wires":[["15947c1c.319ae4"]]},{"id":"eb3d187d.5eae98","type":"influxdb in","z":"a5e97fda.4d467","influxdb":"ab6501aa.2f69a","name":"Get History from Influx","query":"","x":945.2857437133789,"y":758.000002861023,"wires":[["d55f902c.1a3b4"]]},{"id":"e65fbae2.f30598","type":"function","z":"a5e97fda.4d467","name":"Select History","func":"measurement = msg.topic.split('/').join('.');\n\nmsg.query = \"SELECT time, value FROM /\" + measurement + \"/ WHERE time >= \" + msg.startdate + \"ms AND time <= \" + msg.enddate +\"ms ORDER BY time\";\n\nreturn msg;","outputs":1,"noerr":0,"x":722.2857437133789,"y":760.000002861023,"wires":[["eb3d187d.5eae98","8b54b1c8.95d46"]]},{"id":"c01efb63.763dc8","type":"inject","z":"a5e97fda.4d467","name":"","topic":"deviceid","payload":"1897446547","payloadType":"str","repeat":"","crontab":"","once":false,"x":340.2857437133789,"y":768.000002861023,"wires":[["64f1c1c5.dbb0d"]]},{"id":"64f1c1c5.dbb0d","type":"function","z":"a5e97fda.4d467","name":"","func":"msg.topic = \"HA/0/bedroom baba/S_TEMP/0/V_TEMP\";\n\nmsg.startdate = 1463993343938;\nmsg.enddate = 1464166145880;\n              \nreturn msg;","outputs":1,"noerr":0,"x":529.2857437133789,"y":758.000002861023,"wires":[["e65fbae2.f30598"]]},{"id":"6ca3314f.2e221","type":"debug","z":"a5e97fda.4d467","name":"","active":false,"console":"false","complete":"false","x":1262.285743713379,"y":758.000002861023,"wires":[]},{"id":"8b54b1c8.95d46","type":"debug","z":"a5e97fda.4d467","name":"","active":false,"console":"false","complete":"query","x":955.2857437133789,"y":847.000002861023,"wires":[]},{"id":"d55f902c.1a3b4","type":"function","z":"a5e97fda.4d467","name":"Convert to Imperihome Format","func":"erg = msg.payload[0];\n\nvar resp = [];\n\nfor (var i in erg) {\n    var mesDate = new Date(erg[i].time);\n    \n    resp.push( \n        {\n            \"value\" :  erg[i].value,\n            \"date\"  : mesDate.getTime()\n        }\n    );\n}\n\nmsg.payload = {\"values\": resp };\n\nreturn msg;","outputs":1,"noerr":0,"x":979.2857437133789,"y":634.000002861023,"wires":[["6ca3314f.2e221","8746e45c.4cd538"]]},{"id":"2003094c.594996","type":"debug","z":"a5e97fda.4d467","name":"","active":true,"console":"false","complete":"req.params","x":434.2857437133789,"y":471.00000286102295,"wires":[]},{"id":"7eb92db4.13ccf4","type":"http in","z":"a5e97fda.4d467","name":"ISS Rest Actions","url":"/LG53/devices/:deviceID/action/:actionName/:actionParam","method":"get","swaggerDoc":"","x":129.2857437133789,"y":469.00000286102295,"wires":[["2003094c.594996","70c707e7.138c18"]]},{"id":"70c707e7.138c18","type":"function","z":"a5e97fda.4d467","name":"","func":"var alasql = global.get('alasql');\n\nvar ha = context.global.hastate;\n\nvar device =  Number(msg.req.params.deviceID);\n\nvar topic = alasql('SELECT VALUE ha.[1]->topic FROM ? ha  WHERE ha.[1]->topichc=?',[ha,device]);\n\nvar output = {};\n\noutput.topic = \"imperihome/\"+topic+\"/\" + msg.req.params.actionName;\noutput.payload = msg.req.params.actionParam;\n\nreturn output;","outputs":1,"noerr":0,"x":285.2857437133789,"y":543.000002861023,"wires":[["59c69af0.4ef8e4"]]},{"id":"59c69af0.4ef8e4","type":"debug","z":"a5e97fda.4d467","name":"","active":true,"console":"false","complete":"false","x":455.2857437133789,"y":541.000002861023,"wires":[]},{"id":"fe9ee011.09dfa","type":"function","z":"a5e97fda.4d467","name":"devices from context.global.hastate","func":"var alasql = global.get('alasql');\n\nvar devices = [];\n\n\nvar ha = context.global.hastate;\nvar disprooms = [\n        {room:'bedroom parents',disp:'Eltern'}, \n        {room:'bedroom laura', disp:'Laura'},\n        {room:'bedroom baba',disp:'Baba'},\n        {room:'living room',disp:'Wohnzimmer'},\n        {room:'backyard',disp:'Garten hinten'},\n        {room:'basement',disp:'Keller'},\n        {room:'bathroom',disp:'Bad'},\n        {room:'entrance',disp:'Eingang'},\n        {room:'kitchen',disp:'Küche'},\n        {room:'laundry',disp:'Waschküche'},\n        {room:'staircase',disp:'Treppenhaus'},\n        {room:'shower',disp:'Dusche'},\n        {room:'toilet',disp:'Gäste WC'},\n        {room:'tv',disp:'Fernsehraum'}\n        ];\n        \n\n// Tür/Fenstersensoren\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_DOOR\" ORDER BY 1',[ha,disprooms]);\n\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"FT\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevDoor\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"Tripped\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n// Motion\n//var res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_MOTION\" ORDER BY 1',[ha,disprooms]);\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx, ABS(DATEDIFF(Minute, ha.[1]->`timestamp`,NOW())) minuten FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_MOTION\" ORDER BY 1',[ha,disprooms]);\n\n\nfor (var device in res) {\n    if (res[device].minuten > 15) {\n        motion = 0;    \n    } else\n    {\n        motion = 1;\n    }\n    \n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"MO\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevMotion\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"Tripped\",\"value\": motion, \"graphable\": true}]\n        }\n    );\n}\n\n// Temperatur\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_TEMP\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Temp\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevTemperature\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"value\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n// Feuchtigkeit\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_HUM\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Hyg\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevHygrometry\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"value\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n// CO2\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_AIR_QUALITY\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"CO2\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevCO2\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"value\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n// BARO\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_BARO\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Luftdruck\",\n            \"type\"  : \"DevPressure\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"value\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n// Licht\n\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_LIGHT_LEVEL\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Licht\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevLuminosity\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"value\",\"value\": res[device].wert,\"unit\":\"%\", \"graphable\": true}]\n        }\n    );\n}\n\n// Noise\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_SOUND\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Lärm\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevNoise\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"value\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n// S_LIGHT -> V_POWWER, V_STATUS\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_LIGHT\" AND [1]->`unit` = \"V_STATUS\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Schalter\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevSwitch\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"Status\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\nvar res = alasql('SELECT DISTINCT ha.[1]->room room, ha.[1]->`topichc` srcid, ha.[1]->`value` wert, disp.[1]->disp disp, ha.[1]->`index` idx  FROM ? ha LEFT JOIN ? disp ON ha.[1]->room = disp.[1]->room WHERE [1]->`type` = \"S_LIGHT\" AND [1]->`unit` = \"V_POWER\" ORDER BY 1',[ha,disprooms]);\n\nfor (var device in res) {\n    devices.push( \n        {\n            \"id\"    :  res[device].srcid,\n            \"name\"  : \"Watt\" + res[device].idx + \" \" + (res[device].disp || res[device].room),\n            \"type\"  : \"DevElectricity\", \n            \"room\"  : 'room_' + hashcode(res[device].room).toString(),\n            \"params\": [{\"key\": \"Watts\",\"value\": res[device].wert, \"graphable\": true}]\n        }\n    );\n}\n\n\nvar resp = { \"devices\": devices };\n\nmsg.payload = JSON.stringify(resp);\n\n//msg.payload = JSON.stringify(res);\n\n//msg.payload = {\"rooms\": [{ \"id\": \"roomID1\", \"name\": \"Test Room\" }]};\nreturn msg;\n\n\nfunction hashcode(str) {\n  var hash = 0, i, chr, len;\n  if (str.length === 0) return hash;\n  for (i = 0, len = str.length; i < len; i++) {\n    chr   = str.charCodeAt(i);\n    hash  = ((hash << 5) - hash) + chr;\n    hash |= 0; // Convert to 32bit integer\n  }\n  return hash;\n}","outputs":1,"noerr":0,"x":449,"y":222,"wires":[["cfc02ef5.b0a42"]]},{"id":"ab6501aa.2f69a","type":"influxdb","z":"a5e97fda.4d467","hostname":"127.0.0.1","port":"8086","database":"HA","name":"Storage for HA"}]
                                

                                New sensors appear with this setup automagically in imperihome.

                                1 Reply Last reply
                                0
                                • gohanG Offline
                                  gohanG Offline
                                  gohan
                                  Mod
                                  wrote on last edited by
                                  #47

                                  At the moment I'm just playing around with the dashboard. I'll look at it and for sure I'll let you know 😀

                                  1 Reply Last reply
                                  0
                                  • chisightC Offline
                                    chisightC Offline
                                    chisight
                                    wrote on last edited by
                                    #48

                                    @FotoFieber
                                    I like your approach to a Node Red implementation of a home automation controller for MySensors. I understand that the code has grown to the point where it will no longer fit in a post. Could you please upload your code to your GitHub so that the whole program is visible?
                                    I understand that your code may not be up to date for the latest version but what I've seen of your code has already helped to improve my MySensors 2.3.0 compatible version.

                                    Thank you.

                                    See me on IRC at ircs://freenode:6697/##nodered and ircs://freenode:6697/#mysensors

                                    chisightC 1 Reply Last reply
                                    1
                                    • chisightC chisight

                                      @FotoFieber
                                      I like your approach to a Node Red implementation of a home automation controller for MySensors. I understand that the code has grown to the point where it will no longer fit in a post. Could you please upload your code to your GitHub so that the whole program is visible?
                                      I understand that your code may not be up to date for the latest version but what I've seen of your code has already helped to improve my MySensors 2.3.0 compatible version.

                                      Thank you.

                                      chisightC Offline
                                      chisightC Offline
                                      chisight
                                      wrote on last edited by
                                      #49

                                      FotoFieber has been kind enough to post his Node-Red controller on GitHub at: https://github.com/FotoFieber/MySensorsNodeRedController

                                      The direct link to the code to import is: https://raw.githubusercontent.com/FotoFieber/MySensorsNodeRedController/master/README.md

                                      Thank you very much @FotoFieber !

                                      Once I complete a few of the pieces added from his code, I'll post mine as well but it will be a few weeks as I'm traveling now.

                                      See me on IRC at ircs://freenode:6697/##nodered and ircs://freenode:6697/#mysensors

                                      W 1 Reply Last reply
                                      0
                                      • chisightC chisight

                                        FotoFieber has been kind enough to post his Node-Red controller on GitHub at: https://github.com/FotoFieber/MySensorsNodeRedController

                                        The direct link to the code to import is: https://raw.githubusercontent.com/FotoFieber/MySensorsNodeRedController/master/README.md

                                        Thank you very much @FotoFieber !

                                        Once I complete a few of the pieces added from his code, I'll post mine as well but it will be a few weeks as I'm traveling now.

                                        W Offline
                                        W Offline
                                        wergeld
                                        wrote on last edited by
                                        #50

                                        @chisight I attempted to use this code but node-red would not let me import. Checked the json online and it does not appear to be valid.

                                        W 1 Reply Last reply
                                        0
                                        • W wergeld

                                          @chisight I attempted to use this code but node-red would not let me import. Checked the json online and it does not appear to be valid.

                                          W Offline
                                          W Offline
                                          wergeld
                                          wrote on last edited by
                                          #51

                                          A little clean up in notepad++ and I have a working flow!
                                          I made some modifcations (of course) for my setup. The main one is the ability to get the sensor value type. Initially the code in the Parse node did:

                                          // msg.topic = context.global.MYS.TOPIC_PREFIX + '/' + msg.controller + ' / ' + msg.nodeId + ' / ' + msg.childSensorId + ' / ' + msg.subTypeString;
                                          
                                          
                                           var tokens = msg.topic.split('/');
                                           
                                           msg.rawData = tokens;
                                           if(tokens.length >= 5)
                                           {
                                           msg.controller = parseInt(tokens[1]);
                                           msg.nodeId = parseInt(tokens[2]);
                                           msg.childSensorId = parseInt(tokens[3]);
                                           msg.subTypeString = tokens[4];
                                           msg.subType = context.global.MYS.VNum(msg.subTypeString);
                                           msg.command = 1; // SET
                                           msg.acknowledge = 0; // no ack as default
                                           }
                                          
                                          return msg;
                                          

                                          I modified the msg.subType to use:

                                          msg.subType = context.global.MYS.VString(msg.subTypeString);
                                          

                                          Now to set this up to write to my DB.
                                          Many thanks to @FotoFieber and @chisight

                                          chisightC 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          12

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.0k

                                          Posts


                                          Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular