Невозможно получить данные IoT с помощью платы Arduino Ethernet Shield

У меня есть ведущий IFM AL1332 IO-Link. https://media.ifm.com/CIP/mediadelivery/asset/3fe3e997b504a143aa0a54f558f218fd/80284134_EN.pdf?contentdisposition=inline

Я могу получить данные через Ethernet-подключение к своему компьютеру и браузеру. Это выглядит примерно так.

«Значение» описывает состояние порта 1.

Я хочу сделать то же самое с Arduino. Я использую Arduino Mega и Ethernet Shield 2. Изменил код веб-клиента следующим образом.

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

// Введите MAC-адрес вашего контроллера ниже.
// У новых моделей Ethernet-щитов MAC-адрес напечатан на наклейке на щите.
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAF, 0x15, 0x1C };

// если вы не хотите использовать DNS (и уменьшить размер вашего скетча)
// используйте числовой IP вместо имени сервера:
IPAddress server(172, 16, 0, 110);  // числовой IP

// Установить статический IP-адрес
IPAddress ip(172, 16, 0, 101);

// Инициализируем клиентскую библиотеку Ethernet
// с IP-адресом и портом сервера
// к которому вы хотите подключиться (порт 80 по умолчанию для HTTP):
EthernetClient client;

// Переменные для измерения скорости
unsigned long beginMicros, endMicros;
unsigned long byteCount = 0;
bool printWebData = true;  // установите значение false для более точного измерения скорости

void setup() {
  // Вы можете использовать Ethernet.init(pin) для настройки контакта CS
  //Ethernet.init(10); // Большинство плат расширения Arduino
  //Ethernet.init(5); // MKR ETH Shield
  //Ethernet.init(0); // Teensy 2.0
  //Ethernet.init(20); // Teensy++ 2.0
  //Ethernet.init(15); // ESP8266 с Adafruit FeatherWing Ethernet
  //Ethernet.init(33); // ESP32 с Adafruit FeatherWing Ethernet

  // Открываем последовательную связь и ждем открытия порта:
  Serial.begin(9600);
  while (!Serial) {
    ;  // дождитесь подключения последовательного порта. Требуется только для собственного USB-порта.
  }

  // запуск Ethernet-соединения:
  Serial.println("Initialize Ethernet:");

  Ethernet.begin(mac, ip);

  // даем Ethernet-плате секунду на инициализацию:
  delay(1000);
  Serial.print("connecting to ");
  Serial.print(server);
  Serial.println("...");

  // если соединение установлено, сообщите об этом через последовательный порт:
  if (client.connect(server, 80)) {
    Serial.print("connected to ");
    Serial.println(client.remoteIP());
    // Сделайте HTTP-запрос:
    client.println("GET /iolinkmaster/port[1]/iolinkdevice/pdin/getdata HTTP/1.1");
    client.println();
  } else {
    // если не удалось подключиться к серверу:
    Serial.println("connection failed");
  }
  beginMicros = micros();
}

void loop() {
  // если есть входящие байты
  // с сервера, читаем их и печатаем:
  int len = client.available();
  if (len > 0) {
    byte buffer[80];
    if (len > 80) len = 80;
    client.read(buffer, len);
    if (printWebData) {
      Serial.write(buffer, len);  // показать в последовательном мониторе (замедляет некоторые платы)
    }
    byteCount = byteCount + len;
  } 

  // если сервер отключен, останавливаем клиент:
  if (!client.connected()) {
    endMicros = micros();
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    Serial.print("Received ");
    Serial.print(byteCount);
    Serial.print(" bytes in ");
    float seconds = (float)(endMicros - beginMicros) / 1000000.0;
    Serial.print(seconds, 4);
    float rate = (float)byteCount / seconds / 1000.0;
    Serial.print(", rate = ");
    Serial.print(rate);
    Serial.print(" kbytes/second");
    Serial.println();

    // ничего не делать вечно:
    while (true) {
      delay(1);
    }
  }
}

Когда я попробовал это на Arduino, я получил следующее.

Инициализация Ethernet:

подключение к 172.16.0.110...

подключен к 172.16.0.110

отключение.

Получено 0 байт в 32.1074, скорость = 0,00 кбайт/сек

Данные не поступают. Насколько я могу судить, я отправляю правильный GET-запрос. Я проверил элементы изображённой веб-страницы.

Что я упускаю?

, 👍0

Обсуждение

отправьте заголовок Host и завершите запрос пустой строкой (как это делает пример WebClient), @Juraj

@Juraj Именно так я и делаю. Ведущий, похоже, никогда не отвечает., @vini_i

его нет в эскизе в вопросе, @Juraj

@Juraj это почти конец void setup(). client.println("GET /iolinkmaster/port[1]/iolinkdevice/pdin/getdata HTTP/1.1"); client.println();, @vini_i

и заголовок Host?, @Juraj

@Juraj Это не заголовок хоста?, @vini_i

client.println("Хост: 172.16.0.110");, @Juraj

@Juraj, без этого всё работало. А оно нужно?, @vini_i

похоже, что прошивка устройства не имеет строгой реализации протокола, но если ее можно обновить, то в будущей версии это может быть изменено., @Juraj


2 ответа


0
client.println("GET /iolinkmaster/port[1]/iolinkdevice/pdin/getdata HTTP/1.1");

HTTP-запрос был некорректен. В нём отсутствовал \r\n\r\n.

client.println("GET /iolinkmaster/port[1]/iolinkdevice/pdin/getdata HTTP/1.1\r\n\r\n");

Это оператор, который вернул данные с сервера.

,

Сколько новых строк вам нужно? println добавляет одну, затем у вас есть две с \r\n\r\n, а затем у вас есть еще одна client.println(). то есть на две пустые строки больше, чем требует HTTP., @Juraj

@Juraj Вот это сработало. Я пробовал добавить один \r\n, но это не помогло. Добавление двух помогло. Не могу сказать, почему., @vini_i

@Juraj После долгих поисков и тестирования выяснилось, что устройство IFM крайне чувствительно к задержкам. Даже println() недостаточно быстр. Всю информацию заголовка нужно отправлять одной строкой. `client.print("GET /iolinkmaster/port[1]/iolinkdevice/pdin/getdata HTTP/1.1\r\nHost: 172.16.0.110\r\n\r\n");`На эту строку оно отреагирует корректно., @vini_i


0

В ваших запросах к Arduino могут отсутствовать некоторые заголовки. Попробуйте следующее:

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

// Настройка Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(172, 16, 0, 110);  // Замените на IP-адрес вашего сервера
EthernetClient client;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;  // Ожидание подключения последовательного порта
  }

  // Запустить Ethernet-соединение
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    for (;;);
  }

  // Разрешить инициализацию Ethernet-щита:
  delay(1000);

  if (client.connect(server, 80)) {
    Serial.println("connected");

    // Отправить HTTP GET-запрос с дополнительными заголовками
    client.println("GET /iolinkmaster/port[1]/iolinkdevice/pdin/getdata HTTP/1.1");
    client.println("Host: 172.16.0.110");
    client.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
    client.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36");
    client.println("Accept-Encoding: gzip, deflate");
    client.println("Accept-Language: en-US,en;q=0.9");
    client.println("Connection: keep-alive");
    client.println("Upgrade-Insecure-Requests: 1");
    client.println();

  } else {
    Serial.println("connection failed");
  }
}

void loop() {
  // Прочитать ответ от сервера
  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  }

  // Отключиться по завершении
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
}
,