Проброс портов не работает-но причина в библиотеке кода (видимо)

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

ua6em пишет:

если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись

Очевидно, что проблема не в этом. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

brokly пишет:

ua6em пишет:

если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись

Очевидно, что проблема не в этом. 

Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?

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

BOOM пишет:

Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?

Меня это утверждение пугает :)

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

BOOM пишет:

brokly пишет:

ua6em пишет:

если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись

Очевидно, что проблема не в этом. 

Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?

я пробросил и TCP и UDP, реальной железки esp32 нет, роутер тплинк но чуть покруче, ось OWRT, по умолчанию вэбморда предлагала пробросить 85 на 85

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

brokly пишет:

BOOM пишет:

Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?

Меня это утверждение пугает :)

Почему? Вы что-то знаете и не говорите?)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

ua6em пишет:

BOOM пишет:

brokly пишет:

ua6em пишет:

если бы у меня был esp32 проверил бы на реальном, а так, чем мог, пробросил с 85 на 80 nmap сказал, что с UDP всё зашибись

Очевидно, что проблема не в этом. 

Хм, а может и в этом. ТС, скорее всего, tcp «пробрасывал», а как же udp? Может железки по нему общаются?

я пробросил и TCP и UDP, реальной железки esp32 нет, роутер тплинк но чуть покруче, ось OWRT, по умолчанию вэбморда предлагала пробросить 85 на 85

Оно и понятно, по умолчанию так и должно быть. Но wrt очень крутая прошивка, что там в родной происходит - не известно. 

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

TP-Link TL-WR741N, как и любой другой, спокойно даёт пробросить порт 80. Вебсокет использует tcp. Проброс портов в родной прошивке tp-link работает точно так же, как и в open/dd/ху*-wrt. Дело, скорее всего, не в этом.

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

negavoid2 пишет:

TP-Link TL-WR741N, как и любой другой, спокойно даёт пробросить порт 80. Вебсокет использует tcp. Проброс портов в родной прошивке tp-link работает точно так же, как и в open/dd/ху*-wrt. Дело, скорее всего, не в этом.

Конечно вебсокет  работает по tcp. udp никоим боком. Просто челу "апоговорить" похоже. В любом случае не нужно его на 80-й порт вешать. То что TP-Link должен иметь возможность настраиватся на проброс 80 как бы ожидаемо, иначе дома и апачу не развернеш с домашним сайтом.

//Дело, скорее всего, не в этом.

да.

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

brokly пишет:

Ты читать не умеешь ? Где я написал, что не доволен !? Не нужно читать между строк.

Здесь!

brokly пишет:

Я не знаю как это библиотека построена для одно ядерной 8266, но для есп32 это не самое удачное "изделие".

Вообще все негативные отзывы от этой либе в теме - только от тебя. И про проблему больших данных и ссылки на список ошибок. Меня больше возмутило обобщение проблем аж до асинхронного веба. Ну кривая либа (возможно, ты ж о ней такое пишеш), ну некоторые не поняли как ее дергать. Тоже мне новости. Обобщать с ссылкой на "что у огромной массы людей асинхронный веб вызывает стойкую аллергию" не стоит, твои пацаны на районе не тянут просто ;)

brokly пишет:

 

Кстати ты смысл своего первого предложения на русский не переведешь ? Что ты хотел сказать ? Что ТС не использует , как ты выразился "кривую либу тупого автора" ? Или что ? Так , на всякий случай, я говорил именно о библиотеке

 

И я о библиотеке и ее авторе, о чем жеж еще, все ты понял.

brokly пишет:

 

И еще раз повторю, проблема этой библиотеки на ESP32 в том, что в колбэках нельзо долго оставаться. С ними нужно работать практически как с прерываниями, потому как они из другого потока. 

У тя каша в башке, потому то прерывания, то как бы прерывания то другой поток. Ты похоже имел в виду что луп и калбеки в разных потоках и требуют синхронизации... Та неважно, забей, то слишком сложно. 

Кстати можно или нельзя долго оставаться - это совсем не к свойствам калбека или потока, это к качеству либы. И судя по твоим словам, подчеркиваю, именно по твоим словам!!!, не отнекивайся и стрелки не переводи, либа таки действительно кривая.

Потому как таких страстей-мордастей протокол вебсокета вобще не требует. Как и ТСР в общем. Вебсокет  тупо на нем построен и если есть проблема приема больших данных - см. стек ТСР. За некоторым исключением. Как чел, реализовавший себе этот протокол, отмечу, что вопросу длинны данных во фрейме (это терменология спеки на вебсокет) в протоколе особое внимание. Длина поляв котором эта самая длина данных передается переменная и применима для данных до 2^64  байт. А при коротких данных, до 125, свой формат, компактный. Уже из этого следует что проблемы принципиальной нет. А что там автор наваял, поддержал ли все кейсы или нет - на его совести. Я писал так.

  long int Len=b[1]&0x7f;
  long int Ofs;

  switch (Len)
  {
   case 126:
    Len=(uint16_t)b[2];
    Ofs=4;
    break;

   case 127:
    Len=(uint64_t)b[2];
    Ofs=10;
    break;

   default:
    Ofs=2;
  }

Но насколько верно - я даже не знаю т.к. больших данных мне не попадалось. Ну вот так... Не тестил.

Далее. Эта самая длина, и прочая пурга из хедера - в начале фрейма, т.е. в одном tcp пакете с первыми байтами данных. Очевидно при длине данных до 125 у нас всегда все принято на момент парсинга хедера. И попытка получить данные сразу после парсинга будет успешная. А для данных почти 2^64 или около того - придется долго ждать пока приедут, стек ТСР их сложит и т.д.  Как это согласовать с быстрой обработкой калбека - ХЗ, думал ли автор о проблеме - ХЗ, сталкивался ли ты с этим - ХЗ. Но похоже что либа не для этого случая..

Далее, обратил внимание, ТС хочет машинкой рулить. А это как бы значить, что клиент у вебсокета один. Тогда спрашивается, нахрена этот цирк с потоками который приводит к проблемам? И ситуация когда клиент один (реже 2-3 но не много) очень типичная для МК. А автор либы взял типовую архитектуру сервера, и каждому клиенту поток забецал. При скудных ресурсах создал доп проблемы. Это тоже не в плюс либе...

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

Продолжу тут, форум тупит. Так вот, накосячить в либе есть где. И с большими данными тоже. И ее архитектура, многопоточность, калбеки вызывает сомнения.  Но это не повод писать о проблемах асинхронного веба и протокола вебсокет вобще. Свет клином на этой либе не сошолся. И тем более вопросы по либе к теме форума не относятся. У ТС в локалке работает. Причем тут либа. Разнесет порты, настроит проброс и заработает. Не смущайте чела почем зря.

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

Logik пишет:

