Библиотека Ethernet2 и GET на модуле w5500

sadman41
Offline
Зарегистрирован: 19.10.2016

oldxaker пишет:

Откройте две библиотеки и найдите 5 отличий в первых 10 стоках)

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

То, что вы в один скетч тащите String, в другой char[] , а в третий вообще буфер от ethercard и не можете понять при этом отличий какбэ намекает на то, что вопросы о понимании действий задаются абсолютно не по адресу.

b707
Offline
Зарегистрирован: 26.05.2017

oldxaker пишет:

И из за отсутствия

 readString = "";

          break;
        }
      } else {
        readString = "";
      }

не выполнялся поиск по всей строке?

Я верно понимаю?

неверно.

Из-за отсуствия очистки строки

readString = "";

у вас эта строка очень быстро переполнялась и программа переставала нормально работать из-за нехватки памяти.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Блин, весело у Вас тут. А я вчера пошёл бороться со своим операционником (поборол, кстати ... он меня) и всё пропустил :(((

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Блин, весело у Вас тут.

да все как обычно. Пришел обидчивый товарищ, шуток на тему своей личности не понимает, просит "советов по делу" - а сам ни намеков, ни примых советов понять не способен. Единственное, что ему может помочь - это написать код целиком за него, как и сделал в итоге xDriver.

Только ведь это бестолку - в итоге oldxaker ничему не научился.  Добавит он в свой проект еще десяток строк - и снова все развалится.

 

oldxaker
Offline
Зарегистрирован: 23.07.2018

xDriver пишет:

ну получилось, хорошо, я бы не стал так возбуждаться, что нужно сделать: 

работаете вы со string, ну ваше дело, я тоже работаю, тут его не любят хотя платформа ардуино, как и многе другие, его активно используют (тут пришлось С# чутка покывырять, ардуина отдыхает).

надо написать функцию, принимающию два параметра, например входную строку -

"?AHONH=0&AHONM=30&AHOFFH=12&AHOFFM=45&AAUTO=1&AONOFF=0

и итересующий вас токен "AHONH"

а вернет она вам значение этого токена, в надлежащем виде, хотите тот же стринг "0", либо это уже будет число.

вы же знаете что строка начинается с "?",  а разделители у нее "&", и заканчивается она "\n", а аргументы разделяются знаком "="

пример:

SearchToten("?AHONH=0&AHONM=30&AHOFFH=12&AHOFFM=45&AAUTO=1&AONOFF=0", "AHONH");

вернет либо стринг - "0", либо числовой 0.

 

 

Да, я понял Вашу мысль, сейчас пробую, читаю. 

Видел реализацию в примерах, но не мог понять логики, сейчас более понятно  

Благодарю за дельные советы 

oldxaker
Offline
Зарегистрирован: 23.07.2018

b707 пишет:

ЕвгенийП пишет:

Блин, весело у Вас тут.

да все как обычно. Пришел обидчивый товарищ, шуток на тему своей личности не понимает, просит "советов по делу" - а сам ни намеков, ни примых советов понять не способен. Единственное, что ему может помочь - это написать код целиком за него, как и сделал в итоге xDriver.

Только ведь это бестолку - в итоге oldxaker ничему не научился.  Добавит он в свой проект еще десяток строк - и снова все развалится.

 

Вы чего озлобленный такой? ) Принимаю, Вы- человек знающий, материал, психологию людей, даже как оказалось будущее и судьбу!) Уважение Вам, Вашему эго и почёт. Но будет лишь одна просьба, от столь презираемого Вами типа людей (знающих меньше чем Вы)- не пишите, если у Вас, о великий человечище, нет желания чем то реально помочь :) Вы элементарно засоряете своими не имеющими никакой полезной нагрузки форум  

Удачи, веры в людей ну и повторюсь, самореализации в чем то бОльшем)

P.S. А за комментарий о переполнении памяти- спасибо, неожиданно, но действительно спасибо  )

 

oldxaker
Offline
Зарегистрирован: 23.07.2018

sadman41 пишет:

oldxaker пишет:

Откройте две библиотеки и найдите 5 отличий в первых 10 стоках)

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

То, что вы в один скетч тащите String, в другой char[] , а в третий вообще буфер от ethercard и не можете понять при этом отличий какбэ намекает на то, что вопросы о понимании действий задаются абсолютно не по адресу.

Вопрос понимания действий - в очередной раз - я учусь, если не спрашивать, как научиться? Этот форум для помощи и обучения в том числе, поэтому да, не верно, да, не знаю, да, Вы знаете больше. Надеюсь, вопрос моей личности и моих знаний и для Вас прояснен.

