Web интерфейс управления сервоприводами ESP8266 есть скеч. цена в мере розумного

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Подскажите что я делаю не так ? Позиция лево-право: undefined  Позиция верх-вниз: работает нормально

За исправления кода скину $

Вот код можно компилировать.

#include <Servo.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
 
const char *ssid = "Aleksander";
const char *password = "11406080";
 
Servo myservo;  // создаем экземпляр класса «Servo»,
Servo myservo1;  // чтобы с его помощью управлять сервоприводом;
                // большинство плат позволяют
                // создать 12 объектов класса «Servo»
 
// GPIO-контакт, к которому подключен сервопривод:
static const int servoPin = 13;
static const int servo1Pin = 14;
 
// создаем веб-сервер на порте «80»:
WiFiServer server(80);
 
// переменная для хранения HTTP-запроса:
String header;
String header1;
// несколько переменных для расшифровки значения в HTTP-запросе GET:
String valueString = String(5);
String valueString1 = String(5);
int pos1 = 0;
int pos2 = 0;
int pos11 = 0;
int pos22 = 0;
 
void setup() {
  Serial.begin(115200);
 
  myservo.attach(servoPin);  // привязываем сервопривод,
  myservo.attach(servo1Pin); // подключенный к контакту «servoPin»,
                             // к объекту «myservo»
 
  // подключаемся к WiFi при помощи заданных выше SSID и пароля: 
  Serial.print("Connecting to ");  //  "Подключаемся к "
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // печатаем локальный IP-адрес и запускаем веб-сервер:
  Serial.println("");
  Serial.println("WiFi connected.");  //  "WiFi подключен."
  Serial.println("IP address: ");     //  "IP-адрес: "
  Serial.println(WiFi.localIP());
  server.begin();
}
 
void loop(){
  // начинаем прослушивать входящих клиентов:
  WiFiClient client = server.available();
 
  if (client) {                     // если подключился новый клиент,     
    Serial.println("New Client.");  // печатаем сообщение
                                    // «Новый клиент.»
                                    // в мониторе порта;
    String currentLine = "";        // создаем строку для хранения
                                    // входящих данных от клиента;
    while (client.connected()) {    // цикл while() будет работать
                                    // все то время, пока клиент
                                    // будет подключен к серверу;
      if (client.available()) {     // если у клиента есть данные,
                                    // которые можно прочесть, 
        char c = client.read();     // считываем байт, а затем    
        Serial.write(c);            // печатаем его в мониторе порта
        header += c;
        if (c == '\n') {            // если этим байтом является
                                    // символ новой строки
          // если получили два символа новой строки подряд,
          // то это значит, что текущая строчка пуста;
          // это конец HTTP-запроса клиента,
          // а значит – пора отправлять ответ:
          if (currentLine.length() == 0) {
            // HTTP-заголовки всегда начинаются
            // с кода ответа (например, «HTTP/1.1 200 OK»)
            // и информации о типе контента
            // (чтобы клиент понимал, что получает);
            // в конце пишем пустую строчку:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
                       //  "Соединение: отключено"
            client.println();
 
            // показываем веб-страницу:
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");
            client.println(".slider { width: 300px; }</style>");
            client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");
                     
            // веб-страница:
            client.println("</head><body><h1>ESP8266 Управление сервомотором антенны</h1>");
                                        //  "Управление сервомотором
                                        //   с помощью платы ESP32"
            client.println("<p>Позиция верх-вниз: <span id=\"servoPos\"></span></p>");     
            client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");
            client.println("<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>");
            client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider1\" id=\"servoSlider1\" onchange=\"servo1(this.value1)\" value1=\""+valueString1+"\"/>");
            
            client.println("<script>var slider = document.getElementById(\"servoSlider\");");
            client.println("var slider1 = document.getElementById(\"servoSlider1\");");
            client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
            client.println("var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value1;");
            client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
            client.println("slider1.oninput = function() { slider1.value1 = this.value1; servoP1.innerHTML = this.value1; }");
            client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");
            client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}");
            client.println("$.ajaxSetup({timeout:1000}); function servo1(pos1) { ");
            client.println("$.get(\"/?value=\" + pos1 + \"&\"); {Connection: close};}</script>");
           
            client.println("</body></html>");     
            
            //GET /?value=180& HTTP/1.1
            if(header.indexOf("GET /?value=")>=0) {
              pos1 = header.indexOf('=');
              pos2 = header.indexOf('&');
              pos11 = header1.indexOf('=');
              pos22 = header1.indexOf('&');
              valueString = header.substring(pos1+1, pos2);
              valueString1 = header1.substring(pos11+1, pos22);
              // вращаем ось сервомотора:
              myservo.write(valueString.toInt());
              Serial.println(valueString);
              myservo1.write(valueString1.toInt());
              Serial.println(valueString1); 
            }         
            // конец HTTP-ответа задается 
            // с помощью дополнительной пустой строки:
            client.println();
            // выходим из цикла while(): 
            break;
          } else { // если получили символ новой строки,
                   // очищаем текущую строку «currentLine»:
            currentLine = "";
          }
        } else if (c != '\r') {  // если получили любые данные,
                                 // кроме символа возврата каретки,
          currentLine += c;      // добавляем эти данные 
                                 // в конец строки «currentLine»
        }
      }
    }
    // очищаем переменную «header[]»:
    header = "";
    header1 = "";
    // отключаем соединение:
    client.stop();
    Serial.println("Client disconnected.");
               //  "Клиент отключился."
    Serial.println("");
  }
}

 