Продолжу тут, форум тупит. Так вот, накосячить в либе есть где. И с большими данными тоже. И ее архитектура, многопоточность, калбеки вызывает сомнения.  Но это не повод писать о проблемах асинхронного веба и протокола вебсокет вобще. Свет клином на этой либе не сошолся. И тем более вопросы по либе к теме форума не относятся. У ТС в локалке работает. Причем тут либа. Разнесет порты, настроит проброс и заработает. Не смущайте чела почем зря.

Не буду тут растекаться , как это делаешь ты. Придирки к словам , которые ты таскаешь из контекста - хрень ни о чем.

По теме. Дело в том, что скорость потока данных в локалке и из-вне разная. А это приводит к тому, что одни и те же обработки работают разное время. Я не буду тут жевать по буквам почему и как. НО любая асинхронная библиотека первым делом обращает внимание на то, что обработки выполняются в другом потоке нежели основной цикл. Как это достигнуто, с использованием прерываний, потоками, другими способами - значения не имеет. Но они должны быть короткие и правильно оперировать данными.

ЗЫ Ты когда пишешь так многостранично, ты думай зачем ты это делаешь. Я твое "полотенце" не читал. И не буду. Много есть на то причин. Основная - не интересно. Ты все равно ничего умного в таком количестве сказать не мог :)

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

brokly пишет:

ЗЫ Ты когда пишешь так многостранично, ты думай зачем ты это делаешь. Я твое "полотенце" не читал. И не буду. 

И это тот кто обвинял меня в том что я не читаю сообщений! Ты вообще помнишь что пишеш тремя постами ранее?))) То то ты все не в попад отвечаешь, да порешь чушь.  То прерывания, то потоки. Оно так в башке хаос и останется, если не читать. Вот и здесь, в трех предложениях столько ахинеи нанес..

brokly пишет:

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

Библиотека у него обращает внимание)) Та отдельные потоки для клиента как раз создают чтоб они работали независимо и тормоза одного не влияли на остальных. Это оправдано для ПК и как часто бывает не оправдано на МК. В том их отличие от обработчика прерывания в плане длительности исполнения. Ну ты ж не читаешь, ходи дальше дремучим. Считай твой культпросвет закончен, дальше я только время на тупицу потеряю. Если за шесть лет на форуме не понимаешь разницу между потоком и прерыванием - безнадежен.

 

 

 

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

Я пишу по теме. Ты фонтанируешь потоком мысли и придирками. 

Для меня русский не родной :) Так что утрись :)

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Я вас обеих тереть буду. :) 

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

DetSimen пишет:

Я вас обеих тереть буду. :) 

Три ! Или даже ЧЕТЫРЕ !

Я буду кричать что притесняют нацменьшинства :) И мысли у меня не отбирай. Жить с "одной мыслью" скучно :(

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

DetSimen пишет:

Я вас обеих тереть буду. :) 

Всё, что до этого было, я, естественно, не трону, пусь вам стыдно будет. Я просто к тому, что давайте цивилизованно вести дискуссию, без всяких "крысоухих змей" и прочего.  :) 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Меня в этой теме потрите. Писал же что не сильно разбираюсь, следовательно предполагал. А на меня чан г#вна от «не с кем поговорить». (

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

DetSimen пишет:

DetSimen пишет:

Я вас обеих тереть буду. :) 

Всё, что до этого было, я, естественно, не трону, пусь вам стыдно будет. Я просто к тому, что давайте цивилизованно вести дискуссию, без всяких "крысоухих змей" и прочего.  :) 

А я и вел цивилизованно, пока не набежали "двое из ларца" и не стали умные советы бредом называть

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Ой сколько нопесале.... :-)))

Не имел возможности заходить-тупо был загружен работой. Зашел-а тут такоооеее... :-)

Ок, давайте так. Выложу код проекта сюда (мне не жалко). Неплохой пульт управления получился для машинки-со смартфона. Может кто скажет чего умного...

Вот как мне его заставить видеться и работать извне? Видится-но даже кнопки не жмакаются.



#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>


// вставляем ниже SSID и пароль для своей WiFi-сети:
const char* ssid     = "..........";  
const char* password = "..........";


// переменная для хранения HTTP-запроса:
String header;

// мотор 1:
int motor1Pin1 = 21; 
int motor1Pin2 = 19; 
//int enable1Pin = 14; 

// мотор 2:
int motor2Pin1 = 23; 
int motor2Pin2 = 22; 
//int enable2Pin = 32;

// переменные для свойств широтно-импульсной модуляции (ШИМ) 1-двигателя:
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 0;

// переменные для свойств широтно-импульсной модуляции (ШИМ) 2-двигателя:
const int freq2 = 30000;
const int pwmChannel2 = 1;
const int resolution2 = 8;
int dutyCycle2 = 0;


// переменные для расшифровки HTTP-запроса GET:
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;





 //------------------- Работа с оптическими датчиками --------------------------

  String state; //сюда будет писаться состояние, т.е. куда едет машинка в данный момент
 
  volatile uint32_t lasttime1 = 0;
  volatile uint32_t lasttime2 = 0;

  
  //Куда подключены оптические датчики энкодера:
  int SensorPin1 = 13;
  int SensorPin2 = 14;

  volatile uint32_t gap1 = 0;
  volatile uint32_t gap2 = 0;

  //-----------------------------------------------------------------------------
  


//----------------PID регулятор-------------------------

//Величины PID регулятора

int setpoint = 0;   // заданная величина, которую должен поддерживать регулятор
int input = 0;      // сигнал с датчика (например температура, которую мы регулируем)
int output = 0;     // выход с регулятора на управляющее устройство (например величина ШИМ или угол поворота серво)
int pidMin = 0;     // минимальный выход с регулятора/Изначально тут стояло 0
int pidMax = 0;   // максимальный выход с регулятора/Изначально тут стояло 255 - это число для 8-битного ШИМ


// коэффициенты
float Kp = 1.0; //тут стояло 1.0
float Ki = 1.0; //тут стояло 1.0
float Kd = 1.0; //тут стояло 1.0
float _dt_s = 0.1; // время итерации в секундах

// вспомогательные переменные
int prevInput = 0;
float integral = 0.0;

//------------------------------------------------------


//----------------PID регулятор (вариант2)-------------------------

//  GyverPID regulator(0, 0, 0, 10);


  
//-----------------------------------------------------------------





//-------------------БЛОК РАБОТЫ С WEBSOCKET И ОТОБРАЖЕНИЯ ВЕБ-СТРАНИЦЫ----------------------------------------

