 
					
						
					
				
				
					But.... Can you also help me to add to this sketch option to send to example to Home Assistant also DESCRIPTION to each sensors ? And description will be get from sketch from name about address sensor ?
As in this sketch which i have for relay:
#define USE_EXPANDER
// Enable debug prints to serial monitor
//#define MY_DEBUG
#define MY_GATEWAY_SERIAL
#include <MySensors.h>
#include <Bounce2.h>
#ifdef USE_EXPANDER
  #include <Wire.h>    // Required for I2C communication
  #include "PCF8574.h"
  uint8_t expanderAddresses[] = {0x20};
  const int numberOfExpanders = sizeof(expanderAddresses);
  PCF8574 expander[numberOfExpanders];
  #define E(expanderNo, ExpanderPin) (((expanderNo+1)<<8) | (ExpanderPin))
#endif
// No Button Constant
#define NOB -1
#define MULTI_RELAY_VERSION 9
#define RELAY_STATE_STORAGE 1
const uint8_t RELAY_TRIGGER_LOW  = 0;
const uint8_t RELAY_TRIGGER_HIGH = 1;
const uint8_t RELAY_STARTUP_ON   = 2;
const uint8_t RELAY_STARTUP_OFF  = 4;
const uint8_t RELAY_STARTUP_MASK = RELAY_STARTUP_ON | RELAY_STARTUP_OFF;
enum ButtonType {
  MONO_STABLE = 0,
  BI_STABLE = 1,
  DING_DONG = 2 // HIGH state immediatly after push, LOW state after release
};
typedef struct {
  int sensorId;
  int relay;
  int button;
  uint8_t relayOptions;
  ButtonType buttonType;
  const char * relayDescription;
} RelayButton;
// CONFIGURE ONLY THIS ARRAY!
// Row params: sensor ID - sensor ID reported on MySensor Gateway
//             relay pin - Expander supported
//             button pin - <0 for virtual buttons (only available in MySensor Gateway); no support for Expander
//             relay options - [RELAY_TRIGGER_LOW|RELAY_TRIGGER_HIGH] {RELAY_STARTUP_ON|RELAY_STARTUP_OFF}
//             button type - [MONO_STABLE|BI_STABLE|DING_DONG]
//             relay description - reported on MySensor Gateway, can help identify device on initial configuration in Home Automation App, can be empty ("")
RelayButton myRelayButtons[] = {
  {0, 2, A0, RELAY_TRIGGER_LOW, MONO_STABLE, "Ł2 - kinkiet [C10]"},  // WŁ: Ł2
  {1, 16, A1, RELAY_TRIGGER_LOW, BI_STABLE, "Salon 2 [A9]"},  // WŁ: Salon 2
  {2, 15, A2, RELAY_TRIGGER_LOW, BI_STABLE, "Salon 1 [A10]"},  // WŁ: Salon 1
  {3, E(0,1), A3, RELAY_TRIGGER_LOW | RELAY_STARTUP_OFF, BI_STABLE, "Halogen - Taras [B8]"},  // WŁ: Taras
  {4, 22, A4, RELAY_TRIGGER_LOW, BI_STABLE, "Kuchnia [B2]"},  // WŁ: Kuchnia 1
  {5, 23, A5, RELAY_TRIGGER_LOW, BI_STABLE, "Kuchnia - Kinkiet [B3]"},  // WŁ: Kuchnia 2
  {6, 28, A6, RELAY_TRIGGER_LOW, BI_STABLE, "Jadalnia 2 [A4]"},  // WŁ: Hall I/Jadalnia prawy
  {17, 17, A7, RELAY_TRIGGER_LOW, BI_STABLE, "Ł1 - Kinkiet [A11]"},  // WŁ: Hall I/Ł1 prawy
  {8, 31, A8, RELAY_TRIGGER_LOW, MONO_STABLE, "Garaż [A7]"},  // WŁ: Kotłownia/Garaż
  {8, 31, A9, RELAY_TRIGGER_LOW, MONO_STABLE, "Garaż [A7]"},  // WŁ: Garaż
  {10, 14, A10, RELAY_TRIGGER_LOW | RELAY_STARTUP_ON, BI_STABLE, "Halogen - wejście [B4]"},  // WŁ: Drzwi wejściowe
  {11, E(0,7), A11, RELAY_TRIGGER_LOW, DING_DONG, "Dzwonek [?]"},  // WŁ: Dzwonek
  {12, 29, A12, RELAY_TRIGGER_LOW, BI_STABLE, "Hall 1 [A5]"},  // WŁ: Hall I/Jadalnia lewy
  {12, 29, A13, RELAY_TRIGGER_LOW, BI_STABLE, "Hall 1 [A5]"},  // WŁ: Hall I/Wiatrołap
  {14, 32, A14, RELAY_TRIGGER_LOW, BI_STABLE, "Wiatrołap [A8]"},  // WŁ: Wiatrołap/Hall I
  {15, 19, A15, RELAY_TRIGGER_LOW, MONO_STABLE, "Kotłownia [B1]"},  // WŁ: Kotłownia/Hall I
  {16, 24, 53, RELAY_TRIGGER_LOW, BI_STABLE, "Ł1 - Taśma LED [C1]"},  // WŁ: Hall I/Ł1 środek
  {17, 17, 52, RELAY_TRIGGER_LOW, MONO_STABLE, "Ł1 - Kinkiet [A11]"},  // WŁ: Ł1
  {18, 18, 51, RELAY_TRIGGER_LOW, BI_STABLE, "Ł1 [A12]"},  // WŁ: Hall I/Ł1 lewy
  {19, 6, 50, RELAY_TRIGGER_LOW, BI_STABLE, "Klatka Schodowa [B7]"},  // WŁ: Hall I/Schody 1
  {12, 29, 49, RELAY_TRIGGER_LOW, BI_STABLE, "Hall 1 [A5]"},  // WŁ: Hall I/Schody 2
  {21, 26, 48, RELAY_TRIGGER_LOW, BI_STABLE, "Gabinet [A2]"},  // WŁ: Gabinet
  {22, 7, 47, RELAY_TRIGGER_LOW, BI_STABLE, "Hall 2 [B5]"},  // WŁ: Hall II/Schody 1
  {19, 6, 46, RELAY_TRIGGER_LOW, BI_STABLE, "Klatka Schodowa [B7]"},  // WŁ: Hall II/Schody 2
  {24, 10, 45, RELAY_TRIGGER_LOW, BI_STABLE, "Garderoba [C12]"},  // WŁ: Garderoba
  {25, 4, 44, RELAY_TRIGGER_LOW, MONO_STABLE, "Pok. nad kuchnią 2 [B10]"},  // WŁ: Pok. nad kuchnią 2
  {26, 5, 43, RELAY_TRIGGER_LOW, BI_STABLE, "Pok. nad kuchnią 1 [B9]"},  // WŁ: Pok. nad kuchnią 1
  {27, 8, 42, RELAY_TRIGGER_LOW, BI_STABLE, "Pok. nad salonem 2 [B12]"},  // WŁ: Pok. nad salonem 2
  {28, 9, 41, RELAY_TRIGGER_LOW, MONO_STABLE, "Pok. nad salonem 1 [B11]"},  // WŁ: Pok. nad salonem 1
  {29, 3, 40, RELAY_TRIGGER_LOW, BI_STABLE, "Ł2 [C7]"},  // WŁ: Hall II/Ł2 1
  {30, E(0,3), 39, RELAY_TRIGGER_LOW, BI_STABLE, "Ł2 - Taśma LED [?]"},  // WŁ: Hall II/Ł2 2
  {22, 7, 38, RELAY_TRIGGER_LOW, BI_STABLE, "Hall 2 [B5]"},  // WŁ: Hall II/Sypialnia
  {32, 11, 37, RELAY_TRIGGER_LOW, BI_STABLE, "Sypialnia 2 [C9]"},  // WŁ: Sypialnia 2
  {33, 12, 36, RELAY_TRIGGER_LOW, BI_STABLE, "Sypialnia 1 [C8]"},  // WŁ: Sypialnia 1
  {34, 25, -1, RELAY_TRIGGER_LOW | RELAY_STARTUP_ON, MONO_STABLE, "Halogen - Garaż [A1]"},  // WŁ: Virtual Button 1
  {35, 30, -2, RELAY_TRIGGER_LOW | RELAY_STARTUP_OFF, MONO_STABLE, "Ł1 - Wentylator [A3]"},  // WŁ: Virtual Button 2
  {36, E(0,2), -3, RELAY_TRIGGER_LOW | RELAY_STARTUP_OFF, MONO_STABLE, "Halogen - wschód [B6]"},  // WŁ: Virtual Button 3
  {37, E(0,4), -4, RELAY_TRIGGER_LOW, MONO_STABLE, "Lampki schodowe [C6]"},  // WŁ: Virtual Button 4
  {38, E(0,5), -5, RELAY_TRIGGER_LOW, MONO_STABLE, "Lampki podłogowe I [C4]"},  // WŁ: Virtual Button 5
  {39, E(0,6), -6, RELAY_TRIGGER_LOW, MONO_STABLE, "Lampki podłogowe II [C2]"},  // WŁ: Virtual Button 6
  {40, E(0,0), -7, RELAY_TRIGGER_LOW | RELAY_STARTUP_OFF, MONO_STABLE, "Ł2 - wentylator [C11]"},  // WŁ: Virtual Button 7
};
const int numberOfRelayButtons = sizeof(myRelayButtons) / sizeof(RelayButton);
typedef struct {
  int firstButton;
  int nextButton;
} RelayMultiButtons;
RelayMultiButtons relayMultiButtons[numberOfRelayButtons];
uint8_t myRelayState[numberOfRelayButtons];
// MySensors - Sending Data
// To send data you have to create a MyMessage container to hold the information.
MyMessage msgs[numberOfRelayButtons];
Bounce myButtonDebouncer[numberOfRelayButtons];
//Function Declaration
uint8_t loadRelayState(int relayNum, uint8_t forceEeprom = 0);
void saveRelayState(int relayNum, uint8_t state, uint8_t useEeprom);
void saveRelayState(int relayNum, uint8_t state);
void changeRelayState(int relayNum, uint8_t relayState);
// MySensors - This will execute before MySensors starts up
void before() {
  Serial.begin(115200);
  
  #ifdef USE_EXPANDER
    /* Start I2C bus and PCF8574 instance */
    for(int i = 0; i < numberOfExpanders; i++) {
      expander[i].begin(expanderAddresses[i]);
    }
  #endif
  
  // initialize multiple buttons list structure
  for (int i = 0; i < numberOfRelayButtons; i++) {
    relayMultiButtons[i].firstButton = -1;
    relayMultiButtons[i].nextButton = -1;
  }
  // find multiple buttons for the same relay (uni-directional list)
  for (int i = 0; i < numberOfRelayButtons-1; i++) {
    if (relayMultiButtons[i].firstButton == -1) {
      int prevRelayButton = i;
      for (int j = i+1; j < numberOfRelayButtons; j++) {
        if (myRelayButtons[i].relay == myRelayButtons[j].relay) {
          relayMultiButtons[prevRelayButton].firstButton = i;
          relayMultiButtons[prevRelayButton].nextButton = j;
          relayMultiButtons[j].firstButton = i;
          prevRelayButton = j;
        }
      }
    }
  }
  
  // if version has changed, reset state of all relays
  int versionChangeResetState = (MULTI_RELAY_VERSION == loadState(0) ) ? 0 : 1;
  
  for (int i = 0; i < numberOfRelayButtons; i++) {
    // if this relay has multiple buttons, load only first
    if (relayMultiButtons[i].firstButton == -1 || relayMultiButtons[i].firstButton == i) {
      // Then set relay pins in output mode
      #ifdef USE_EXPANDER
        if ( myRelayButtons[i].relay & 0xff00 ) {
          // EXPANDER
          int expanderNo = (myRelayButtons[i].relay >> 8) - 1;
          int expanderPin = myRelayButtons[i].relay & 0xff;
          expander[expanderNo].pinMode(expanderPin, OUTPUT);
        } else {
      #endif
          pinMode(myRelayButtons[i].relay, OUTPUT);
      #ifdef USE_EXPANDER
        }
      #endif
      
      uint8_t isTurnedOn = 0;
      
      if (myRelayButtons[i].relayOptions & RELAY_STARTUP_ON) {
        isTurnedOn = 1;
      } else if (myRelayButtons[i].relayOptions & RELAY_STARTUP_OFF) {
      } else {
        // Set relay to last known state (using eeprom storage)
        isTurnedOn = loadRelayState(i, 1); // 1 - true, 0 - false
        if (versionChangeResetState && isTurnedOn) {
          saveRelayState(i, 0, 1);
          isTurnedOn = 0;
        }
      }
      changeRelayState(i, isTurnedOn);
      myRelayState[i] = isTurnedOn;
    }
  }
  if (versionChangeResetState) {
    // version has changed, so store new version in eeporom
    saveState(0, MULTI_RELAY_VERSION);
  }
}
// executed AFTER mysensors has been initialised
void setup() {
  for(int i = 0; i < numberOfRelayButtons; i++) {
    if (myRelayButtons[i].button >= 0) {
      // No Expander support for buttons (de-bouncing)
      pinMode(myRelayButtons[i].button, INPUT_PULLUP); // HIGH state when button is not pushed
    }
  }
  // Setup locally attached sensors
  delay(5000);
  // Send state to MySensor Gateway
  for(int i = 0; i < numberOfRelayButtons; i++) {
    // if this relay has multiple buttons, send only first
    if (relayMultiButtons[i].firstButton == -1 || relayMultiButtons[i].firstButton == i) {
      msgs[i] = MyMessage(myRelayButtons[i].sensorId, V_LIGHT);
      uint8_t relayState;
      if (myRelayButtons[i].relayOptions & RELAY_STARTUP_ON) {
        relayState = 1;
      } else if (myRelayButtons[i].relayOptions & RELAY_STARTUP_OFF) {
        relayState = 0;
      } else {
        relayState = loadRelayState(i);
      }
      send(msgs[i].set(relayState)); // send current state
    }
  }
  // Setup buttons
  for(int i = 0; i < numberOfRelayButtons; i++) {
    if (myRelayButtons[i].button >= 0) {
      // setup debouncer
      myButtonDebouncer[i] = Bounce();
      myButtonDebouncer[i].attach(myRelayButtons[i].button);
      myButtonDebouncer[i].interval(50);
    }
  }
}
void loop() {
  for(int i = 0; i < numberOfRelayButtons; i++) {
    if (myRelayButtons[i].button >= 0 && myButtonDebouncer[i].update()) {
      int buttonState = myButtonDebouncer[i].read();
      #ifdef MY_DEBUG
        Serial.print("# Button ");
        Serial.print(i);
        Serial.print(" changed to: ");
        Serial.println(buttonState);
      #endif
      
      int relayNum = (relayMultiButtons[i].firstButton == -1) ? i : relayMultiButtons[i].firstButton;
      
      if (myRelayButtons[i].buttonType == DING_DONG) {
        if (buttonState == LOW) { // button pressed
          changeRelayState(relayNum, 1);
          send(msgs[relayNum].set(1));
        } else { // button released
          changeRelayState(relayNum, 0);
          send(msgs[relayNum].set(0));
        }
      } else if (myRelayButtons[i].buttonType == BI_STABLE || buttonState == HIGH) {
        // If button type is BI_STABLE, any change will toggle relay state
        // For MONO_STABLE, button must be pushed and released (HIGH)
        uint8_t isTurnedOn = ! loadRelayState(relayNum); // 1 - true, 0 - false
        changeRelayState(relayNum, isTurnedOn);
        send(msgs[relayNum].set(isTurnedOn));
        saveRelayState(relayNum, isTurnedOn);
      }
    }
  }
}
// MySensors - Presentation
// Your sensor must first present itself to the controller.
// The presentation is a hint to allow controller prepare for the sensor data that eventually will come.
// Executed after "before()" and before "setup()" in: _begin (MySensorsCore.cpp) > gatewayTransportInit() > presentNode()
void presentation() {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Multi Relay", "1.2");
  
  // Register every relay as separate sensor
  for (int i = 0; i < numberOfRelayButtons; i++) {
    // if this relay has multiple buttons, register only first
    if (relayMultiButtons[i].firstButton == -1 || relayMultiButtons[i].firstButton == i) {
      // Register all sensors to gw (they will be created as child devices)
      // void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool ack);
      //   childSensorId - The unique child id you want to choose for the sensor connected to this Arduino. Range 0-254.
      //   sensorType - The sensor type you want to create.
      //   description An optional textual description of the attached sensor.
      //   ack - Set this to true if you want destination node to send ack back to this node. Default is not to request any ack.
      present(myRelayButtons[i].sensorId, S_BINARY, myRelayButtons[i].relayDescription);
    }
  }
}
// MySensors - Handling incoming messages
// Nodes that expects incoming data, such as an actuator or repeating nodes,
// must implement the receive() - function to handle the incoming messages.
// Do not sleep a node where you expect incoming data or you will lose messages.
void receive(const MyMessage &message) {
  // We only expect one type of message from controller. But we better check anyway.
  if (message.type == V_STATUS) {
    uint8_t isTurnedOn = message.getBool(); // 1 - true, 0 - false
    changeRelayState(message.sensor, isTurnedOn);
    // Store state in eeprom if changed
    if (loadRelayState(message.sensor) != isTurnedOn) {
      saveRelayState(message.sensor, isTurnedOn);
    }
    send(msgs[message.sensor].set(isTurnedOn)); // support for OPTIMISTIC=FALSE (Home Asistant)
    #ifdef MY_DEBUG
      // Write some debug info
      Serial.print("# Incoming change for sensor: " + message.sensor);
      Serial.println(", New status: " + isTurnedOn);
    #endif
  }
}
uint8_t loadRelayState(int relayNum, uint8_t forceEeprom) {
  uint8_t relayState;
  if (forceEeprom) {
    relayState = loadState(RELAY_STATE_STORAGE + relayNum);
  } else {
    relayState = myRelayState[relayNum];
  }
  #ifdef MY_DEBUG
    Serial.print("# loadRelayState: ");
    Serial.print(relayNum);
    if (forceEeprom) {
      Serial.print("(byte ");
      Serial.print(RELAY_STATE_STORAGE + relayNum);
      Serial.print(")");
    }
    Serial.print(" = ");
    Serial.println(relayState);
  #endif
  return(relayState);
}
void saveRelayState(int relayNum, uint8_t state, uint8_t useEeprom) {
  
  int mainRelayNum = (relayMultiButtons[relayNum].firstButton == -1) ? relayNum : relayMultiButtons[relayNum].firstButton;
  
  myRelayState[mainRelayNum] = state;
  if (useEeprom && (relayNum == mainRelayNum)) {
    saveState(RELAY_STATE_STORAGE + mainRelayNum, state);
  }
  
  int nextButton = mainRelayNum;
  // update all buttons
  while ((nextButton = relayMultiButtons[nextButton].nextButton) != -1) {
    myRelayState[nextButton] = state;
  };
}
void saveRelayState(int relayNum, uint8_t state) {
  uint8_t useEeprom = ((myRelayButtons[relayNum].relayOptions & RELAY_STARTUP_MASK) == 0);
  saveRelayState(relayNum, state, useEeprom);
}
void changeRelayState(int relayNum, uint8_t relayState) {
  
  uint8_t relayTrigger = myRelayButtons[relayNum].relayOptions & RELAY_TRIGGER_HIGH;
  uint8_t digitalOutState = relayState ? relayTrigger : ! relayTrigger;
  
  #ifdef USE_EXPANDER
    if ( myRelayButtons[relayNum].relay & 0xff00 ) {
      int expanderNo = (myRelayButtons[relayNum].relay >> 8) - 1;
      int expanderPin = myRelayButtons[relayNum].relay & 0xff;
      expander[expanderNo].digitalWrite(expanderPin, digitalOutState);
    } else {
  #endif
    digitalWrite(myRelayButtons[relayNum].relay, digitalOutState);
  #ifdef USE_EXPANDER
    }
  #endif
}
And in Home assistant show example decription: Ł2 - kinkiet [C10] or for second Salon 2 [A9] etc.
Please help me... because it will be good to identify sensors when add to Controller.