Страница 1 из 1

Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 13 янв 2018, 10:05
Berk
Приветствую форумчан.
Продолжаю серию постов "аля mysensors cooking book :)"

В этом посте хочу показать реализацию бесперебойной работы НОДЫ при проблемах радиосвязи с гейтом в радиосети MySensors.

1.Новая нода стартует как обычная, задача получить от контролера уникальный ID.
2.После всегда стартует с задержкой доступа к сетапу и лупу в 30 секунд, если за это время не найдена сеть то стартует с псевдо готовым транспортом(это не пассивный режим, тк подтверждения отправки и доставки работают) и с отключенной презентацией(nodePresent()) , тк смысла в ней нет.
3.запускает кастомную реализацию поиска родителя, при подтверждении, производит инициализацию парента, отправляет презентацию, тк ее не было при старте и в тоже время продолжает выполнять какой то заданный функционал, работать с другими нодами.
4.Если гейт становится недоступен уже во время работы, то через несколько неудачных попыток отправки, просто включается кастомный поиск парента, без перевода в режим псевдо готового транспорта, тк во время всех отправок сообщений обнуляется контейнер и библиотека не может запустить самостоятельно поиск парента.
5.Если после поиска парента, парентом становится например не гейт или наоборот парентом был репитер, а стал гейт, то для обновления информации на контролер отправляется кастомное сообщение которое меняет в таблице модуля майсенсорс информацию к какому паренту привязана нода(нет необходимости делать это через презентацию, зачем спамить в радиосеть :))
6.Если после того как гейт стал недоступен и потом была начата инициализация нового парента и она не прошла успешно, тогда уже запускается режим превдо готового транспорта.
7. В пример добавил "как бы" отправку показаний температуры на гейт и отправку просто значения на какую то ноду в сети, номер ноды на которую слать укажите в скетче(это для наглядности примера, можно и не указывать, отправлять будет все равно, даже на несуществующую)
8. При востановлении работы через гейт "счастливая ожидающая нода" сразу старается обновить данные в модуле майсенсорс на контролере.

https://www.youtube.com/watch?v=jFDBeIn ... e=youtu.be

Re: Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 18 янв 2018, 19:18
mikhail
ок

Re: Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 19 янв 2018, 11:53
Berk
Боюсь что упрощать не стоит. Возможно позже выложу экземпл..

Re: Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 22 янв 2018, 12:36
ahelper
Не совсем понятна необходимость такого кода. Ведь код из пассивной ноды тоже работает. Выключатели работают даже без гейта, независимо от того была регистрация у гейта при включении или нет. Гейт появился в сети, нода продолжает нормально слать свое состояние.

Re: Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 01 дек 2018, 09:13
lyskovm
Добрый день!
А где же сам код?

Похоже Ваше решение поможет разобраться с моей проблемой.
Проблема такая: Mysensor нода управляет шторами как с локальных кнопок так и через сеть. Но если отключить шлюз и передернуть питание на ноде, то пока она к шлюзу не подключится, кнопки не работают, т.к. мега занята попытками подключения к шлюзу. Как перехватить управление? Вроде как есть такой человек: Андрей Ламченко. Он что-то делал с библиотекой и у него ноды умеют работать в автономном режиме. Но найти его на нашем форуме у меня не получилось

Re: Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 03 дек 2018, 23:43
Berk
Приветствую.
>>А где же сам код? Эта задачка не имеет простого решения, на этом форуме есть примеры, но говорят что даже в этих примерах трудно разобратся :)
Впринципе Вам может помоч такая штука - #define MY_TRANSPORT_WAIT_READY_MS 5000. Добавьте ее в начале скетча и через 5 секунд после старта нода получит доступ к сетапу и лупу, следовательно кнопки начнут работать. Это не отменяет поиск гейта, возможно будет подтупливать, возможно и нет. Так же есть режим пасивной ноды:
#define MY_NODE_ID 100
#define MY_PASSIVE_NODE
но это в основном подходит для батарейных девайсов(имхо), которые только спят и просыпаясь просто что то шлют на контролер. Что касается моих изысканий на тему бесперебойного режима, работы без гейта то о них можно почитать тут - http://mysensors.ru/forum/viewtopic.php?f=5&t=24