bool ledState = 0;
const int ledPin = 2;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
  html {
    font-family: Arial, Helvetica, sans-serif;
    text-align: center;
  }
  h1 {
    font-size: 1.8rem;
    color: white;
  }
  h2{
    font-size: 1.5rem;
    font-weight: bold;
    color: #143642;
  }
  .topnav {
    overflow: hidden;
    background-color: #143642;
  }
  body {
    margin: 0;
  }
  .content {
    padding:  5 px; //30px;
    display: flex;
    justify-content: center;
//    margin: 0 auto;
    text-align: center;
//    margin-left: auto;
//    margin-right: auto;
  }

    .content2 {
    padding:  5 px; //30px;
    display: flex;
    justify-content: space-between;
//   // padding:  px; //30px;
//     max-width: 400px;
//    margin: 0 auto;
  }

    .content3 {
       padding: 40 px; //30px;
       display: flex;
       justify-content: center;
  }



  .button1 {
    
    padding: 15px 50px;
    font-size: 24px;
    text-align: center;
    outline: none;
    color: #fff;
    background-color: #0f8b8d;
    border: none;
    border-radius: 5px;
    width: 670px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
   }

  .button2 {
    padding: 15px 5px;
    font-size: 24px;
    text-align: center;
    outline: none;
    color: #fff;
    background-color: #0f8b8d;
    border: none;
    border-radius: 5px;
    width: 140px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
   }

   /*.button:hover {background-color: #0f8b8d}*/
   .button:active {
     background-color: #0f8b8d;
     box-shadow: 2 2px #CDCDCD;
     transform: translateY(2px);
   }
     
//   .state {
//     font-size: 1.5rem;
//     color:#8c8c8c;
//     font-weight: bold;
//   }
  </style>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>


<body>

   
   <div class="content">
      <p><button id="button" class="button1">forward</button></p>
   </div>
  
   <div class="content2">
      <p><button id="button2" class="button2"><<< left</button></p>
      <p><button id="button2_1" class="button2">< slow</button></p>
      
      <p><button id="button3_1" class="button2">slow ></button></p>
      <p><button id="button3" class="button2">right >>></button></p>
      </div>
      
   <div class="content3">    
      <p><button id="button4" class="button1">reverse</button></p>
  </div>
<script>
  var gateway = `ws://${window.location.hostname}/ws`;
  var websocket;
  window.addEventListener('load', onLoad);
  function initWebSocket() {
    console.log('Trying to open a WebSocket connection...');
    websocket = new WebSocket(gateway);
    websocket.onopen    = onOpen;
    websocket.onclose   = onClose;
    websocket.onmessage = onMessage; // <-- add this line
  }
  function onOpen(event) {
    console.log('Connection opened');
  }
  function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
  }
  function onMessage(event) {
    var state;
    if (event.data == "1"){
      state = "ON";
    }
    else{
      state = "OFF";
    }
    document.getElementById('state').innerHTML = state;
  }
  function onLoad(event) {
    initWebSocket();
    initButton();
    initButton2();
    initButton2_1();
    initButton3();
    initButton3_1();
    initButton4();
  }
  function initButton() {
    //document.getElementById('button').addEventListener('click', toggle);
      document.getElementById('button').addEventListener('touchstart', forward, false);
      document.getElementById('button').addEventListener('touchend', stopper, false);
  }
  function forward(){
    websocket.send('forward');
  }


   function initButton2() {
      document.getElementById('button2').addEventListener('touchstart', left, false);
      document.getElementById('button2').addEventListener('touchend', stopper, false);
  }
  function left(){
    websocket.send('left');
  }

  function initButton2_1() {
      document.getElementById('button2_1').addEventListener('touchstart', left_slow, false);
      document.getElementById('button2_1').addEventListener('touchend', stopper, false);
  }
  function left_slow(){
    websocket.send('left_slow');
  }


  function initButton3() {
      document.getElementById('button3').addEventListener('touchstart', right, false);
      document.getElementById('button3').addEventListener('touchend', stopper, false);
  }
  function right(){
    websocket.send('right');
  }  

  function initButton3_1() {
      document.getElementById('button3_1').addEventListener('touchstart', right_slow, false);
      document.getElementById('button3_1').addEventListener('touchend', stopper, false);
  }
  function right_slow(){
    websocket.send('right_slow');
  }  
   function initButton4() {
        document.getElementById('button4').addEventListener('touchstart', reverse, false);
        document.getElementById('button4').addEventListener('touchend', stopper, false);
    }
    function reverse(){
      websocket.send('reverse');
    }  

 function stopper(){
    websocket.send('stop');
  }
  
</script>
</body>



</html>
)rawliteral";

void notifyClients() {
  ws.textAll(String(ledState));
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) { // обрабатываем получаемые сообщения
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    if (strcmp((char*)data, "forward") == 0) {
      ledState = !ledState;


      Serial.println("Forward");  //  "Вперед"

      state = "Forward";

      ledcWrite(pwmChannel, 0); //0 - максимум оборотов
      ledcWrite(pwmChannel2, 0); //0 - максимум оборотов
             
      digitalWrite(motor1Pin1, LOW);
      digitalWrite(motor1Pin2, HIGH); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);
      //notifyClients();
    }
    else if (strcmp((char*)data, "left") == 0) {
      ledState = !ledState;


      Serial.println("Left");  //  "Влево"

      state = "Left";
               
      ledcWrite(pwmChannel, 255);
      ledcWrite(pwmChannel2, 0);                
      digitalWrite(motor1Pin1, HIGH); 
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "left_slow") == 0) {
      ledState = !ledState;


      Serial.println("LeftSlow");  //  "Влево медленно"

      state = "LeftSlow";
               
      ledcWrite(pwmChannel, 155);
      ledcWrite(pwmChannel2, 100);                
      digitalWrite(motor1Pin1, HIGH); 
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "right") == 0) {
      ledState = !ledState;

      Serial.println("Right");  //  "Вправо"

      state = "Right";
             
      ledcWrite(pwmChannel, 0);
      ledcWrite(pwmChannel2, 255);
      digitalWrite(motor1Pin1, LOW); 
      digitalWrite(motor1Pin2, HIGH); 
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "right_slow") == 0) {
      ledState = !ledState;

      Serial.println("RightSlow");  //  "Вправо медленно"

      state = "RightSlow";
             
      ledcWrite(pwmChannel, 100);
      ledcWrite(pwmChannel2, 155);
      digitalWrite(motor1Pin1, LOW); 
      digitalWrite(motor1Pin2, HIGH); 
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "reverse") == 0) {
      ledState = !ledState;

      Serial.println("Reverse");  //  "Назад"

      state = "Reverse";
              
      ledcWrite(pwmChannel, 255); //255 - максимум оборотов
      ledcWrite(pwmChannel2, 255); //255 - максимум оборотов
      digitalWrite(motor1Pin1, HIGH);
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);          
      //notifyClients();
    }
    else if (strcmp((char*)data, "stop") == 0) {
      ledState = !ledState;

      Serial.println("Stop");  //  "Стоп"

      state = "Stop";
              
      ledcWrite(pwmChannel, 0);
      ledcWrite(pwmChannel2, 0);
      digitalWrite(motor1Pin1, LOW); 
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, LOW);  
      //notifyClients();
    }
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
             void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if (ledState){
      return "ON";
    }
    else{
      return "OFF";
    }
  }
}

//-------------------------------------------------------------------------------------------------------