fridgetester
fridgetester аватар
Offline
Зарегистрирован: 09.02.2019

Если верх-вниз действительно работает, то поправлю скетч для лево-право за 500р, fridgetester@mail.ru

ЗЫ: оплата, разумеецца, вперёд.

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

zDimaBY - вставьте код правильно, с номерами строк, чтоб я мог указать вам ошибку

zDimaBY
Offline
Зарегистрирован: 10.06.2018
001#include <Servo.h>
002#include <ESP8266WiFi.h>
003#include <WiFiClient.h>
004#include <ESP8266WebServer.h>
005#include <ESP8266mDNS.h>
006 
007const char *ssid = "Aleksander";
008const char *password = "11406080";
009 
010Servo myservo;  // создаем экземпляр класса «Servo»,
011Servo myservo1;  // чтобы с его помощью управлять сервоприводом;
012                // большинство плат позволяют
013                // создать 12 объектов класса «Servo»
014 
015// GPIO-контакт, к которому подключен сервопривод:
016static const int servoPin = 13;
017static const int servo1Pin = 14;
018 
019// создаем веб-сервер на порте «80»:
020WiFiServer server(80);
021 
022// переменная для хранения HTTP-запроса:
023String header;
024String header1;
025// несколько переменных для расшифровки значения в HTTP-запросе GET:
026String valueString = String(5);
027String valueString1 = String(5);
028int pos1 = 0;
029int pos2 = 0;
030int pos11 = 0;
031int pos22 = 0;
032 
033void setup() {
034  Serial.begin(115200);
035 
036  myservo.attach(servoPin);  // привязываем сервопривод,
037  myservo.attach(servo1Pin); // подключенный к контакту «servoPin»,
038                             // к объекту «myservo»
039 
040  // подключаемся к WiFi при помощи заданных выше SSID и пароля:
041  Serial.print("Connecting to ");  //  "Подключаемся к "
042  Serial.println(ssid);
043  WiFi.begin(ssid, password);
044  while (WiFi.status() != WL_CONNECTED) {
045    delay(500);
046    Serial.print(".");
047  }
048  // печатаем локальный IP-адрес и запускаем веб-сервер:
049  Serial.println("");
050  Serial.println("WiFi connected.");  //  "WiFi подключен."
051  Serial.println("IP address: ");     //  "IP-адрес: "
052  Serial.println(WiFi.localIP());
053  server.begin();
054}
055 
056void loop(){
057  // начинаем прослушивать входящих клиентов:
058  WiFiClient client = server.available();
059 
060  if (client) {                     // если подключился новый клиент,    
061    Serial.println("New Client.");  // печатаем сообщение
062                                    // «Новый клиент.»
063                                    // в мониторе порта;
064    String currentLine = "";        // создаем строку для хранения
065                                    // входящих данных от клиента;
066    while (client.connected()) {    // цикл while() будет работать
067                                    // все то время, пока клиент
068                                    // будет подключен к серверу;
069      if (client.available()) {     // если у клиента есть данные,
070                                    // которые можно прочесть,
071        char c = client.read();     // считываем байт, а затем   
072        Serial.write(c);            // печатаем его в мониторе порта
073        header += c;
074        if (c == '\n') {            // если этим байтом является
075                                    // символ новой строки
076          // если получили два символа новой строки подряд,
077          // то это значит, что текущая строчка пуста;
078          // это конец HTTP-запроса клиента,
079          // а значит – пора отправлять ответ:
080          if (currentLine.length() == 0) {
081            // HTTP-заголовки всегда начинаются
082            // с кода ответа (например, «HTTP/1.1 200 OK»)
083            // и информации о типе контента
084            // (чтобы клиент понимал, что получает);
085            // в конце пишем пустую строчку:
086            client.println("HTTP/1.1 200 OK");
087            client.println("Content-type:text/html");
088            client.println("Connection: close");
089                       //  "Соединение: отключено"
090            client.println();
091 
092            // показываем веб-страницу:
093            client.println("<!DOCTYPE html><html>");
094            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
095            client.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
096            client.println("<link rel=\"icon\" href=\"data:,\">");
097            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");
098            client.println(".slider { width: 300px; }</style>");
099            client.println("<script src=\"<a href="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js%5C" rel="nofollow">https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\</a>"></script>");
100                      
101            // веб-страница:
102            client.println("</head><body><h1>ESP8266 Управление сервомотором антенны</h1>");
103                                        //  "Управление сервомотором
104                                        //   с помощью платы ESP32"
105            client.println("<p>Позиция верх-вниз: <span id=\"servoPos\"></span></p>");    
106            client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");
107            client.println("<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>");
108            client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider1\" id=\"servoSlider1\" onchange=\"servo1(this.value1)\" value1=\""+valueString1+"\"/>");
109             
110            client.println("<script>var slider = document.getElementById(\"servoSlider\");");
111            client.println("var slider1 = document.getElementById(\"servoSlider1\");");
112            client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
113            client.println("var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value1;");
114            client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
115            client.println("slider1.oninput = function() { slider1.value1 = this.value1; servoP1.innerHTML = this.value1; }");
116            client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");
117            client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}");
118            client.println("$.ajaxSetup({timeout:1000}); function servo1(pos1) { ");
119            client.println("$.get(\"/?value=\" + pos1 + \"&\"); {Connection: close};}</script>");
120            
121            client.println("</body></html>");    
122             
123            //GET /?value=180& HTTP/1.1
124            if(header.indexOf("GET /?value=")>=0) {
125              pos1 = header.indexOf('=');
126              pos2 = header.indexOf('&');
127              pos11 = header1.indexOf('=');
128              pos22 = header1.indexOf('&');
129              valueString = header.substring(pos1+1, pos2);
130              valueString1 = header1.substring(pos11+1, pos22);
131              // вращаем ось сервомотора:
132              myservo.write(valueString.toInt());
133              Serial.println(valueString);
134              myservo1.write(valueString1.toInt());
135              Serial.println(valueString1);
136            }        
137            // конец HTTP-ответа задается
138            // с помощью дополнительной пустой строки:
139            client.println();
140            // выходим из цикла while():
141            break;
142          } else { // если получили символ новой строки,
143                   // очищаем текущую строку «currentLine»:
144            currentLine = "";
145          }
146        } else if (c != '\r') {  // если получили любые данные,
147                                 // кроме символа возврата каретки,
148          currentLine += c;      // добавляем эти данные
149                                 // в конец строки «currentLine»
150        }
151      }
152    }
153    // очищаем переменную «header[]»:
154    header = "";
155    header1 = "";
156    // отключаем соединение:
157    client.stop();
158    Serial.println("Client disconnected.");
159               //  "Клиент отключился."
160    Serial.println("");
161  }
162}

 

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Через https://kwork.ru работаете ?

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

код списали что ли, ничего в нем не смыслите?

строка 36 и 37 - одна должна быть myservo.attach(), а вторая myservo1.attach() - а у вас обе строки для одного и того же серво

zDimaBY
Offline
Зарегистрирован: 10.06.2018

строка 36 и 37 это понимаю.. но не понимаю как брать запрос с 2-х ползунков один показывает значения undefined

Списал, смыслю но не все например с 124 до 130 не очень понимаю 

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

zDimaBY пишет:

строка 36 и 37 это понимаю..

так исправляйте, так работать заведомо не будет

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Исправил. https://ibb.co/jvW830v но думаю на это ничего не повлияло имею виду "Позиция лево-право: undefined"

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

а, увидел, у вас еще код сайта неверный, строчки 116-119 видимо изначально брали из примера, где был один запрос, и тупо скопировали дважды? - так работать не будет.

И еще в строке 124 и дальше всунули какой-то header1, не понимая, что это значит.

В итоге у вас в коде передается только один параметр слайдера, не важно какой...

В общем, переписать это несложно, но уже выходит за рамки "помощи в форуме". Обращайтесь к фриджетестеру выше

zDimaBY
Offline
Зарегистрирован: 10.06.2018

fridgetester - помог, спасибо большое. Все решено.

junior_developer
Offline
Зарегистрирован: 27.11.2017