правда со временем простая отработка этого transportSwitchSM(stReady);
оформилась примерно в это:

void happy_node_mode() {
_transportSM.findingParentNode = false;
_transportSM.transportActive = true;
_transportSM.uplinkOk = true;
_transportSM.pingActive = false;
transportSwitchSM(stReady);
_transportSM.failureCounter = 0;
}

...Вообще все сложно, как и написал сразу простого рецепта нет, что бы все работало как часы надо много чего добавить в код скетча и причем это все индивидуально в зависимости что это за девайс и какой функционал он выполняет. Если Вам это направление интересно то советую начать с изучения самой библиотеки майсенсорс, подсказки все там, ну и задавайте мне вопросы я всегда с удовольствием отвечаю на правильные вопросы. Готовый экземпл врядли будет, но готовые программы под мои устройства будут выкладыватся. следите за https://www.openhardware.io/user/1627#view=projects

>> есть такой человек
Блин популярным становлюсь что ли?)).

>>Он что-то делал с библиотекой
Вот с ней он ничего не делал, и Вам не советует, лучше ее изучать, а использовать то к чему там есть доступ уже из своей программы :)

>>Но найти его на нашем форуме у меня не получилось
Ну... он такой вечно прячется под ником - Berk https://translate.google.ru/#view=home& ... &text=Berk

Re: Happy Standby Node | Нода с бесперебойным режимом работы

Добавлено: 08 июн 2019, 17:44
Berk
Пример использования кастомного режима работы ноды - хапи нода. Примерно что то похожее на пассивную ноду, но сохранены все подтверждения отправки доставки, работа с с гейтом, перестроение маршрутов через репитеры. Прошу потестируйте, вродебы завалить даже эту простую версию низя. Скетч под мой датчик bme280(распостраняется бесплатно, платы, корпус, код) - https://www.openhardware.io/view/638

Код: Выделить всё

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
//#define MY_DEBUG
#define MY_RADIO_NRF5_ESB
#define MY_DISABLED_SERIAL
int16_t mtwr;
#define MY_TRANSPORT_WAIT_READY_MS (mtwr)
#include <MySensors.h>

typedef enum {
  I_SIGNAL_REPORT_QUALITY  = 35, //!< Device signal quality
} custom_mysensors_internal_t;

bool flag_fcount;
bool flag_no_present;
bool flag_nogateway_mode;
bool flag_find_parent_process;
bool sleep_flag;
bool last_sent_value;
bool flag_update_transport_param;
bool Ack_FP;
bool Ack_TL;
bool PRESENT_ACK;
bool SKETCH_VERSION_ACK;
bool SKETCH_NAME_ACK;
bool flag_sendRoute_parent;
bool metric = true;

byte err_delivery_beat;
byte problem_mode_count;

int16_t myid;
int16_t mypar;
int16_t old_mypar = -1;
int16_t master_id;
int16_t RSSIQuality;
uint16_t currentBatteryPercent;
uint16_t lastBatteryPercent = 1000;
uint16_t battery_vcc_min = 2150;
uint16_t battery_vcc_max = 2950;
uint16_t batteryVoltage;
uint16_t battery_alert_level = 25;

uint32_t default_sleep_time = 60000;
uint32_t SLEEP_TIME;
uint32_t newmillisforbatt;
uint32_t battsendinterval = 3600000;

float tempThreshold = 0.5;
float humThreshold = 5;
float presThreshold = 1;
float pres_mmThreshold = 1;
float temperature;
float pressure;
float pressure_mm;
float humidity;
float lastTemperature = -1;
float lastHumidity = -1;
float lastPressure = -1;
float lastPressure_mm = -1;

#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;

#define TEMP_CHILD_ID 0
#define HUM_CHILD_ID 1
#define BARO_CHILD_ID 2
#define CHILD_ID_VOLT 254

MyMessage voltMsg(CHILD_ID_VOLT, V_VOLTAGE);
MyMessage temperatureMsg(TEMP_CHILD_ID, V_TEMP);
MyMessage humidityMsg(HUM_CHILD_ID, V_HUM);
MyMessage pressureMsg(BARO_CHILD_ID, V_PRESSURE);


