ESP8266 отправляет TCP HEX-пакет из 4 символов

Я создаю пульт дистанционного управления для своих WiFi-RGB-ламп. У меня есть ESP8266, который должен отправлять один TCP-пакет с 4 символами.

Мой код:

#include <ESP8266WiFi.h>

const char* ssid     = "Wifi";
const char* password = "wifikey";

void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[WiFi-event] event: %d\n", event);  
}

void setup() {
  Serial.begin(115200);
  WiFi.disconnect(true);
  delay(1000);
  WiFi.onEvent(WiFiEvent);
  WiFi.begin(ssid, password);
}

void loop() {
  delay(1000);
  const uint16_t port = 5577;
  const char * host = "192.168.178.150";
  WiFiClient client;
  client.connect(host, port);
  client.print(char(0x71));
  client.print(char(0x24));
  client.print(char(0x0f));
  client.print(char(0xa4));
  client.flush();
  client.stop();
  delay(5000);   
}

Проблема: я отправляю 4 TCP-пакета, хотя должен отправить 1 TCP-пакет со всеми 4 символами.

Спасибо за помощь.

, 👍0

Обсуждение

Поток данных TCP не ориентирован на пакеты, скорее, это деталь, скрытая в самой реализации; правильно реализованный TCP-сервер *должен* принимать данные, поступающие в любой комбинации пакетов, включая один символ на пакет, слова или строки, разбитые между пакетами, пакеты, содержащие конец одного объекта и начало другого и т. д., @Chris Stratton

Вы можете попробовать отправить все символы одним print(), но по сути вы пытаетесь использовать недокументированное поведение одного объекта, чтобы приспособиться к ошибочному поведению другого., @Chris Stratton

Похоже, проблема на принимающей стороне. Попробуйте сдвинуть/сделать ИЛИ всех значений в один unsigned long и отправить его одним вызовом print., @Johnny Mopp


1 ответ


1

После поисков и экспериментов по этому вопросу я пришел к выводу, что краткий ответ на этот вопрос заключается в том, что вам нужно отправить командную строку как буфер символов И поместить вашу шестнадцатеричную кодированную команду для контроллера светодиода как экранированную строку символов.

Вот мой код (он переключает контроллер светодиодов между зеленым и синим каждые 5 секунд, но вы можете расширить его для других команд и цветов, как описано на http://jpelectron.com/sample/Electronics/WiFi%20LED%20control/):

/*
Отправка команд на светодиодный контроллер через сеть Wi-Fi и плату Wemos D1
*/
#include <ESP8266WiFi.h>

const char* ssid     = "***yourWifiSSID***"; //Измените это значение для вашей сети
const char* password = "***yourWifiPassword***"; //Измените это значение для вашей сети
boolean connected = false;
boolean colorToggle = false;

void WiFiEvent(WiFiEvent_t event) {
    //Serial.printf("[WiFi-event] событие: %d\n", event);

    switch(event) {
    case 3:
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());
        connected = true;
        break;
    case 6:
        Serial.println("WiFi lost connection");
        connected = false;
        break;
    }

    // 0 : WL_IDLE_STATUS, когда Wi-Fi находится в процессе смены статусов
    // 1 : WL_NO_SSID_AVAIL в случае, если настроенный SSID не может быть достигнут
    // 3 : WL_CONNECTED после успешного установления соединения
    // 4 : WL_CONNECT_FAILED если пароль неверный
    // 6 : WL_DISCONNECTED, если модуль не настроен в режиме станции

}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Инициализируем вывод LED_BUILTIN как выход
    Serial.begin(115200);
    WiFi.disconnect(true);
    delay(1000);
    WiFi.onEvent(WiFiEvent);
    WiFi.begin(ssid, password);
    Serial.println("");

    // Ожидание соединения
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());

}

// функция цикла выполняется снова и снова вечно
void loop() {   
    //если мы подключены
    if(connected){
      digitalWrite(LED_BUILTIN, LOW); //Включаем светодиод на плате
      turnLEDSOn();
    }
    else
    {
      digitalWrite(LED_BUILTIN, HIGH); //Выключаем светодиод на плате
      setup();
    }
}

void turnLEDSOn() {
    const uint16_t port = 5577;
    const char * host = "192.168.10.2";  //Измените на IP-адрес вашего контроллера светодиодов

     WiFiClient client;

     if (client.connect(host, port)) //Попробовать подключиться к TCP-серверу
     {
        Serial.println("Connected to LED Controller... ");
        if (colorToggle)
        { //Зеленый
          char command[] = "\x31\x00\xff\x00\x00\x00\xf0\x0f\x2f";
          client.write((uint8_t *)command, sizeof(command));
          colorToggle = false;
          delay(5000); 
        }
        else
        { //Синий
          char command[] = "\x31\x00\x00\xff\x00\x00\xf0\x0f\x2f";
          client.write((uint8_t *)command, sizeof(command));
          colorToggle = true;       
          delay(5000);   
        }

        Serial.println("Command sent ... "); // команда — это цвет или анимация, отправляемая на контроллер светодиода
     } 
     else
     {
        Serial.println("connection failed ... ");
     }

      if (client.available())
      {
        //Чтение с контроллера светодиодов
        char c = client.read();
        Serial.print(c);
      }

      if (!client.connected())
      {
        Serial.println();
        Serial.println("disconnecting ... ");
        client.stop();
        for(;;);
      }    
}
,