Navigation

    • Register
    • Login
    • Search
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. cranky
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    cranky

    @cranky

    22
    Reputation
    41
    Posts
    960
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online
    Website crankylinuxuser.net

    cranky Follow

    Best posts made by cranky

    • Neopixel Node, using 1.6.0 Beta

      I've been working on a few different concepts about a new node type, called the "Neopixel Node"! Using 1.6.0 Beta MySensors.

      Initially, I thought it would be easy to port the strandtest code over... I was wrong. The code is all blocking with delay() everywhere. It means that your sent messages to this node won't send. And then, what's the point?

      So I am in the works to make the code as non-blocking as I can make it. So far, I have many functions non-blocking with the exception of the theatre crawling lights. And the delay at most is 150ms.

      I pieced everything together on my controller side with Node-Red. I only wanted a basic shell of connecting functionality, whereas you can easily hook it up to a web gui with a few basic blocks.

      And remember, the code is very rough right now. I'm working on making more functions non-blocking along with adding new patterns and cool ideas. But using Node-Red makes a very quick turn-around time for testing and updating! Perhaps we can get a Node-Red as a Controller forum added?

      V_RGB = give this a hex code. 000000 is off, ff0000 is red
      V_VAR1 = Different modes. 2 is slow rainbow. 3 is fast rainbow. 4 is theater chase after you use a hex code.
      V_VAR2 = Speed control for mode 2 and 3 for V_VAR1

      node_red_neopixels.png

      [Node-Red Flow Code]

      [{"id":"c02382bd.ae5","type":"serial-port","z":"387afd49.a6b0fa","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":true},{"id":"23d05132.32938e","type":"serial out","z":"387afd49.a6b0fa","name":"","serial":"c02382bd.ae5","x":671,"y":298,"wires":[]},{"id":"db668f27.44ac8","type":"mysdecenc","z":"387afd49.a6b0fa","name":"","x":666,"y":217,"wires":[["23d05132.32938e"]]},{"id":"c18b87a6.cc82d8","type":"mysencap","z":"387afd49.a6b0fa","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":415,"y":110,"wires":[["db668f27.44ac8"]]},{"id":"3542cfac.f962d8","type":"mysencap","z":"387afd49.a6b0fa","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":414,"y":313,"wires":[["db668f27.44ac8"]]},{"id":"186b7cdb.c952e3","type":"mysencap","z":"387afd49.a6b0fa","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":420,"y":470,"wires":[["db668f27.44ac8"]]},{"id":"29819ac0.48d326","type":"function","z":"387afd49.a6b0fa","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":277,"y":109,"wires":[["c18b87a6.cc82d8"]]},{"id":"8cfbe481.6b1de8","type":"function","z":"387afd49.a6b0fa","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":286,"y":312,"wires":[["3542cfac.f962d8"]]},{"id":"f40043ae.2a3dd8","type":"function","z":"387afd49.a6b0fa","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":289,"y":469,"wires":[["186b7cdb.c952e3"]]},{"id":"f5a3d9a5.f04d5","type":"inject","z":"387afd49.a6b0fa","name":"Speed9 (slow)","topic":"","payload":"9","payloadType":"string","repeat":"","crontab":"","once":false,"x":115,"y":506,"wires":[["f40043ae.2a3dd8"]]},{"id":"346a22ac.72f7be","type":"inject","z":"387afd49.a6b0fa","name":"Speed0 (fast)","topic":"","payload":"0","payloadType":"string","repeat":"","crontab":"","once":false,"x":111,"y":431,"wires":[["f40043ae.2a3dd8"]]},{"id":"ccdef1a.ef36e1","type":"inject","z":"387afd49.a6b0fa","name":"rainbow","topic":"","payload":"2","payloadType":"string","repeat":"","crontab":"","once":false,"x":113,"y":267,"wires":[["8cfbe481.6b1de8"]]},{"id":"eeaad340.169418","type":"inject","z":"387afd49.a6b0fa","name":"fast rainbow","topic":"","payload":"3","payloadType":"string","repeat":"","crontab":"","once":false,"x":123,"y":303,"wires":[["8cfbe481.6b1de8"]]},{"id":"43c0b3c7.fd6814","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"000000","payloadType":"string","repeat":"","crontab":"","once":false,"x":88,"y":24,"wires":[["29819ac0.48d326"]]},{"id":"24524b50.eb8acc","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"ff0000","payloadType":"string","repeat":"","crontab":"","once":false,"x":87,"y":77,"wires":[["29819ac0.48d326"]]},{"id":"1b069543.32c0ab","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"00ff00","payloadType":"string","repeat":"","crontab":"","once":true,"x":87,"y":117,"wires":[["29819ac0.48d326"]]},{"id":"e789eab3.9a517","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"ffffff","payloadType":"string","repeat":"","crontab":"","once":false,"x":252,"y":23,"wires":[["29819ac0.48d326"]]},{"id":"d912e499.b4cc28","type":"inject","z":"387afd49.a6b0fa","name":"Speed5 (medium)","topic":"","payload":"5","payloadType":"string","repeat":"","crontab":"","once":false,"x":126,"y":471,"wires":[["f40043ae.2a3dd8"]]},{"id":"1087e912.c8ddbf","type":"inject","z":"387afd49.a6b0fa","name":"","topic":"","payload":"0000ff","payloadType":"string","repeat":"","crontab":"","once":false,"x":89,"y":154,"wires":[["29819ac0.48d326"]]},{"id":"2e6a0789.d500b","type":"inject","z":"387afd49.a6b0fa","name":"theater chase","topic":"","payload":"4","payloadType":"string","repeat":"","crontab":"","once":false,"x":128,"y":336,"wires":[["8cfbe481.6b1de8"]]},{"id":"f66f1235.3e7e58","type":"comment","z":"387afd49.a6b0fa","name":"Init solid color before using theater","info":"","x":153,"y":370,"wires":[]},{"id":"afeca932.c1ba68","type":"comment","z":"387afd49.a6b0fa","name":"Hex colors","info":"","x":92,"y":187,"wires":[]}]
      
      

      [Arduino Sketch Code]

      //#define MY_DEBUG
      #define MY_RADIO_NRF24
      #define MY_NODE_ID 9
      #include <SPI.h>
      #include <MySensor.h>
      
      #include <Adafruit_NeoPixel.h>
      #include <avr/power.h>
      Adafruit_NeoPixel strip = Adafruit_NeoPixel(38, 3, NEO_GRB + NEO_KHZ800);
      
      unsigned int requestedMode = 0 ;
      unsigned int requestedSpeed = 0 ;
      unsigned int currentSpeed = 0 ;
      int messageType = 0 ;
      long hexColor = -1 ;
      
      unsigned long previousTime = 0 ;
      int j = 0 ;
      int q = 0 ;
      
      void setup() {
        Serial.begin(115200);
      
        strip.begin();
        strip.show();
        Serial.println("Neopixel Node device ready");
      }
      
      void presentation() {
        sendSketchInfo("Neopixel Node", "1.0");
        present(0, S_RGB_LIGHT, "Makes strip said color", true);
      }
      
      void loop() {
        
        switch (messageType) {
          case (1):
            Serial.print("Hex color override: "); Serial.println(hexColor);
            colorWipe(hexColor);
            messageType = 0 ;
          break;
      
          case (2):
          
            if ( (previousTime + (long) currentSpeed) < millis() ){
              if (requestedMode == 2) { 
                if (j > 256) { j = 0;}
                for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, Wheel((i+j) & 255)) ; strip.show(); } 
                j++;
                if ( (j%255) == 0 ) { Serial.println("Rainbow  completed, continuing");}
              }
                
              if (requestedMode == 3) {
                if (j > 256) { j = 0;}
                for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); strip.show(); }
                j = j + 5; 
                if ( (j%255) == 0 ) { Serial.println("Rainbow cycle completed, continuing");}
              }
      
              if (requestedMode == 4) {
                if (j > 10) { j = 0;}
                if (q > 3) { q = 0;}
                for (int j=0; j<10; j++) {
                  for (q=0; q < 3; q++) {
                    for (int i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, hexColor ); }
                    strip.show();
                    delay(50);
                    for (int i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); }
                  }
                }
              }
              
              previousTime = millis();
            }
          break;
      
          case (3):   // Adjust timing of case 2 using non-blocking code (no DELAYs)
            Serial.print("Case 3 received. Speed set to: "); Serial.print(requestedSpeed * 10); Serial.println(" ms.");
            currentSpeed = requestedSpeed * 10;
            messageType = 2 ;
          break;
        }
      }
      
      
      
      void receive(const MyMessage &message) {
        Serial.println("Message received: ");
      
        if (message.type == V_RGB) { 
          messageType = 1 ;
          String hexstring = message.getString();
          Serial.print("RGB color: "); Serial.println(hexstring);
          hexColor = strtol( &hexstring[0], NULL, 16); 
          }
          
        if (message.type == V_VAR1) { 
          String junkString = message.getString();
          Serial.println(junkString);
          requestedMode = junkString.charAt(0) - 48;
          messageType = 2 ;
          Serial.print("Neo mode: "); Serial.println(requestedMode);
        }
      
        if (message.type == V_VAR2) { // This line is for the speed of said mode
          String junkString = message.getString();
          Serial.println(junkString);
          requestedSpeed = junkString.charAt(0) - 48;
          messageType = 3 ;
          Serial.print("Neo speed: "); Serial.println(requestedSpeed);
        }
      }
      
      
      
      //************* Neopixel subroutines, with DELAYs removed. ***************
      
      
      void rainbowCycle() {
        Serial.println("Rainbow Cycle loop");
        uint16_t i, j;
        for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
          for (i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));}
          strip.show();
        }
      }
      
      void colorWipe(long number) {
        long r = hexColor >> 16;
        long g = hexColor >> 8 & 0xFF;
        long b = hexColor & 0xFF;
        for (uint16_t i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, r,g,b);
          strip.show();
        }
      }
      
      uint32_t Wheel(byte WheelPos) {
        WheelPos = 255 - WheelPos;
        if (WheelPos < 85) {
          return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
        } else if (WheelPos < 170) {
          WheelPos -= 85;
          return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
        } else {
          WheelPos -= 170;
          return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
        }
      }
      
      
      
      posted in My Project
      cranky
      cranky
    • Flow to turn SerialGateway into MQTT-SerialGateway

      After installing and working with Mosquitto, I realized that this was going to be easier than implement a SQlite db. However, I already have a SerialGateway and don't have an i2c/spi ethernet device for my microcontrollers. Not a big deal; I have Node-Red.

      No, why would I want Mosquitto? It's the MQTT broker, and a really good lean one. The configuration sucks, but time for learning, eh? Ideally, instead of having "In-Serial" and "Out-Serial" littered all around in your code, you can have clear MQTT topic subscriptions and topic outputs in your code.

      It also allows you to use other Controllers as well. Let's get started.

      1. Install Mosquitto for your platform.
      2. (optional) Configure Mosquitto for security. Login/pass and generate SSL certs. If this is public facing, you will need LetsEncrypt certs for encrypted Websockets
      3. Node-Red flow:
      [{"id":"72a5a797.020098","type":"mqtt-broker","z":"b2cff5f2.9cc8b","broker":"localhost","port":"8883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":null,"willPayload":"","birthTopic":"","birthQos":"0","birthRetain":null,"birthPayload":""},{"id":"fe37ebc7.c69d68","type":"serial-port","z":"b2cff5f2.9cc8b","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"1d5d1eec.5b3009","type":"debug","z":"b2cff5f2.9cc8b","name":"Serial to MQTT debug","active":false,"console":"false","complete":"true","x":635,"y":48,"wires":[]},{"id":"6c0c081e.aac08","type":"serial in","z":"b2cff5f2.9cc8b","name":"","serial":"fe37ebc7.c69d68","x":99,"y":98,"wires":[["4f1327d4.d482c"]]},{"id":"88f499d1.fae8c","type":"mqtt in","z":"b2cff5f2.9cc8b","name":"","topic":"MySensors/#","broker":"72a5a797.020098","x":115.5,"y":158,"wires":[["b006de82.c402b"]]},{"id":"b006de82.c402b","type":"function","z":"b2cff5f2.9cc8b","name":"convert topic to Serial protocol","func":"msg.topic = msg.topic.replace(\"MySensors\\/\", \"\"); // Gets rid of MySensors preamble\nfor (i=0;i<4;i++){\n    msg.topic = msg.topic.replace(\"\\/\", \";\");\n}\nmsg.payload = msg.topic + \";\" + msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":334,"y":158,"wires":[["3f76ac9e.e553cc","543d809e.d80758"]]},{"id":"3f76ac9e.e553cc","type":"debug","z":"b2cff5f2.9cc8b","name":"MQTT to Serial debug","active":false,"console":"false","complete":"true","x":600,"y":207,"wires":[]},{"id":"543d809e.d80758","type":"serial out","z":"b2cff5f2.9cc8b","name":"","serial":"fe37ebc7.c69d68","x":562,"y":157,"wires":[]},{"id":"f8db4507.4574c8","type":"mqtt out","z":"b2cff5f2.9cc8b","name":"","topic":"To MQTT","qos":"","retain":"","broker":"72a5a797.020098","x":614,"y":98,"wires":[]},{"id":"4f1327d4.d482c","type":"mysdecenc","z":"b2cff5f2.9cc8b","name":"","x":254,"y":98,"wires":[["4fe1aca3.083e44"]]},{"id":"4fe1aca3.083e44","type":"function","z":"b2cff5f2.9cc8b","name":"Formats MQTT topic","func":"msg.topic = \"MySensors\" + \"/\" + msg.nodeId + \"/\" + msg.childSensorId + \"/\" + msg.messageType + \"/\" + msg.ack + \"/\" + msg.subType;\nreturn msg;","outputs":1,"noerr":0,"x":439,"y":98,"wires":[["f8db4507.4574c8","1d5d1eec.5b3009"]]}]
      

      Citation: The MQTT submission format (along with challenge/response network flow) is NOT documented(on library or serial API page) . This makes any work past basic Library and Serial coding laborious.

      Would be willing to make proper documentation. Given from comments elsewhere, "source is documentation", to which I respectfully disagree.

      Arduino-development/libraries/MySensors/core/MyGatewayTransportMQTTClient.cpp Line #26 has the hint

      // Topic structure: MY_MQTT_PUBLISH_TOPIC_PREFIX/NODE-ID/SENSOR-ID/CMD-TYPE/ACK-FLAG/SUB-TYPE

      This is what it looks like:

      mysensors to mqtt.png

      Now when you proceed to inject packets into the MySensors network, you can send data to the appropriate topic or send data directly to the serial port.

      The structure on MQTT that the data is stored is the following:

      MySensors/nodeId/childSensorId/messageType/ack/subType
      And the msg.payload is your data

      Note that MySensors/ is user configurable within this MQTT-SerialGateway. I chose MySensors. You can change this by modifying "Formats MQTT topic" and "Convert Topic to Serial Protocol" and change "MySensors" to the name you want. Don't use spaces. MQTT doesn't always like that.

      This does allow that you can have 2 or more gateways and have different topics for different networks to increase the number of your devices past 256.

      I also have not included the messageType or subType substitutions found on the lists in Serial API. That would have included an extra step if that was stored in MQTT to translate between the messageType(number) and messageType(variable name). Although I may write a quick lookup depending on how bad I need that.

      posted in Node-RED
      cranky
      cranky
    • FastLED / Neopixel (ws2811) Node, From Arduino code to Web page (with API)

      This is running Dev 1.6.0 , so beware. You will have to convert it to 1.5.0 if you aren't running crazy like me!

      Edited: There was a bug in the code where it had an unroutable IP address along with a script hosted at Google. Fixed.

      Arduino Neopixel Node code

      //#define MY_DEBUG
      #define MY_RADIO_NRF24
      #define MY_NODE_ID 9
      #include <SPI.h>
      #include <MySensor.h>
      
      #include <Adafruit_NeoPixel.h>
      #include <avr/power.h>
      Adafruit_NeoPixel strip = Adafruit_NeoPixel(38, 3, NEO_GRB + NEO_KHZ800);
      
      unsigned int requestedMode = 0 ;
      unsigned int requestedSpeed = 0 ;
      unsigned int currentSpeed = 0 ;
      int messageType = 0 ;
      long hexColor = -1 ;
      
      unsigned long previousTime = 0 ;
      int j = 0 ;
      int q = 0 ;
      
      void setup() {
        Serial.begin(115200);
      
        strip.begin();
        strip.show();
        Serial.println("Neopixel Node device ready");
      }
      
      void presentation() {
        sendSketchInfo("Neopixel Node", "1.0");
        present(0, S_RGB_LIGHT, "Makes strip said color", true);
      }
      
      void loop() {
        
        switch (messageType) {
          case (1):
            Serial.print("Hex color override: "); Serial.println(hexColor);
            colorWipe(hexColor);
            messageType = 0 ;
          break;
      
          case (2):
          
            if ( (previousTime + (long) currentSpeed) < millis() ){
              if (requestedMode == 2) { 
                if (j > 256) { j = 0;}
                for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, Wheel((i+j) & 255)) ; strip.show(); } 
                j++;
                if ( (j%255) == 0 ) { Serial.println("Rainbow  completed, continuing");}
              }
                
              if (requestedMode == 3) {
                if (j > 256) { j = 0;}
                for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); strip.show(); }
                j = j + 5; 
                if ( (j%255) == 0 ) { Serial.println("Rainbow cycle completed, continuing");}
              }
      
              if (requestedMode == 4) {
                if (j > 10) { j = 0;}
                if (q > 3) { q = 0;}
                for (int j=0; j<10; j++) {
                  for (q=0; q < 3; q++) {
                    for (int i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, hexColor ); }
                    strip.show();
                    delay(50);
                    for (int i=0; i < strip.numPixels(); i=i+3) { strip.setPixelColor(i+q, 0); }
                  }
                }
              }
              
              previousTime = millis();
            }
          break;
      
          case (3):   // Adjust timing of case 2 using non-blocking code (no DELAYs)
            Serial.print("Case 3 received. Speed set to: "); Serial.print(requestedSpeed * 10); Serial.println(" ms.");
            currentSpeed = requestedSpeed * 10;
            messageType = 2 ;
          break;
        }
      }
      
      
      
      void receive(const MyMessage &message) {
        Serial.println("Message received: ");
      
        if (message.type == V_RGB) { 
          messageType = 1 ;
          String hexstring = message.getString();
          Serial.print("RGB color: "); Serial.println(hexstring);
          hexColor = strtol( &hexstring[0], NULL, 16); 
          }
          
        if (message.type == V_VAR1) { 
          String junkString = message.getString();
          Serial.println(junkString);
          requestedMode = junkString.charAt(0) - 48;
          messageType = 2 ;
          Serial.print("Neo mode: "); Serial.println(requestedMode);
        }
      
        if (message.type == V_VAR2) { // This line is for the speed of said mode
          String junkString = message.getString();
          Serial.println(junkString);
          requestedSpeed = junkString.charAt(0) - 48;
          messageType = 3 ;
          Serial.print("Neo speed: "); Serial.println(requestedSpeed);
        }
      }
      
      
      
      //************* Neopixel subroutines, with DELAYs removed. ***************
      
      
      void rainbowCycle() {
        Serial.println("Rainbow Cycle loop");
        uint16_t i, j;
        for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
          for (i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));}
          strip.show();
        }
      }
      
      void colorWipe(long number) {
        long r = hexColor >> 16;
        long g = hexColor >> 8 & 0xFF;
        long b = hexColor & 0xFF;
        for (uint16_t i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, r,g,b);
          strip.show();
        }
      }
      
      uint32_t Wheel(byte WheelPos) {
        WheelPos = 255 - WheelPos;
        if (WheelPos < 85) {
          return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
        } else if (WheelPos < 170) {
          WheelPos -= 85;
          return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
        } else {
          WheelPos -= 170;
          return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
        }
      }
      
      

      Node-Red Neopixel Node subroutine
      neopixel subroutine.png

      [{"id":"5bb468f1.8ac468","type":"subflow","name":"Neopixel Node","info":"","in":[{"x":27,"y":212,"wires":[{"id":"b168409e.83cfa"}]}],"out":[{"x":721,"y":215,"wires":[{"id":"18fb6ecc.c732b9","port":0}]}]},{"id":"18fb6ecc.c732b9","type":"mysdecenc","z":"5bb468f1.8ac468","name":"","x":608,"y":214,"wires":[[]]},{"id":"d4cbf034.7f9f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":453,"y":175,"wires":[["18fb6ecc.c732b9"]]},{"id":"f841fa59.3ad42","type":"mysencap","z":"5bb468f1.8ac468","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":446,"y":211,"wires":[["18fb6ecc.c732b9"]]},{"id":"43e75cfc.4fd6f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":451,"y":248,"wires":[["18fb6ecc.c732b9"]]},{"id":"78baceb2.c1add","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":315,"y":174,"wires":[["d4cbf034.7f9f4"]]},{"id":"4aa5e51d.b8370c","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":318,"y":210,"wires":[["f841fa59.3ad42"]]},{"id":"fdfcef4c.e51f8","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":247,"wires":[["43e75cfc.4fd6f4"]]},{"id":"b168409e.83cfa","type":"function","z":"5bb468f1.8ac468","name":"","func":"var hexcolor = msg.payload.hexcolor;\nvar mode = msg.payload.mode;\nvar speed = msg.payload.speed;\n\nif (hexcolor !== undefined ){  // Pass the hexcolor down the path\n    msg.payload = hexcolor ;\n    return [msg, null, null];\n}\n\nif (mode !== undefined ){  // Pass the pattern mode down the path\n    msg.payload = mode ;\n    return [null, msg, null];\n}\n\nif (speed !== undefined ){  // Pass the speed down the path\n    msg.payload = speed ;\n    return [null, null, msg];\n}","outputs":"3","noerr":0,"x":166,"y":211,"wires":[["78baceb2.c1add"],["4aa5e51d.b8370c"],["fdfcef4c.e51f8"]]},{"id":"e2669ab0.c9db9","type":"subflow:5bb468f1.8ac468","z":"395349b4.bbb1be","name":"","x":529,"y":263,"wires":[["d34e424a.c3ba6"]]}]
      

      Node-Red Neopixel Web API
      Neopixel Web API.png

      [{"id":"57fddc52.c8549c","type":"serial-port","z":"395349b4.bbb1be","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":false},{"id":"5bb468f1.8ac468","type":"subflow","name":"Neopixel Node","info":"","in":[{"x":27,"y":212,"wires":[{"id":"b168409e.83cfa"}]}],"out":[{"x":721,"y":215,"wires":[{"id":"18fb6ecc.c732b9","port":0}]}]},{"id":"18fb6ecc.c732b9","type":"mysdecenc","z":"5bb468f1.8ac468","name":"","x":608,"y":214,"wires":[[]]},{"id":"d4cbf034.7f9f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Solid RGB set","nodeid":"9","childid":0,"subtype":"40","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":453,"y":175,"wires":[["18fb6ecc.c732b9"]]},{"id":"f841fa59.3ad42","type":"mysencap","z":"5bb468f1.8ac468","name":"Mode Call","nodeid":"9","childid":0,"subtype":"24","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":446,"y":211,"wires":[["18fb6ecc.c732b9"]]},{"id":"43e75cfc.4fd6f4","type":"mysencap","z":"5bb468f1.8ac468","name":"Speed Call","nodeid":"9","childid":0,"subtype":"25","internal":0,"ack":false,"msgtype":"1","presentation":false,"presentationtype":0,"presentationtext":"","fullpresentation":false,"firmwarename":"","firmwareversion":"","x":451,"y":248,"wires":[["18fb6ecc.c732b9"]]},{"id":"78baceb2.c1add","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":315,"y":174,"wires":[["d4cbf034.7f9f4"]]},{"id":"4aa5e51d.b8370c","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":318,"y":210,"wires":[["f841fa59.3ad42"]]},{"id":"fdfcef4c.e51f8","type":"function","z":"5bb468f1.8ac468","name":"slash n","func":"msg.payload = msg.payload + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":320,"y":247,"wires":[["43e75cfc.4fd6f4"]]},{"id":"b168409e.83cfa","type":"function","z":"5bb468f1.8ac468","name":"","func":"var hexcolor = msg.payload.hexcolor;\nvar mode = msg.payload.mode;\nvar speed = msg.payload.speed;\n\nif (hexcolor !== undefined ){  // Pass the hexcolor down the path\n    msg.payload = hexcolor ;\n    return [msg, null, null];\n}\n\nif (mode !== undefined ){  // Pass the pattern mode down the path\n    msg.payload = mode ;\n    return [null, msg, null];\n}\n\nif (speed !== undefined ){  // Pass the speed down the path\n    msg.payload = speed ;\n    return [null, null, msg];\n}","outputs":"3","noerr":0,"x":166,"y":211,"wires":[["78baceb2.c1add"],["4aa5e51d.b8370c"],["fdfcef4c.e51f8"]]},{"id":"944f576d.f793c8","type":"http in","z":"395349b4.bbb1be","name":"","url":"/neopixel","method":"get","swaggerDoc":"","x":84,"y":182,"wires":[["f7981706.1d0b08"]]},{"id":"512f4e11.a571b8","type":"template","z":"395349b4.bbb1be","name":"Prints data ","field":"payload","format":"handlebars","template":"Hexcolor: {{payload.hexcolor}} \nMode: {{payload.mode}} \nSpeed: {{payload.speed}}","x":528,"y":164,"wires":[["98fabd8f.db8f8"]]},{"id":"e2669ab0.c9db9","type":"subflow:5bb468f1.8ac468","z":"395349b4.bbb1be","name":"","x":529,"y":263,"wires":[["d34e424a.c3ba6"]]},{"id":"98fabd8f.db8f8","type":"http response","z":"395349b4.bbb1be","name":"","x":731,"y":164,"wires":[]},{"id":"2e9eb2d7.d49bfe","type":"debug","z":"395349b4.bbb1be","name":"","active":true,"console":"false","complete":"false","x":536,"y":73,"wires":[]},{"id":"5b91c6df.ea9e18","type":"http in","z":"395349b4.bbb1be","name":"","url":"/neopixel","method":"post","swaggerDoc":"","x":82,"y":145,"wires":[["f7981706.1d0b08"]]},{"id":"9c565a2d.52db08","type":"comment","z":"395349b4.bbb1be","name":"Valid commands ~readme~","info":"hexcolor:000000~ffffff\n    First 2 are red, second 2 are green, last 2 are blue. \n    Just like standard HTML hexcolors without #\nmode:2~4\n    2 is slow rainbow\n    3 is fast rainbow\n    4 is theater chase. Must set a hexcolor before doing this\nspeed:0~9\n    0 is fastest, as 0 ms (0*10 ms) per loop\n    9 is slowest, as 90 ms (9*10 ms) per loop","x":124,"y":266,"wires":[]},{"id":"d34e424a.c3ba6","type":"serial out","z":"395349b4.bbb1be","name":"","serial":"57fddc52.c8549c","x":743,"y":263,"wires":[]},{"id":"f7981706.1d0b08","type":"function","z":"395349b4.bbb1be","name":"Combine Post/Get","func":"return msg;","outputs":1,"noerr":0,"x":298,"y":163,"wires":[["2e9eb2d7.d49bfe","512f4e11.a571b8","e2669ab0.c9db9"]]}]
      

      Node-Red Neopixel Web interface
      Neopixel Node Web Interface.png

      [{"id":"9d9299f7.ff826","type":"http in","z":"163c57ed.326588","name":"","url":"/index.html","method":"get","swaggerDoc":"","x":173,"y":84,"wires":[["8b6f494e.e388b8"]]},{"id":"8b6f494e.e388b8","type":"template","z":"163c57ed.326588","name":"index.html","field":"payload","format":"html","template":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Neopixel MySensors Configuration</title>\n\t<script src=\"/jquery.min.js\"></script>\n\t\n\t<script type=\"text/javascript\">\n        $(document).ready(function(){\n            $(\"button[name='rainbow']\").click(function(){ $.post(\"/neopixel\",{ mode: \"2\"}, function() {} ); });\n        });\n    </script>\n    \n    <script type=\"text/javascript\">\n        $(document).ready(function(){\n            $(\"button[name='fastrainbow']\").click(function(){ $.post(\"/neopixel\",{ mode: \"3\"}, function() {} ); });\n        });\n    </script>\n    \n    <script type=\"text/javascript\">\n        $(document).ready(function(){\n            $(\"button[name='chase']\").click(function(){ $.post(\"/neopixel\",{ mode: \"4\"}, function() {} ); });\n        });\n    </script>\n    \n    \n\n</head>\n<body>\n\n<div align=\"center\">\n<canvas width=\"550\" height=\"450\" id=\"canvas_picker\"></canvas>\n<div id=\"hex\">HEX: <input type=\"text\"></input></div>\n\n<button name=\"rainbow\">Rainbow</button>\n<button name=\"fastrainbow\">Fast Rainbow</button>\n<button name=\"chase\">Chase</button><br><br>\n0 (fast) <input type=\"range\"  min=\"0\" max=\"10\" onchange=\"emitValue(this.value)\"/> (slow) 10\n</div>\n\n<script type=\"text/javascript\">\n\tvar canvas = document.getElementById('canvas_picker').getContext('2d');\n\n\t// create an image object and get it’s source\n\tvar img = new Image();\n\timg.src = '/colorwheel3.png';\n\n\t// copy the image to the canvas\n\t$(img).load(function(){ canvas.drawImage(img,0,0); });\n\n\t// http://www.javascripter.net/faq/rgbtohex.htm\n\tfunction rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B)}\n\tfunction toHex(n) {\n\t  n = parseInt(n,10);\n\t  if (isNaN(n)) return \"00\";\n\t  n = Math.max(0,Math.min(n,255));\n\t  return \"0123456789ABCDEF\".charAt((n-n%16)/16)  + \"0123456789ABCDEF\".charAt(n%16);\n\t}\n\t$('#canvas_picker').click(function(event){\n\t  // getting user coordinates\n\t  var x = event.pageX - this.offsetLeft;\n\t  var y = event.pageY - this.offsetTop;\n\t  // getting image data and RGB values\n\t  var img_data = canvas.getImageData(x, y, 1, 1).data;\n\t  var R = img_data[0];\n\t  var G = img_data[1];\n\t  var B = img_data[2];  var rgb = R + ',' + G + ',' + B;\n\t  // convert RGB to HEX\n\t  var hex = rgbToHex(R,G,B);\n\t  // making the color the value of the input\n\t  $('#rgb input').val(rgb);\n\t  $('#hex input').val(hex);\n\t  $.post( \"/neopixel\", { hexcolor: hex } );  }\n\t  );\n</script>\n\n<script type=\"text/javascript\">\nfunction emitValue(newValue)\n    { $.post(\"/neopixel\",{ speed: newValue}, function() {} ); }\n</script>\n\n\n</body>\n</html>","x":373,"y":82,"wires":[["bf09f135.39cec8"]]},{"id":"fa066d3a.ea6ff8","type":"http in","z":"163c57ed.326588","name":"","url":"/colorwheel3.png","method":"get","swaggerDoc":"","x":153,"y":134,"wires":[["eafd1d33.cc13b8"]]},{"id":"eafd1d33.cc13b8","type":"file in","z":"163c57ed.326588","name":"","filename":"/home/josh/colorwheel3.png","format":"","x":388,"y":134,"wires":[["bf09f135.39cec8"]]},{"id":"bf09f135.39cec8","type":"http response","z":"163c57ed.326588","name":"","x":638,"y":103,"wires":[]},{"id":"5e929b72.ba9364","type":"http in","z":"163c57ed.326588","name":"","url":"/jquery.min.js","method":"get","swaggerDoc":"","x":175,"y":186,"wires":[["521c39b0.344748"]]},{"id":"521c39b0.344748","type":"file in","z":"163c57ed.326588","name":"","filename":"/home/josh/jquery.min.js","format":"","x":397,"y":184,"wires":[["bf09f135.39cec8"]]}]
      
      

      Location for the jquery.min.js : https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js

      Image for Color-Wheel: colorwheel3.png

      Results:

      screenshot.png

      posted in Node-RED
      cranky
      cranky
    • "DHCP" (I_ID_REQUEST) Handler

      This code is to be used in conjunction of a set up MQTT broker (Mosquitto) and the prior flow listed in "Flow to turn SerialGateway into MQTT-SerialGateway"

      This watches all data coming in from topic MySensors/255/255/3/0/3/ and does a lookup in the DB for a new unused ID. Then it assigns the sensors the ID as well as updating the DB.

      There may be some bugs, as testing this code requires extra work.

      Essentially, in a location in EEprom lives the assigned ID number. So in order to test this, you need to:

      load ClearEEPROM sketch. open Serial console and wait till done.
      Then load a sketch that doesn't have the Node ID set (#define NODE_ID 1.6 and gw.begin(NULL, AUTO) in 1.5)
      Assigning happens once. If messed up, load clearEEPROM and do again

      BIG NOTE: You do need read/write access to file /root/leases.file from whatever user you are running in Node-Red. I chose /root/leases.file because I wanted it easy to find and of indication that it is an important file. You can change it, but make sure to catch all the file nodes that reference to it.

      [{"id":"8e3e8f02.7fd0c","type":"mqtt-broker","z":"63842e72.893f78","broker":"localhost","port":"8883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":null,"willPayload":"","birthTopic":"","birthQos":"0","birthRetain":null,"birthPayload":""},{"id":"778435ae.0d9c4c","type":"mqtt in","z":"63842e72.893f78","name":"Incoming DHCP request","topic":"MySensors/255/255/3/+/3","broker":"8e3e8f02.7fd0c","x":112.5,"y":136,"wires":[["c77f47f6.5dcc1"]]},{"id":"c77f47f6.5dcc1","type":"file in","z":"63842e72.893f78","name":"","filename":"/root/leases.file","format":"utf8","x":307,"y":137,"wires":[["a09e2794.97bca8"]]},{"id":"a09e2794.97bca8","type":"csv","z":"63842e72.893f78","name":"","sep":",","hdrin":"","hdrout":"","multi":"mult","ret":"\\n","temp":"","x":450,"y":136,"wires":[["f33caa99.b57308"]]},{"id":"f33caa99.b57308","type":"function","z":"63842e72.893f78","name":"Saves and emits assigned ID","func":"var lease = -1 ;\nvar splitString;\n\nfor (var i=0; (i<msg.payload.length) && (lease == -1);i++){\n    if(msg.payload[i].col1 != i){\n        msg.payload.splice(i,0, {col1: i, col2:\"temporary\"});\n        lease = i ;\n    }\n}\n\nif (lease == -1){ // means there's no holes in the lease file\n    lease = msg.payload.length ;\n    msg.payload.push( {col1: lease, col2:\"temporary\"} ); // returns next number in order\n}\n\nvar msg2 = { payload:lease};\n\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":640,"y":136,"wires":[["15c23ce9.f74c03","ccd034fb.54b728"],["50521f88.55082","ccd034fb.54b728"]]},{"id":"15c23ce9.f74c03","type":"csv","z":"63842e72.893f78","name":"","sep":",","hdrin":"","hdrout":"","multi":"one","ret":"\\n","temp":"col1,col2","x":663,"y":96,"wires":[["2092d4a1.661c84"]]},{"id":"2092d4a1.661c84","type":"file","z":"63842e72.893f78","name":"","filename":"/root/leases.file","appendNewline":false,"createDir":false,"overwriteFile":"true","x":670,"y":55,"wires":[]},{"id":"50521f88.55082","type":"mqtt out","z":"63842e72.893f78","name":"","topic":"MySensors/255/255/3/0/4","qos":"","retain":"","broker":"8e3e8f02.7fd0c","x":636,"y":199,"wires":[]},{"id":"ccd034fb.54b728","type":"debug","z":"63842e72.893f78","name":"DHCP result","active":false,"console":"false","complete":"payload","x":865,"y":135,"wires":[]},{"id":"420b8cdd.3a696c","type":"comment","z":"63842e72.893f78","name":"I_ID_REQUEST handler (255;255;3;0;3 , 255;255;3;0;4;[ID])","info":"Beginning listens to messages of 255;255;3;0;3;\\n , which is broadcast request for ID\nLeases file is read, and interpreted as CSV. \nFunction block does 2 things:\n    1. Adds new sensor's ID to lease file\n    2. Sends back to MQTT the ID the device is granted to 255;255;3;0;4;[ID]\\n","x":272,"y":83,"wires":[]}]
      
      
      posted in Node-RED
      cranky
      cranky
    • RE: MyController+Domoticz at same time?

      You'll also probably want node-red-contrib-mysensors and a few other modules on flows.nodered.org

      I use TOR extensively for being able to nicely manage and manipulate data on my network securely. The trick is a few things:

      TOR: Providing a Hidden Service to SSH and HTTPS
      Node-Red: Self-signed certs, HTTPS, and user authentication turned on.
      Mosquitto: Providing MQTTSSL. node-red-contrib-mqttssl provides support for that

      But hek was gracious to make a "Controller>Node-Red" subforum, so come join me there!

      Edit: also, because npm is sometimes really braindead sometimes, try using -debug with whatever you're doing. It will many a times make it work where without debut will just hang forever.

      posted in MyController.org
      cranky
      cranky
    • RE: Riots

      Am I the only one that actively denigrates IoT projects that demand data be sent to some remote server and then funneled back via a half-baked API? Why not MQTT/CoAP/AMQP ?

      Or am I the only one that despises that companies can remotely update firmware at a whim, like the way that Phillips did deactivating all 3rd party lights? It took a day to "fix", but they retain the ability as they choose. https://www.reddit.com/r/Hue/comments/3wy5t7/philips_hue_debacle_the_online_press_is_picking/

      Or that my profiling data on all of my devices are, by default, someone else's data? One can glean a lot of stuff from a sensor-covered house. This can be scary: https://www.researchgate.net/publication/224155275_Real-Time_Recognition_and_Profiling_of_Appliances_through_a_Single_Electricity_Sensor

      Or that if the internet goes down, all my devices go dumb? Somehow

      Device->DeviceGateway->Router->internet->Your Database Server->internet->router->DeviceGateway->Device

      is better than....

      Device->DeviceGateway->Controller->DeviceGateway->Device ??? Because that's what nRF24L01+ , Arduino Nano, Node-Red, and Mysensors lets me do.

      But then again, there's a reason I'm the "Cranky Linux User"....

      posted in General Discussion
      cranky
      cranky
    • RE: Neopixel Node, using 1.6.0 Beta

      https://www.youtube.com/watch?v=77MjJLMA244

      Of what it's capable of doing.

      posted in My Project
      cranky
      cranky
    • RE: Node-Red as Controller

      @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 🙂

      posted in Node-RED
      cranky
      cranky
    • RE: repeater node with sensor

      You sure can. I made early on a MotionSensorRepeater using 1.5.0 . The gotcha is you need to implement some sort of NON_BLOCKING rate limiting so the sensor doesn't spam the repeater. If you use DELAY(), you will lose messages. A lot of them.

      Also, I'm using a junky Sparkfun PIR sensor for this, with NO potentiometers for sensitivity or triggered duration, so I had to do duration in software. That's why the extra complication.

      #define NODE_ID 3
      #define CHILD_ID 5   // Id of the sensor child
      String ROOM_ID = " ID 5, living room repeater" ;
      
      
      #include <MySensor.h>
      #include <SPI.h>
      
      unsigned long MIN_TIME_TRIGGERED = 60000 ; // Time for sensor to report "off". Normally set on the PIR itself but this is junky sparkfun.
      boolean previousTripped = LOW;
      unsigned long PREVIOUS_TRIPPED_TIME = millis();
      unsigned long MIN_RETRIGGER = 3500;
      
      
      #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
      #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
      
      
      MySensor gw;
      // Initialize motion message
      MyMessage msg(CHILD_ID, V_TRIPPED);
      
      void setup()
      {
        gw.begin(NULL, NODE_ID, true);
      
        // Send the sketch version information to the gateway and Controller
        gw.sendSketchInfo("Motion Sensor", "1.0");
      
        pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
        // Register all sensors to gw (they will be created as child devices)
        gw.present(CHILD_ID, S_MOTION);
      
      }
      
      void loop()
      {
        boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
      
        // Sensor must be HIGH and not yet sent the status of the sensor
        if ((tripped == HIGH) && (tripped != previousTripped) ) { 
          Serial.print(tripped); Serial.println(ROOM_ID);
          gw.send(msg.set(tripped ? "1" : "0")); // Send tripped value to gw
          previousTripped = tripped;
          PREVIOUS_TRIPPED_TIME = millis();
        }
      
        // Is sensor HIGH, already sent to gateway, and under the minimum time to trigger? Then don't send
        if ( (PREVIOUS_TRIPPED_TIME + MIN_RETRIGGER) < millis() ) { 
          if ( (tripped == HIGH) && (tripped == previousTripped) ) { 
            Serial.println("Counter Reset"); PREVIOUS_TRIPPED_TIME = millis();
          }
        }
      
        // Is sensor low and not sent? Then send LOW to gateway
        if (tripped == LOW) {
          if ( ((PREVIOUS_TRIPPED_TIME + MIN_TIME_TRIGGERED) <= millis() ) && (tripped != previousTripped) ) {
            Serial.print(tripped); Serial.println(ROOM_ID);
            gw.send(msg.set(tripped ? "1" : "0")); // Send tripped value to gw
            previousTripped = tripped;
            PREVIOUS_TRIPPED_TIME = millis();
          }
        }
      
        gw.process(); // makes the node repeat
      }
      
      
      
      
      posted in General Discussion
      cranky
      cranky
    • RE: ioBroker = Home automation/Node ALL in ONE/ for noobs https +Let's encrypt/MQTT/Node Red/

      I'm honestly torn on making Windows/Linux programs. I certainly get the idea why you would want something like that, but I'd much rather have an HTML5 website that does that instead of an x86 program...

      Web browsers are on everything, whereas the idea of fat binaries is still a very rare one.

      My underlying works revolve in making web APIs, so I can create websites and scripts that can do "stuff" without me even hitting buttons.

      For example, I'd like to have an IoT doorbell. Simple. When it triggers, a flow interrogates if there is anybody in the house. If yes, ring the doorbell. Also, when doorbell is triggered, take a photo from the door and run it through a facial recognizer and send to me.

      ... And that's just a doorbell.

      posted in My Project
      cranky
      cranky

    Latest posts made by cranky

    • RE: FastLED / Neopixel (ws2811) Node, From Arduino code to Web page (with API)

      I can change it back to a 1.5.* code. It'll be a day or so, as I'm busy right now (homework, etc).

      posted in Node-RED
      cranky
      cranky
    • RE: ioBroker = Home automation/Node ALL in ONE/ for noobs https +Let's encrypt/MQTT/Node Red/

      I'm honestly torn on making Windows/Linux programs. I certainly get the idea why you would want something like that, but I'd much rather have an HTML5 website that does that instead of an x86 program...

      Web browsers are on everything, whereas the idea of fat binaries is still a very rare one.

      My underlying works revolve in making web APIs, so I can create websites and scripts that can do "stuff" without me even hitting buttons.

      For example, I'd like to have an IoT doorbell. Simple. When it triggers, a flow interrogates if there is anybody in the house. If yes, ring the doorbell. Also, when doorbell is triggered, take a photo from the door and run it through a facial recognizer and send to me.

      ... And that's just a doorbell.

      posted in My Project
      cranky
      cranky
    • RE: Flow to turn SerialGateway into MQTT-SerialGateway

      Ok, as you saw, I got the MQTT<-->TCP connector done , and that's live 🙂

      Now, I have my GH up and populated. It's pretty sparse with documentation right now, but that will change.
      https://github.com/jwcrawley/node-red-mysensors-flows/

      What's cool is I can use a the "Watch" NR node and watch for updates in my working directory and auto-push 😄

      All you need is your SSH keys set up.

      Then you watch for /.git/COMMIT_EDITMSG and when a change hits that, do a

      git add (repo directory)
      

      Then read the /.git/COMMIT_EDITMSG into msg.payload and then send it to an EXEC node as

      git commit -m {{payload}}
      

      And then

      git push origin master
      

      ..... And there you have it: automated local to Github.

      posted in Node-RED
      cranky
      cranky
    • RE: Windows GUI/Controller for MySensors

      @tekka You might not have to. I've been working on Node-Red as a controller and more.

      With my kit, you need Node-Red, node-red-contrib-mysensors , Mosquitto, and some of my flows which I have available ( http://forum.mysensors.org/topic/2802/flow-to-turn-serialgateway-into-mqtt-serialgateway ).

      And it makes this:
      http://forum.mysensors.org/topic/2815/flow-to-turn-serialgateway-with-mqtt-flow-to-ethernetgateway

      The only flaw is that when you first connect MYSController, you need to send a junk topic so that MYSController can receive data. It's a bug/peculiarity with Node-Red, but honestly not a big deal. I'm also working on how to fix even that.

      posted in Controllers
      cranky
      cranky
    • RE: "Sketch Time" (I_TIME) Handler

      Ah cool 🙂 So yes, make the user do it. I like the sound of that.

      Time stinks. Only thing I can say about that is, "Never again."

      posted in Node-RED
      cranky
      cranky
    • RE: "Sketch Time" (I_TIME) Handler

      Really? I'd rather handle absolute time of "Seconds since the Epoch". If you use that, there's no reason or need to mess with DST, time zones, or anything else. It's only when you convert "Seconds Since Epoch"->"String of Current time/date" do you get into having to deal with TZdata and all that garbage.

      Then, on the local device, the user can bake in the Arduino sketch the timezone they are using. Of course, then they have to deal with the horrors of DST and timezones... that is if they want to.

      I log most of my data in seconds(or ms) since epoch. All my logs are then completely synchronized, as much as an NTP client can manage.

      Sincerely,
      Cranky

      posted in Node-RED
      cranky
      cranky
    • Flow to turn SerialGateway with MQTT-FLOW to EthernetGateway

      Whew. This is a hard one, and not completely debugged. But as of right now, I can receive and send data through MYSController!

      You will need:
      http://forum.mysensors.org/topic/2802/flow-to-turn-serialgateway-into-mqtt-serialgateway
      mosquitto MQTT broker (server)
      node-red-contrib-mysensors
      download of MYSController

      What you get:
      Serial communication (duh!)
      MQTT communication
      TCP server that MYSController speaks ------ WOOT
      ~and you can connect as many clients to this TCP server as you want O_o

      The current topology is that I'm using a SerialGateway. All data to and from this goes into a Mosquitto MQTT broker. From then on, I only work with the broker, and not serial ports.

      This flow is the same: this should work with any MQTT implementation. Do note, my root topic is named MySensors/ . If yours is different, you will have to find and replace in my code.

      ethernetGateway.png

      Screenshot_2016-01-14_09-55-07.png

      And yes, MYSController works well on WINE 😄

      KNOWN BUG: Because of the way Node-Red tracks connections, you MUST send a packet from MYScontroller after connecting in order to capture the session. From then on, everything will work. If you do not do this, then you will not be able to receive any data in MYSController.

      [{"id":"72a5a797.020098","type":"mqtt-broker","z":"b2cff5f2.9cc8b","broker":"localhost","port":"8883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":null,"willPayload":"","birthTopic":"","birthQos":"0","birthRetain":null,"birthPayload":""},{"id":"5d726ee1.43674","type":"mqtt-broker","z":"316a4c44.7a9114","broker":"localhost","port":"8883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":null,"willPayload":"","birthTopic":"","birthQos":"0","birthRetain":null,"birthPayload":""},{"id":"e7324836.248338","type":"mqtt in","z":"316a4c44.7a9114","name":"","topic":"MySensors/#","broker":"5d726ee1.43674","x":80,"y":216,"wires":[["a009a85d.aa4b58"]]},{"id":"a009a85d.aa4b58","type":"function","z":"316a4c44.7a9114","name":"MQTT to MYS Serial","func":"var splitTopic= msg.topic.split(\"\\/\");\n\n// splitTopic[0] is the MySensors/ preamble. #1 is NODE_ID and on up. \nmsg.payload = splitTopic[1] + \";\" + splitTopic[2] + \";\" +  splitTopic[3] + \";\" +  splitTopic[4] + \";\" +  splitTopic[5] + \";\" +  msg.payload ;\nreturn msg;","outputs":1,"noerr":0,"x":260,"y":216,"wires":[["87d95f68.d5bf28"]]},{"id":"61cc3040.0a2ce","type":"mqtt out","z":"316a4c44.7a9114","name":"To MQTT","topic":"","qos":"","retain":"","broker":"72a5a797.020098","x":700,"y":148,"wires":[]},{"id":"57b96ecb.e396f","type":"mysdecenc","z":"316a4c44.7a9114","name":"","x":340,"y":148,"wires":[["2d0808fa.b5f988"]]},{"id":"2d0808fa.b5f988","type":"function","z":"316a4c44.7a9114","name":"Formats MQTT topic","func":"msg.topic = \"MySensors\" + \"/\" + msg.nodeId + \"/\" + msg.childSensorId + \"/\" + msg.messageType + \"/\" + msg.ack + \"/\" + msg.subType;\nreturn msg;","outputs":1,"noerr":0,"x":525,"y":148,"wires":[["61cc3040.0a2ce"]]},{"id":"172ecad5.7d5e7d","type":"debug","z":"316a4c44.7a9114","name":"","active":true,"console":"false","complete":"true","x":568,"y":287,"wires":[]},{"id":"e374dc2e.759fe8","type":"tcp out","z":"316a4c44.7a9114","host":"","port":"","beserver":"reply","base64":false,"end":false,"name":"","x":560,"y":218,"wires":[]},{"id":"d8774c60.3e3718","type":"tcp in","z":"316a4c44.7a9114","name":"","server":"server","host":"","port":"5003","datamode":"stream","datatype":"utf8","newline":"\\n","topic":"","base64":false,"x":76,"y":146,"wires":[["2cdfadb8.70f112","73ae599e.322238"]]},{"id":"2cdfadb8.70f112","type":"debug","z":"316a4c44.7a9114","name":"","active":true,"console":"false","complete":"true","x":218,"y":89,"wires":[]},{"id":"73ae599e.322238","type":"function","z":"316a4c44.7a9114","name":"","func":"context.global.tcpsess = context.global.tcpsess || msg._session;\nreturn msg;","outputs":1,"noerr":0,"x":204,"y":147,"wires":[["57b96ecb.e396f"]]},{"id":"87d95f68.d5bf28","type":"function","z":"316a4c44.7a9114","name":"","func":"msg._session = context.global.tcpsess;\nreturn msg;","outputs":1,"noerr":0,"x":432,"y":217,"wires":[["e374dc2e.759fe8","172ecad5.7d5e7d"]]}]
      
      posted in Node-RED
      cranky
      cranky
    • RE: Flow to turn SerialGateway into MQTT-SerialGateway

      Unfortunately, I do not. Until when I just looked at the source "MyGatewayTransportEthernet.cpp", I mistakenly assumed that it too published to an MQTT broker.

      It doesn't look too terribly hard to do; with UDP being easier. But my main caveat here is that I don't have an SPI ethernet port for an arduino. That means I wouldn't be able to test my code.

      If there was a packet documentation for TCP and UDP, I could write code for the reference. Again, past library and serial documentation, there is none I can refer to.

      Of if some hardware fairy would be willing to send me a compatible SPI ethernet port, I could do it 😄


      documentation

      MY_PORT = (default) 5003
      (TCP/UDP) choice
      (server mode / client mode) choice. IP dest. reqd for being client
      buffer receiving: 100 B
      buffer sending: 120 B

      posted in Node-RED
      cranky
      cranky
    • RE: "Sketch Config" (I_CONFIG) Handler

      Not yet, but that was my goal tomorrow.

      My GH account is https://github.com/jwcrawley

      It'll be obvious when I add in the repo 🙂 I'll also mention it here.

      Sincerely,
      Cranky

      posted in Node-RED
      cranky
      cranky
    • "Sketch Config" (I_CONFIG) Handler

      This flow takes care of the challenge/response for when a sensor asks what config to use (Metric or imperial).

      By default, the code returns M for metric. I don't believe Imperial is used anywhere, but it can be changed to I... if you support it in your code. (Honestly, no clue, but some sketches do make use of the call getConfig() .)

      [{"id":"8e3e8f02.7fd0c","type":"mqtt-broker","z":"63842e72.893f78","broker":"localhost","port":"8883","clientid":"","usetls":false,"verifyservercert":true,"compatmode":true,"keepalive":"15","cleansession":true,"willTopic":"","willQos":"0","willRetain":null,"willPayload":"","birthTopic":"","birthQos":"0","birthRetain":null,"birthPayload":""},{"id":"57ad0c01.895c9c","type":"mqtt in","z":"63842e72.893f78","name":"Sensor Requests Config","topic":"MySensors/+/255/3/0/6","broker":"8e3e8f02.7fd0c","x":105,"y":993,"wires":[["cd60b38.ef7405"]]},{"id":"86a8016b.bd47a","type":"mqtt out","z":"63842e72.893f78","name":"","topic":"","qos":"","retain":"","broker":"8e3e8f02.7fd0c","x":672,"y":993,"wires":[]},{"id":"65a6cc53.392ccc","type":"function","z":"63842e72.893f78","name":"Metric/Imperial definition","func":"var config = \"M\" ; //M for metric, and I for imperial\n\nmsg.payload = config + \"\\n\";\nreturn msg;","outputs":1,"noerr":0,"x":488,"y":993,"wires":[["86a8016b.bd47a","165c11cd.40adbe"]]},{"id":"165c11cd.40adbe","type":"debug","z":"63842e72.893f78","name":"","active":true,"console":"false","complete":"false","x":692,"y":952,"wires":[]},{"id":"cd60b38.ef7405","type":"delay","z":"63842e72.893f78","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":295,"y":993,"wires":[["65a6cc53.392ccc"]]},{"id":"9687065f.28c08","type":"comment","z":"63842e72.893f78","name":"I_CONFIG handler ([0-255];255;3;0;6;[M or I])","info":"Whenever a sensor announces itself to the network as [any];255;3;0;6;(null),\n\nThe cntroller returns a M for metric or I for imperial. \nTo my understanding, imperial measurement reportings aren't used.\n\n\nA rate limiter was required as to keep NR and the sensor from a spam-loop","x":298,"y":1030,"wires":[]}]```
      posted in Node-RED
      cranky
      cranky