void preHwInit() {
  pinMode(21, INPUT);
  pinMode(25, OUTPUT);
  digitalWrite(25, HIGH);
  pinMode(26, OUTPUT);
  digitalWrite(26, HIGH);
  pinMode(27, OUTPUT);
  digitalWrite(27, HIGH);
}


void before() {
  NRF_POWER->DCDCEN = 1;
  disableNfc();
  turnOffAdc();
  pinMode(BLUE_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  digitalWrite(BLUE_LED, HIGH);
  digitalWrite(RED_LED, HIGH);
  happy_init();
  digitalWrite(27, LOW);
}

void setup()
{
  digitalWrite(27, HIGH);
  config_Happy_node();
  bme_initAsleep();
}


void presentation()  {
  if (!sendSketchInfo("EFEKTA BME280 Sensor", "1.2")) {
    _transportSM.failedUplinkTransmissions = 0;
    sleep(2000);
    if (!sendSketchInfo("EFEKTA BME280 Sensor", "1.2")) {
      _transportSM.failedUplinkTransmissions = 0;
      //...
    }
  }
  present(CHILD_ID_VOLT, S_MULTIMETER, "Battery", 1);
  wait(3000, C_PRESENTATION, S_MULTIMETER);
  CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
  if (PRESENT_ACK == 0) {
    _transportSM.failedUplinkTransmissions = 0;
    sleep(2000);
    present(CHILD_ID_VOLT, S_MULTIMETER, "Battery", 1);
    wait(3000, C_PRESENTATION, S_MULTIMETER);
    CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
    _transportSM.failedUplinkTransmissions = 0;
  } else {
    PRESENT_ACK = 0;
  }
  present(TEMP_CHILD_ID, S_TEMP, "TEMPERATURE [C or F]", 1);
  wait(3000, C_PRESENTATION, S_TEMP);
  CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
  if (PRESENT_ACK == 0) {
    _transportSM.failedUplinkTransmissions = 0;
    sleep(2000);
    present(TEMP_CHILD_ID, S_TEMP, "TEMPERATURE [C or F]", 1);
    wait(3000, C_PRESENTATION, S_TEMP);
    CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
    _transportSM.failedUplinkTransmissions = 0;
  } else {
    PRESENT_ACK = 0;
  }
  present(HUM_CHILD_ID, S_HUM, "HUMIDITY [%]", 1);
  wait(3000, C_PRESENTATION, S_HUM);
  CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
  if (PRESENT_ACK == 0) {
    _transportSM.failedUplinkTransmissions = 0;
    sleep(2000);
    present(HUM_CHILD_ID, S_HUM, "HUMIDITY [%]", 1);
    wait(3000, C_PRESENTATION, S_HUM);
    CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
    _transportSM.failedUplinkTransmissions = 0;
  } else {
    PRESENT_ACK = 0;
  }
  present(BARO_CHILD_ID, S_BARO, "PRESSURE [hPa or mmHg]", 1);
  wait(3000, C_PRESENTATION, S_BARO);
  CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
  if (PRESENT_ACK == 0) {
    _transportSM.failedUplinkTransmissions = 0;
    sleep(2000);
    present(BARO_CHILD_ID, S_BARO, "PRESSURE [hPa or mmHg]", 1);
    wait(3000, C_PRESENTATION, S_BARO);
    CORE_DEBUG(PSTR("MyS: TEST WAIT AFTER PRESENT SENSOR\n"));
    _transportSM.failedUplinkTransmissions = 0;
  } else {
    PRESENT_ACK = 0;
  }
}


void loop() {
  if (flag_update_transport_param == 1) {
    update_Happy_transport();
  }
  if (flag_sendRoute_parent == 1) {
    present_only_parent();
  }
  if (isTransportReady() == true) {
    if (flag_nogateway_mode == 0) {
      if (flag_find_parent_process == 1) {
        find_parent_process();
      }
      wait(10);
      bme.takeForcedMeasurement();
      wait(100);
      sendData();
      if (millis() - newmillisforbatt >= battsendinterval) {
        sleep_flag = 1;
        sendBatteryStatus();
      }


    } else {
      check_parent();
    }
  }
  if (_transportSM.failureCounter > 0)
  {
    _transportConfig.parentNodeId = loadState(101);
    _transportConfig.nodeId = myid;
    _transportConfig.distanceGW = loadState(103);
    mypar = _transportConfig.parentNodeId;
    sleep_flag = 0;
    flag_fcount = 1;
    err_delivery_beat = 4;
    happy_node_mode();
    gateway_fail();
  }
  if (sleep_flag == 0) {
    CORE_DEBUG(PSTR("ERROR DELIVERY COUNTER: %d\n"), err_delivery_beat);
    sleep(SLEEP_TIME);
    sleep_flag = 1;
  }
}


void blinky(uint8_t pulses, uint8_t repit, uint8_t ledColor) {
  for (int x = 0; x < repit; x++) {
    if (x > 0) {
      sleep(500);
    }
    for (int i = 0; i < pulses; i++) {
      if (i > 0) {
        sleep(100);
      }
      digitalWrite(ledColor, LOW);
      wait(20);
      digitalWrite(ledColor, HIGH);
    }
  }
}


void sendBatteryStatus() {
  wait(20);
  batteryVoltage = hwCPUVoltage();
  wait(2);

  if (batteryVoltage > battery_vcc_max) {
    currentBatteryPercent = 100;
  }
  else if (batteryVoltage < battery_vcc_min) {
    currentBatteryPercent = 0;
  }
  else {
    if (lastBatteryPercent == 1000) {
      currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min) + 5;
    } else {
      currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min) - 5;
    }
  }
  //if (currentBatteryPercent != lastBatteryPercent) {
  //if (currentBatteryPercent < lastBatteryPercent) {
  lastBatteryPercent = currentBatteryPercent;
  if (_transportConfig.parentNodeId == 0) {
    //if (send(voltMsg.setDestination(master_id).set(batteryVoltage))) {
    if (sendBatteryLevel(currentBatteryPercent)) {
      //sleep_flag = 0;
      err_delivery_beat = 0;
      if (flag_nogateway_mode == 1) {
        flag_nogateway_mode = 0;
        CORE_DEBUG(PSTR("MyS: NORMAL GATEWAY MODE\n"));
        err_delivery_beat = 0;
      }
    } else {
      _transportSM.failedUplinkTransmissions = 0;
      if (err_delivery_beat < 4) {
        err_delivery_beat++;
      }
      if (err_delivery_beat == 3) {
        if (flag_nogateway_mode == 0) {
          gateway_fail();
          CORE_DEBUG(PSTR("MyS: LOST GATEWAY MODE\n"));
        }
      }
    }
    //wait(200);
  }
  if (_transportConfig.parentNodeId > 0) {
    //send(voltMsg.setDestination(master_id).set(batteryVoltage), 1);
    //wait(3000, C_SET, V_VOLTAGE);
    sendBatteryLevel(currentBatteryPercent, 1);
    wait(3000, C_INTERNAL, I_BATTERY_LEVEL);
    if (Ack_TL == 1) {
      Ack_TL = 0;
      err_delivery_beat = 0;
      //sleep_flag = 0;
      if (flag_nogateway_mode == 1) {
        flag_nogateway_mode = 0;
        CORE_DEBUG(PSTR("MyS: NORMAL GATEWAY MODE\n"));
        err_delivery_beat = 0;
      }
    } else {
      _transportSM.failedUplinkTransmissions = 0;
      if (err_delivery_beat < 4) {
        err_delivery_beat++;
      }
      if (err_delivery_beat == 3) {
        if (flag_nogateway_mode == 0) {
          gateway_fail();
          CORE_DEBUG(PSTR("MyS: LOST GATEWAY MODE\n"));
        }
      }
    }
    //wait(200);
  }
  if (lastBatteryPercent < battery_alert_level) {
    blinky(3, 1, RED_LED);
  }
  else {
    blinky((last_sent_value == true ? 2 : 1), 1, BLUE_LED);
  }
  sleep(1000);
  RSSIQuality = calculationRssiRxQuality();
  sendSignalStrength(RSSIQuality, 1);
  wait(3000, C_INTERNAL, I_SIGNAL_REPORT_QUALITY);
  CORE_DEBUG(PSTR("MyS: TEST WAIT\n"));
  // }
  //} else {
  // sleep_flag = 0;
  // }
  sleep_flag = 0;
  newmillisforbatt = millis();
}


