ESP8266 отправляет данные на сайт, но не возвращает статус
У меня проблема с моим esp8266, он подключается к моему сайту и отправляет 89 байт данных, но возвращает статус подтверждения, все, что я получаю, это ОТПРАВИТЬ ОК, но я не получаю подтверждения от своего сервера
Это мой код ниже
#include <SoftwareSerial.h>
#include<time.h>
SoftwareSerial ESP8266(3, 2); // прием, передача
//ОПРЕДЕЛИТЕ ЗДЕСЬ ВСЕ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
unsigned int timeout_start_val;
char scratch_data_from_ESP[20];//первый байт - это длина байтов
char payload[150];
byte payload_size=0, counter=0;
char ip_address[16];
char youtube_subs[10];
char youtube_views[13];
char current_temp[5];
char hi_temp[5];
char lo_temp[5];
//РЕЖИМЫ
const char CWMODE = '3';//CWMODE 1=СТАНЦИЯ, 2=APMODE, 3=ОБА
const char CIPMUX = '1';//CIPMUX 0=одно подключение, 1=несколько подключений
//Пароль
const char SSID_ESP[]="Xamel";//"AOTEA TZ";//из константы
const char SSID_KEY[]="cewu5103";//"wyrnC592";
//ОПРЕДЕЛИТЕ ЗДЕСЬ КЛЮЧЕВЫЕ СЛОВА
const char keyword_OK[]="OK";
const char keyword_FAIL[]="FAIL";
const char keyword_Ready[] = "Ready";
const char keyword_no_change[] = "no change";
const char keyword_blank[] = "#&";
const char keyword_ip[] = "192.";
const char keyword_rn[] = "\r\n";
const char keyword_quote[] = "\"";
const char keyword_carrot[] = ">";
const char keyword_sendok[] = "SEND OK";
const char keyword_linkdisc[] = "Unlink";
const char keyword_CHECKCWMODE[] = "+CWMODE:3";
const char keyword_URL_CONNECTION_ERROR[]="Link typ ERROR";
const char TEST_URL[]="";
const char GET_URL[]="GET /ESP8266_BackEnd/SaveDetail.php?Name=";
int str1=strlen(GET_URL);
const char Name[]="Alex ";
int str2=strlen(Name);
const char TRAILING_URL[]="HTTP/1.1 \\r\\nHost: www.pick2get.com\\r\\n\\r\\n";
int str3=strlen(TRAILING_URL);
int strTotal=str1+str2+str3;
const char AT_CIPSTART[]="AT+CIPSTART=4,\"TCP\",\"pick2get.com\",80 \r\n";
const char AT_CIPSEND[]="AT+CIPSEND=4,";
//прототип функции
boolean read_until_ESP(const char keyword1[], int key_size, int timeout_val, byte mode);
void serial_dump_ESP();
boolean setup_ESP(const char SSID_ESP[],const char SSID_KEY);
String url="&School=4D616B6F6E676F";
void setup() {
// Открытие последовательной связи и ожидание открытия порта:
Serial.begin(9600);
while (!Serial) {
; // ждем подключения последовательного порта. Требуется только для родного порта USB
}
//.print("Общая длина строки");Serial.println(strTotal);
// устанавливаем скорость передачи данных для порта SoftwareSerial
ESP8266.begin(9600);
//
//Serial.println(read_until_ESP(keyword_URL_CONNECTION_ERROR,sizeof(keyword_URL_CONNECTION_ERROR),5000,0));
setup_ESP(SSID_ESP,SSID_KEY);
ESP8266.print(AT_CIPSTART);
ESP8266.print("");
delay(1000);
ESP8266.print(AT_CIPSEND);
ESP8266.print(strTotal);
ESP8266.print("\r\n");
delay(1000);
ESP8266.print("");
ESP8266.print(GET_URL);
ESP8266.print(Name);
ESP8266.print(TRAILING_URL);
delay(1000);
ESP8266.print("");
//ESP8266.println("&Grade=466F726D204F6E65");
//ESP8266.println("&DeviceIP=3139322E3136382E302E31");
//ESP8266.println(TRAILING_URL);
}
void loop() { // повторяем снова и снова
byte buffer[300];
if (ESP8266.available()) {
Serial.write(ESP8266.read());
}
if (Serial.available()) {
ESP8266.write(Serial.read());
}
}
Это вывод, созданный на последовательном мониторе
ESP CHECK OK
ESP RESET OK
ESP RESET OK
timeout
ESP CWMODE SET FAILED
CWMODE ALREADY SET
SETTING SSID_ESP: Xamel
SETTING SSID_KEY: cewu5103
ESP SSID SET OK DEVICE CONNECTED
CHECKING FOR AN IP ADDRESS
IP ADDRESS = 192.168.4.1
ESP CIPMUX SET
AT+CIPSTART=4,"TCP","pick2get.com",80
OK
Linked
AT+CIPSEND=4,89
> GET /ESP8266_BackEnd/SaveDetail.php?Name=Alex HTTP/1.1 \r\nHost: www.pick2get.com\r\n\r\n
SEND OK
OK
Unlink
Может ли кто-нибудь помочь здесь.
При добавлении ESP8266.print("+IPD\r\n"); это результат, который я получаю
ESP CHECK OK
ESP RESET OK
ESP RESET OK
timeout
ESP CWMODE SET FAILED
CWMODE ALREADY SET
SETTING SSID_ESP: Xamel
SETTING SSID_KEY: cewu5103
ESP SSID SET OK DEVICE CONNECTED
CHECKING FOR AN IP ADDRESS
IP ADDRESS = 192.168.4.1
ESP CIPMUX SET
AT+CIPSTART=4,"TCP","pick2get.com",80
AT+CIPSEND=4,89
busy p...
OK
Linked
GET /ESP8266_BackEnd/SaveDetail.php?Name=Alex HTTP/1.1 \r\nHost: www.pick2get.com\r\n\r\n
wrong syntax
ERROR
AT+IPD
ERROR
Мне удалось исправить отсутствие ответа сервера, удалив \r\n \nd и заменив их обычными \r\n\r\n
enter code here
const char TRAILING_URL[]="HTTP/1.1 \r\nHost: www.pick2get.com \r\n\r\n";
int str3=strlen(TRAILING_URL);
int strTotal=str1+str2+str3;
const char AT_CIPSTART[]="AT+CIPSTART=4,\"TCP\",\"pick2get.com\",80 \r\n";
const char AT_CIPSEND[]="AT+CIPSEND=4,";
В этих строках удалось получить ответ сервера
+IPD,4,392:HTTP/1.1 400 Неверный запрос Дата: вторник, 15 мая 2018 г., 12:07:08 по Гринвичу Сервер: Апач Длина контента: 226 Подключение: близко Тип содержимого: текст/html; кодировка = iso-8859-1
ошибка 400, неверный запрос Неверный запрос
Ваш браузер отправил запрос, который этот сервер не смог понять.
наконец-то я отладил и исправил все ошибки, и код работает просто отлично Это и сервер возвращает статус 200
Оказывается, я просто указал GET-запросу неправильный путь к папке с этим кодом строки в переменной GET_URL
const char GET_URL[]="GET pick2get.com/ESP8266_BackEnd/SaveDetail.php?Name=";
Я заменил это
const char GET_URL[]="GET /ESP8266_BackEnd/SaveDetail.php?Name=";
И получили желаемый результат
+IPD,4,166:HTTP/1.1 200 ОК Дата: вторник, 15 мая 2018 г., 12:22:49 по Гринвичу Сервер: Апач Улучшение: h2 Подключение: Обновление Передача-кодирование: по частям Тип контента: text/html
2
ОК
+IPD,4 191:16
Подключено успешно
5с
ДАННЫЕ ПЕРЕДАНЫ УСПЕШНО ИМЯ СТУДЕНТА ПОЛУЧЕНО: Alex
ИМЯ СТУДЕНТА ПОЛУЧЕНО:
3б
ПОЛУЧЕНА СТУДЕНЧЕСКАЯ ОЦЕНКА:
ПОЛУЧЕНО IP-АДРЕС УСТРОЙСТВА:
ОК
+IPD,4,42:1f Новая запись успешно создана 0 Большое спасибо, ребята, ниже приведен полный рабочий код
/* Множественный серийный тест программного обеспечения Получает от аппаратного серийного номера, отправляет на Software Serial. Получает от SoftwareSerial, отправляет hardware serial. Схема: * RX — это цифровой контакт 10 (подключение к TX другого устройства) * TX — это цифровой контакт 11 (подключается к RX другого устройства) Примечание: Не все выводы на Mega и Mega 2560 поддерживают прерывания изменения, поэтому для RX можно использовать только следующее: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 Не все выводы на Leonardo и Micro поддерживают прерывания изменения, поэтому для RX можно использовать только следующее: 8, 9, 10, 11, 14 (МИСО), 15 (СКК), 16 (МОСИ). созданный еще в глубине веков изменено 25 мая 2012 г. Нолави Соломон */ #include <SoftwareSerial.h> #include<time.h> Программное обеспечение Serial ESP8266(3, 2); // прием, передача //ОПРЕДЕЛИТЕ ЗДЕСЬ ВСЕ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ беззнаковое целое время timeout_start_val; charcratch_data_from_ESP[20];//первый байт - это длина байтов символьная полезная нагрузка[150]; byte payload_size=0, counter=0; char ip_адрес[16]; //РЕЖИМЫ const char CWMODE = '3';//CWMODE 1=СТАНЦИЯ, 2=APMODE, 3=ОБА const char CIPMUX = '1';//CIPMUX 0=одно подключение, 1=несколько подключений //Пароль const char SSID_ESP[]="Xamel";//"AOTEA TZ";//из константы const char SSID_KEY[]="cewu5103";//"wyrnC592"; //ОПРЕДЕЛИТЕ ЗДЕСЬ КЛЮЧЕВЫЕ СЛОВА const char keyword_OK[]="OK"; const char keyword_FAIL[]="FAIL"; const char keyword_Ready[] = "Готово"; const char keyword_no_change[] = "без изменений"; const char keyword_blank[] = "#&"; const char keyword_ip[] = "192."; const char keyword_rn[] = "\r\n"; const char keyword_quote[] = "\""; const char keyword_carrot[] = ">"; const char keyword_sendok[] = "ОТПРАВИТЬ ОК"; const char keyword_linkdisc[] = "Отключить связь"; const char keyword_CHECKCWMODE[] = "+CWMODE:3"; const char keyword_URL_CONNECTION_ERROR[]="ОШИБКА типа ссылки"; //const char TEST_URL[]=""; const char GET_URL[]="GET /ESP8266_BackEnd/SaveDetail.php?Name="; int str1 = strlen (GET_URL); const char Имя[]="Алекс"; int str2 = strlen (имя); const char TRAILING_URL[]="HTTP/1.1\r\nХост: www.pick2get.com \r\n\r\n"; int str3 = strlen (TRAILING_URL); int strTotal=str1+str2+str3; const char AT_CIPSTART[]="AT+CIPSTART=4,\"TCP\",\"pick2get.com\",80 \r\n"; const char AT_CIPSEND[]="AT+CIPSEND=4,"; //прототип функции логическое значение read_until_ESP (const char ключевое слово1 [], int key_size, int timeout_val, байтовый режим); недействительными serial_dump_ESP(); логическое значение setup_ESP(const char SSID_ESP[],const char SSID_KEY); //String url="&School=4D616B6F6E676F"; недействительная установка () { // Открытие последовательной связи и ожидание открытия порта: Серийный.начать(9600); пока (!Серийный) { ; // ждем подключения последовательного порта. Требуется только для родного порта USB } //.print("Общая длина строки");Serial.println(strTotal); // устанавливаем скорость передачи данных для порта SoftwareSerial ESP8266.начало(9600); // //Serial.println(read_until_ESP(keyword_URL_CONNECTION_ERROR,sizeof(keyword_URL_CONNECTION_ERROR),5000,0)); setup_ESP (SSID_ESP, SSID_KEY); ESP8266.print(AT_CIPSTART); ESP8266.print(""); delay(1000); ESP8266.print(AT_CIPSEND); ESP8266.print(strTotal); ESP8266.print("\r\n"); delay(1000); ESP8266.print(""); ESP8266.print(GET_URL); ESP8266.print(Имя); ESP8266.print(TRAILING_URL); // задержка (3000); //ESP8266.print(""); // задержка (2000); //ESP8266.print("\r\n"); // задержка (2000); //ESP8266.print(""); //ESP8266.print("AT+IPD\r\n"); //ESP8266.println("&Grade=466F726D204F6E65"); //ESP8266.println("&DeviceIP=3139322E3136382E302E31"); //ESP8266.println(TRAILING_URL); } void loop() { // повторяем снова и снова байтовый буфер[300]; если (ESP8266.доступно()) { Serial.write(ESP8266.read()); } если (серийный.доступный()) { ESP8266.write(Serial.read()); } } логическое значение read_until_ESP (const char ключевое слово1 [], int key_size, int timeout_val, байтовый режим) { timeout_start_val=millis();//для тайм-аута char data_in[20];//это буфер - если ключевое слово длиннее 20, то увеличить его intcratch_length=1;//длина массива рабочих данных key_size--;//поскольку мы собираемся получить лишний символ от sizeof() // ЗАПОЛНЯЕМ БУФЕР for(byte i=0; i<key_size; i++){//нам нужен только буфер, если ключевое слово //управление временем while(!ESP8266.available()){//ждите, пока новый байт не будет отправлен из ESP – хороший способ синхронизировать работу с последовательным портом. if((millis()-timeout_start_val)>timeout_val){//если в течение тайм-аута ничего не происходит, уходите отсюда Serial.println ("время ожидания"); return 0;//это завершит функцию }//тайм-аут }// пока !доступно data_in[i]=ESP8266.read();// сохраняем байт в буфер 'data_in[] if(mode==1){//это сохранит все данные в файлеcrat_data_from cratch_data_from_ESP[scratch_length]=data_in[i];//начинается с 1 cratch_data_from_ESP[0]=scratch_length;// [0] используется для хранения длины массива cratch_length++;//увеличиваем длину }//режим 1 }//для я // БУФЕР ЗАПОЛНЕН, ПОЭТОМУ НАЧНИТЕ ВВОД НОВЫХ ДАННЫХ И ИЗВЛЕЧЕНИЕ СТАРЫХ ДАННЫХ while(1){//оставаться здесь, пока не будет найдено ключевое слово или не истечет время ожидания //проходим по всему буферу и ищем ключевое слово //эта проверка здесь, на тот случай, если первое, что было выведено из ESP, было ключевым словом, означающим, что буфер действительно был заполнен ключевым словом for(byte i=0; i< key_size; i++){ if(keyword1[i]!=data_in[i])//если не совпадает, выходим из поиска перерыв; // убирайся отсюда if(i==(key_size-1)){//мы полностью прошли ключевое слово, не нарушая его, должно быть совпадение! вернуть 1; // верни 1 и убирайся отсюда! }//если }//для байта i //запускаем буфер for(byte i=0; i<(key_size-1); i++){// keysize-1, потому что все смещено – см. следующую строку data_in[i]=data_in[i+1];// таким образом, данные с номером 0 становятся данными с номером 1 и т. д.... последнее значение — это место, куда мы поместим новые данные }//для //управление временем while(!ESP8266.available()){// то же самое, что и в буфере if((millis()-timeout_start_val)>timeout_val){ Serial.println ("время ожидания"); вернуть 0; }//тайм-аут }// пока !доступно data_in[key_size-1]=ESP8266.read();//сохраняем новые данные в последней позиции в буфере if(mode==1){//продолжать сохранять все, если это установлено cratch_data_from_ESP[scratch_length]=data_in[key_size-1]; скретч_данные_из_ESP[0]=скретч_длина; скретч_длина++; }//режим 1 /* ТОЛЬКО ДЛЯ ОТЛАДКИ если(ESP8266.переполнение()) Serial.println("*ПЕРЕВЕРНИТЕ"); */ }//пока 1 }//читаем до ESP логическое значение setup_ESP(const char SSID_ESP[],const char SSID_KEY[]){//возвращает 1 в случае успеха ESP8266.print("AT\r\n");// Отправьте только 'AT', чтобы убедиться, что ESP отвечает //эта функция read_until_... используется для поиска ключевого слова в ответе ESP — подробнее об этом позже и в самой функции if(read_until_ESP(keyword_OK,sizeof(keyword_OK),5000,0))//ищем ключевое слово "ОК" с тайм-аутом 5 секунд Serial.println("ПРОВЕРКА ESP ОК"); еще Serial.println ("ОШИБКА ПРОВЕРКИ ESP"); serial_dump_ESP();//это просто считывает все, что находится в буфере, и то, что еще поступает из ESP ESP8266.print("AT+RST\r\n");// Сделайте сброс - кто знает, в каком состоянии он был, лучше начать заново if(read_until_ESP(keyword_Ready,sizeof(keyword_Ready),5000,0))//находим ключевое слово "Готово" - выполнение занимает на несколько секунд больше Serial.println("ESP RESET OK");//в зависимости от версии FW на ESP, иногда Ready пишется строчной буквой r - готово еще Serial.println("ОШИБКА СБРОСА ESP"); серийный_дамп_ESP(); ESP8266.print("AT+RST\r\n");// Сделайте сброс - кто знает, в каком состоянии он был, лучше начать заново if(read_until_ESP(keyword_Ready,sizeof(keyword_Ready),5000,0))//находим ключевое слово "Готово" - выполнение занимает на несколько секунд больше Serial.println("ESP RESET OK");//в зависимости от версии FW на ESP, иногда Ready пишется строчной буквой r - готово еще Serial.println("ОШИБКА СБРОСА ESP"); серийный_дамп_ESP(); ESP8266.print("AT+CWMODE=");// устанавливаем CWMODE ESP8266.print(CWMODE);//просто отправить то, что установлено в константе ESP8266.print("\r\n"); if(read_until_ESP(keyword_OK,sizeof(keyword_OK),1000,0))//находим ключевое слово "ОК" Serial.println ("ESP CWMODE SET"); еще Serial.println("ESP CWMODE SET FAILED");//вероятно, произойдет сбой, так как возвращается "без изменений", если уже установлено - было бы неплохо проверить два слова ESP8266.println("AT+CWMODE?"); if(read_until_ESP(keyword_CHECKCWMODE,sizeof(keyword_CHECKCWMODE),1000,0)) { Serial.println("CWMODE УЖЕ УСТАНОВЛЕН"); серийный_дамп_ESP(); } серийный_дамп_ESP(); //Здесь устанавливаются SSID и PW Serial.print("НАСТРОЙКА SSID_ESP: "); Serial.println(SSID_ESP); Serial.print("НАСТРОЙКА SSID_KEY: "); Serial.println(SSID_KEY); //Точка DEbug ESP8266.print("AT+CWJAP=");// ESP8266.print("\""); ESP8266.print(SSID_ESP);// ESP8266.print("\",\""); ESP8266.print(SSID_KEY);// ESP8266.print("\"\r\n"); if(read_until_ESP(keyword_OK,sizeof(keyword_OK),5000,0)==1)//находим ключевое слово "ОК" Serial.println("ESP SSID SET OK DEVICE CONNECTED"); иначе, если (read_until_ESP (keyword_FAIL, sizeof (keyword_FAIL), 5000,0) == 1) Serial.println ("ESP SSID SET FAILED"); серийный_дамп_ESP(); // Это проверяет и сохраняет IP-адрес Serial.println("ПРОВЕРКА IP-АДРЕСА"); ESP8266.print("AT+CIFSR\r\n");//команда для получения IP-адреса из ESP if(read_until_ESP(keyword_rn,sizeof(keyword_rn),10000,0)){//ищите первый \r\n после AT+CIFSR echo - режим примечания '0', IP-адрес сразу после этого if(read_until_ESP(keyword_rn,sizeof(keyword_rn),1000,1)){//ищите второй \r\n и сохраняйте все, что он получает, mode='1' // сохраняем IP-адрес в своей переменной ip_address[] for(int i=1; i<=(scratch_data_from_ESP[0]-sizeof(keyword_rn)+1); i++)//что i<=... потребует некоторого объяснения, см. следующие строки ip_address[i] =cratch_data_from_ESP[i];//заполняем ip_address полученными скретч-данными //i=1, потому что i=0 - это длина данных, найденных между двумя ключевыми словами, НО это включает длину второго ключевого слова, поэтому i<= до длины минус // размер ключевого слова, но помните, что sizeof() вернет один дополнительный, который будет вычтен, поэтому я просто добавил его обратно в +1 ip_address[0] = (scratch_data_from_ESP[0]-sizeof(keyword_rn)+1);//сохраняем длину ip_address в [0], то же самое, что и раньше Serial.print("IP ADDRESS = ");//распечатайте его для проверки for(int i=1; i<=ip_address[0]; i++)//отправляем IP-адрес Serial.print(ip_address[i]); Серийный.println(""); }}//если сначала \r\n еще Serial.print("ОШИБКА IP-АДРЕСА"); серийный_дамп_ESP(); ESP8266.print("AT+CIPMUX=");// устанавливаем CIPMUX ESP8266.print(CIPMUX);//из константы ESP8266.print("\r\n"); if(read_until_ESP(keyword_OK,sizeof(keyword_OK),5000,0))//находим ключевое слово "ОК" или "без изменений" Serial.println("ESP CIPMUX SET"); еще Serial.println ("ESP CIPMUX SET FAILED"); серийный_дамп_ESP(); //вот и все! Можно сделать, вложив все вместе, поэтому, если что-то не получается, он возвращает «0», а если он проходит весь путь, он возвращает «1» ... ну ладно }//настройка ESP // довольно простая функция - прочитать все из последовательного буфера и все, что приходит, и избавиться от этого недействительными serial_dump_ESP () { температура угля; пока(ESP8266.доступно()){ темп =ESP8266.read(); delay(1);//можно поэкспериментировать с этим значением, если происходит переполнение буфера }//пока }//серийный дамп
@Charles, 👍-1
Обсуждение1 ответ
В заголовке http должно быть указано "Connection: keep-alive", по умолчанию стоит "Connection: close", и поэтому вы никогда не получите ничего взамен от сервера.
Я описал все это вместе с образцом кода в https://arduino.stackexchange.com/a/54558/48149
.В примере кода используется библиотека WifiEsp для подключения к ESP8266.
Да, спасибо, я исправил это давно, но все равно большое уважение за ваш вклад, @Charles
- Чтение данных из Google Таблиц с помощью Nodemcu
- ESP8266 отключается через несколько часов
- Случайные символы, передаваемые из ESP8266 в Arduino
- Программировать ESP8266, чтобы избежать случайных исключений?
- Веб-сокеты с ESP8266 с использованием платы Arduino Uno
- nodemcu не отвечает в командном режиме
- Исправление последовательной связи, условие доступности последовательных данных проверяется даже после считывания всех отправленных данных.
- Как код, набранный в Arduino IDE, работает на nodemcu?
Что произойдет, если вы напишете
+IPD\r\n
в качестве следующей AT-команды? (https://github.com/espressif/ESP8266_AT/wiki/IPD), @Maximilian Gerhardt@MaximilianGerhardt Можете ли вы рассказать подробнее, я почти новичок с esp8266, @Charles
Я думаю, вам нужно отправить эту дополнительную AT-команду для получения данных. Добавьте
ESP8266.print("+IPD\r\n");
в качестве последнего оператора в вашей функцииsetup
. См. https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf, @Maximilian GerhardtЯ добавил эту команду AT, и, похоже, есть синтаксическая ошибка., @Charles
Отредактируйте свой вопрос с обновленным кодом и ошибкой., @Maximilian Gerhardt
Можете попробовать команду
"+IPD,500\r\n"
. Это должно запросить 500 байт от соединения. Попробуйте поиграть с цифрой., @Maximilian Gerhardt\\r\\n
; Вы уверены, что вам нужно дважды экранировать эти новые строки?, @Gerben@Gerben большое спасибо, очевидно, заменив \\r\\n на обычный \r\n, я получаю ответ, видимо, его статус 400, но он все еще прогрессирует :), @Charles
У @Gerben когда-либо была ситуация, когда esp8266 просто зависал после отправки запроса на получение, @Charles
С ESP ничего не делал. Попробуйте выяснить, где программа останавливается. В большинстве случаев это просто программная проблема. Если программа время от времени перестает работать, вы можете рассмотреть возможность включения WatchDog., @Gerben