request variable from gateway



  • In my current setup I use an ESP8266 as a mqtt gateway.

    To maintain a global variable across all nodes I use a V_ARMED on the gateway. mycontroller is able to change the armed variable.

    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if(message.type == V_ARMED && message.sender != 0)
      {
          Serial.print("Node "); Serial.print(message.sender); Serial.print(" requested armed status");
          Serial.print("Commandtype: "); Serial.print(message.getCommand());
          Serial.println();
          
          MyMessage msg(0,V_ARMED);
          msg.setDestination(message.sender);
          msg.set(armed);
          send(msg);
      }
      else if (message.type==V_ARMED && message.sender == 0) {
         Serial.print("Node "); Serial.print(message.sender); Serial.print(" set armed status");
         Serial.print("Commandtype: "); Serial.print(message.getCommand());
         Serial.println();
         // Change relay state
         if(message.getBool() == true)
         {
            armed = true;
            saveState(V_ARMED, true);
         }
         else
         {
            armed = false;
            saveState(V_ARMED, false);
         }
       }
       else
       {
         
       }
       
       // Write some debug info
       Serial.print("Incoming change for sensor:");
       Serial.print(message.sensor);
       Serial.print(", New status: ");
       Serial.println(message.getBool());
    }
    

    however .. running

          // Request armed status from gateway (default)
          request(0,V_ARMED,0);
    

    from my node which I would expect to request V_ARMED from the gatway results in no call of the receive function. Not even the general print statement at the end of the receive function of the gatway is called. Am I missing something?

    But one thing is disturbing me

    The requestions node gets an RESPONES .. form .. i dont know where ?!

    -------------Message Information:-------------<\r><\n>
    last:               0<\r><\n>
    sender:             0<\r><\n>
    destination:       20<\r><\n>
    command:     set (1)<\r><\n>
    isAck:          false<\r><\n>
    type:              15<\r><\n>
    sensor:             0<\r><\n>
    payload:     1<\r><\n>
    ----------------------------------------------<\r><\n>
    

    I can only say, that it is not from my gateways .. as there is no output from the receive function.

    Upon further notification I noticed this on mycontroller:

    0_1472301014297_upload-e8a592bd-077b-47c5-a548-df4e2f098b73

    This happend after I changed

          // Request armed status from gateway (default)
          request(0,V_ARMED,0);
    

    to

          // Request armed status from gateway (default)
          request(15,V_ARMED,0);
    

    Which leads me to the believe that the function request is actually broken on mqtt_gateway as the message is interpreted the same as any other message and thus relayed to the controller.

    enabling debug on the gateway:

    0;255;3;0;9;TSP:MSG:SEND 0-0-20-20 s=0,c=1,t=25,pt=3,l=2,sg=0,ft=0,st=ok:0<\n>
    0;255;3;0;9;Sending message on topic: mygateway-out/20/0/1/0/25<\n>
    0;255;3;0;9;Sending message on topic: mygateway-out/0/0/1/0/15<\n>
    

    Yep ..it is being published .. but why? It is only a request message!!!

    Throwing a quicksearch on the mysensor folder results in ...

    0_1472301565932_upload-792068bc-8ab8-42c2-b876-f0b69a71715d

    Wait .. C_REQ is set but there is no code to actually handle it? ANYWHERE?

    I opend an issue on github:

    https://github.com/mysensors/MySensors/issues/573


  • Contest Winner

    @cimba007 if understand your question correctly. Then your assumption is that the gateway responds to a request made by any node?

    If that is your question and if I understand MySensors correctly, then to answer is "Partly true". Because the gateway is just gateway and contains no logic. It delegates the request to the controller. In your case any MQTT client that happens to listen to request made by a node. That client should publish a response to that request to your MQTT gateway (which I believe is also an MQTT client).

    So if no one is responding to a node's request, a node will never receive the answers to it's requests.



  • @TheoL Thanks for your very quick reply

    First and foremost the gateway is a node like any node (from my understanding). It just happended to have the gateway feature enabled:

    #define MY_GATEWAY_MQTT_CLIENT
    #define MY_GATEWAY_ESP8266
    

    I understand the issue that it is (for me at least) not clear who will responst to the REQUEST function? If I request a variable from any normal node I have to handle the conde in the receive function (I do this on the gateway) .. but as it is a gateway it magically forwards the message to the controller.

    In my case the requestions node receives an response .. always payload "1" .. so I am not sure if the controller is not doing its job (mycontroller). I will open an issue there too.

    The documentation states:

    https://www.mysensors.org/download/sensor_api_20#requesting-data

    Requests a variable value from gateway or some other sensor in the radio network.

    If the controller should handle the request there should be written:

    Requests a variable value from THE CONTROLLER or some other sensor in the radio network.

    To differentiate between different messages (for example if the message is a normal "sensor value") which should be send to the controller should be determined by evaluating C_REQ

    Having a look at send and request there seems to be a difference:

    void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) {
    	_sendRoute(build(_msgTmp, _nc.nodeId, destination, childSensorId, **C_REQ**, variableType, false).set(""));
    }
    
    bool send(MyMessage &message, bool enableAck) {
    	message.sender = _nc.nodeId;
    	**mSetCommand(message, C_SET);**
    	mSetRequestAck(message, enableAck);
    
    	#if defined(MY_REGISTRATION_FEATURE) && !defined(MY_GATEWAY_FEATURE)
    		if (_nodeRegistered) {	
    			return _sendRoute(message);
    		}
    		else {
    			debug(PSTR("NODE:!REG\n"));
    			return false;
    		}
    	#else
    		return _sendRoute(message);
    	#endif
    	}
    

    But from my quick look this is not handled anywhere in the sourcecode 😉



  • https://github.com/mycontroller-org/mycontroller/issues/264

    I think i narrowed down the issue .. the wrong value is returned from mycontroller.org upon receiving the request.

    Still the documentation on mysensor should clearly state who will respond the the request message .. the controller or the actual sensor.


  • Plugin Developer

    @cimba007 AFAIK, earlier version of MySensors.org does not support any sensors. It was acting only as a gateway. never control any sensors. request feature was designed that time. It was designed as, if some one request data from gateway(default), it will forward the request to controller. If do a request from other than gateway (other destination - like you have mentioned) it will be forwarded to that particular destination node(this operation happens without controller knowledge).

    But recently MySensors introduced sensors support on Gateway too. I hope this request feature not redesigned yet. I believe it is tough to change this logic. Because gateway's primary response is, if some one asked any request with the destination id as 0, gateway believes it is for controller.

    In your case it happens as follows,

    • You requested sensor 0 of V_ARMED status and destination is 0 (gateway id)
    • Gateway thinks this message for controller(as per current design) and sent to controller
    • controller reads this message as 50;0;2;0;15;(node-id;child-sensor-id;message-type;ack;sub-type;payload), which means nodeId=50 requested V_ARMED data of SensorId 0. It looks in db and nothing found. It creates entry for this node/sensor/variable and sends some default value(MyController designed like if it receives message from new device, create an entry for that).


  • Okay .. I tried the following:

    void loop()
    {
      Serial.println(".");
      request(0,V_LIGHT_LEVEL,10);
      wait(50);
      sleep(5000);
    }
    

    0_1472320551772_upload-8f40a3ca-539e-4f22-ad15-0e56f62feeae

    But I get no response as node 10 is 99% of the time in sleep mode.

    This creates a funny situation .. if a node wants to request the latest value of another node .. the other node has to process the request and responde accordingly. This will not working if the other node is sleeping.

    If the same nodes requests data from the gateway which is online .. the gateway does not process the message and querys the controller to supply the data .. which it does not have.

    Sofar that I understand the request feature it is utterly useless. Either all responses should come from the controller or all responses should come from the designated destination of the message. In the current design it is mixed and is working different for nodes and gateways as destination.



  • Okay .. I tried the following:

    void loop()
    {
      Serial.println(".");
      request(0,V_LIGHT_LEVEL,10);
      wait(50);
      sleep(5000);
    }
    

    0_1472320551772_upload-8f40a3ca-539e-4f22-ad15-0e56f62feeae

    But I get no response as node 10 is 99% of the time in sleep mode.

    This creates a funny situation .. if a node wants to request the latest value of another node .. the other node has to process the request and responde accordingly. This will not working if the other node is sleeping.

    If the same nodes requests data from the gateway which is online .. the gateway does not process the message and querys the controller to supply the data .. which it does not have.

    Sofar that I understand the request feature it is utterly useless. Either all responses should come from the controller or all responses should come from the designated destination of the message. In the current design it is mixed and is working different for nodes and gateways as destination.

    MySensor 1.5

    0_1472321377252_upload-750e6187-f0e0-4cba-857d-3b1601e664bc ![0_1472321069793_upload-385a2970-1384-4d2a-9076-4b7f9e32ca1a](Uploading 100%)

    MySensor 2.0

    0_1472321343368_upload-a2d76890-60bc-47b3-af53-e2b325f53961 ![0_1472321136082_upload-83419ed7-f4e0-4ba9-a064-be915feb3476](Uploading 100%)

    From this reading the controller should never respond to request messages, the destination node had to handle the responde itself. Correct me if I am wrong but this is how it is written in the mysensor documentation.


  • Plugin Developer

    @cimba007 said:

    From this reading the controller should never respond to request messages, the destination node had to handle the responde itself. Correct me if I am wrong but this is how it is written in the mysensor documentation.

    Controller receives request from gateway, So it is doing it's job.
    It is correct for other nodes not for gateway node

    Think other way, with the current design,

    • A node wants to get it is own state/configuration/etc from controller, it has to be sent to gateway(default). So gateway forwards to controller and controller responds back.
    • If we change this step gateway will respond. But if node wants to get it own configuration/state/etc., from gateway it never reach to controller. Gateway will deal with it's local sensor id.
    • As per current design you cannot request gateway's sensor data
    Workaround #1
    • You have to move your sensor from gateway node to non-gateway node. and use non-gateway node id as destination
    Workaround #2 (MyController.org specific)
    • Create new dummy sensor on a node from where you are requesting data
    • Add Forward payload for gateway-sensor data to node-dummy-sensor
    • do self request with dummy-sensor id
    • My controller reads dummy-sensor-data(gateway sensor data) and reports back to your node


  • Okay, thanks for this very good explanation.

    @HEK: Would it be possible to adjust the current documentation of mysensor 2.0 request feature to include jkandasa's explanation? If it confuses me I think it might confuse other people as well.

    Requesting its own configuration from the controller is a usecase I never thought about.

    I thought saveState and loadState should be used to store this data on the node itself.

    WORKAROUND #3 😉

    To mitigate the issue I think I will save the V_ARMED state on the nodes. In addition to that my nodes will query their own V_ARMED status from the controler. Even if the change of status from CONTROLLER->NODE was not received by the node the node will eventually update to the correct status.

    Still somehow sad that there is currently no way for a node to request data from other nodes if they are offline. This could be addressed by changing the request feature:

    @HEK: Do you think this is something other users might want as well? If so I would gladly open an issue as featurerequest on github.

    • Request data from controller
    • Request data from destination node

    This would make clear what the request function is for and what the expected result would be.


  • Plugin Developer

    @cimba007 said:

    I thought saveState and loadState should be used to store this data on the node itself.

    Yes, saveState and loadState used to store data on local node itself (EEPROM). Do not get confused requests with loadState and saveState. Both are completely different 😉



  • @jkandasa

    I just never thought that requesting your own configuration from the controller would be needed, exactly as there is saveState and loadState so requesting from controller would be unnecessary.


  • Plugin Developer

    @cimba007 said:

    I just never thought that requesting your own configuration from the controller would be needed, exactly as there is saveState and loadState so requesting from controller would be unnecessary.

    It is necessary in some cases,

    • When you want to get offset/calibration values.
    • Smart-sleep recently added, before when node wake-up get some date(adjust sleep duration) from controller with request
    • etc.,


  • @jkandasa said:

    It is necessary in some cases,

    • Smart-sleep recently added, before when node wake-up get some date(adjust sleep duration) from controller with request

    Yep .. but this would be even more useful if one node could query other nodes data and receive the resonse from the controller (if the other node is sleeping).

    Again .. my proposal is to differentiate between:

    • Request data from controller (for any other node, including gateway) ( = history query of most recent update the controller knows about)
    • Request data from destination node ( = live query )

    Edit: I just discovered resource groups on mycontroller .. think this will help out a lot with my planned workaround 😉

    Edit2: I could not help myself and request an improvement: https://github.com/mysensors/MySensors/issues/574


Log in to reply
 

Suggested Topics

  • 1
  • 6
  • 3
  • 3
  • 5
  • 1

0
Online

11.4k
Users

11.1k
Topics

112.7k
Posts