void disableNfc() {
  NRF_NFCT->TASKS_DISABLE = 1;
  NRF_NVMC->CONFIG = 1;
  NRF_UICR->NFCPINS = 0;
  NRF_NVMC->CONFIG = 0;
}


void turnOffAdc() {
  if (NRF_SAADC->ENABLE) {
    NRF_SAADC->TASKS_STOP = 1;
    while (NRF_SAADC->EVENTS_STOPPED) {}
    NRF_SAADC->ENABLE = 0;
    while (NRF_SAADC->ENABLE) {}
  }
}
/*
void i2c_off()
{
  NRF_TWI1->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
  *(volatile uint32_t *)0x40004FFC = 0;
  *(volatile uint32_t *)0x40004FFC;
  *(volatile uint32_t *)0x40004FFC = 1;
  wait(100);
}
*/

void happy_init() {
  //hwWriteConfig(EEPROM_NODE_ID_ADDRESS, 255); // ******************** checking the node config reset *************************

  if (hwReadConfig(EEPROM_NODE_ID_ADDRESS) == 0) {
    hwWriteConfig(EEPROM_NODE_ID_ADDRESS, 255);
  }
  if (loadState(100) == 0) {
    saveState(100, 255);
  }
  CORE_DEBUG(PSTR("EEPROM NODE ID: %d\n"), hwReadConfig(EEPROM_NODE_ID_ADDRESS));
  CORE_DEBUG(PSTR("USER MEMORY SECTOR NODE ID: %d\n"), loadState(100));

  if (hwReadConfig(EEPROM_NODE_ID_ADDRESS) == 255) {
    mtwr = 0;
  } else {
    mtwr = 10000;
    no_present();
  }
  CORE_DEBUG(PSTR("MY_TRANSPORT_WAIT_MS: %d\n"), mtwr);

}


