isAck(): differentiation between sent and received messages



  • Excuse my English, I have to work with translators.

    Hello, everybody,
    I get messages about Fhem and request and send messages to Fhem as well.
    Now I want to use Software-ACK and isAck() (new isEcho()) to make sure that the sent messages arrive.
    Problem is, the requests and messages from Fhem do not contain Ack and the serial port goes into endless loop.
    How can I check the messages in this regard (set, request)?



  • I have found a way:

    message.getCommand()



  • @frober Great news! - Perhaps you can post an example to help others who may hit the same problem?



  • As soon as all tests are positive, I will publish an example.

    I found my solution here, first entry:
    Sketch



  • The approach to differentiate the message did not work for my purpose:

    • commands sent from Fhem are a set message
    • requests return as set message
    • Status message of the node (set message) returns as set message with Ack

    I.e. all are set messages (no differentiation possible)

    Because I use a counter to limit the resending of the status message from the node I used this counter to get to the destination.

    In short: If the reception was successful the counter goes to 0, the request to <0 and the send to >0.

    Here is my sketch, it is for switching several time controlled relays, for clarity I have removed the debug messages:

    /**
    * The MySensors Arduino library handles the wireless radio link and protocol
    * between your home built sensors/actuators and HA controller of choice.
    * The sensors forms a self healing radio network with optional repeaters. Each
    * repeater and gateway builds a routing tables in EEPROM which keeps track of the
    * network topology allowing messages to be routed to nodes.
    *
    * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
    * Copyright (C) 2013-2018 Sensnology AB
    * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
    *
    * Documentation: http://www.mysensors.org
    * Support Forum: http://forum.mysensors.org
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * version 2 as published by the Free Software Foundation.
    *
    *******************************
    *
    * DESCRIPTION
    * The RS485 Gateway prints data received from sensors on the serial link.
    * The gateway accepts input on seral which will be sent out on
    * the RS485 link.
    *
    * Wire connections (OPTIONAL):
    * - Inclusion button should be connected between digital pin 3 and GND
    * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
    *
    * LEDs (OPTIONAL):
    * - RX (green) - blink fast on radio message received. In inclusion mode will blink fast only on presentation received
    * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
    * - ERR (red) - fast blink on error during transmission error or receive crc error
    *
    * If your Arduino board has additional serial ports
    * you can use to connect the RS485 module.
    * Otherwise, the gateway uses AltSoftSerial to handle two serial
    * links on one Arduino. Use the following pins for RS485 link
    *
    *  Board          Transmit  Receive   PWM Unusable
    * -----          --------  -------   ------------
    * Teensy 3.0 & 3.1  21        20         22
    * Teensy 2.0         9        10       (none)
    * Teensy++ 2.0      25         4       26, 27
    * Arduino Uno        9         8         10
    * Arduino Leonardo   5        13       (none)
    * Arduino Mega      46        48       44, 45
    * Wiring-S           5         6          4
    * Sanguino          13        14         12
    *
    */
    
    #define SN "MultiTimerRelay"
    #define SV "1.0"
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    // Enable RS485 transport layer
    #define MY_RS485
    
    // Define this to enables DE-pin management on defined pin
    //#define MY_RS485_DE_PIN 2
    
    // Set RS485 baud rate to use
    #define MY_RS485_BAUD_RATE 19200
    
    // Enable this if RS485 is connected to a hardware serial port
    #define MY_RS485_HWSERIAL Serial
    
    #define MY_NODE_ID 2   // Id of the Node
    #define MY_TRANSPORT_WAIT_READY_MS 30000  //loop is beginning at 3000ms whitout connection
    
    
    #include <MySensors.h>
    
    //++++++++ Relays +++++++++
    #define RELAY_ON 1                         // switch around for ACTIVE LOW / ACTIVE HIGH relay
    #define RELAY_OFF 0
    #define noRelays 3                         // min 2
    const int relayPin[] = {7, 8, 9};          // switch around pins to your desire
    uint32_t relayTime[] = {0, 0, 0};          // on time for Relay to set from Fhem
    volatile uint32_t startTime[] = {0, 0, 0}; // time to switch Relay on
    int relayAckCountR[noRelays];              // ACK retry counter relay
    int relayAckCountT[noRelays];              // ACK retry counter time
    const uint32_t timeFactor = 1000UL;        // to send minutes = 60000UL or seconds = 1000UL; UL says compiler is unsigned long!!!
    
    class Relay                                // relay class, store all relevant data (equivalent to struct)
    {
      public:
        int relayPin;                          // physical pin number of relay
        boolean relayState;                    // relay status (also stored in EEPROM)
        uint32_t relayTime;                    // on time for Relay
        uint32_t startTime;                    // time to switch Relay on
        int relayAckCountR;                     // ACK retry counter relay
        int relayAckCountT;                     // ACK retry counter time
    };
    
    Relay Relays[noRelays];
    MyMessage msgRelay[noRelays];
    MyMessage msgTime[noRelays];
    
    
    void before() 
    {
      
    }
    
    void presentation() 
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
    
       //++++++++ Relays +++++++++
       for (int i = 0; i < noRelays; i++)
      {
        present(i, S_DIMMER);                                  // present sensor to gateway
        wait(20);
      }
     }
    
    void setup()
    {
      //++++++++ Relays +++++++++
      for (int i = 0; i < noRelays; i++) {    
        Relays[i].relayPin = relayPin[i];           // assign physical pins
        Relays[i].startTime = startTime[i];         // assign time to switch relay on
        Relays[i].relayTime = relayTime[i];         // assign time for relay on
        msgRelay[i].sensor = i;                     // initialize messages
        msgRelay[i].type = V_STATUS;
        msgTime[i].sensor = i;                       
        msgTime[i].type = V_PERCENTAGE;
        pinMode(Relays[i].relayPin, OUTPUT);
        Relays[i].relayState = RELAY_OFF;           // set all relaysState off
        digitalWrite(Relays[i].relayPin, Relays[i].relayState ? RELAY_ON : RELAY_OFF); // write all relays off
        //send(msgRelay[i].set(Relays[i].relayState ? true : false));
        wait(20);
        }
      for (int i = 0; i < noRelays; i++)
      {
        request(i, V_STATUS);                        // Set relay to last known state
        Relays[i].relayAckCountR = -1;               // for the control of the request
        wait(100);
        request(i, V_PERCENTAGE);                   // Set relay to last known state
        Relays[i].relayAckCountT = -1;              // for the control of the request
        wait(100);
      }
    }
    
    void loop() 
    {
      //++++++++ Relays +++++++++
      uint32_t currentTime = millis();
      
      //Zeitsteuerung der Relays
      for (byte i = 0; i < noRelays; i++) {
        if ( Relays[i].relayState == RELAY_ON && (currentTime - Relays[i].startTime > Relays[i].relayTime)) {
          digitalWrite(Relays[i].relayPin, !Relays[i].relayState ? RELAY_ON : RELAY_OFF);
          Relays[i].relayState = !Relays[i].relayState;
          send(msgRelay[i].set(Relays[i].relayState ? true : false), true); // Send value to gw with ACK
          Relays[i].relayTime = 0;
          Relays[i].relayAckCountR = 3;
          wait(100);
          send(msgTime[i].set(Relays[i].relayTime), true); // Send value to gw with ACK
          Relays[i].relayAckCountT = 3;
          wait(100);
    
         }
      }
      for (int i = 0; i < noRelays; i++) {
        if (Relays[i].relayAckCountR < 0) {
          wait(200);
          request(i, V_STATUS);                        // Set relay to last known state
          Relays[i].relayAckCountR = 0;
          wait(100);
       
         }
         if (Relays[i].relayAckCountT < 0) {
          wait(200);
          request(i, V_PERCENTAGE);                    // Set relay to last known state
          Relays[i].relayAckCountT = 0;
          wait(100);
        
         }
      if (Relays[i].relayAckCountR > 0) {
          wait(200);
          send(msgRelay[i].set(Relays[i].relayState ? true : false), true); // Send value to gw with ACK
          wait(100);
         
         }
         if (Relays[i].relayAckCountT > 0) {
          wait(200);
          send(msgTime[i].set(Relays[i].relayTime), true); // Send value to gw with ACK
          wait(100);
          
         }
      }
    }
    
    
    void receive(const MyMessage &message) {
    
     //++++++++ Relays +++++++++
      if (message.type == V_STATUS && Relays[message.sensor].relayAckCountR <= 0) {
        Relays[message.sensor].relayAckCountR = 0;
        if (message.sensor < noRelays) {          // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
          Relays[message.sensor].relayState = message.getBool();
          digitalWrite(Relays[message.sensor].relayPin, Relays[message.sensor].relayState ? RELAY_ON : RELAY_OFF); // and set relays accordingly
          //saveState( message.sensor, Relays[message.sensor].relayState ); // save sensor state in EEPROM (location == sensor number)
          }
        if (Relays[message.sensor].relayState == RELAY_ON) {
          Relays[message.sensor].startTime = millis();
        }
     }
     else if (message.isAck() && message.type == V_STATUS && Relays[message.sensor].relayAckCountR > 0) {
          Relays[message.sensor].relayAckCountR = 0;
     }
     else if (!message.isAck() && message.type == V_STATUS && Relays[message.sensor].relayAckCountR > 0) {
          Relays[message.sensor].relayAckCountR--;
     }
     else if (message.type == V_PERCENTAGE && Relays[message.sensor].relayAckCountT <= 0) {
        if (message.sensor < noRelays) {          // check if message is valid for relays..... previous line  [[[ if (message.sensor <=noRelays){ ]]]
          Relays[message.sensor].relayTime = (message.getByte() * timeFactor);    // calculate to millis
          }
     }
     else if (message.isAck() && message.type == V_PERCENTAGE && Relays[message.sensor].relayAckCountT > 0) {
          Relays[message.sensor].relayAckCountT = 0;
     }
     else if (!message.isAck() && message.type == V_PERCENTAGE && Relays[message.sensor].relayAckCountT > 0) {
          Relays[message.sensor].relayAckCountT --;
     }
    }
     
    

Log in to reply
 

Suggested Topics

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts