Выполнение http запроса Ethernet.h

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

При прямом подключении я не получаю

Serial.println(Ethernet.begin(mac) );

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Initialize Ethernet with DHCP:

 DHCP assigned IP  192.168.1.56

connecting to 192.168.1.55

Получается что мой IP адрес не устанавливается

byte ip[] = {192, 168, 1, 3};

Вместо него ставится 192.168.1.56

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

Так у меня до этой строчки кода не доходит, if (Ethernet.begin(mac) == 0) {

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

попробовать - byte ip[] = {192, 168, 1, 56};

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Убрала проверки из стандартного примера библиотеки

получаю connection failed

#include <SPI.h>
#include <Ethernet.h>

//byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte mac[] = { 0x2D, 0x3D, 0xE2, 0x95, 0xAA, 0xA3 };
byte ip[] = {192, 168, 1, 3};
byte gateway[] = {192, 168, 1, 1};
byte subnet[] = {255, 255, 255, 0};
byte dns[] = {192, 168, 1, 1};

IPAddress server(192, 168, 1, 55);
EthernetClient client;
uint32_t Time;

void setup() {
Serial.begin(9600);
Time=millis();
Ethernet.begin(mac, ip, dns, gateway, subnet);
Serial.println(Ethernet.localIP());//Выводит 192.168.1.3
}



void getwww() {

  if (client.connect(server, 80)) {
  Serial.print("connected to ");
    Serial.println(client.remoteIP());
    client.print("GET /script/php/readsuser.php");
    client.print(" HTTP/1.1");
    client.println();
    client.println("Host: 192.168.1.55");
    client.println("Connection: close");
    client.println();
    //client.stop();
  } else {
    client.stop();
    Serial.println("connection failed");
  }
}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Соответственно адрес 192,168,1,3 пингуется

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Ахаххххх, дурочка я глупая......Брандмауэр........................проститеее

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

так прямым кабелем работает?

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

Irinka пишет:

Ахаххххх, дурочка я глупая

Да.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

Irinka пишет:

Ахаххххх, дурочка я глупая

Да.

Дима, у Иринки высокая степень эмпатии просто, а это способ, развести на эмоции )))

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

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

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

ua6em пишет:

так прямым кабелем работает?

32 пост 1 вариант соединения.

Всем спасибо.

Я не знала что брандмауэр заблокирует прямое соединение (хотя писали в 44 посту про фаэрвол) )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

negavoid2 пишет:

Нет,

не спорь,  психологии у Михаила Литвака учился )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

Я не знала что брандмауэр заблокирует прямое соединение (хотя писали в 44 посту про фаэрвол) )))

а вот так пробовать не стали

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

ua6em пишет:

Irinka пишет:

Я не знала что брандмауэр заблокирует прямое соединение (хотя писали в 44 посту про фаэрвол) )))

а вот так пробовать не стали

Так в моем коде IP адрес задаётся точно так же

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Ещё вопрос

Я отправляю GET запрос формата ?text=000|2222|3333|4444|5555|

Я хочу первым параметром (вместо "000") отправлять "контрольную сумму" всего пакета, как это сделать? Хочу на сервере првоерять целостность пакета. Или не надо это..?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

ua6em пишет:

Irinka пишет:

Я не знала что брандмауэр заблокирует прямое соединение (хотя писали в 44 посту про фаэрвол) )))

а вот так пробовать не стали

Так в моем коде IP адрес задаётся точно так же

Разговор шёл именно о 56 адресе, если через DHCP отрабатывал. то должен был этот адрес отрабатывать и напрямую (файрвол бы не блокировал)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

ua6em пишет:

Разговор шёл именно о 56 адресе, если через DHCP отрабатывал. то должен был этот адрес отрабатывать и напрямую (файрвол бы не блокировал)

Попробую

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Irinka пишет:

Ещё вопрос

Я отправляю GET запрос формата ?text=000|2222|3333|4444|5555|

Я хочу первым параметром (вместо "000") отправлять "контрольную сумму" всего пакета, как это сделать? Хочу на сервере првоерять целостность пакета. Или не надо это..?

Не надо, за целостность отвечает tcp.

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

Irinka пишет:

Ещё вопрос

Я отправляю GET запрос формата ?text=000|2222|3333|4444|5555|

Я хочу первым параметром (вместо "000") отправлять "контрольную сумму" всего пакета, как это сделать? Хочу на сервере првоерять целостность пакета. Или не надо это..?


Сеть плохо работает или подделки опасаетесь?

https://stackoverflow.com/questions/8269693/crc-checking-done-automatica...

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

И лучше POST, хотя и с GET тоже работать будет.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Теперь вопрос по организации сервера

char buffers[50];
byte pos_buf;
#define MAX_SIZE_RESP_BUF 50

void buffersclear() {
  memset(buffers, 0, MAX_SIZE_RESP_BUF);
  pos_buf = 0;
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("New client");
    while (client.connected()) {
      if (client.available()) {
        byte temp = client.read();
        if (temp) {
          if (pos_buf >= MAX_SIZE_RESP_BUF) {
            buffersclear();
          } else {
            buffers[pos_buf] = temp;
            pos_buf++;
            if (temp == '\n' && pos_buf > 1 && buffers[pos_buf - 2] == '\r') {
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: text/html");
              client.println("Access-Control-Allow-Origin:*");
              client.println("Connection: close");
              client.println();
              if (strstr (buffers, "parts=false") != NULL) client.print("Off");
              if (strstr (buffers, "parts=true") != NULL) client.print("On");
              buffersclear();
              client.stop();
            }//if (temp == '\n'....
          }//if (pos_buf >= MAX_SIZE_RESP_BUF) {
        }//if (temp)
      }//if (client.available()
    }//while (client.connected()) {
  }//if (client) {
}//

В какой момент нужно вызывать client.stop();

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

Теперь вопрос по организации сервера

char buffers[50];
byte pos_buf;
#define MAX_SIZE_RESP_BUF 50

void buffersclear() {
  memset(buffers, 0, MAX_SIZE_RESP_BUF);
  pos_buf = 0;
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("New client");
    while (client.connected()) {
      if (client.available()) {
        byte temp = client.read();
        if (temp) {
          if (pos_buf >= MAX_SIZE_RESP_BUF) {
            buffersclear();
          } else {
            buffers[pos_buf] = temp;
            pos_buf++;
            if (temp == '\n' && pos_buf > 1 && buffers[pos_buf - 2] == '\r') {
              client.println("HTTP/1.1 200 OK");
              client.println("Content-Type: text/html");
              client.println("Access-Control-Allow-Origin:*");
              client.println("Connection: close");
              client.println();
              if (strstr (buffers, "parts=false") != NULL) client.print("Off");
              if (strstr (buffers, "parts=true") != NULL) client.print("On");
              buffersclear();
              client.stop();
            }//if (temp == '\n'....
          }//if (pos_buf >= MAX_SIZE_RESP_BUF) {
        }//if (temp)
      }//if (client.available()
    }//while (client.connected()) {
  }//if (client) {
}//

В какой момент нужно вызывать client.stop();

после 37 строки

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Тогда while (client.connected()) { висит

 

void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("New client");
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Access-Control-Allow-Origin:*");
    client.println("Connection: close");
    client.println();
    client.println("OK");
    client.stop();
  }//if (client) {
}//loop

Так то конечно работает, но мне нужно разобрать полученный get запрос

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

Закрой после разбора... Вроде же все логично - работу закончил, клиента остановил (сокет закрыл). Никто же тарелку не начинает мыть до того, как суп закончил есть.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

В моём варианте, когда client.stop(); 32 строчкой я получаю в монитор порта 

New client
GET /?parts=12345 HTTP/1.1
 
Т.е. закрываю соединение после получения 1 строки в которой как раз GET запрос.
 
sadman41
Offline
Зарегистрирован: 19.10.2016

Надо определиться с тем, какова цель и что требуется обработать. Без этого нет смысла рассуждать о моменте закрытия соединения.

К тому же, по-моему, библиотека Ethernet в процессе эволюции меняла своё поведение при stop(). Но я давно уже не читал её на ночь, конечно.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Цель посмотреть что запрашивается и отправить соответствующие данные

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