А можно ли вместо запроса

1GET /?value=45& HTTP/1.1  // например, угол поворота сервопривода 45.
2использовать
3GET /?value1=45&value2=90& HTTP/1.1 // угол поворота первого сервопривода 45, второго 90

а так написать можно?

1client.println("$.ajaxSetup({timeout:1000}); function servo(pos_1, pos_2) { "); // принять два значения (позиция первого сервопривода и второго)
2client.println("$.get(\"/?value1=\" + pos_1 + \"&value2=\" + pos_2 + \"&\");{Connection: close};}");

Или лучше всё-таки сделать отдельные функции для каждого сервопривода? И проверять на соответствие
 

1if(header.indexOf("GET /?value1=")>=0) // первый сервопривод
2if(header.indexOf("GET /?value2=")>=0) // второй

Подскажите пожалуйста, кто разбирается!

zDimaBY
Offline
Зарегистрирован: 10.06.2018

В 1 функцию.

junior_developer
Offline
Зарегистрирован: 27.11.2017
Вот как это можно сделать на JavaScript с помощью всего одного массива!

в него "запихиваются" значения всех найденных позиций символа "=", а затем аналогичным образом, символа "&". Используется метод "push"

1positions.push(currentPos); // запихнуть текущую позицию в массив
2currentPos = header.indexOf('=', currentPos+1);
Ну вот, что интересно, почему-то если написать currentPos++ вместо currentPos+1 страница в браузере "зависает" и отладчик "отваливается"? 
Разве ++ не то же самое, что +1?
У кого есть свободная минута, можете посмотреть, если нетрудно? Никакого "железа" ведь не нужно. Просто вставить код и нажать F12 в браузере!
Ещё вариант по моему лучший, чем предыдущий:

 

 

smart_pic
Offline
Зарегистрирован: 17.04.2016

junior_developer пишет:

Ну вот, что интересно, почему-то если написать currentPos++ вместо currentPos+1 страница в браузере "зависает" и отладчик "отваливается"? 
Разве ++ не то же самое, что +1?