void no_present() {
  _coreConfig.presentationSent = true;
  _coreConfig.nodeRegistered = true;
}


void happy_node_mode() {
  _transportSM.findingParentNode = false;
  _transportSM.transportActive = true;
  _transportSM.uplinkOk = true;
  _transportSM.pingActive = false;
  transportSwitchSM(stReady);
  _transportSM.failureCounter = 0;
}


void gateway_fail() {
  flag_nogateway_mode = 1;
  flag_update_transport_param = 0;
  SLEEP_TIME = default_sleep_time / 2;
}


void sendData() {
  temperature = bme.readTemperature();
  wait(20);
  humidity = bme.readHumidity();
  wait(20);
  pressure = bme.readPressure() / 100.0F;
  if (!metric) {
    temperature = temperature * 9.0 / 5.0 + 32.0;
  } else {
    pressure = pressure * 0.75006375541921;
  }
  CORE_DEBUG(PSTR("MY_TEMPERATURE: %d\n"), (int)temperature);
  CORE_DEBUG(PSTR("MY_HUMIDITY: %d\n"), (int)humidity);
  CORE_DEBUG(PSTR("MY_PRESSURE: %d\n"), (int)pressure);

  if (_transportConfig.parentNodeId == 0) {

    if (abs(temperature - lastTemperature) >= tempThreshold) {
      if (send(temperatureMsg.setDestination(master_id).set(temperature, 1))) {
        err_delivery_beat = 0;
        if (flag_nogateway_mode == 1) {
          flag_nogateway_mode = 0;
          CORE_DEBUG(PSTR("MyS: NORMAL GATEWAY MODE\n"));
          err_delivery_beat = 0;
        }
      } else {
        _transportSM.failedUplinkTransmissions = 0;
        if (err_delivery_beat < 4) {
          err_delivery_beat++;
        }
        if (err_delivery_beat == 3) {
          if (flag_nogateway_mode == 0) {
            gateway_fail();
            CORE_DEBUG(PSTR("MyS: LOST GATEWAY MODE\n"));
          }
        }
      }
      lastTemperature = temperature;
      sleep(1000);
    }

    if (abs(humidity - lastHumidity) >= humThreshold) {
      if (send(humidityMsg.setDestination(master_id).set(humidity, 0))) {
        err_delivery_beat = 0;
        if (flag_nogateway_mode == 1) {
          flag_nogateway_mode = 0;
          CORE_DEBUG(PSTR("MyS: NORMAL GATEWAY MODE\n"));
          err_delivery_beat = 0;
        }
      } else {
        _transportSM.failedUplinkTransmissions = 0;
        if (err_delivery_beat < 4) {
          err_delivery_beat++;
        }
        if (err_delivery_beat == 3) {
          if (flag_nogateway_mode == 0) {
            gateway_fail();
            CORE_DEBUG(PSTR("MyS: LOST GATEWAY MODE\n"));
          }
        }
      }
      lastHumidity = humidity;
      sleep(1000);
    }

    if (abs(pressure - lastPressure) >= presThreshold) {
      if (send(pressureMsg.setDestination(master_id).set(pressure, 0))) {
        err_delivery_beat = 0;
        if (flag_nogateway_mode == 1) {
          flag_nogateway_mode = 0;
          CORE_DEBUG(PSTR("MyS: NORMAL GATEWAY MODE\n"));
          err_delivery_beat = 0;
        }
      } else {
        _transportSM.failedUplinkTransmissions = 0;
        if (err_delivery_beat < 4) {
          err_delivery_beat++;
        }
        if (err_delivery_beat == 3) {
          if (flag_nogateway_mode == 0) {
            gateway_fail();
            CORE_DEBUG(PSTR("MyS: LOST GATEWAY MODE\n"));
          }
        }
      }
      lastPressure = pressure;
      sleep(1000);
    }
  }

  sleep_flag = 0;
}