void setup() {
  Serial.begin(115200);

  // переключаем контакты моторов в режим «OUTPUT»:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);


  // подключаем контакты оптических датчиков к пину, в режим «INPUT»:
  pinMode (SensorPin1, INPUT);
  pinMode (SensorPin2, INPUT);

  
  //подключаем реакцию на прерывания - к пинам датчиков:
  
  attachInterrupt(SensorPin1, sensor_impulse, LOW);
  attachInterrupt(SensorPin2, sensor_impulse2, LOW);



  // задаем настройки ШИМ-канала каждого из 2 двигателей:
 
  ledcSetup(pwmChannel, freq, resolution); // первый двигатель
  ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель
  
  // подключаем ШИМ-канал, к контактам для управления скоростью вращения каждого из 2 моторов:

    ledcAttachPin(motor1Pin1, pwmChannel); // первый двигатель
    ledcAttachPin(motor2Pin1, pwmChannel2); // второй двигатель
 
  // подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»:
  ledcWrite(pwmChannel, dutyCycle);
  ledcWrite(pwmChannel2, dutyCycle2);



  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

// Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  initWebSocket();

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Start server
  server.begin();


  
}//setup

  
 


void loop(){

  ws.cleanupClients();
//  
    
}
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а порт более 1024 задать можешь?

mu_ssina
Offline
Зарегистрирован: 30.08.2013

ua6em пишет:

а порт более 1024 задать можешь?

Не подкола ради-пробовал разные...Но не то, что ты говоришь... Не работало. А что это даст?

mu_ssina
Offline
Зарегистрирован: 30.08.2013

задвоение сообщения запостилось.

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

mu_ssina пишет:

ua6em пишет:

а порт более 1024 задать можешь?

Не подкола ради-пробовал разные...Но не то, что ты говоришь... Не работало. А что это даст?

мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Ок, сейчас залью и протестю. Отпишусь.

UPD: протестил. Залил 1025 порт. Так же-видится отлично, но не работает.

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

интернет от какого сотового оператора?

mu_ssina
Offline
Зарегистрирован: 30.08.2013

ua6em пишет:

интернет от какого сотового оператора?

Билайн-Москва.

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

ua6em пишет:

мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема

Это ни о чем не говорит. Относитесь к портам и их пробросу проще. Это я вам как цисковод с дипломами говорю ;)

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

brokly пишет:

ua6em пишет:

мыслей нет, но выше 1024 это пользовательские порты, может в этом проблема

Это ни о чем не говорит. Относитесь к портам и их пробросу проще. Это я вам как цисковод с дипломами говорю ;)

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

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

Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)

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

brokly пишет:

Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)

он же говорит, что в локалке работает, проблем нет

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

ua6em пишет:

brokly пишет:

Зачем все так усложнять ? Не в этом дело. Почему мы всегда пытаемся искать ошибки у других. Нужно искать у себя. Ошибка в коде ESP, она же сваливает в ошибку, значит кривой код. Если бы было все нормально, то с какого фига эксепшены возникали бы ? Есп это вам не мега328, есп даже на ноль делить не даст :)

он же говорит, что в локалке работает, проблем нет

Еще раз . Внимательно. ЕСП сваливается с ошибкой. Кто сваливается роутер ? Провайдер ? Так почему мы пытаемся роутер крутить ? Ну смешно :)

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

mu_ssina пишет:

Ок, сейчас залью и протестю. Отпишусь.

UPD: протестил. Залил 1025 порт. Так же-видится отлично, но не работает.

А в строке 241 не забыл указать этот порт, типа var gateway = `ws://${window.location.hostname}/ws:1025`; 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Logik пишет:

mu_ssina пишет:

Ок, сейчас залью и протестю. Отпишусь.

UPD: протестил. Залил 1025 порт. Так же-видится отлично, но не работает.

А в строке 241 не забыл указать этот порт, типа var gateway = `ws://${window.location.hostname}/ws:1025`; 

Протестил-не хочет...Та же история-видится снаружи,но не работает. В локалке всё ок.

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

Включите уже лог. Запишите его для удачного подключения и для неудачного. Проще будет "гадать на кофейной гуще".

Включить системный лог для ESP 

arduino_debug.png

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

mu_ssina пишет:

Выложу код проекта сюда (мне не жалко). Неплохой пульт управления получился для машинки-со смартфона. Может кто скажет чего умного...

тут был КОТ

а что сказать, если ОНО даже не компилируется, хотел по быстрому проверить, получил ESP32 и время есть )))

Замаркировал, скомпилировал, страничка отображается, а где индикация?

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

Код не рабочий даже без проброса портов )))

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

mu_ssina пишет:

Feofan пишет:
Цитата:
роутер пробрасывает его на внутренний 80
на какой ip?

На зарезервированный. То бишь: я выяснил MAC адрес своей esp32 и связал ее MAC с ip адресом (в моем случае, внутренний адрес от роутера выдан такой: 192.168.0.106) в настройках роутера.

То есть: теперь при любом коннекте esp32 к роутеру- он ей выдает этот ip.

Ну и опять же: все видится снаружи, то бишь всё вроде работает. Но через задницу :-))))

 и не надо выяснять МАС, надо просто назначить статический IP на девайс, добавить:
 

// Задайте свой статический IP-адрес
IPAddress local_IP(192, 168, 1, 240);
// Укажите IP-адрес шлюза
IPAddress gateway(192, 168, 1, 1);

IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   // опционально
IPAddress secondaryDNS(8, 8, 4, 4); // опционально



void setup() {
  Serial.begin(115200);

    // переключаем контакты моторов в режим «OUTPUT»:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);


  // подключаем контакты оптических датчиков к пину, в режим «INPUT»:
  pinMode (SensorPin1, INPUT);
  pinMode (SensorPin2, INPUT);

  
  //подключаем реакцию на прерывания - к пинам датчиков:
  
//  attachInterrupt(SensorPin1, sensor_impulse, LOW);
//  attachInterrupt(SensorPin2, sensor_impulse2, LOW);



  // задаем настройки ШИМ-канала каждого из 2 двигателей:
 
  ledcSetup(pwmChannel, freq, resolution); // первый двигатель
  ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель
  
  // подключаем ШИМ-канал, к контактам для управления скоростью вращения каждого из 2 моторов:

    ledcAttachPin(motor1Pin1, pwmChannel); // первый двигатель
    ledcAttachPin(motor2Pin1, pwmChannel2); // второй двигатель
 
  // подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»:
  ledcWrite(pwmChannel, dutyCycle);
  ledcWrite(pwmChannel2, dutyCycle2);

 // Настраиваем статический IP-адрес сервера:
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");  //  "Не удалось задать статический IP-адрес"
  }
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

// Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  initWebSocket();

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Start server
  server.begin();
  
}// END SETUP

 

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

Залил скетч из примеров ESP32 для вэбсокета!
ДА! Через проброшенный порт не работает (OpenWrt, TP-LINK 842ND)
Пробрасываю порт 8080 на 80, а вот если пробрасывать 80 на 80 порт, то работает

На кроссоверных портах не устанавливается websocket соединение, так получается, осталось понять почему

Один и тот же код для проверки использую и для ESP8266 и для ESP32, только библиотеки разные...
 

// Подключаем необходимые библиотеки
// http://www.joyta.ru/12931-asinxronnyj-veb-server-esp8266-nodemcu-upravlenie-vyvodami-esp-biblioteka-espasyncwebserver/
#define ESP32

#ifdef ESP32
#include <WiFi.h>
uint16_t ports = 80;
#else
#include <ESPAsyncTCP.h>
#include <ESP8266WiFi.h>
uint16_t ports = 8000;
#endif

#include <ESPAsyncWebServer.h>

// Замените учетными данными своей сети
const char* ssid = "OpenWrt"; //"REPLACE_WITH_YOUR_SSID";
const char* password = "123456789"; //"REPLACE_WITH_YOUR_PASSWORD";
const char* PARAM_INPUT_1 = "output";
const char* PARAM_INPUT_2 = "state";

// Задайте свой статический IP-адрес
IPAddress local_IP(192, 168, 1, 240);
// Укажите IP-адрес шлюза
IPAddress gateway(192, 168, 1, 1);
// Задайте маску сети
IPAddress subnet(255, 255, 255, 0);
// Задайте DNS 
IPAddress primaryDNS(8, 8, 8, 8);   // опционально
IPAddress secondaryDNS(8, 8, 4, 4); // опционально


// Создаем объект AsyncWebServer на порту 80 (8000)
AsyncWebServer server(ports);
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
h2 {font-size: 3.0rem;}
p {font-size: 3.0rem;}
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
.switch {position: relative; display: inline-block; width: 120px; height: 68px}
.switch input {display: none}
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}
input:checked+.slider {background-color: #b30000}
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
</style>
</head>
<body>
<h2>ESP Web Server</h2>
%BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
var xhr = new XMLHttpRequest();
if(element.checked){ xhr.open("GET", "/update?output="+element.id+"&state=1", true); }
else { xhr.open("GET", "/update?output="+element.id+"&state=0", true); }
xhr.send();
}
</script>
</body>
</html>
)rawliteral";

// PLACEHOLDER выбранной кнопкой на вашей веб-странице
String processor(const String& var){
//Serial.println(var);
if(var == "BUTTONPLACEHOLDER"){
String buttons = "";
buttons += "<h4>Output - GPIO 5</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"5\" " + outputState(5) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"4\" " + outputState(4) + "><span class=\"slider\"></span></label>";
buttons += "<h4>Output - GPIO 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>";
return buttons;
}
return String();
}
String outputState(int output){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
}

void setup(){
// Последовательный порт для отладки
Serial.begin(115200);
pinMode(5, OUTPUT);
digitalWrite(5, LOW);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(2, OUTPUT);
digitalWrite(2, LOW);

 // Настраиваем статический IP-адрес сервера:
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");  //  "Не удалось задать статический IP-адрес"
}

// Соединяемся по Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}

// Распечатать локальный IP-адрес ESP
Serial.println(WiFi.localIP());

// Маршрут для корневой / веб-страницы
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});

// Отправить GET запрос в <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage1;
String inputMessage2;

// Получить запрос GET значения input1 от <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());
}
else {
inputMessage1 = "No message sent";
inputMessage2 = "No message sent";
}
Serial.print("GPIO: ");
Serial.print(inputMessage1);
Serial.print(" - Set to: ");
Serial.println(inputMessage2);
request->send(200, "text/plain", "OK");
});

// Запустить сервер
server.begin();
}

void loop() {
}

Проверил сделав проброс с 8080 на 80 на ESP32 и, работает...скетч правда websocket не использует

Беру еще один пример. там где WS отрабатывает в обе стороны и, через проброшенный порт не работает ни на ESP8266 ни на ESP32, мало того и сервер на порту отличном от 80 не работает на обоих девайсах...
ДА УЖ с этим вэбсокетом всё не так просто

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

А вот так?

#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
// https://github.com/me-no-dev/ESPAsyncTCP
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

const char* ssid = ".....";
const char* password = "....";

const uint16_t httpPort = 80;

AsyncWebServer server(httpPort);
AsyncWebSocket ws("/ws");

const char indexPageContent[] PROGMEM = R"rawliteral(
  <!DOCTYPE HTML>
  <html>
  <head>
    <title>ESP Web Server</title>
     <script>
        var host = 'ws://'+ window.location.hostname + (window.location.port ? ":" + window.location.port : '') + '/ws';
        var socket = new WebSocket(host);
        console.log('Test started');
        socket.onopen    = function(e) { console.log('Connection opened'); };
        socket.onclose   = function(e) { console.log('Connection closed'); };
        socket.onmessage = function(e) { document.getElementById('root').innerHTML = e.data; };

     </script>
  </head>
  <body>
     <h3>Websocket simple test</h3><div id="root"></div>
  </body>
  </html>
  )rawliteral";

void notFoundPage(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void indexPage(AsyncWebServerRequest *request) {
  request->send(200, "text/html", indexPageContent);
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      client->printf("Hello Client %u :)", client->id());
      client->ping();
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("WiFi Failed!\n");
    return;
  }

  Serial.print("\nIP Address: "); Serial.println(WiFi.localIP());

  ws.onEvent(onEvent);

  server.addHandler(&ws);
  server.on("/", HTTP_GET, indexPage);
  server.onNotFound(notFoundPage);
  server.begin();
}

void loop() {
  ws.textAll("Now: " + String(millis()));
  delay(1000);
  ws.cleanupClients();
}

 

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

Так работает )))
Попробую 8000 порт, но уже завтра

вот кстати, приходил к мысли, что вэбсокет отвечает на 80 порту...

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

На любом назначенном порту он отвечает.

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

sadman41 пишет:

На любом назначенном порту он отвечает.

так оно не назначено было видимо!
Проверил и на esp8266 и на ESP32 в любых комбинациях портов работает, еще бы кнопку прилепить и индикатор, что от клиента до сервера и обратно отрабатывает...
Выходит дело было не в бобине? )))

PS Значит скетчи из инета с примерами вэбсокетов кривые, надо же а они информацию даже продают...

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

Не в бобине, а в непонимании принципа работы протокола. Скетчей "из интернета" я не видел. Может и кривые, а может и просто заточены под конкретную задачу.

Кнопки мне неинтересно приделывать, а вот демо клиентской части поустойчивей я сделал для тестов:

<html>
<head>
    <title>Websocket simple test</title>
    <style> 
      #wsData       { padding: 5px; border: 1px solid darkGray; border-radius: 5px; }
      #wsState      { padding: 5px; }
      .wsConnecting { color: white; background: darkSlateGrey; }
      .wsOpened     { color: white; background: darkGreen; }
      .wsWorking    { color: white; background: darkBlue; }
      .wsClosed     { color: white; background: red; }
    </style> 
    <script>
        var host = 'ws://'+ window.location.hostname + (window.location.port ? ":" + window.location.port : '') + '/ws';
        var reopenTime = 2000;
        var ws;
        
        window.onload = function() { wsReopen(); }

        function reportState(c, d) { 
          var wsStateSpan = document.getElementById('wsState');
          wsStateSpan.className = c;
          wsStateSpan.textContent = d;
        }

        function wsOnOpen(e) {
          console.log('Connection opened');
          reportState('wsOpened', 'Opened');
        }
        function wsOnClose(e) {
          console.log('Connection closed'); 
          reportState('wsClosed', 'Closed');
          setTimeout(wsReopen, reopenTime);
        }
        function wsOnMessage(e) {
          console.log('Recieved message: ' + e.data); 
          reportState('wsWorking', 'Working');
          document.getElementById('wsData').innerHTML = e.data;
        }

        function wsReopen() {
          console.log('Trying to reopen connection with ' + host);
          if (!ws || ws.readyState == 3) { 
             console.log('Connecting...');
             reportState('wsConnecting', 'Connecting');
             ws = new WebSocket(host); 
             ws.onmessage = wsOnMessage;
             ws.onopen    = wsOnOpen;
             ws.onclose   = wsOnClose;
             console.log(ws);
          }
       }
    </script>

</head>
<body>
    <h3>Websocket simple test</h3>
    <p>State: <span id='wsState' class='wsClosed'>Closed</span></p>
    <p>Latest incoming data: <span id='wsData'></span></p>
</body>
</html>

 

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

Заменил кусок, работает, сейчас сервер работает на 8000 порту а проброс снаружи делаю с порта 8080, сейчас еще пару правил в роутере добавлю, посмотрю
тестирую на 12 клиентах, я правильно понимаю, если обмен завис более чем на 2 секунды сокет переоткрывается?

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

Если клиент отвалился (штатно или нет), то следующая попытка переподключения будет произведена через 2 секунды.

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

sadman41 пишет:

Если клиент отвалился (штатно или нет), то следующая попытка переподключения будет произведена через 2 секунды.

прекрасная надёжность получается, напрашивается дополнить скетч подсчётом числа переподключений...
Для тестовых испытаний

Даже столь косметические изменения программы делают её работоспособной для доступа с наружней сети

Код конечно совсем кривой, ТС, ты бы поправил:
 

// взято отсюда - http://arduino.ru/forum/programmirovanie/probros-portov-ne-rabotaet-no-prichina-v-biblioteke-koda-vidimo?page=1#comment-568781
// изменено для работы со статическим IP адресом
#define ESP32   // Для ESP32 размаркировать
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
const uint16_t ports = 8000;
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>              // https://github.com/me-no-dev/ESPAsyncTCP
const uint16_t ports = 8000;
#endif
#include <ESPAsyncWebServer.h>

// вставляем ниже SSID и пароль для своей WiFi-сети:
const char* ssid     = "OpenWrt";  
const char* password = "123456789";

// Create AsyncWebServer object on port
AsyncWebServer server(ports);
AsyncWebSocket ws("/ws");

// Задайте свой статический IP-адрес
IPAddress local_IP(192, 168, 1, 240);
// Укажите IP-адрес шлюза
IPAddress gateway(192, 168, 1, 1);

IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   // опционально
IPAddress secondaryDNS(8, 8, 4, 4); // опционально



// переменная для хранения HTTP-запроса:
String header;

// мотор 1:
int motor1Pin1 = 21; 
int motor1Pin2 = 19; 
//int enable1Pin = 14; 

// мотор 2:
int motor2Pin1 = 23; 
int motor2Pin2 = 22; 
//int enable2Pin = 32;

// переменные для свойств широтно-импульсной модуляции (ШИМ) 1-двигателя:
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 0;

// переменные для свойств широтно-импульсной модуляции (ШИМ) 2-двигателя:
const int freq2 = 30000;
const int pwmChannel2 = 1;
const int resolution2 = 8;
int dutyCycle2 = 0;


// переменные для расшифровки HTTP-запроса GET:
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;





 //------------------- Работа с оптическими датчиками --------------------------

  String state; //сюда будет писаться состояние, т.е. куда едет машинка в данный момент
 
  volatile uint32_t lasttime1 = 0;
  volatile uint32_t lasttime2 = 0;

  
  //Куда подключены оптические датчики энкодера:
  int SensorPin1 = 13;
  int SensorPin2 = 14;

  volatile uint32_t gap1 = 0;
  volatile uint32_t gap2 = 0;

  //-----------------------------------------------------------------------------
  


//----------------PID регулятор-------------------------

//Величины PID регулятора

int setpoint = 0;   // заданная величина, которую должен поддерживать регулятор
int input = 0;      // сигнал с датчика (например температура, которую мы регулируем)
int output = 0;     // выход с регулятора на управляющее устройство (например величина ШИМ или угол поворота серво)
int pidMin = 0;     // минимальный выход с регулятора/Изначально тут стояло 0
int pidMax = 0;   // максимальный выход с регулятора/Изначально тут стояло 255 - это число для 8-битного ШИМ


// коэффициенты
float Kp = 1.0; //тут стояло 1.0
float Ki = 1.0; //тут стояло 1.0
float Kd = 1.0; //тут стояло 1.0
float _dt_s = 0.1; // время итерации в секундах

// вспомогательные переменные
int prevInput = 0;
float integral = 0.0;

//------------------------------------------------------


//----------------PID регулятор (вариант2)-------------------------

//  GyverPID regulator(0, 0, 0, 10);


  
//-----------------------------------------------------------------





//-------------------БЛОК РАБОТЫ С WEBSOCKET И ОТОБРАЖЕНИЯ ВЕБ-СТРАНИЦЫ----------------------------------------

bool ledState = 0;
const int ledPin = 2;

// Create AsyncWebServer object on port 80
// AsyncWebServer server(80);
// AsyncWebSocket ws("/ws");

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
  html {
    font-family: Arial, Helvetica, sans-serif;
    text-align: center;
  }
  h1 {
    font-size: 1.8rem;
    color: white;
  }
  h2{
    font-size: 1.5rem;
    font-weight: bold;
    color: #143642;
  }
  .topnav {
    overflow: hidden;
    background-color: #143642;
  }
  body {
    margin: 0;
  }
  .content {
    padding:  5 px; //30px;
    display: flex;
    justify-content: center;
//    margin: 0 auto;
    text-align: center;
//    margin-left: auto;
//    margin-right: auto;
  }

    .content2 {
    padding:  5 px; //30px;
    display: flex;
    justify-content: space-between;
//   // padding:  px; //30px;
//     max-width: 400px;
//    margin: 0 auto;
  }

    .content3 {
       padding: 40 px; //30px;
       display: flex;
       justify-content: center;
  }



  .button1 {
    
    padding: 15px 50px;
    font-size: 24px;
    text-align: center;
    outline: none;
    color: #fff;
    background-color: #0f8b8d;
    border: none;
    border-radius: 5px;
    width: 670px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
   }

  .button2 {
    padding: 15px 5px;
    font-size: 24px;
    text-align: center;
    outline: none;
    color: #fff;
    background-color: #0f008d;
    border: none;
    border-radius: 5px;
    width: 140px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
   }

   /*.button:hover {background-color: #0f8b8d}*/
   .button:active {
     background-color: #0f8b8d;
     box-shadow: 2 2px #CDCDCD;
     transform: translateY(2px);
   }
     
   .state {
     font-size: 1.5rem;
     color:#8c8c8c;
     font-weight: bold;
   }
  </style>
  
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>