Не тоже самое. Операция ++ выполняется после того , как будет выполнено основное выражение, а +1 сначала будет прибавлено 1, а потом уже выполнено основное выражение.

Такова особенность выражения ++

 

 

 

 

 

 

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Не забываем про наличие операции ++currentPos :)

junior_developer
Offline
Зарегистрирован: 27.11.2017

Да с плюсами перед переменной работает! Однако странно, что в отладчике, НЕ видно как currentPos увеличивается на 1.
Как не пиши, хоть ++currentPos, хоть currentPos+1 все равно.
Что это? Глюк отладчика или так и должно быть?
А вот если написать  так, видно! 

1positions.push(currentPos);
2currentPos++;
3currentPos = header.indexOf('=', currentPos);
brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

У вас же не си. Зависания это может быть проблема отладчика, брaузера, да всего чего угодно. Может у вас где то брейк установлен и срабатывает. Зачем вы вообще отлаживаете этот простейший код ? Проверьте без отладчика и двигайтесь дальше.

Вот смотрите строка

currentLeftPos = header.indexOf('=', currentLeftPos++);

Происходит следующее в момент работы  header.indexOf значение currentLeftPos равно 12, по окончании работы оно увеличивается на единицу и становится 13, но поиск проводился с символа номер 12, а этот символ удовлетворяет условиям, поскольку вы присваиваете результат header.indexOf этой переменной, то она вновь становится 12

 

 

currentLeftPos = header.indexOf('=', currentLeftPos+1);

В момент работы  header.indexOf значение currentLeftPos равно 12, но в функцию header.indexOf передается значение 13, поскольку 12+1=13, поиск начинается с символа под номером 13 и успешно находится следующий, номер которого загружается в переменную currentLeftPos .
 
 
 
 

currentLeftPos = header.indexOf('=', ++currentLeftPos);

Значение currentLeftPos перед обращением в функцию поиска вычисляется и становится равно 13, поиск проводился с символа номер 13, следовательно поиск находит следующий символ.
 
Что удивляет ? Вам просто не понятен порядок работы операторов. И самое главное ВСЕ ЭТИ СТРОКИ ЗАГРУЖАЮТ В ПЕРЕМЕННУЮ РЕЗУЛЬТАТ header.indexOf и не имеет никакого значения что в момент загрузки находится в этой переменной.
 
01<!doctype html>
02<html dir="ltr" lang="ru">
03  <head>
04    <meta charset="utf-8">
05    <title>Новая вкладка</title>
06  </head>
07  <body>
08<script>
09let header = "GET /?value1=45&value2=90&value3=105& HTTP/1.1";
10 
11let positions =[]; // массив для позиций символов в строке
12 if(header.indexOf("GET /?value")>=0) { // если начало заголовка появилось...
13let currentLeftPos = header.indexOf('=');
14let currentRightPos = header.indexOf('&');
15while (currentLeftPos != -1 || currentRightPos != -1) {
16    alert(currentLeftPos+' '+currentRightPos);
17    positions.push(currentLeftPos); // запихнуть левую позицию
18    positions.push(currentRightPos); // запихнуть правую позицию
19    currentLeftPos = header.indexOf('=', currentLeftPos++);
20    currentRightPos = header.indexOf('&', currentRightPos++);
21 }  
22}   
23        let valueString1 = header.substring(positions[0]+1, positions[1]);
24        let valueString2 = header.substring(positions[2]+1, positions[3]);
25        let valueString3 = header.substring(positions[4]+1, positions[5]);
26        console.log(valueString1);
27        console.log(valueString2);
28        console.log(valueString3);
29        console.log(positions);
30</script>
31  </body>
32</html>

 

 
junior_developer
Offline
Зарегистрирован: 27.11.2017

Большое спасибо Вам за детальное объяснение!