void update_Happy_transport() {
  CORE_DEBUG(PSTR("MyS: UPDATE TRANSPORT CONFIGURATION\n"));
  mypar = _transportConfig.parentNodeId;
  master_id = 0; // *************************** master slave mode is not initialized in this example, ..stub *******************************
  if (mypar != loadState(101))
  {
    saveState(101, mypar);
  }
  if (_transportConfig.distanceGW != loadState(102))
  {
    saveState(102, _transportConfig.distanceGW);
  }
  present_only_parent();
  wait(1000);
  sleep_flag = 0;
  flag_update_transport_param = 0;
}


void config_Happy_node() {
  if (mtwr == 0) {
    myid = getNodeId();
    saveState(100, myid);
    mypar = _transportConfig.parentNodeId;
    old_mypar = mypar;
    master_id = 0; // *************************** master slave mode is not initialized in this example, ..stub *******************************
    saveState(101, mypar);
    saveState(102, _transportConfig.distanceGW);
    //first_send_param ();
    SLEEP_TIME = default_sleep_time;
    sendBatteryStatus();
  }
  if (mtwr != 0) {
    myid = getNodeId();
    if (myid != loadState(100)) {
      saveState(100, myid);
    }
    if (isTransportReady() == true) {
      mypar = _transportConfig.parentNodeId;
      master_id = 0; // *************************** master slave mode is not initialized in this example, ..stub *******************************
      if (mypar != loadState(101)) {
        saveState(101, mypar);
      }
      if (_transportConfig.distanceGW != loadState(102)) {
        saveState(102, _transportConfig.distanceGW);
      }
      //first_send_param ();
      SLEEP_TIME = default_sleep_time;
      present_only_parent();
      sendBatteryStatus();
    }
    if (isTransportReady() == false)
    {
      no_present();
      flag_fcount = 1;
      err_delivery_beat = 4;
      _transportConfig.nodeId = myid;
      _transportConfig.parentNodeId = loadState(101);
      _transportConfig.distanceGW = loadState(102);
      mypar = _transportConfig.parentNodeId;
      happy_node_mode();
      gateway_fail();
    }
  }
  //wdt_enable(WDTO_4S);
  //CORE_DEBUG(PSTR("MyS: WDT ENABLE\n"));
}