<body>

   
   <div class="content">
      <p><button id="button" class="button1">forward</button></p>
   </div>
  
   <div class="content2">
      <p><button id="button2" class="button2"><<< left</button></p>
      <p><button id="button2_1" class="button2">< slow</button></p>
      
      <p><button id="button3_1" class="button2">slow ></button></p>
      <p><button id="button3" class="button2">right >>></button></p>
      </div>
      
   <div class="content3">    
      <p><button id="button4" class="button1">reverse</button></p>
  </div>
<script>
  var gateway = 'ws://'+ window.location.hostname + (window.location.port ? ":" + window.location.port : '') + '/ws';
  var websocket;
  window.addEventListener('load', onLoad);
  function initWebSocket() {
    console.log('Trying to open a WebSocket connection...');
    websocket = new WebSocket(gateway);
    websocket.onopen    = onOpen;
    websocket.onclose   = onClose;
    websocket.onmessage = onMessage; // <-- add this line
  }
  function onOpen(event) {
    console.log('Connection opened');
  }
  function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
  }
  function onMessage(event) {
    var state;
    if (event.data == "1"){
      state = "ON";
    }
    else{
      state = "OFF";
    }
    document.getElementById('state').innerHTML = state;
  }
  function onLoad(event) {
    initWebSocket();
    initButton();
    initButton2();
    initButton2_1();
    initButton3();
    initButton3_1();
    initButton4();
  }
  function initButton() {
    //document.getElementById('button').addEventListener('click', toggle);
      document.getElementById('button').addEventListener('touchstart', forward, false);
      document.getElementById('button').addEventListener('touchend', stopper, false);
  }
  function forward(){
    websocket.send('forward');
  }


   function initButton2() {
      document.getElementById('button2').addEventListener('touchstart', left, false);
      document.getElementById('button2').addEventListener('touchend', stopper, false);
  }
  function left(){
    websocket.send('left');
  }

  function initButton2_1() {
      document.getElementById('button2_1').addEventListener('touchstart', left_slow, false);
      document.getElementById('button2_1').addEventListener('touchend', stopper, false);
  }
  function left_slow(){
    websocket.send('left_slow');
  }


  function initButton3() {
      document.getElementById('button3').addEventListener('touchstart', right, false);
      document.getElementById('button3').addEventListener('touchend', stopper, false);
  }
  function right(){
    websocket.send('right');
  }  

  function initButton3_1() {
      document.getElementById('button3_1').addEventListener('touchstart', right_slow, false);
      document.getElementById('button3_1').addEventListener('touchend', stopper, false);
  }
  function right_slow(){
    websocket.send('right_slow');
  }  
   function initButton4() {
        document.getElementById('button4').addEventListener('touchstart', reverse, false);
        document.getElementById('button4').addEventListener('touchend', stopper, false);
    }
    function reverse(){
      websocket.send('reverse');
    }  

 function stopper(){
    websocket.send('stop');
  }
  
</script>
</body>



</html>
)rawliteral";

void notifyClients() {
  ws.textAll(String(ledState));
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) { // обрабатываем получаемые сообщения
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    if (strcmp((char*)data, "forward") == 0) {
      ledState = !ledState;


      Serial.println("Forward");  //  "Вперед"

      state = "Forward";

      ledcWrite(pwmChannel, 0); //0 - максимум оборотов
      ledcWrite(pwmChannel2, 0); //0 - максимум оборотов
             
      digitalWrite(motor1Pin1, LOW);
      digitalWrite(motor1Pin2, HIGH); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);
      //notifyClients();
    }
    else if (strcmp((char*)data, "left") == 0) {
      ledState = !ledState;


      Serial.println("Left");  //  "Влево"

      state = "Left";
               
      ledcWrite(pwmChannel, 255);
      ledcWrite(pwmChannel2, 0);                
      digitalWrite(motor1Pin1, HIGH); 
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "left_slow") == 0) {
      ledState = !ledState;


      Serial.println("LeftSlow");  //  "Влево медленно"

      state = "LeftSlow";
               
      ledcWrite(pwmChannel, 155);
      ledcWrite(pwmChannel2, 100);                
      digitalWrite(motor1Pin1, HIGH); 
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "right") == 0) {
      ledState = !ledState;

      Serial.println("Right");  //  "Вправо"

      state = "Right";
             
      ledcWrite(pwmChannel, 0);
      ledcWrite(pwmChannel2, 255);
      digitalWrite(motor1Pin1, LOW); 
      digitalWrite(motor1Pin2, HIGH); 
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "right_slow") == 0) {
      ledState = !ledState;

      Serial.println("RightSlow");  //  "Вправо медленно"

      state = "RightSlow";
             
      ledcWrite(pwmChannel, 100);
      ledcWrite(pwmChannel2, 155);
      digitalWrite(motor1Pin1, LOW); 
      digitalWrite(motor1Pin2, HIGH); 
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);    
      //notifyClients();
    }
    else if (strcmp((char*)data, "reverse") == 0) {
      ledState = !ledState;

      Serial.println("Reverse");  //  "Назад"

      state = "Reverse";
              
      ledcWrite(pwmChannel, 255); //255 - максимум оборотов
      ledcWrite(pwmChannel2, 255); //255 - максимум оборотов
      digitalWrite(motor1Pin1, HIGH);
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);          
      //notifyClients();
    }
    else if (strcmp((char*)data, "stop") == 0) {
      ledState = !ledState;

      Serial.println("Stop");  //  "Стоп"

      state = "Stop";
              
      ledcWrite(pwmChannel, 0);
      ledcWrite(pwmChannel2, 0);
      digitalWrite(motor1Pin1, LOW); 
      digitalWrite(motor1Pin2, LOW); 
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, LOW);  
      //notifyClients();
    }
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
             void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if (ledState){
      return "ON";
    }
    else{
      return "OFF";
    }
  }
}

//-------------------------------------------------------------------------------------------------------








void setup() {
  Serial.begin(115200);

    // переключаем контакты моторов в режим «OUTPUT»:
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);


  // подключаем контакты оптических датчиков к пину, в режим «INPUT»:
  pinMode (SensorPin1, INPUT);
  pinMode (SensorPin2, INPUT);

  
  //подключаем реакцию на прерывания - к пинам датчиков:
  