zDimaBY
Offline
Зарегистрирован: 10.06.2018
001#include <Servo.h>
002#include <ESP8266WiFi.h>
003#include <WiFiClient.h>
004#include <WiFiUdp.h>
005#include <ESP8266WebServer.h>
006#include <ESP8266mDNS.h>
007#include <ArduinoOTA.h> // Библиотека для OTA-прошивки
008const char *ssid = "Aleksander"; //Имя сети вайфай
009const char *password = "11406080"; // пароль вайфай
010Servo myservo;  // создаем экземпляр класса «Servo»,
011Servo myservo1; // чтобы с его помощью управлять сервоприводом;
012                // большинство плат позволяют
013                // создать 12 объектов класса «Servo»
014// GPIO-контакт, к которому подключен сервопривод:
015static const int servoPin = 5;
016static const int servo1Pin = 4;
017 
018// создаем веб-сервер на порте «80»:
019WiFiServer server(80);
020 
021// переменная для хранения HTTP-запроса:
022String header;
023// несколько переменных для расшифровки значения в HTTP-запросе GET:
024String valueString = String(170);
025String valueString1 = String(180);
026int pos1 = 0;
027int pos2 = 0;
028 
029void setup() {
030  Serial.begin(115200);
031 
032  myservo.attach(servoPin, 544, 1520);;  // привязываем сервопривод,
033  myservo1.attach(servo1Pin); // подключенный к контакту «servoPin»,
034                             // к объекту «myservo»
035  // подключаемся к WiFi при помощи заданных выше SSID и пароля:
036  Serial.print("Connecting to ");  //  "Подключаемся к "
037  Serial.println(ssid);
038  WiFi.begin(ssid, password);
039  while (WiFi.status() != WL_CONNECTED) {
040    delay(500);
041    Serial.print(".");
042  }
043  ArduinoOTA.setHostname("ESP8266_Серво-привод_антенны"); // Задаем имя сетевого порта
044  //ArduinoOTA.setPassword((const char *)"0000"); // Задаем пароль доступа для удаленной прошивки
045  ArduinoOTA.begin(); // Инициализируем OTA
046  // печатаем локальный IP-адрес и запускаем веб-сервер:
047  Serial.println("");
048  Serial.println("WiFi connected.");  //  "WiFi подключен."
049  Serial.println("IP address: ");     //  "IP-адрес: "
050  Serial.println(WiFi.localIP());
051  server.begin();
052}
053 
054void loop(){
055  ArduinoOTA.handle(); // Всегда готовы к прошивке
056  // начинаем прослушивать входящих клиентов:
057  WiFiClient client = server.available();
058 
059  if (client) {                     // если подключился новый клиент,    
060    Serial.println("New Client.");  // печатаем сообщение
061                                    // «Новый клиент.»
062                                    // в мониторе порта;
063    String currentLine = "";        // создаем строку для хранения
064                                    // входящих данных от клиента;
065    while (client.connected()) {    // цикл while() будет работать
066                                    // все то время, пока клиент
067                                    // будет подключен к серверу;
068      if (client.available()) {     // если у клиента есть данные,
069                                    // которые можно прочесть,
070        char c = client.read();     // считываем байт, а затем   
071        Serial.write(c);            // печатаем его в мониторе порта
072        header += c;
073        if (c == '\n') {            // если этим байтом является
074                                    // символ новой строки
075          // если получили два символа новой строки подряд,
076          // то это значит, что текущая строчка пуста;
077          // это конец HTTP-запроса клиента,
078          // а значит – пора отправлять ответ:
079          if (currentLine.length() == 0) {
080            // HTTP-заголовки всегда начинаются
081            // с кода ответа (например, «HTTP/1.1 200 OK»)
082            // и информации о типе контента
083            // (чтобы клиент понимал, что получает);
084            // в конце пишем пустую строчку:
085            client.println("HTTP/1.1 200 OK");
086            client.println("Content-type:text/html");
087            client.println("Connection: close");
088                       //  "Соединение: отключено"
089            client.println();
090 
091            // показываем веб-страницу:
092            client.println("<!DOCTYPE html><html>");
093            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
094            client.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
095            client.println("<link rel=\"icon\" href=\"data:,\">");
096            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial; margin-left:auto; margin-right:auto;}");
097            client.println(".slider { width: 300px; }</style>");
098            client.println("<script src=\"<a href="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js%5C" rel="nofollow">https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\</a>"></script>");
099                      
100            // веб-страница:
101            client.println("</head><body><h1>ESP8266 Управление сервомотором антенны</h1>");
102                                        //  "Управление сервомотором
103                                        //   с помощью платы ESP32"
104            client.println("<p>Позиция верх-вниз: <span id=\"servoPos\"></span></p>");    
105            client.println("<input type=\"range\" min=\"70\" max=\"180\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");
106            client.println("<p>Позиция лево-право: <span id=\"servoPos1\"></span></p>");
107            client.println("<input type=\"range\" min=\"0\" max=\"180\" class=\"slider\" id=\"servoSlider1\" onchange=\"servo1(this.value)\" value=\""+valueString1+"\"/>");
108             
109            client.println("<script>var slider = document.getElementById(\"servoSlider\");");
110            client.println("var slider1 = document.getElementById(\"servoSlider1\");");
111            client.println("var servoP = document.getElementById(\"servoPos\"); servoP.innerHTML = slider.value;");
112            client.println("var servoP1 = document.getElementById(\"servoPos1\"); servoP1.innerHTML = slider1.value;");
113            client.println("slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }");
114            client.println("slider1.oninput = function() { slider1.value = this.value; servoP1.innerHTML = this.value; }");
115            client.println("$.ajaxSetup({timeout:1000}); function servo(pos) { ");           
116            client.println("$.get(\"/?value=\" + pos + \"&\"); {Connection: close};}");
117            client.println("function servo1(pos) { ");           
118            client.println("$.get(\"/?value1=\" + pos + \"&\"); {Connection: close};}</script>");
119             
120            client.println("</body></html>");    
121             
122            //GET /?value=180& HTTP/1.1
123            if(header.indexOf("GET /?value=")>=0)
124            {
125              pos1 = header.indexOf('=');
126              pos2 = header.indexOf('&');
127              valueString = header.substring(pos1+1, pos2);
128               
129              //Rotate the servo
130              myservo.write(valueString.toInt());
131              Serial.print("Got servro val: ");
132              Serial.println(valueString);
133            }
134            else if(header.indexOf("GET /?value1=")>=0)
135            {
136              pos1 = header.indexOf('=');
137              pos2 = header.indexOf('&');
138              valueString1 = header.substring(pos1+1, pos2);
139               
140              //Rotate the servo
141              myservo1.write(valueString1.toInt());
142              Serial.print("Got servro1 val: ");
143              Serial.println(valueString1);
144            }
145             
146            // конец HTTP-ответа задается
147            // с помощью дополнительной пустой строки:
148            client.println();
149            // выходим из цикла while():
150            break;
151          } else { // если получили символ новой строки,
152                   // очищаем текущую строку «currentLine»:
153            currentLine = "";
154          }
155        } else if (c != '\r') {  // если получили любые данные,
156                                 // кроме символа возврата каретки,
157          currentLine += c;      // добавляем эти данные
158                                 // в конец строки «currentLine»
159        }
160      }
161    }
162    // очищаем переменную «header[]»:
163    header = "";   
164    // отключаем соединение:
165    client.stop();
166    Serial.println("Client disconnected.");
167               //  "Клиент отключился."
168    Serial.println("");
169  }
170}

