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. Development
  3. Node to Node communication

Node to Node communication

Scheduled Pinned Locked Moved Development
22 Posts 3 Posters 220 Views 3 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.
  • boumB Offline
    boumB Offline
    boum
    wrote on last edited by
    #7

    The destination is a state inside the MyMessage object. You need to reset it every time you change destination, from controller to the other node and back:

     send(msg_LEAK_1.setDestination(0).setSensor(LEAK_1_CHILD_ID).set(LEAK_1));
     send(msg_LEAK_1.setDestination(15).setSensor(10).set(LEAK_1));
    
    

    Or you could create a second message object for the node to node communication:

    MyMessage msg_LEAK_1(LEAK_1_CHILD_ID,V_TRIPPED);
    MyMessage msg_LEAK_to_15(10,V_TRIPPED);
    
    void setup()  
    {  
      pinMode(LEAK_1_PIN,INPUT_PULLUP);
    
      // Set destination only once, sensor is set on constructor above
      msg_LEAK_to_15.setDestination(15);
    }
    //[...]
     if (LEAK_1 != last_LEAK_1) 
     {
       send(msg_LEAK_1.set(LEAK_1));
       send(msg_LEAK_to_15.set(LEAK_1));
       last_LEAK_1 = LEAK_1;
     }
    
    A 1 Reply Last reply
    1
    • boumB boum

      The destination is a state inside the MyMessage object. You need to reset it every time you change destination, from controller to the other node and back:

       send(msg_LEAK_1.setDestination(0).setSensor(LEAK_1_CHILD_ID).set(LEAK_1));
       send(msg_LEAK_1.setDestination(15).setSensor(10).set(LEAK_1));
      
      

      Or you could create a second message object for the node to node communication:

      MyMessage msg_LEAK_1(LEAK_1_CHILD_ID,V_TRIPPED);
      MyMessage msg_LEAK_to_15(10,V_TRIPPED);
      
      void setup()  
      {  
        pinMode(LEAK_1_PIN,INPUT_PULLUP);
      
        // Set destination only once, sensor is set on constructor above
        msg_LEAK_to_15.setDestination(15);
      }
      //[...]
       if (LEAK_1 != last_LEAK_1) 
       {
         send(msg_LEAK_1.set(LEAK_1));
         send(msg_LEAK_to_15.set(LEAK_1));
         last_LEAK_1 = LEAK_1;
       }
      
      A Offline
      A Offline
      APL2017
      wrote on last edited by APL2017
      #8

      @boum said in Node to Node communication:

      MyMessage msg_LEAK_to_15(10,V_TRIPPED);

      Thank you, here is what I have on receiving node (simplified). I am not getting the leak flag on receiving node. Is this correct? Elimination of sleeping did not help. I've noticed that there is no receiving commands within the LOOP, but it was advised as not required in previously referenced discussion.

      #define MY_DEBUG 
      #define MY_RADIO_RF24
      #include <MySensors.h>
      #define LEAK_RECEIVED_CHILD_ID 10
      bool LEAK_RECEIVED;
      uint32_t SLEEP_TIME = 1000; // Sleep time between reads (in milliseconds)
      MyMessage msg_LEAK_RECEIVED(LEAK_RECEIVED_CHILD_ID,V_TRIPPED);
      
      void setup()  
      {  
       }
      void presentation() {
        sendSketchInfo("Basement Water", "1.0");
        present(LEAK_RECEIVED_CHILD_ID, S_DOOR);
      }
      void receive(const MyMessage &message)
       {if (message.type==V_TRIPPED)
        {if (message.sensor==15)
          { Serial.print(message.sensor);
            Serial.print("\n");
            Serial.print(", New status: ");
            Serial.print(message.getBool());
            LEAK_RECEIVED=message.getBool();
          }
          }
       }
      void loop() 
      {
          sleep(SLEEP_TIME);
       }
      
      1 Reply Last reply
      0
      • boumB Offline
        boumB Offline
        boum
        wrote on last edited by
        #9

        Yes, you should replace the sleep with a wait. If you module is sleeping, it won't receive any message.
        While prototyping/debugging, you should put more Serial.print around your blocks, not only in the innermost block.

        I guess you are mixing different things in the message object. In the receive() function, you should test message.sensor against 10, the sensor value you put in the sent message, 15 is the node ID destination, that is the current node.

        A 1 Reply Last reply
        0
        • boumB boum

          Yes, you should replace the sleep with a wait. If you module is sleeping, it won't receive any message.
          While prototyping/debugging, you should put more Serial.print around your blocks, not only in the innermost block.

          I guess you are mixing different things in the message object. In the receive() function, you should test message.sensor against 10, the sensor value you put in the sent message, 15 is the node ID destination, that is the current node.

          A Offline
          A Offline
          APL2017
          wrote on last edited by APL2017
          #10

          @boum Thank you! So, in my receiving function i should have the following, where 10 is sending node?

          void receive(const MyMessage &message)
           {if (message.type==V_TRIPPED)
            {if (message.sensor==10)
              { Serial.print(message.sensor);
                Serial.print("\n");
                Serial.print(", New status: ");
                Serial.print(message.getBool());
                LEAK_RECEIVED=message.getBool();
              }
              }
           }
          
          1 Reply Last reply
          0
          • BearWithBeardB Offline
            BearWithBeardB Offline
            BearWithBeard
            wrote on last edited by BearWithBeard
            #11

            sensor or sensor ID is synonymous for child ID, one of the many sensors a single node can have. sender is the ID of the node which sent the message.

            On the sending node:

            #define MY_NODE_ID 7
            //                 ^ sender / node ID
            [...]
            MyMessage msg_LEAK_to_15( 10, V_TRIPPED );
            //                        ^^ sensor / child ID
            [...]
            msg_LEAK_to_15.setDestination(15);
            //                            ^^ ID of the destination / receiving node
            

            On the receiving node:

            // returns sender / node ID (7)
            msg.getSender();
            
            // returns sensor / child ID (10)
            msg.getSensor();
            

            So yes, with the changes in your latest code snipped, you should start seeing some serial output.

            On a different note: Not that it would change anything here, but l'd like to advise to use the availabe getter and setter functions, whenever possible.

            message.sensor==10 works perfectly fine if you want to compare the current value of the variable against 10. But if you accidently omit one of the equal signs, you assign 10 to the variable instead. Bugs like these can be hard to spot - the if-condition would always evaluate true in this case. Using message.getSensor() prevents such mistakes.

            A 1 Reply Last reply
            1
            • BearWithBeardB BearWithBeard

              sensor or sensor ID is synonymous for child ID, one of the many sensors a single node can have. sender is the ID of the node which sent the message.

              On the sending node:

              #define MY_NODE_ID 7
              //                 ^ sender / node ID
              [...]
              MyMessage msg_LEAK_to_15( 10, V_TRIPPED );
              //                        ^^ sensor / child ID
              [...]
              msg_LEAK_to_15.setDestination(15);
              //                            ^^ ID of the destination / receiving node
              

              On the receiving node:

              // returns sender / node ID (7)
              msg.getSender();
              
              // returns sensor / child ID (10)
              msg.getSensor();
              

              So yes, with the changes in your latest code snipped, you should start seeing some serial output.

              On a different note: Not that it would change anything here, but l'd like to advise to use the availabe getter and setter functions, whenever possible.

              message.sensor==10 works perfectly fine if you want to compare the current value of the variable against 10. But if you accidently omit one of the equal signs, you assign 10 to the variable instead. Bugs like these can be hard to spot - the if-condition would always evaluate true in this case. Using message.getSensor() prevents such mistakes.

              A Offline
              A Offline
              APL2017
              wrote on last edited by
              #12

              @BearWithBeard Thank you. I do not define my nodes ID, they are being assigned automatically (by controller? gateway?), but I do see nodes ID in my controller configuration. Is this a problem?

              1 Reply Last reply
              0
              • BearWithBeardB Offline
                BearWithBeardB Offline
                BearWithBeard
                wrote on last edited by
                #13

                I'm not sure if a node's automatically assigned ID can change in special circumstances (apart from clearing the EEPROM), but as long as you don't care about which specific node sent a message in a node-to-node relationship, this shouldn't be a problem. So it's best to avoid using msg.getSender() on the receiving node.

                I just added a static node ID in the example above to better illustrate what each variable means, since you seem to mix up sender and sensor.

                A 1 Reply Last reply
                1
                • BearWithBeardB BearWithBeard

                  I'm not sure if a node's automatically assigned ID can change in special circumstances (apart from clearing the EEPROM), but as long as you don't care about which specific node sent a message in a node-to-node relationship, this shouldn't be a problem. So it's best to avoid using msg.getSender() on the receiving node.

                  I just added a static node ID in the example above to better illustrate what each variable means, since you seem to mix up sender and sensor.

                  A Offline
                  A Offline
                  APL2017
                  wrote on last edited by
                  #14

                  @BearWithBeard Sorry, I am still confused. Is it possible to publish a complete example of sending Boolean from one node to another to be used in control logic? Thank you.

                  1 Reply Last reply
                  0
                  • BearWithBeardB Offline
                    BearWithBeardB Offline
                    BearWithBeard
                    wrote on last edited by BearWithBeard
                    #15

                    Unfortunately, I don't have a test setup running right now, otherwise I would quickly whip up and test two minimal example sketches.

                    But here are some snippets that should include everything related to node-to-node communication you need. My best advice at this point, if it still confuses you, is to get rid of all the magic numbers in the code and define macros / constants.

                    On the leak detector node, you need the following bits:

                    bool leakState = false;
                    bool previousLeakState = false;
                    
                    #define LEAK_CHILD_ID 0 // 0 to 254
                    #define LEAK_CHILD_ID_TO_NODE 100 // 0 to 254
                    #define LEAK_TARGET_NODE_ID 15 // The ID of the node you want to report to
                    
                    // Setup two separate messages. One reports to the GW, the other to the target node
                    MyMessage msgToGw(LEAK_CHILD_ID, V_TRIPPED);
                    MyMessage msgToNode(LEAK_CHILD_ID_TO_NODE, V_TRIPPED);
                    
                    void presentation() 
                    {
                    	// Register and present sketch and sensors
                    	sendSketchInfo("Leak Detector", "1.0");
                    	present(LEAK_CHILD_ID, S_WATER_LEAK);
                    }
                    
                    void setup()  
                    {
                    	// Set the destination for msgToNode permanently to the target node's ID 
                    	// msgToGw doesn't need that; it defaults to 0 (=GW)
                    	msgToNode.setDestination(LEAK_TARGET_NODE_ID);
                    }
                    
                    void loop() 
                    {
                    	// Check if things have changed
                    	if (leakState != previousLeakState)
                    	{
                    		// Report new state to GW and target node
                    		send(msgToGw.set(leakState));
                    		wait(100); // Optional, but a short pause inbetween can't hurt
                    		send(msgToNode.set(leakState));
                    		
                    		// Update state
                    		previousLeakState = leakState;
                    	}
                    }
                    

                    This will inform the GW via msgToGw as well as the the node with the ID 15 (LEAK_TARGET_NODE_ID) via msgToNode about the updated leakState.

                    The GW will receive this message with the child ID 0 (LEAK_CHILD_ID), node 15 will receive it with the child ID 100 (LEAK_CHILD_ID_TO_NODE). You do not need to change the child ID you send to the destination node - you can keep using the same as for the GW. Just note that you can change it.

                    On the target node, you need this:

                    bool leakState = false;
                    bool previousLeakState = false;
                    #define LEAK_CHILD_ID_INCOMING 100 
                    
                    void loop() 
                    {
                    	// Check if leakState has changed
                    	if (leakState != previousLeakState)
                    	{
                    		// Do something
                    		
                    		// Update state
                    		previousLeakState = leakState;
                    	}
                    }
                    
                    void receive(const MyMessage & msg) 
                    {
                    	Serial.print("Incoming message... ");
                    
                    	// Filter out our message
                    	if (msg.getType() == V_TRIPPED && 
                    		msg.getSensor() == LEAK_CHILD_ID_INCOMING)
                    	{
                    		// Update the local leakState variable
                    		leakState = msg.getBool();
                    
                    		// Print some infos
                    		Serial.println("is a new leak state!");
                    		Serial.print("From (Node ID):");
                    		Serial.println(msg.getSender());
                    		Serial.print("Child ID: ");
                    		Serial.println(msg.getSensor());
                    		Serial.print("State: ");
                    		Serial.println(leakState);
                    	} else 
                    	{
                    		Serial.println("is something else. :(");
                    	}
                    }
                    

                    Hope I didn't miss anything.

                    Once you got it working, it's best to remove most if not all serial prints from the receive function, as it's generally bad practice and can cause various problems.

                    A 1 Reply Last reply
                    1
                    • BearWithBeardB BearWithBeard

                      Unfortunately, I don't have a test setup running right now, otherwise I would quickly whip up and test two minimal example sketches.

                      But here are some snippets that should include everything related to node-to-node communication you need. My best advice at this point, if it still confuses you, is to get rid of all the magic numbers in the code and define macros / constants.

                      On the leak detector node, you need the following bits:

                      bool leakState = false;
                      bool previousLeakState = false;
                      
                      #define LEAK_CHILD_ID 0 // 0 to 254
                      #define LEAK_CHILD_ID_TO_NODE 100 // 0 to 254
                      #define LEAK_TARGET_NODE_ID 15 // The ID of the node you want to report to
                      
                      // Setup two separate messages. One reports to the GW, the other to the target node
                      MyMessage msgToGw(LEAK_CHILD_ID, V_TRIPPED);
                      MyMessage msgToNode(LEAK_CHILD_ID_TO_NODE, V_TRIPPED);
                      
                      void presentation() 
                      {
                      	// Register and present sketch and sensors
                      	sendSketchInfo("Leak Detector", "1.0");
                      	present(LEAK_CHILD_ID, S_WATER_LEAK);
                      }
                      
                      void setup()  
                      {
                      	// Set the destination for msgToNode permanently to the target node's ID 
                      	// msgToGw doesn't need that; it defaults to 0 (=GW)
                      	msgToNode.setDestination(LEAK_TARGET_NODE_ID);
                      }
                      
                      void loop() 
                      {
                      	// Check if things have changed
                      	if (leakState != previousLeakState)
                      	{
                      		// Report new state to GW and target node
                      		send(msgToGw.set(leakState));
                      		wait(100); // Optional, but a short pause inbetween can't hurt
                      		send(msgToNode.set(leakState));
                      		
                      		// Update state
                      		previousLeakState = leakState;
                      	}
                      }
                      

                      This will inform the GW via msgToGw as well as the the node with the ID 15 (LEAK_TARGET_NODE_ID) via msgToNode about the updated leakState.

                      The GW will receive this message with the child ID 0 (LEAK_CHILD_ID), node 15 will receive it with the child ID 100 (LEAK_CHILD_ID_TO_NODE). You do not need to change the child ID you send to the destination node - you can keep using the same as for the GW. Just note that you can change it.

                      On the target node, you need this:

                      bool leakState = false;
                      bool previousLeakState = false;
                      #define LEAK_CHILD_ID_INCOMING 100 
                      
                      void loop() 
                      {
                      	// Check if leakState has changed
                      	if (leakState != previousLeakState)
                      	{
                      		// Do something
                      		
                      		// Update state
                      		previousLeakState = leakState;
                      	}
                      }
                      
                      void receive(const MyMessage & msg) 
                      {
                      	Serial.print("Incoming message... ");
                      
                      	// Filter out our message
                      	if (msg.getType() == V_TRIPPED && 
                      		msg.getSensor() == LEAK_CHILD_ID_INCOMING)
                      	{
                      		// Update the local leakState variable
                      		leakState = msg.getBool();
                      
                      		// Print some infos
                      		Serial.println("is a new leak state!");
                      		Serial.print("From (Node ID):");
                      		Serial.println(msg.getSender());
                      		Serial.print("Child ID: ");
                      		Serial.println(msg.getSensor());
                      		Serial.print("State: ");
                      		Serial.println(leakState);
                      	} else 
                      	{
                      		Serial.println("is something else. :(");
                      	}
                      }
                      

                      Hope I didn't miss anything.

                      Once you got it working, it's best to remove most if not all serial prints from the receive function, as it's generally bad practice and can cause various problems.

                      A Offline
                      A Offline
                      APL2017
                      wrote on last edited by APL2017
                      #16

                      @BearWithBeard THANK YOU! It works fine. The only change I had to make is to replace msg with message in all commands. Couple of questions, if you don't mind:

                      1. Is it critical to have void receive after void loop?
                      2. How receiving node distinguishes between same sensor ID coming from different nodes? Or, I need to assign unique sensor ID throughout complete sensors pool?

                      It will be useful to include working example into mySensors library.

                      1 Reply Last reply
                      0
                      • BearWithBeardB Offline
                        BearWithBeardB Offline
                        BearWithBeard
                        wrote on last edited by
                        #17

                        Glad you got it working!

                        1. The order of the functions in the sketch doesn't determine their execution order, which is managed behind the scenes by the framework. You could place receive() right below the mysensors.h inclusion if you wish.

                        2. They don't. That's why I showed you how to assign a different child ID. You could assing a unique ID per node-to-node-message to make them identifiable.
                          If multiple node-to-node-message end up having the same child ID, you would have to factor in other variables, like getSender() to tell them apart. Let's say you have three nodes (IDs 1, 2, 3) sending a boolean to a fourth target node and all messages have the same child ID of 0, you could tell them apart like this:

                          #define LEAK_CHILD_ID_INCOMING 0
                          // [...]
                          void receive(const MyMessage & msg) 
                          {
                          	// Message is what we're looking for
                          	if (msg.getType() == V_TRIPPED && 
                          		msg.getSensor() == LEAK_CHILD_ID_INCOMING)
                          	{
                          		// Find out where it's from
                          		switch (msg.getSender())
                          		{
                          			case 1: // From node ID 1
                          				leakStateNode1 = msg.getBool();
                          				break;
                          			case 2: // From node ID 2
                          				leakStateNode2 = msg.getBool();
                          				break;
                          			case 3: // From node ID 3
                          				leakStateNode3 = msg.getBool();
                          				break;
                          			default: // From GW or 4 - 254
                          				break;
                          		}
                          	}
                          }
                          

                          But again, since you're using automatic ID assignment - I'm not sure if node IDs can change under specific circumstances. So If you make use of getSender() you may want to consider assigning static node IDs.

                        A 2 Replies Last reply
                        1
                        • BearWithBeardB BearWithBeard

                          Glad you got it working!

                          1. The order of the functions in the sketch doesn't determine their execution order, which is managed behind the scenes by the framework. You could place receive() right below the mysensors.h inclusion if you wish.

                          2. They don't. That's why I showed you how to assign a different child ID. You could assing a unique ID per node-to-node-message to make them identifiable.
                            If multiple node-to-node-message end up having the same child ID, you would have to factor in other variables, like getSender() to tell them apart. Let's say you have three nodes (IDs 1, 2, 3) sending a boolean to a fourth target node and all messages have the same child ID of 0, you could tell them apart like this:

                            #define LEAK_CHILD_ID_INCOMING 0
                            // [...]
                            void receive(const MyMessage & msg) 
                            {
                            	// Message is what we're looking for
                            	if (msg.getType() == V_TRIPPED && 
                            		msg.getSensor() == LEAK_CHILD_ID_INCOMING)
                            	{
                            		// Find out where it's from
                            		switch (msg.getSender())
                            		{
                            			case 1: // From node ID 1
                            				leakStateNode1 = msg.getBool();
                            				break;
                            			case 2: // From node ID 2
                            				leakStateNode2 = msg.getBool();
                            				break;
                            			case 3: // From node ID 3
                            				leakStateNode3 = msg.getBool();
                            				break;
                            			default: // From GW or 4 - 254
                            				break;
                            		}
                            	}
                            }
                            

                            But again, since you're using automatic ID assignment - I'm not sure if node IDs can change under specific circumstances. So If you make use of getSender() you may want to consider assigning static node IDs.

                          A Offline
                          A Offline
                          APL2017
                          wrote on last edited by
                          #18

                          @BearWithBeard Thank you!!!

                          1 Reply Last reply
                          0
                          • BearWithBeardB BearWithBeard

                            Glad you got it working!

                            1. The order of the functions in the sketch doesn't determine their execution order, which is managed behind the scenes by the framework. You could place receive() right below the mysensors.h inclusion if you wish.

                            2. They don't. That's why I showed you how to assign a different child ID. You could assing a unique ID per node-to-node-message to make them identifiable.
                              If multiple node-to-node-message end up having the same child ID, you would have to factor in other variables, like getSender() to tell them apart. Let's say you have three nodes (IDs 1, 2, 3) sending a boolean to a fourth target node and all messages have the same child ID of 0, you could tell them apart like this:

                              #define LEAK_CHILD_ID_INCOMING 0
                              // [...]
                              void receive(const MyMessage & msg) 
                              {
                              	// Message is what we're looking for
                              	if (msg.getType() == V_TRIPPED && 
                              		msg.getSensor() == LEAK_CHILD_ID_INCOMING)
                              	{
                              		// Find out where it's from
                              		switch (msg.getSender())
                              		{
                              			case 1: // From node ID 1
                              				leakStateNode1 = msg.getBool();
                              				break;
                              			case 2: // From node ID 2
                              				leakStateNode2 = msg.getBool();
                              				break;
                              			case 3: // From node ID 3
                              				leakStateNode3 = msg.getBool();
                              				break;
                              			default: // From GW or 4 - 254
                              				break;
                              		}
                              	}
                              }
                              

                              But again, since you're using automatic ID assignment - I'm not sure if node IDs can change under specific circumstances. So If you make use of getSender() you may want to consider assigning static node IDs.

                            A Offline
                            A Offline
                            APL2017
                            wrote on last edited by APL2017
                            #19

                            @BearWithBeard Thanks to you my water leak detection system works fine. My next challenge is to let node receive Boolean (RESET_SOFT) from GW - directly from controller logic. I am looking at example RelayActuator and trying to make sense of it, see below simplified version of it. The idea is to get message from GW (node 0) and received it as sensor ID 20 on the receiving node. Is this close to what is should be?

                            #define MY_DEBUG 
                            #define MY_RADIO_RF24
                            #include <MySensors.h>
                            
                            bool RESET_SOFT;
                            
                            void setup()  
                            {  
                             
                            }
                            void presentation() {
                              sendSketchInfo("Basement Water", "1.0");
                              present(20, S_BINARY);
                            }
                            
                            void loop() 
                            {
                              
                            }
                             void receive(const MyMessage &message)
                             {
                                if (message.getType()==S_BINARY &&
                                  message.getSensor()==0)
                                 {RESET_SOFT=message.getBool(); }
                                 
                             } 
                            
                            1 Reply Last reply
                            0
                            • BearWithBeardB Offline
                              BearWithBeardB Offline
                              BearWithBeard
                              wrote on last edited by BearWithBeard
                              #20

                              Well, it looks like you are still mixing up the meaning of sensor and sender in the code. If the controller sends a message to the sensor you have set up in the sketch above (20), while you are comparing against 0 in receive(), you will never detect that message. Compare against 20.

                              Remember how I advised to get rid of magic numbers and use constants instead? If you would add something like #define SENSOR_ID 20 and use that variable instead of 0 and 20, you might be able to avoid such confusions, because you give those arguments a meaningful name.

                              Let's try to explain it another way, so that you can adapt it to any situation in the future.

                              Sensor: In the context of a MySensors sketch, stop thinking of a sensor being a (physical) device. It is just a unique identifier for one of many different data points a device (MySensors calls this device a node) wants to share with others. Think of a sensor (or also often called child) as one of up to 255 wires going from one node to any other, whereby each wire represents a single type of data, like a temperature, a string, voltage level, a boolean value.

                              Sender: When a node sends a message, it includes a reference to itself - the node ID - as the sender, as well as a reference to the target node as the destination. Both sender and destination enable MySensors to route messages through the network, no matter if it is a direct A-to-B connection or if the message needs to be forwarded by multiple repeaters.

                              The MyMessage class is used to manage those messages. It stores all kinds of information neccessary to share data between nodes, send and request commands independently from the selected transport method (RF24, Sub-GHz, wired) and controller connection (Serial, MQTT, WiFi, Ethernet).

                              Imagine a simplified MyMessage instance as a collection of variables and a bunch of helper functions to make your life easier. When the controller (via the GW) sends the message to the node, as you described above, the message would look like this on the receiving node:

                              MyMessage msg 
                              {
                              	sender = 0;       // Node ID of the message's origin (the GW)
                              	destination = 7;  // Node ID of this device (I assumed this number!)
                              	sensor = 20;      // Child ID / data point that this message wants to update
                              	type = 3;         // S_BINARY == 3
                              	[...]
                              	getBool();        // Returns the payload as a boolean
                              	getSensor();      // Returns the value of sensor
                              	setSensor(n);     // Changes the value of sensor
                              	getDestination(); // Returns the value of destination
                              	[...]
                              }
                              

                              So what do you have to do if you want to update the local variable RESET_SOFT on that node whenever it receives a new value? You have to test that the incoming message is of the expected type and that it concerns the right sensor. If you also want to make sure that only the controller or GW can cause an update of RESET_SOFT, you must validate that sender - in other words, the origin of this message - is valid as well.

                              I really hope this makes sense to you, as I'm running out of ideas how to explain what is going on behind the scenes.

                              Maybe a look at the Serial API introduction can also help you further.

                              A 2 Replies Last reply
                              2
                              • BearWithBeardB BearWithBeard

                                Well, it looks like you are still mixing up the meaning of sensor and sender in the code. If the controller sends a message to the sensor you have set up in the sketch above (20), while you are comparing against 0 in receive(), you will never detect that message. Compare against 20.

                                Remember how I advised to get rid of magic numbers and use constants instead? If you would add something like #define SENSOR_ID 20 and use that variable instead of 0 and 20, you might be able to avoid such confusions, because you give those arguments a meaningful name.

                                Let's try to explain it another way, so that you can adapt it to any situation in the future.

                                Sensor: In the context of a MySensors sketch, stop thinking of a sensor being a (physical) device. It is just a unique identifier for one of many different data points a device (MySensors calls this device a node) wants to share with others. Think of a sensor (or also often called child) as one of up to 255 wires going from one node to any other, whereby each wire represents a single type of data, like a temperature, a string, voltage level, a boolean value.

                                Sender: When a node sends a message, it includes a reference to itself - the node ID - as the sender, as well as a reference to the target node as the destination. Both sender and destination enable MySensors to route messages through the network, no matter if it is a direct A-to-B connection or if the message needs to be forwarded by multiple repeaters.

                                The MyMessage class is used to manage those messages. It stores all kinds of information neccessary to share data between nodes, send and request commands independently from the selected transport method (RF24, Sub-GHz, wired) and controller connection (Serial, MQTT, WiFi, Ethernet).

                                Imagine a simplified MyMessage instance as a collection of variables and a bunch of helper functions to make your life easier. When the controller (via the GW) sends the message to the node, as you described above, the message would look like this on the receiving node:

                                MyMessage msg 
                                {
                                	sender = 0;       // Node ID of the message's origin (the GW)
                                	destination = 7;  // Node ID of this device (I assumed this number!)
                                	sensor = 20;      // Child ID / data point that this message wants to update
                                	type = 3;         // S_BINARY == 3
                                	[...]
                                	getBool();        // Returns the payload as a boolean
                                	getSensor();      // Returns the value of sensor
                                	setSensor(n);     // Changes the value of sensor
                                	getDestination(); // Returns the value of destination
                                	[...]
                                }
                                

                                So what do you have to do if you want to update the local variable RESET_SOFT on that node whenever it receives a new value? You have to test that the incoming message is of the expected type and that it concerns the right sensor. If you also want to make sure that only the controller or GW can cause an update of RESET_SOFT, you must validate that sender - in other words, the origin of this message - is valid as well.

                                I really hope this makes sense to you, as I'm running out of ideas how to explain what is going on behind the scenes.

                                Maybe a look at the Serial API introduction can also help you further.

                                A Offline
                                A Offline
                                APL2017
                                wrote on last edited by APL2017
                                #21

                                @BearWithBeard Thank you! I am really embarrassed with my, let's say, luck of understanding. But you made it clear again. Everything works as required!

                                1 Reply Last reply
                                0
                                • BearWithBeardB BearWithBeard

                                  Well, it looks like you are still mixing up the meaning of sensor and sender in the code. If the controller sends a message to the sensor you have set up in the sketch above (20), while you are comparing against 0 in receive(), you will never detect that message. Compare against 20.

                                  Remember how I advised to get rid of magic numbers and use constants instead? If you would add something like #define SENSOR_ID 20 and use that variable instead of 0 and 20, you might be able to avoid such confusions, because you give those arguments a meaningful name.

                                  Let's try to explain it another way, so that you can adapt it to any situation in the future.

                                  Sensor: In the context of a MySensors sketch, stop thinking of a sensor being a (physical) device. It is just a unique identifier for one of many different data points a device (MySensors calls this device a node) wants to share with others. Think of a sensor (or also often called child) as one of up to 255 wires going from one node to any other, whereby each wire represents a single type of data, like a temperature, a string, voltage level, a boolean value.

                                  Sender: When a node sends a message, it includes a reference to itself - the node ID - as the sender, as well as a reference to the target node as the destination. Both sender and destination enable MySensors to route messages through the network, no matter if it is a direct A-to-B connection or if the message needs to be forwarded by multiple repeaters.

                                  The MyMessage class is used to manage those messages. It stores all kinds of information neccessary to share data between nodes, send and request commands independently from the selected transport method (RF24, Sub-GHz, wired) and controller connection (Serial, MQTT, WiFi, Ethernet).

                                  Imagine a simplified MyMessage instance as a collection of variables and a bunch of helper functions to make your life easier. When the controller (via the GW) sends the message to the node, as you described above, the message would look like this on the receiving node:

                                  MyMessage msg 
                                  {
                                  	sender = 0;       // Node ID of the message's origin (the GW)
                                  	destination = 7;  // Node ID of this device (I assumed this number!)
                                  	sensor = 20;      // Child ID / data point that this message wants to update
                                  	type = 3;         // S_BINARY == 3
                                  	[...]
                                  	getBool();        // Returns the payload as a boolean
                                  	getSensor();      // Returns the value of sensor
                                  	setSensor(n);     // Changes the value of sensor
                                  	getDestination(); // Returns the value of destination
                                  	[...]
                                  }
                                  

                                  So what do you have to do if you want to update the local variable RESET_SOFT on that node whenever it receives a new value? You have to test that the incoming message is of the expected type and that it concerns the right sensor. If you also want to make sure that only the controller or GW can cause an update of RESET_SOFT, you must validate that sender - in other words, the origin of this message - is valid as well.

                                  I really hope this makes sense to you, as I'm running out of ideas how to explain what is going on behind the scenes.

                                  Maybe a look at the Serial API introduction can also help you further.

                                  A Offline
                                  A Offline
                                  APL2017
                                  wrote on last edited by APL2017
                                  #22
                                  This post is deleted!
                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  8

                                  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