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. How to properly handle variable requests

How to properly handle variable requests

Scheduled Pinned Locked Moved Development
9 Posts 3 Posters 104 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.
  • T Offline
    T Offline
    tante ju
    wrote on last edited by
    #1

    Hello,

    I've seen this ask several times, dating back to 2015 or so, but no really appropriate answer. Hence I try to find a definitive answer to this question.

    How to properly handle requests of variables in the nodes?

    According to documentation the request(...) function could be used to request variables from the controller or any other node.

    What it does is sending a message with command C_REQ. But how should an answer properly be sent?

    Example (shortened to what is really important here):
    Node 1 has a variable V_STATUS, Node 2 has a variable V_STATUS.
    Node 1 now septs C_REQ for V_STATUS to Node 2.
    What should Node 2 answer?
    If it would answer with C_REQ, this could be read by Node 1 as request for its V_STATUS. If it would send C_SET it would be a set of V_STATUS in Node 1.

    Only reasonable way I see with available tools would be:
    Node 1 sends C_REQ for V_STATUS to Node 2, with EchoRequest (because it is for sure requesting for something back), payload is empty.
    Node 2 replies C_REQ for V_STATUS, puts V_STATUS value in payload and sets isEcho.

    Problem with this approach: The echo request is not seen in the receive function as it is handled in transportProcessMessage() inside library. Plus: This would stretch the definition of echo, because the answer is not an echo, as it has payload the request did not have. But that would probably be acceptable, because an empty payload would still be an echo in case Node 2 does not have variable V_STATUS.

    Did I miss anything?

    Boots33B 1 Reply Last reply
    0
    • T tante ju

      Hello,

      I've seen this ask several times, dating back to 2015 or so, but no really appropriate answer. Hence I try to find a definitive answer to this question.

      How to properly handle requests of variables in the nodes?

      According to documentation the request(...) function could be used to request variables from the controller or any other node.

      What it does is sending a message with command C_REQ. But how should an answer properly be sent?

      Example (shortened to what is really important here):
      Node 1 has a variable V_STATUS, Node 2 has a variable V_STATUS.
      Node 1 now septs C_REQ for V_STATUS to Node 2.
      What should Node 2 answer?
      If it would answer with C_REQ, this could be read by Node 1 as request for its V_STATUS. If it would send C_SET it would be a set of V_STATUS in Node 1.

      Only reasonable way I see with available tools would be:
      Node 1 sends C_REQ for V_STATUS to Node 2, with EchoRequest (because it is for sure requesting for something back), payload is empty.
      Node 2 replies C_REQ for V_STATUS, puts V_STATUS value in payload and sets isEcho.

      Problem with this approach: The echo request is not seen in the receive function as it is handled in transportProcessMessage() inside library. Plus: This would stretch the definition of echo, because the answer is not an echo, as it has payload the request did not have. But that would probably be acceptable, because an empty payload would still be an echo in case Node 2 does not have variable V_STATUS.

      Did I miss anything?

      Boots33B Offline
      Boots33B Offline
      Boots33
      Hero Member
      wrote on last edited by Boots33
      #2

      @tante-ju

      If you are making a request to the controller it will return the required data for you to use, you will then need to have code on the requesting node to handle this return.

      If you are making a node to node request you will need to manually handle both the incoming request on the target node and then use node to node communication to the return of the required data to the node that requested the data. Then on the node that sent the request you will need to have code to separate this return from normal controller commands.

      In MySensors you can use message.sender to determine where the message came from and message.getCommand to see if the message is a request or command etc.

      Have a look at these three posts to see what these look like in use and also how to format a node to node message.

      https://forum.mysensors.org/topic/6422/display-node-how-to-set-up/20

      https://forum.mysensors.org/topic/6948/synchronising-light-switch

      https://forum.mysensors.org/topic/6542/outdoors-touch-switch-light-controller?_=1596330659286

      T 1 Reply Last reply
      0
      • Boots33B Boots33

        @tante-ju

        If you are making a request to the controller it will return the required data for you to use, you will then need to have code on the requesting node to handle this return.

        If you are making a node to node request you will need to manually handle both the incoming request on the target node and then use node to node communication to the return of the required data to the node that requested the data. Then on the node that sent the request you will need to have code to separate this return from normal controller commands.

        In MySensors you can use message.sender to determine where the message came from and message.getCommand to see if the message is a request or command etc.

        Have a look at these three posts to see what these look like in use and also how to format a node to node message.

        https://forum.mysensors.org/topic/6422/display-node-how-to-set-up/20

        https://forum.mysensors.org/topic/6948/synchronising-light-switch

        https://forum.mysensors.org/topic/6542/outdoors-touch-switch-light-controller?_=1596330659286

        T Offline
        T Offline
        tante ju
        wrote on last edited by
        #3

        @Boots33

        I don't see any of the posts addressing the core issue.
        You could have different actions regarding variables:

        1. set variable in destination node
        2. request variable from destination node
        3. deliver variable from source node

        3 is a result of 2. In controller/node communication 3 is no issue, as it could just C_SET (as it would be with 1), because I think it is unlikely that a node wants to set a variable in the controller other than its own variable representation.

        But for 3 between nodes: How to differentiate it from 1 and 2? I could not find any standard or best practice approach. All the ones I found are based on assumption of using different variables in the nodes or that a node could not set a variable in another node (and hence could use C_SET as answer) or that the request is always from the controller.

        Boots33B 1 Reply Last reply
        0
        • T tante ju

          @Boots33

          I don't see any of the posts addressing the core issue.
          You could have different actions regarding variables:

          1. set variable in destination node
          2. request variable from destination node
          3. deliver variable from source node

          3 is a result of 2. In controller/node communication 3 is no issue, as it could just C_SET (as it would be with 1), because I think it is unlikely that a node wants to set a variable in the controller other than its own variable representation.

          But for 3 between nodes: How to differentiate it from 1 and 2? I could not find any standard or best practice approach. All the ones I found are based on assumption of using different variables in the nodes or that a node could not set a variable in another node (and hence could use C_SET as answer) or that the request is always from the controller.

          Boots33B Offline
          Boots33B Offline
          Boots33
          Hero Member
          wrote on last edited by
          #4

          sorry @tante-ju I am not quite getting what you are trying to achieve. Are you trying to request data directly from one node to the other of from a node to the controller.

          T 1 Reply Last reply
          0
          • Boots33B Boots33

            sorry @tante-ju I am not quite getting what you are trying to achieve. Are you trying to request data directly from one node to the other of from a node to the controller.

            T Offline
            T Offline
            tante ju
            wrote on last edited by
            #5

            @Boots33

            Node to Node. Between Nodes that have the same set of Variables.

            1 Reply Last reply
            0
            • S Offline
              S Offline
              Sasquatch
              wrote on last edited by
              #6

              I see it this way:
              NodeA sends C_REQ of Var1 to NodeB
              NodeB processes C_REQ message in receive();
              NodeB replies with C_SET of Var1 to NodeA just as controller would
              NodeA processes C_SET message in receive();

              You can use echo/ACK functionality or not, it doesn't matter.

              If you want both nodes to synchronise their variables, then it seems best to:
              a)request values on boot
              b)On variable change send values without prompt

              That way you cut traffic by half compared to request-reply approach.

              T 1 Reply Last reply
              0
              • S Sasquatch

                I see it this way:
                NodeA sends C_REQ of Var1 to NodeB
                NodeB processes C_REQ message in receive();
                NodeB replies with C_SET of Var1 to NodeA just as controller would
                NodeA processes C_SET message in receive();

                You can use echo/ACK functionality or not, it doesn't matter.

                If you want both nodes to synchronise their variables, then it seems best to:
                a)request values on boot
                b)On variable change send values without prompt

                That way you cut traffic by half compared to request-reply approach.

                T Offline
                T Offline
                tante ju
                wrote on last edited by
                #7

                @Sasquatch said in How to properly handle variable requests:

                I see it this way:
                NodeA sends C_REQ of Var1 to NodeB
                NodeB processes C_REQ message in receive();
                NodeB replies with C_SET of Var1 to NodeA just as controller would
                NodeA processes C_SET message in receive();

                You can use echo/ACK functionality or not, it doesn't matter.

                If you want both nodes to synchronise their variables, then it seems best to:
                a)request values on boot
                b)On variable change send values without prompt

                That way you cut traffic by half compared to request-reply approach.

                In case of vars to be synced that could be an approach. But in case, that is not intended, the C_SET looks for NodeA as a request to modify Var1 in NodeA.

                T 1 Reply Last reply
                0
                • T tante ju

                  @Sasquatch said in How to properly handle variable requests:

                  I see it this way:
                  NodeA sends C_REQ of Var1 to NodeB
                  NodeB processes C_REQ message in receive();
                  NodeB replies with C_SET of Var1 to NodeA just as controller would
                  NodeA processes C_SET message in receive();

                  You can use echo/ACK functionality or not, it doesn't matter.

                  If you want both nodes to synchronise their variables, then it seems best to:
                  a)request values on boot
                  b)On variable change send values without prompt

                  That way you cut traffic by half compared to request-reply approach.

                  In case of vars to be synced that could be an approach. But in case, that is not intended, the C_SET looks for NodeA as a request to modify Var1 in NodeA.

                  T Offline
                  T Offline
                  tante ju
                  wrote on last edited by
                  #8

                  I think I found a way, maybe an idea to document it somewhere?

                  If the C_REQ received has getLength()==0, it is a request for a value. If it has any payload, it is reply to a request.

                  Makes sense?

                  Boots33B 1 Reply Last reply
                  0
                  • T tante ju

                    I think I found a way, maybe an idea to document it somewhere?

                    If the C_REQ received has getLength()==0, it is a request for a value. If it has any payload, it is reply to a request.

                    Makes sense?

                    Boots33B Offline
                    Boots33B Offline
                    Boots33
                    Hero Member
                    wrote on last edited by Boots33
                    #9

                    @tante-ju
                    Sorry for the late reply, I have been away for a few days with work.

                    While I am sure there will be more than one way to achieve your goal I have given a brief outline of the way i did it below.

                    If all you want to do is request data from another node it should not need any more steps than @Sasquatch has listed above.
                    Lets say we have node A with an id of 1
                    we also have node B with an id of 2 and it has a binary sensor with a child id of 3

                    Node A wants to know the the status of the binary sensor on node B
                    So in your code on node A you will issue the request to query child id 3 on node 2

                     request( 3, V_STATUS,  2);
                    

                    The gateway will rout this directly to node B where you will need to have code to deal with the request in the receive(); function. In it's simplest form you could have something like this below.

                    void receive(const MyMessage &message) {
                    
                         if (message.type == V_STATUS) { 
                           if (message.getCommand() == C_REQ){   // message is request
                    
                             // put code here to be executed when the message is from a request
                             // most likely you will call a function that will get the requested 
                             // data and return it to node A. If you are expecting requests for more than 1
                             // sensor you can use  message.sensor to test which sensor the request is for 
                           
                    }
                           else {                                                             // message is from gateway,process the message as per normal
                               
                                // put code here to be executed when the message is from gateway   
                                }
                         }
                     }
                    

                    in the scenario above node B only expects requests from node A or commands from the gateway so it is easy to check what has arrived. If the message is a request we can execute code to get the required data and send it back. if it is a command (C_SET) from the gateway then it will fall through to the else part of the statement and be available as per normal.

                    To send back the Data you will need to use a node to node message.
                    this can be done on the fly, the format is shown below

                     /*   Node to Node message format.                                                                                     *
                              *                                                                                                            *
                              *                                                                                                            *
                              *            : Id of sending  : message  :   Destination     :     Destination      : Payload                *
                              *            :    sensor      :  Type    :    sensor Id      :       Node Id        :                        */ 
                             send(MyMessage(sendingSensorId, V_STATUS).setSensor(sensorId).setDestination(nodeId).set(true));  //send message to desitination node 
                    

                    So using our example you would have. (As we are not trying to actually switch any sensors on node A we can leave out the setSensor() part of the message)

                    send(MyMessage(3, V_STATUS).setDestination(1).set(true));
                    

                    Being a binary sensor the payload would be set to either true or false.

                    Now we have sent the data all that is left to do is catch it in the recieve part of node A. One way to do this is simply to test for where the message has come from, if it is from the gateway (node 0) or in our case node 2.

                    void receive(const MyMessage &message) {
                    
                     if (message.type == V_STATUS) {
                       if (message.sender == 0) {                                        // check if message is from gateway (node 0)
                        
                        // put code here for normal gateway messages
                        
                    }
                      else {                                                           // message is not from gateway so check to see if it is from node B 
                        
                        if (message.sender == 2 ){
                    
                             Put code here to deal with returning request
                        }
                    
                    } 
                    }
                    }
                    
                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    14

                    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