negavoid2 пишет:

Так и подсчитать. Сперва получить данные, потом сформировать запрос, и только потом отправлять, а считывать данные прямо в процессе отправки запроса считается дурным тоном.

String s;

for (int i = 1; i < 3; i++) {
   s += "cat";
   s += String(i);
   s += "=";
   s += String(analogRead(i));
   // ... что-то типа того
 }

 client.println("POST /temp.php HTTP/1.1");
 client.println("Host: 192.168.0.22");
 client.println("Content-Length: " + String(s.length()) );
 client.println("Content-Type: application/x-www-form-urlencoded");
 client.println("");
 client.print(s);

ps приведённый пример псевдокод, может даже и не скомпилируется, но суть вот такая

Поговорить хочу.

Так как я теперь 'умею' работать с char, String я трогать не хочу, тяжелее, медленнее.

Отправлять я буду строку формата val=1111|2222|3333}4444|5555.............nnnn|

К примеру, таких показаний у меня 100 штук.

Я создала char[510] и задумалась...как много динамической памяти трачу...а зачем?

Ведь можно в цикле подсчитать длину показаний и прибавить к ним число постоянных параметров (разделители и текст).

Т.е. если у меня 100 четырёхзначных показаний 100*4=400

Прибавляем 100 разделителей "|" 400+100=500

и добавляем ещё 4 (val=) итого Content-Length: 504

Всё верно?))))

 

byte count = 100;
int analog = 1024;
int ContentLength = 0;



void setup() {
  Serial.begin(9600);
  for (int i = 0; i < count; i++) {
    char GetReadings[10];
    //memset(GetReadings, 0, 10);//чистить не надо?
    itoa(analog, GetReadings, DEC);
    ContentLength = ContentLength + strlen(GetReadings);
  }
  Serial.println(ContentLength);
}

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Можно, всё верно.

Единственное, память не надо жалеть до тех пор, пока её хватает, у есп куча минимум 40 килобайт, так что можно не жалеть. Сам по себе http-клиент или кто там, сервер, занимает гораздо больше памяти, и что теперь, не использовать его, что ли?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

negavoid2 пишет:

у есп куча минимум 40 килобайт, так что мож

Atmega328

 client.println("POST /temp.php HTTP/1.1");
 client.println("Host: 192.168.0.22");
 client.println("Content-Length: ***");
 client.println("Content-Type: application/x-www-form-urlencoded");
 client.println("");

client.print("val="); 
for (int i = 1; i < 8; i++) {
client.print(analogRead(i)); 
client.print("|");
 }

Я могу строчку client.println("Content-Length: ***"); отправить после 12 строки? Хотя нет, нельзя.

Всё таки придётся создавать массив? Т.к. считанные показания я сразу отправляю в клиент

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

Irinka пишет:

Цель посмотреть что запрашивается и отправить соответствующие данные

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

Оно эквивалентно такому вопросу: "Хочу посчитать сколько машин проезжает под окном и позвонить в ГИБДД. Когда мне отходить от окна?"

Очевидно, что если нет критерия, по которому определяется момент завершения процесса наблюдения, от окна вас унесут, когда потеряете сознание. 

Поэтому следует определиться: "сколько машин проезжает за час?", "сколько машин проезжает до того, как будет замечен автомобиль с сиреной" и пр.

На что вы опираетесь, когда заключаете: "я получила достаточно данных"?

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

Irinka пишет:

Всё таки придётся создавать массив? Т.к. считанные показания я сразу отправляю в клиент

Нет. Метод применения предрасчёта длины верен и оптимален. Если есть возможность при отсылке всегда соблюдать одну и ту же длину поля данных, а это позволяет любой *printf* (например с %05d), то все становится вовсе простым: content-length = 5 * кол-во полей +  сепараторы + хидер.

Я, лично, предпочитаю snprintf.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Длина поля данных разная, показания с аналогового порта

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

sadman41 пишет:
Я, лично, предпочитаю snprintf.

Ента всё равно память аллоцировать, а её, вишь, жалко :) Сами же и запугали блин новичков :)

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