void present_only_parent() {
  if (old_mypar != mypar) {
    CORE_DEBUG(PSTR("MyS: SEND LITTLE PRESENT:) WITH PARENT ID\n"));
    if (_sendRoute(build(_msgTmp, 0, NODE_SENSOR_ID, 3, 6).set(mypar))) {
      //wait(3000, 3, 6);
      flag_sendRoute_parent = 0;
      old_mypar = mypar;
    } else {
      flag_sendRoute_parent = 1;
    }
  }
}


void check_parent() {
  _transportSM.findingParentNode = true;
  CORE_DEBUG(PSTR("MyS: SEND FIND PARENT REQUEST, WAIT RESPONSE\n"));
  _sendRoute(build(_msg, 255, NODE_SENSOR_ID, 3, 7).set(""));
  wait(3000, 3, 8);
  if (_msg.sensor == 255) {
    if (mGetCommand(_msg) == 3) {
      if (_msg.type == 8) {
        Ack_FP = 1;
        CORE_DEBUG(PSTR("MyS: PARENT RESPONSE FOUND\n"));
      }
    }
  }
  if (Ack_FP == 1) {
    CORE_DEBUG(PSTR("MyS: FIND PARENT PROCESS\n"));
    Ack_FP = 0;
    transportSwitchSM(stParent);
    flag_nogateway_mode = 0;
    flag_find_parent_process = 1;
    SLEEP_TIME = default_sleep_time;
    problem_mode_count = 0;
  } else {
    _transportSM.findingParentNode = false;
    CORE_DEBUG(PSTR("MyS: PARENT RESPONSE NOT FOUND\n"));
    _transportSM.failedUplinkTransmissions = 0;
    sleep_flag = 0;
    if (problem_mode_count < 24) {
      CORE_DEBUG(PSTR("PROBLEM MODE COUNTER: %d\n"), problem_mode_count);
      problem_mode_count++;
      SLEEP_TIME = SLEEP_TIME / 100 * 120;
    } else if (problem_mode_count == 24) {
      SLEEP_TIME = default_sleep_time * 30;
      CORE_DEBUG(PSTR("PROBLEM MODE COUNTER: %d\n"), problem_mode_count);
    }
  }
}


void find_parent_process() {
  flag_update_transport_param = 1;
  flag_find_parent_process = 0;
  CORE_DEBUG(PSTR("MyS: STANDART TRANSPORT MODE IS RESTORED\n"));
  err_delivery_beat = 0;
}


void receive(const MyMessage & message) {
  if (message.type == V_VOLTAGE) {
    if (message.sensor == CHILD_ID_VOLT) {
      if (mGetCommand(message) == 1) {
        if (message.isAck()) {
          Ack_TL = 1;
        } else {

        }
      }
      if (mGetCommand(message) == 2) {

      }
    }
  }

  if (mGetCommand(message) == 0) {
    PRESENT_ACK = 1;
    CORE_DEBUG(PSTR("MyS: !!!ACK OF THE PRESENTATION IN THE FUNCTION RECEIVE RECEIVED!!!\n"));
  }
}


void bme_initAsleep() {
  if (! bme.begin(&Wire)) {
    while (1);
  }
  bme.setSampling(Adafruit_BME280::MODE_FORCED,
                  Adafruit_BME280::SAMPLING_X1, // temperature
                  Adafruit_BME280::SAMPLING_X1, // pressure
                  Adafruit_BME280::SAMPLING_X1, // humidity
                  Adafruit_BME280::FILTER_OFF   );
  wait(1000);
}


//****************************** very experimental *******************************


bool sendSignalStrength(const int16_t level, const bool ack)
{
  return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SIGNAL_REPORT_QUALITY,
                          ack).set(level));
}
int16_t calculationRssiRxQuality() {
  int16_t nRFRSSI_temp = transportGetReceivingRSSI();
  int16_t nRFRSSI = map(nRFRSSI_temp, -85, -40, 0, 100);
  if (nRFRSSI < 0) {
    nRFRSSI = 0;
  }
  if (nRFRSSI > 100) {
    nRFRSSI = 100;
  }
  return nRFRSSI;
}