И по библиотекам:

Раз Вы настаиваете. В библиотеках Ethernet  и Ethernet2 иначе назначаются IP и MAC  адреса, это только на этапе первых 5 строк, в итоге, код будет нерботоспособен, давая новичку совет просто заменить название библиотек, Вы вводите его в заблуждение.

sadman41
Offline
Зарегистрирован: 19.10.2016

oldxaker пишет:

Раз Вы настаиваете. В библиотеках Ethernet  и Ethernet2 иначе назначаются IP и MAC  адреса, это только на этапе первых 5 строк, в итоге, код будет нерботоспособен, давая новичку совет просто заменить название библиотек, Вы вводите его в заблуждение.

Конечно настаиваю. Может вы еще и кодопример разночтений запостите?

Ибо производитель библиотек дает на них единую документацию: https://www.arduino.cc/en/Reference/ethernet (большие буквы в заголовке ищите)

oldxaker
Offline
Зарегистрирован: 23.07.2018

oldxaker пишет:

xDriver пишет:

ну получилось, хорошо, я бы не стал так возбуждаться, что нужно сделать: 

работаете вы со string, ну ваше дело, я тоже работаю, тут его не любят хотя платформа ардуино, как и многе другие, его активно используют (тут пришлось С# чутка покывырять, ардуина отдыхает).

надо написать функцию, принимающию два параметра, например входную строку -

"?AHONH=0&AHONM=30&AHOFFH=12&AHOFFM=45&AAUTO=1&AONOFF=0

и итересующий вас токен "AHONH"

а вернет она вам значение этого токена, в надлежащем виде, хотите тот же стринг "0", либо это уже будет число.

вы же знаете что строка начинается с "?",  а разделители у нее "&", и заканчивается она "\n", а аргументы разделяются знаком "="

пример:

SearchToten("?AHONH=0&AHONM=30&AHOFFH=12&AHOFFM=45&AAUTO=1&AONOFF=0", "AHONH");

вернет либо стринг - "0", либо числовой 0.

 

 

Да, я понял Вашу мысль, сейчас пробую, читаю. 

Видел реализацию в примерах, но не мог понять логики, сейчас более понятно  

Благодарю за дельные советы 

 

(пока пробую string)

Поковырялся, почитал, понял как вытаскивать значение AHONH из строки. Что уже прогресс (для меня)

может кому то из новичков пригодится, поэтому прокомментирую (знатокам не читать, это будет жестко для ваших ранимых эго)

i+6 - это отсчитывается кол-во символов до значения (то есть сколько символов в имени искомого в данном случае AHONH и знак равно)

значение присваивается testString (название произвольное), то есть его уже можно как то обрабатывать, в зависимости от целей (например отправить в массиве как команду другой ардуино и тп) НО не забывайте что String "число" необходимо будет преобразовать.

Следующая задача - обработка всей строки и получение значений каждой переменной

String testString;
  for (int i=0;i<readString.length();){
     if (readString.substring(i).startsWith("AHONH=")) {
        i+=6;
        int s=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        testString=readString.substring(s,i);
     }
     ++i;
  }   
  Serial.println(testString);

 

oldxaker
Offline
Зарегистрирован: 23.07.2018

sadman41 пишет:

oldxaker пишет:

Раз Вы настаиваете. В библиотеках Ethernet  и Ethernet2 иначе назначаются IP и MAC  адреса, это только на этапе первых 5 строк, в итоге, код будет нерботоспособен, давая новичку совет просто заменить название библиотек, Вы вводите его в заблуждение.

Конечно настаиваю. Может вы еще и кодопример разночтений запостите?

Ибо производитель библиотек дает на них единую документацию: https://www.arduino.cc/en/Reference/ethernet (большие буквы в заголовке ищите)

Это не отменяет неверности Вашего совета. 

Замена названия библиотеки приведет у неработоспособности кода. Попробуйте принять свою ошибку, легче станет, однозначно) Но, это совет, не поучение. 

Удачи.

sadman41
Offline
Зарегистрирован: 19.10.2016

Уговорили, пойду покаюсь.

Кстати, случаем, вы 20 языков выше университетского уровня не знаете? 

oldxaker
Offline
Зарегистрирован: 23.07.2018

sadman41 пишет:

Уговорили, пойду покаюсь.

Кстати, случаем, вы 20 языков выше университетского уровня не знаете? 

Нужна помощь? Опишите проблему, буду рад помочь в меру возможностей

b707
Offline
Зарегистрирован: 26.05.2017

oldxaker пишет:

Это не отменяет неверности Вашего совета. 

Замена названия библиотеки приведет у неработоспособности кода. Попробуйте принять свою ошибку, легче станет, однозначно) Но, это совет, не поучение. 

Удачи.

да уж...  А тон-то, тон каков :) Учитесь все!

и у кого тут ЭГО раздуто? :)

и как вам советовать, если вы принимаете советы с видом начальника, выслушивающего провинившихся подчиненных?

oldxaker
Offline
Зарегистрирован: 23.07.2018

b707 пишет:

oldxaker пишет:

Это не отменяет неверности Вашего совета. 

Замена названия библиотеки приведет у неработоспособности кода. Попробуйте принять свою ошибку, легче станет, однозначно) Но, это совет, не поучение. 

Удачи.

да уж...  А тон-то, тон каков :) Учитесь все!

и у кого тут ЭГО раздуто? :)

и как вам советовать, если вы принимаете советы с видом начальника, выслушивающего провинившихся подчиненных?

Это Ваша фантазия, Вам с ней жить)) Если пробежитесь по сообщениям - я ни разу никого не оскорбил, напротив, наберется с 20 странных сообщений о том какой я)))) Что неожиданно, вопрос то по коду и обучению)

Если Вам невыносимо общение со мной, я пойму, но тем не менее

за замечание по переполнению памяти благодарю. 

oldxaker
Offline
Зарегистрирован: 23.07.2018

Задача извлекать из строки значения каждой переменной так же решена, другое дело что топорным способом (насколько хватило знаний и помощи) 

Через string . Топорно, но проще и понятнее чем те примеры, которые смотрел и которые пока слишком сложны для моего понимания. Но, для новичков как я это может здорово помочь и пригодиться. По сути, так вы уже можете обрабатывать любые данные из строки на начальном этапе изучения.

Далее буду учиться через SearchToten как посоветовал xDriver

Поправил корону, иду дальше. Все мира, добра, доброты и самореализации конечно).

String testString;
  for (int i=0;i<readString.length();){
     if (readString.substring(i).startsWith("AHONH=")) {
        i+=6;
        int s=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        param1=readString.substring(s,i);
     }

    if (readString.substring(i).startsWith("AHONM=")) {
        i+=6;
        int b=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        param2=readString.substring(b,i);
     }

     ++i;
  }   
  Serial.println(param1);
  Serial.println(param2);

Ну и код целиком


#include <SPI.h>
#include <Ethernet2.h>
#include <EEPROM.h>
#include <SPI.h>

uint8_t address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};
uint8_t transmitt_data[21];
uint8_t value;
uint8_t mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

IPAddress ip(192, 168, 178, 221);
EthernetServer server(80);
String readString;
char c;

String AHONH;
String AHONM;
String AHOFFH;
String AHOFFM;
String AAUTO;
String AONOFF;

void setup() {

  Serial.begin(9600);
  while (!Serial);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

}
void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    while (client.connected()) {
      if (client.available()) {
        c = client.read();
        readString += c;
        if (c == '\n') {
            Serial.println(readString);
          
          String testString;
          
  for (int i=0;i<readString.length();){
     if (readString.substring(i).startsWith("AHONH=")) 
     {
        i+=6;
        int s=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        AHONH=readString.substring(s,i);
     }

    if (readString.substring(i).startsWith("AHONM=")) 
    {
        i+=6;
        int b=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        AHONM=readString.substring(b,i);
     }

    if (readString.substring(i).startsWith("AHOFFH=")) 
    {
        i+=7;
        int b=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        AHOFFH=readString.substring(b,i);
     }

     if (readString.substring(i).startsWith("AHOFFM=")) {
        i+=7;
        int b=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        AHOFFM=readString.substring(b,i);
     }

     if (readString.substring(i).startsWith("AAUTO=")) 
     {
        i+=6;
        int b=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        AAUTO=readString.substring(b,i);
     }

     if (readString.substring(i).startsWith("AONOFF=")) 
     {
        i+=7;
        int b=i; 
        while((i<readString.length())&&((readString.charAt(i)>=0x30)&&(readString.charAt(i)<=0x39))) {
           ++i;
        }
        AONOFF=readString.substring(b,i);
     }

     ++i;
  }   
  
  Serial.println(AHONH);
  Serial.println(AHONM);
  Serial.println(AHOFFH);
  Serial.println(AHOFFM);
  Serial.println(AAUTO);
  Serial.println(AONOFF);

  //

          client.println(F("HTTP/1.1 200 OK"));
          client.println(F("Content-Type: text/html"));
          client.println(F("Connection: close"));  // the connection will be closed after completion of the response
          client.println(F("<?xml version= 1.0 encoding= UTF-8 ?>"));
          client.println(F("<!DOCTYPE html PUBLIC "));
          //client.println("Refresh: 5"));  // refresh the page automatically every 5 sec
          client.println();
          client.println(F("<!DOCTYPE HTML>"));
          client.println(F("<html>"));
          client.println(F("  <br>"));
          client.println(F(" <hr align= center  width= 300  size= 3 color= #0000dd  /> "));
          client.println(F(" <b> <center> Achtertuin <center> </b>"));
          client.println(F(" <hr align= center  width= 300  size= 3 color= #0000dd  /> "));
          client.println(F("<br>"));
          client.println(F(" <form>"));
          client.println(F(" &nbsp;  TIME ON &nbsp;"));
          client.println(F("<input type= number  name= AHONH  max= 23 min= 0  value=  style= width:60px </p>")); // окно ввода
          client.println(F("<input type= number  name= AHONM  max= 59 min= 0  value=   style= width:60px </p>")); // окно ввода
          client.println(F("<br>"));
          client.println(F(" &nbsp;  TIME OFF &nbsp;"));
          client.println(F("<input type= number  name= AHOFFH  max= 23 min= 0  value=   style= width:60px </p>")); // окно ввода
          client.println(F("<input type= number  name= AHOFFM  max= 59 min= 0  value=   style= width:60px </p>")); // окно ввода
          client.println(F(" <hr align= center  width= 300  size= 3  color= #dddddd  /> "));
          client.println(F("&nbsp; AUTO MODE &nbsp;"));
          client.println(F("<form>"));
          client.println(F("<select name= AAUTO >"));
          client.println(F("<option value= 2 > ON/OFF </option>"));
          client.println(F("<option value= 1 >ON</option>"));
          client.println(F("<option value= 0 >OFF</option>"));
          client.println(F("</select></p>"));
          client.println(F("&nbsp; ON OFF BUTTON &nbsp;"));
          client.println(F("<form>"));
          client.println(F("<select name= AONOFF >"));
          client.println(F("<option value= 2 > ON/OFF </option>"));
          client.println(F("<option value= 1 >OFF</option>"));
          client.println(F("<option value= 0 >ON</option>"));
          client.println(F("</select></p>"));
          client.println(F("</select>"));
          client.println(F("<p><input type= submit  value= SEND  ></p>"));
          client.println(F("</html>"));

          readString = "";
          break;
        }
      } else {
        readString = "";
      }
    }  
    delay(1);
    client.stop();
    Serial.println("client disconnected");
  }

}

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

oldxaker пишет:

Поправил корону, иду дальше.

Нимб ещё поправь, а то сбивается как-то.

oldxaker
Offline
Зарегистрирован: 23.07.2018

Ворота пишет:

oldxaker пишет:

Поправил корону, иду дальше.

Нимб ещё поправь, а то сбивается как-то.

 

+5 благодарю, Вы облататель поистине искрометного чувства юмора

oldxaker
Offline
Зарегистрирован: 23.07.2018

UPD

опять же, для новичков как я, может пригодиться:

в этом коде мы получаем значение String и для дальнейшего использования (например записать в массив для отправки) необходимо его преобразовать, делается это такой строкой

transmitt_data[0] = AHONH.toInt();

Где первая часть - название массива и номер ячейки, вторая - присвоение ячейке значения но уже long (благодарю за корректировку sadman41, я написал uint8_t что не верно, можно предположить что это int (toInt), но в принципе

int - 4 байта с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31) 

long - 4 байта, с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31)

так что будет одно и то же))

Всем удачи!

sadman41
Offline
Зарегистрирован: 19.10.2016

toInt(), возвращаемые значения: long

Хотя, зачем вам советовать - один хрен снобом назовете.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Ох, не надо, Дон!

А то щас ТС опять начнёт рассказывать какие тут все гады, заодно доказыва, что разницы между long и uint8_t никакой.

oldxaker
Offline
Зарегистрирован: 23.07.2018

sadman41 пишет:

toInt(), возвращаемые значения: long

Хотя, зачем вам советовать - один хрен снобом назовете.

Не усложняйте) А как иначе я мог реагировать на реки "позитива"?))