Готовый код. Кому нужно будет.

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

zDimaBY пишет:

Готовый код. Кому нужно будет.

не взлетит, сайт ссылки ломает...к примеру 98 строка

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Не ломает, открой код в отдельном окошке, там строка без переносов.

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

brokly пишет:

Не ломает, открой код в отдельном окошке, там строка без переносов.

у меня сломано (FIREFOX) поправил как надо:

          client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");

junior_developer
Offline
Зарегистрирован: 27.11.2017

Насколько я понял, это подгружается библиотека jQuery с какого-то удаленного сервера, и это значит, что без доступа к нему скетч нормально работать не будет! Интересно, как добавить её прямо в память модуля и использовать локально?
Если бы не куча дополнительных символов, то наверно просто вставить содержимое между тегами <script> </script> в которых стоит ссылка на источник.

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

На SPIFFS положить, если влезет.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

84 килобайта, влезет. Только со SPIFFS грузится будет долго, нужно с кешированием шаманить. Только воз из этого скрипта могут быть обращения к другим ресурсам, это точно нужно проверять. 

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

Браузер закэширует. Наврядли стоит ESP-шкой CDN заменять.

junior_developer
Offline
Зарегистрирован: 27.11.2017
C помощью Ctrl+F попробовал найти в коде последовательность "http". Есть только 2 соответствия, и это не ссылки, а "XMLHttpRequest". 
1{try{return new e.XMLHttpRequest}   // первое
2(i["X-Requested-With"]="XMLHttpRequest") // второе

Ни к каким внешним ресурсам, насколько я понял, библиотека не обращается.
Значит файл с ней можно загрузить в файловую систему и просто указать на него ссылку?
И эта строка
client.println("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>");

станет выглядеть так:
client.println("<script src=\"/jquery.min.js\"></script>");
Верно?
 
Конечно в начале файла нужно вставить
#include <FS.h> // библиотека для работы с файловой системой
в setup  инициализировать её
SPIFFS.begin();
а дальше в функцию handleFileRead добавить:
else if(path.endsWith("/jquery.min.js")) path += "jquery.min.js";
Или я ошибаюсь?
brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Нет конечно. Скорее всего нужно так:

if(path.endsWith("/jquery.min.js")) path = "/jquery.min.js";

Только вот , по моему, стандартный SPIFFS не поддерживает две точки в имени. Так что имя файлы нужно привести к нормальному виду. Более того конструкция if(path.endsWith("/")) path += "index.html" не однозначна, например на запрос типа /blablabla/ она будет пытаться отправить файл /blablabla/index.html, которого , конечно, на диске не будет.

rst
Offline
Зарегистрирован: 25.06.2018

junior_developer пишет:
C помощью Ctrl+F попробовал найти в коде последовательность "http".
А с чего решили что в коде может храниться только в таком виде?

Хранить в коде можно как угодно - как удобнее программе. Например в одном моём проекте, где нужно хранить много ссылок на разные HTTP-ресурсы, они хранятся в виде URL-ов без префикса протокола (http://). Протокол хранится отдельно - двоичным числом. Да и сами URL-ы хранятся в сжатом виде и тупым текстовым поиском их не найдёшь.

junior_developer
Offline
Зарегистрирован: 27.11.2017
Наверно проще всего скопировать всё содержимое скрипта в текстовый файл, например jquery_min.txt, загрузить его в файловую систему, и 
1client.println("<script>"); // начало скрипта
2jquery_min = SPIFFS.open("/jquery_min.txt", "r"); // открыть файл с текстом скрипта и присвоить его содержимое jquery_min
3if (!jquery_min) { Serial.println("file open failed");} //  "открыть файл не удалось"
4}
5while (jquery_min.available()) {
6  client.print(char(jquery_min.read())); // вывод всех символов
7}
8jquery_min.close();
9client.println("</script>"); //конец скрипта

Код целиком

brokly пишет:

84 килобайта, влезет. Только со SPIFFS грузится будет долго, нужно с кешированием шаманить.

Да, Вы абсолютно правы! Эта простая страничка грузится почти 9 секунд! И даже реакция на перемещение ползунков примерно 1 секунда! 

rkit
Offline
Зарегистрирован: 23.11.2016

spiffs работает приемлемо. Веб-сервер медленный.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

rkit пишет:

spiffs работает приемлемо. Веб-сервер медленный.

Переход на внешнюю SDшку с фатом дает прирост скорости в два раза.