Сделайте одинаковую. Забейте пустые места нулями, если пробелы не нравятся или сделайте выравнивание по левому краю. Методов-то много. Вплоть до передачи в шестнадцатеричном виде с фиксированной шириной поля в 4 символа. 

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

negavoid2 пишет:

sadman41 пишет:
Я, лично, предпочитаю snprintf.

Ента всё равно память аллоцировать, а её, вишь, жалко :)

За буфер в 10 байт можно жабу и придушить слегонца... 

Logik
Offline
Зарегистрирован: 05.08.2014

Irinka пишет:

.. client.println("Content-Length: ***"); отправить после 12 строки? Хотя нет, нельзя.

Всё таки придётся создавать массив? Т.к. считанные показания я сразу отправляю в клиент

не нужен массив.

1. В Content-Length с запасом величину отправляем.

2. Отправляем данные и считаем их длину.

3. После отправки всех данных вычисляем, сколько не хватило до отправленной в п.1 и дополняем, например пробелами.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Сделайте одинаковую. Забейте пустые места нулями, если пробелы не нравятся или сделайте выравнивание по левому краю. Методов-то много. Вплоть до передачи в шестнадцатеричном виде с фиксированной шириной поля в 4 символа. 

 

if (analog<=999 && analog>99 )Serial.print("0");
if (analog<=99 && analog>9)Serial.print("00");
if (analog<=9 && analog<99)Serial.print("000");
Serial.print(analog);
Serial.print("|");

Хороший вариант, теперь у меня строка будет фиксированной длины.

Так же понравился вариант дополнения 0.

По быстродействию будет значительная разница?

Feofan
Offline
Зарегистрирован: 28.05.2017
  if (analog < 10) Serial.print("000");
  else if (analog < 100) Serial.print("00");
  else if (analog < 1000) Serial.print("0");
  Serial.print(analog);
  Serial.print("|");

Так не проще?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Проще. Спасибо.

При каждой новой отправке данных вывожу в монитор порта millis()

  if (client.connect(server, 80)) {
    DEBUG_PRINT("connected-");
    DEBUG_PRINT(millis());
    DEBUG_PRINTLN("");

Столбец millis() - это время которое приходит в монитор порта. Красные цифры - это разница между 1 и 2, 2 и 3 и т.д. показаниями millis() 

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

Коли уж решили зафлудить, то можно и так сыканомить RAM:

if (analog < 10) Serial.print('0');
if (analog < 100) Serial.print('0');
if (analog < 1000) Serial.print('0');
Serial.print(analog);
Serial.print("|");

 

Только имейте в виду - каждый print инициирует отправку пакета. Выиграли память ардуины - потеряли производительность сетевой подсистемы. Нельзя сказать, что сеть ляжет под нагрузкой сразу же, но как-то неаккуратненько.

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Irinka пишет:
Столбец millis() - это время которое приходит в монитор порта. Красные цифры - это разница между 1 и 2, 2 и 3 и т.д. показаниями millis()

Зачем это?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

 

if (analog < 10) Serial.print('0');
if (analog < 100) Serial.print('0');
if (analog < 1000) Serial.print('0');
Serial.print(analog);
Serial.print("|");

Спасибо )

negavoid2 пишет:

Irinka пишет:
Столбец millis() - это время которое приходит в монитор порта. Красные цифры - это разница между 1 и 2, 2 и 3 и т.д. показаниями millis()

Зачем это?

Косвенно проверяла быстроту работы

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Быстроту работы сериала на 9600??????

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

negavoid2 пишет:

Быстроту работы сериала на 9600??????

115200

Проверка косвенная, в сравнении GET с POST

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

А заодно ещё и бессмысленная :) но за попытку молодец.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:

Только имейте в виду - каждый print инициирует отправку пакета. Выиграли память ардуины - потеряли производительность сетевой подсистемы. Нельзя сказать, что сеть ляжет под нагрузкой сразу же, но как-то неаккуратненько.

 

А как надо?

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Это перестраховка. Делайте пока, как вам надо и как получается. Потом, (если) наткнётесь, переделаете правильно, без блокирований.