Исправил!

Благодарю!!!!

oldxaker
Offline
Зарегистрирован: 23.07.2018

Ворота пишет:

Ох, не надо, Дон!

А то щас ТС опять начнёт рассказывать какие тут все гады, заодно доказыва, что разницы между long и uint8_t никакой.

А если не начнет?)

b707
Offline
Зарегистрирован: 26.05.2017

oldxaker пишет:

я написал uint8_t что не верно, можно предположить что это int (toInt), но в принципе

int - 4 байта с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31) 

long - 4 байта, с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31)

так что будет одно и то же))

 

неверно

int - 2 байта

long - 4 байта

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Вот щас и начнет.

oldxaker
Offline
Зарегистрирован: 23.07.2018

DetSimen пишет:

Вот щас и начнет.

 

Нет, опять не начнет))

oldxaker
Offline
Зарегистрирован: 23.07.2018

b707 пишет:

oldxaker пишет:

я написал uint8_t что не верно, можно предположить что это int (toInt), но в принципе

int - 4 байта с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31) 

long - 4 байта, с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31)

так что будет одно и то же))

 

неверно

int - 2 байта

long - 4 байта

 

Понял, спасибо, взял отсюда. Буду знать

http://qaru.site/questions/7264/what-is-the-difference-between-an-int-and-a-long-in-c

b707
Offline
Зарегистрирован: 26.05.2017

oldxaker пишет:

Понял, спасибо, взял отсюда. Буду знать

http://qaru.site/questions/7264/what-is-the-difference-between-an-int-and-a-long-in-c

там в первом же ответе сказано, что эти цифры не догма:

Это зависит от реализации. Например, в Windows они одинаковы, но, например, в Alpha-системах длинное было 64 бита,

на ардуино они разные

oldxaker
Offline
Зарегистрирован: 23.07.2018

b707 пишет:

oldxaker пишет:

Понял, спасибо, взял отсюда. Буду знать

http://qaru.site/questions/7264/what-is-the-difference-between-an-int-and-a-long-in-c

там в первом же ответе сказано, что эти цифры не догма:

Это зависит от реализации. Например, в Windows они одинаковы, но, например, в Alpha-системах длинное было 64 бита,

на ардуино они разные

Понял, благодарю!

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

b707 пишет:

oldxaker пишет:

я написал uint8_t что не верно, можно предположить что это int (toInt), но в принципе

int - 4 байта с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31) 

long - 4 байта, с диапазоном значений от -2,147,483,648 до 2,147,483,647 (2 ^ 31)

так что будет одно и то же))

 

неверно

int - 2 байта

long - 4 байта

Неверно, зависит от платформы :) :) :)

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Поэтому лучше пользоваться типами:

int8_t - 8 бит (1 байт, знаковый) или uint8_t (беззнаковый)

int16_t - 16 бит (2 байта, знаковый) или uint16_t (беззнаковый)

int32_t - 32 бит (4 байта, знаковый) или uint32_t (беззнаковый)

P.S. Это я для топикстартера.

oldxaker
Offline
Зарегистрирован: 23.07.2018

Jeka_M пишет:

Поэтому лучше пользоваться типами:

int8_t - 8 бит (1 байт, знаковый) или uint8_t (беззнаковый)

int16_t - 16 бит (2 байта, знаковый) или uint16_t (беззнаковый)

int32_t - 32 бит (4 байта, знаковый) или uint32_t (беззнаковый)

P.S. Это я для топикстартера.

Спасибо! Очень актуально, так как на UNO памяти порою не хватает (как оказалось склонен по незнанию применять перменные занимающие бОльшее место чем требуется под значение)

Благодарю Вас за полезный комментарий

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

oldxaker пишет:

Ворота пишет:

ТС опять начнёт рассказывать какие тут все гады, заодно доказыва, что разницы между long и uint8_t никакой.

А если не начнет?)

Так уже ж начал доказывать, что разницы никакой.

oldxaker пишет:

так что будет одно и то же))

oldxaker
Offline
Зарегистрирован: 23.07.2018

Ворота пишет:

oldxaker пишет:

Ворота пишет:

ТС опять начнёт рассказывать какие тут все гады, заодно доказыва, что разницы между long и uint8_t никакой.

А если не начнет?)

Так уже ж начал доказывать, что разницы никакой.

oldxaker пишет:

так что будет одно и то же))

 

А Вы забавный, все по делу ) Хронология сообщений конечно мимо прошла) Спасибо, это очень поможет