//  attachInterrupt(SensorPin1, sensor_impulse, LOW);
//  attachInterrupt(SensorPin2, sensor_impulse2, LOW);



  // задаем настройки ШИМ-канала каждого из 2 двигателей:
 
  ledcSetup(pwmChannel, freq, resolution); // первый двигатель
  ledcSetup(pwmChannel2, freq2, resolution2); // второй двигатель
  
  // подключаем ШИМ-канал, к контактам для управления скоростью вращения каждого из 2 моторов:

    ledcAttachPin(motor1Pin1, pwmChannel); // первый двигатель
    ledcAttachPin(motor2Pin1, pwmChannel2); // второй двигатель
 
  // подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»:
  ledcWrite(pwmChannel, dutyCycle);
  ledcWrite(pwmChannel2, dutyCycle2);

 // Настраиваем статический IP-адрес сервера:
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");  //  "Не удалось задать статический IP-адрес"
  }
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

// Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  initWebSocket();

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Start server
  server.begin();
  
}// END SETUP


void loop(){
  ws.cleanupClients();
} // END LOOP
Connecting to WiFi..
192.168.1.240
WebSocket client #1 connected from 192.168.1.216
WebSocket client #2 connected from 192.168.1.1
WebSocket client #3 connected from 192.168.1.1
WebSocket client #4 connected from 192.168.1.1

внутри работает на порту 8000
снаружи виден на портах 8080, 9000 и т.д.

 

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

Не знаю, зачем реконнекты считать, но для интересу...

#if defined(ESP32)
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
// https://github.com/me-no-dev/ESPAsyncTCP
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

#if defined(ESP8266)
ADC_MODE(ADC_VCC);
#endif

const char* ssid = "DonDon";
const char* password = "8fjd3ciy";

const uint16_t httpPort = 8080;

AsyncWebServer server(httpPort);
AsyncWebSocket ws("/ws");

const char indexPageContent[] PROGMEM = R"rawliteral(
  <!DOCTYPE HTML>
<html>
<head>
    <title>Simple WebSocket client</title>
    <style> 
      #wsRawData, #wsParsedData { padding: 5px; border-radius: 5px; border: 1px solid darkGray; }
      #wsState      { padding: 5px; border-radius: 5px; }
      .wsConnecting { color: white; background: darkSlateGrey; }
      .wsOpened     { color: white; background: darkGreen; }
      .wsWorking    { color: white; background: darkBlue; }
      .wsClosed     { color: white; background: red; }
    </style> 
    <script>
        var host = 'ws://'+ window.location.hostname + (window.location.port ? ":" + window.location.port : '') + '/ws';
        var reopenTime = 2000;
        var ws, reopenAttempts = 0;
        
        window.onload = function() { wsReopen(); }

        function reportState(c, d) { 
          var wsStateSpan = document.getElementById('wsState');
          wsStateSpan.className = c;
          wsStateSpan.textContent = d;
        }

        function wsOnOpen(e) {
          reopenAttempts++;
          reportState('wsOpened', 'Opened');
          document.getElementById('wsReopenAttempts').textContent = reopenAttempts;
        }
        function wsOnClose(e) {
          console.log('Connection closed'); 
          reportState('wsClosed', 'Closed');
          setTimeout(wsReopen, reopenTime);
        }
        function wsOnMessage(e) {
          console.log('Recieved message: ' + e.data); 
          reportState('wsWorking', 'Working');
          document.getElementById('wsRawData').textContent = e.data;
          var jsonObject = JSON.parse(e.data);
          document.getElementById('wsTime').textContent = jsonObject.time;
          document.getElementById('wsFreeMem').textContent = jsonObject.freeMem;
          document.getElementById('wsVcc').textContent = jsonObject.vcc;
        }

        function wsReopen() {
          console.log('Trying to reopen connection with ' + host);
          if (!ws || ws.readyState == 3) { 
             document.getElementById('wsReopenAttempts').textContent = reopenAttempts;
             console.log('Connecting...');
             reportState('wsConnecting', 'Connecting');
             ws = new WebSocket(host); 
             ws.onmessage = wsOnMessage;
             ws.onopen    = wsOnOpen;
             ws.onclose   = wsOnClose;
             console.log(ws);
          }
       }
    </script>

</head>
<body>
    <h3>Simple WebSocket client</h3>
    <p>Reopen attempts: <span id='wsReopenAttempts'>0</span></p>
    <p>State: <span id='wsState' class='wsClosed'>Closed</span></p>
    <p>Latest incoming data: <span id='wsRawData'></span></p>
    <p>Latest parsed data: <span id='wsParsedData'>Time: <span id='wsTime'>---</span> | Free Memory <span id='wsFreeMem'>---</span> | VCC: <span id='wsVcc'>---</span></span></p>
</body>
</html>
    )rawliteral";

uint16_t getMcuVoltage() {
#if defined(ESP32)
  // !!! No any warranty when rom_phy_get_vdd33 used
  return rom_phy_get_vdd33();
#elif defined(ESP8266)
  return ESP.getVcc();
#endif
}

void notFoundPage(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void indexPage(AsyncWebServerRequest *request) {
  request->send(200, "text/html", indexPageContent);
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      client->printf("Hello Client %u :)", client->id());
      client->ping();
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("WiFi Failed!\n");
    return;
  }

  Serial.print("\nIP Address: "); Serial.println(WiFi.localIP());

  ws.onEvent(onEvent);

  server.addHandler(&ws);
  server.on("/", HTTP_GET, indexPage);
  server.onNotFound(notFoundPage);
  server.begin();
}

void loop() {
  char buffer[100];
  snprintf(buffer, sizeof(buffer), "{ \"time\": %lu, \"freeMem\": %u, \"vcc\": %u }", millis(), ESP.getFreeHeap(), ESP.getVcc());
  ws.textAll(buffer);
  delay(1000);
  ws.cleanupClients();
}

PS. При нештатном отключении сети (ребуте ESP-шки) браузер почему-то событие onClose не генерирует... Не знаю, что за хрень. Жаваскриптом раз в год занимаюсь, тратить на него время не буду, пока стимула не будет ))  Порты пробрасываются, а это единственное что меня тут заинтересовало.

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

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

Почему никто из заинтересовавшихся не включил отладку, по крайней мере была бы понятна причина потребовавшая "косметических" изменений.

 

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

Я уже прочитал, что из JS Websocket API пинг-понг недоступен и, возможно, просто в нём нереализован. Т.е. рисовать его нужно самому, а это уже выходит за рамки расследования "што там с портами". Браузер ничего не пишет. Просто висит и ждет входящих фреймов.

Хотя, конечно, API странное.  Всякое бывает по роутингу и почему канал при этом не контролируется - загадка...

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

brokly пишет:

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

Почему никто из заинтересовавшихся не включил отладку, по крайней мере была бы понятна причина потребовавшая "косметических" изменений.

включал, нет там никакой информации, коннект-дисконнект и пожалуй всё, забыл, один раз немного высыпало, но повторить аналогичное сообщение не получилось, а скопировать в буфер что-то не догадался