Разработка ‘библиотеки’ малого webсервера на esp8266.

pvvx

Активный участник сообщества
Вообще существуют разработки для ARM типа "микро база данных"
Возможностей у ESP + SD вполне достаточно для поддержки чего-нибудь типа sqlite
Неа. Нет либ на ESP8266 с полной поддержкой даже FAT32 на SD или они занимают все ресурсы.
У ESP8266 нет DMA, а есть жалкое подобие и работать с SD выходит очень медленно и вся прыть ESP8266 уходит на обработку SPI запросов-ответов к SD.
Тем более SD не приспособлена для БД - если не вовремя выключить питание при записи, то умирает вся внутренняя разметка блоков SD... Ставить на ESP8266 UPS - моветон...
Буферизировать запросы БД просто негде.
QSPI шину тоже не выходит использовать, т.к. придется понижать частоту работы Flash, что приведет к понижению скорости работы самого CPU ESP.
 
Последнее редактирование:

seasanitar

New member
Доброго времени суток!
Уважаемый pvvx, опрос электросчетчика НЕВА124 по RS485 через TCP2UATRT. Захожу через статический IP 188.134.ххх.ххх:4444 (188.134.xxx.xxx:12345) , проброс портов (web 192.168.1.26:4444, uart 192.168.1.26:12345) через роутер. Данные по UART ходят прекрасно, перезапросов не возникает. Но не отображается web страничка webserver esp8266 когда заходишь из внешней сети. По внутренней сети все ок (веб сервер работает). Используемые порты открыты у оператора. Для проверки на 192.168.1.26 подключил роутер TPlink (взамен esp8266), прописал доступ на WAN по порту 4444, веб страничка TPlink отображаться без проблем. Читал форум (может, что и упустил), пробовал увеличить задержки с 5 до 15 секунд, пробовал разных операторов 3G, оптика, менял порты местами, MTU 1400, результат, один и тот же, uart работает, веб нет. Если есть возможность и идеи, подскажите, что еще можно посмотреть?
 

pvvx

Активный участник сообщества
Вот инструкцию для чайников написал, буду рад помощи в организации обратной связи от Ардуины в ESP

WiFi Розетка на ESP8266 + Arduino | www.voltrans.az
Пора бы уже вопрошающим переходить на Arduino. Там уже написали примитивы для web и прочей обвязки к ESP...
Используемые порты открыты у оператора.
Наверняка не открыт порт 80. "Операторы" ныне мутят, скидывая это на то, что типа вас защищают брендмауэром и ... на самом деле висит какой односторонний NAT с перекинутыми (на другие нужды) основными ходовыми портами... Пробуйте переадресацию внешнего порта в 80-ый или смените у самого сервера...
Читал форум (может, что и упустил), пробовал увеличить задержки с 5 до 15 секунд, пробовал разных операторов 3G, оптика, менял порты местами, MTU 1400, результат, один и тот же, uart работает, веб нет. Если есть возможность и идеи, подскажите, что еще можно посмотреть?
Кроме как изменить размер TCP_MSS и всяких PPP_MTU на -50 байт в lwipopts.h и перетранслировать проект вариантов нет. Всё остальное, если Station ESP у вас не отваливается от присутствия рядом других WiFi устройств - это обычно неправильные внешние настройки или проблемы операторов, дающих вам инет... Fix IP со всеми портами стоит денех, и бесплатно ныне не бывает.
 
Последнее редактирование:

viknull

New member
Нашел проблему при работе TCP2UART в режиме TCPClient.
Проблема с callback tcpsrv_error в следующем:
1) При неудачном соединении, вызывается tcpsrv_client_reconnect
2) Затем вызывается tcp_abandon, что приводит к ошибке "Connection aborted"; // ERR_ABRT -8
3) В tcpsrv_error ловится эта ошибка и вызывается tcpsrv_client_reconnect, что приводит к рекурсии
4) Все виснет и перезагружается

Исправить можно так:
в tcpsrv_error изменить условие
if (ts_conn->state != SRVCONN_CLOSEWAIT)
на
if ((ts_conn->state != SRVCONN_CLOSEWAIT)&& (err != -8))

И все начинает работать верно, с ожиданием 5 сек на переподключение.
 

pvvx

Активный участник сообщества
Нашел проблему при работе TCP2UART в режиме TCPClient.
Проблема с callback tcpsrv_error в следующем:
1) При неудачном соединении, вызывается tcpsrv_client_reconnect
2) Затем вызывается tcp_abandon, что приводит к ошибке "Connection aborted"; // ERR_ABRT -8
3) В tcpsrv_error ловится эта ошибка и вызывается tcpsrv_client_reconnect, что приводит к рекурсии
4) Все виснет и перезагружается

Исправить можно так:
в tcpsrv_error изменить условие
if (ts_conn->state != SRVCONN_CLOSEWAIT)
на
if ((ts_conn->state != SRVCONN_CLOSEWAIT)&& (err != -8))

И все начинает работать верно, с ожиданием 5 сек на переподключение.
Видимо не полностью перенес-доделал последние обновления с RTL871x, там как раз было переписано вокруг да около закрытия соединений (были выловлены редкие ошибки вызовов в разной последовательности при множественных закрытиях пачки соединений)...
Здесь, в tcpsrv_client_reconnect, нет tcp_abandon() RTL00_WEB/tcp_srv_conn.c at master · pvvx/RTL00_WEB · GitHub (устарело - уже совсем стер - см PS)
А исправление err != -8 не верно и, к примеру в LwIP 1.4.1 ERR_ABRT = -10, ...
Проще наверно исправить так:
tcp_err(pcb, NULL);
tcp_abandon(pcb, 0);

------
PS: Убрал вообще tcp-клиента из web-свалки на RTL. Не нужен он в такой реализации, когда есть socket да RTOS, а вот в ESP8266 пока не проверял и не чинил tcp-клиента...
 
Последнее редактирование:

viknull

New member
Проще наверно исправить так:
tcp_err(pcb, NULL);
Да, действительно, ошибка ERR_ABRT может возникнуть не только в tcpsrv_client_reconnect, поэтому лучше сбросить collback, а при повторном коннекте в tcpsrv_client_connect, он присвоится обратно.

Еще момент, кому нужно следить что разорвалось TCP соединение(в момент простоя), можно включить keep-alive.
В tcpsrv_client_connect после if(err == ERR_OK) {
добавить:
pcb->so_options |= SOF_KEEPALIVE;
pcb->keep_idle = 1000; //Интервал времени, по истечении которого начинаются пробы (мс)
pcb->keep_intvl = 1000; //Интервал времени между пробами
pcb->keep_cnt = 2; //Количество проб
 

kozmich

New member
Пытаюсь разобраться с вебсокетами. К примеру, клиент отправляет запрос с именем переменной. Она парсится,вызывается соответствующая функция и результат помещается в поток. Но. Если я правильно понимаю, данные передаются фреймами.
В проекте есть соответствующая функция -websock_tx_frame. Но используется только в служебных целях при чтении данных и при закрытии соединения. Я так же не нашел, чтобы она использовалась в качестве коллбека. Т.е. данные, помещенные в исходящий буфер, передаются "как есть", без всякой обработки? Такая работа с вебсокетами допустима?
Еще вопрос. Если необходимо, чтобы сервер инициировал обмен, нужно явно вызывать эту функцию?
 

pvvx

Активный участник сообщества
Пытаюсь разобраться с вебсокетами. К примеру, клиент отправляет запрос с именем переменной. Она парсится,вызывается соответствующая функция и результат помещается в поток. Но. Если я правильно понимаю, данные передаются фреймами.
Много не понятного в вопросах...
Какие ещё "фреймы" или что под ними у вас понимается?
Данные или "фреймы", в websocket бывают двух типов - бинарные и текстовые.
В проекте есть соответствующая функция -websock_tx_frame. Но используется только в служебных целях при чтении данных и при закрытии соединения. Я так же не нашел, чтобы она использовалась в качестве коллбека.
Что за "коллбек" или зачем он? :confused:
Т.е. данные, помещенные в исходящий буфер, передаются "как есть", без всякой обработки? Такая работа с вебсокетами допустима?
Бинарные данные всегда как есть, текстовые - так-же.
Еще вопрос. Если необходимо, чтобы сервер инициировал обмен, нужно явно вызывать эту функцию?
Какую?
Websocket-ов может быть открыто до исчерпания памяти, т.е. дцать штук. Какой при этом вызов, какой "коллбек", для каких целей, в какой из открытых веб-сокетов?

Используйте запросно-ответный режим при работе с websocket. Так проще и все вопросы отпадут и сложности...
Отдача в бинарном виде в текущей версии не описана до конца, т.к. не требовалась.
Пример реализации есть в аналогичной web-свалке для RTL RTL00_WEB/ina219drv.c at master · pvvx/RTL00_WEB · GitHub
RTL00_WEB/ws_test_ina219d.html at master · pvvx/RTL00_WEB · GitHub
Итог показан тут: https://esp8266.ru/forum/threads/web-svalka-na-rtl871x.2403/page-4#post-38678
Примерно аналогично через websocket передается и 48 кГц 16 бит ADC (такой у RTL8711AM)
 
Последнее редактирование:

kozmich

New member
Вопросы непонятные, потому что о вебсокетах знаю чуть больше, чем ничего.
Судя по информации, что я нашел, протокол websocet определяет, что после установления соединения обмен данными происходит фреймами, т.е. особым образом сформированными пакетами с заголовком и данными. В заголовке определяется в том числе и формат данных - бинарные или текстовые. В Вашем проекте есть функция websock_tx_frame, которая вызывает другую - WebsocketTxFrame для формирования и отправки такого фрейма. Вопросы у меня появились, когда я не смог найти вызов функции websock_tx_frame при отправке данных. Т.е. данные отправляются в сыром виде, без формирования фрейма. Примет ли браузер "неоформленные" данные и как он определит их тип?
Насчет запросно-ответного режима - он и планируется, просто ответ может быть с задержкой до нескольких секунд.
 

pvvx

Активный участник сообщества
Вопросы у меня появились, когда я не смог найти вызов функции websock_tx_frame при отправке данных. Т.е. данные отправляются в сыром виде, без формирования фрейма.
Никакого сырого вида. Всё само из буфера вывода упакуется в пакеты. Буфер после вывода проверяется на размер данных и это выводится.
esp8266web/web_websocket.c at master · pvvx/esp8266web · GitHub
Не забывайте, что буфер не резиновый, да и памяти у ESP вообще нет. Проверяйте объем перед выводом. Примеры там даны... Для ускорения передачи по TCP желательно передавать блоки объемом до объема 2*tcp_mss.
Запустите пример websocket, он есть на web-диске...
Насчет запросно-ответного режима - он и планируется, просто ответ может быть с задержкой до нескольких секунд.
Чем и зачем тормозить собрались? :)
Значит ответ должен содержать "ждите", или "лежать полчаса", или "заходите завтра".
На приемной стороне, при приеме данного ответа повторяете запрос, пока не получите ответ "есть данные: 12345..."
TCP связь без потерь. Если послали запрос и на него описан ответ, то придет этот ответ. Ничего в javascript не перепутается при вызове отсылки и приеме, хоть по одной букве...
 
Последнее редактирование:

Elik

New member
Почему при перезагрузке модуля все настройки сбрасываются на дефолтные, гдето читал, не могу найти...иными словами как сбросить настройки малого вебсервера на дефолтные?
 

pvvx

Активный участник сообщества
Почему при перезагрузке модуля все настройки сбрасываются на дефолтные, гдето читал, не могу найти...иными словами как сбросить настройки малого вебсервера на дефолтные?
RX на gnd, отключение в меню.
 

verybad

New member
в релизе 0.6.4 есть опция PROGECT_NUMBER 1. (MODBUS TCP to RTU) Чудесно компилируется и шьётся.
по части MODBUS TCP даже работает, RTU не проверял. Этот проект в данном релизе поддерживается?
 

pvvx

Активный участник сообщества
в релизе 0.6.4 есть опция PROGECT_NUMBER 1. (MODBUS TCP to RTU) Чудесно компилируется и шьётся.
по части MODBUS TCP даже работает, RTU не проверял. Этот проект в данном релизе поддерживается?
Да.
---------
Посмотрел старые сообщения:
Обработчик прерывания не может размещаться в FLASH, поэтому и нет модификатора.
Так происходит и-зта того что флэш кэшируется и в какой то момент код обработчика прерываний может быть вытеснен из кэша. Когда возникает прерывание оно должно быть обработано немедленно и если в кэше этого кода нет - система упадет.
Учитывайте что во флэш не могут размещаться также и все функции вызываемые из обработчика прерываний.
Тут ошибка в объяснении. Задержка чтения строки кода в "кэш" не сверх большая и не влияет на описанные вещи. Включение в прерывание "кэшируемых" функций работает, как прямое обращение по прерыванию в "кэшируемую" область. "Кэш" не работает когда идет запись или стирание в Flash. Flash занята. Хотя в процедуре записи или стирании Flash в коде стоит запрет прерываний и опустошение/отключение/включение "кэш", там не всё гладко... Контроллер прерываний не имеет "стека" и какие-то прерывания неизбежно будут пропущены... NMI вообще не маскируется...
Код "распределителя" основных пользовательских прерываний находиться в ROM или IRAM и вызов пользовательской части кода прерывания в Flash работает, если она не занята своими делами...

По этим причинам, код, требующий время-зависимого исполнения, помещается в RAM или ROM. У современных MCU со встроенной Flash выделяются раздельные сегменты, в которых запись не останавливает процесс чтения из другой области...
Это относиться ко многим процедурам WiFi и прочего HAL. От этого большая часть RAM того-же ESP-32 и тратиться, т.к. Espressif не cмог поместить в ROM нормальный рабочий код API+HAL, а вместо это поместил туда BASIC. В процедурах ROM у ESP8266 нагородили слишком много ошибок, что создало невозможность его использования по назначению и исправлениями пришлось забить всю IRAM, вместо выпуска чипа с новой маской ROM и буквенным индексом...

На закуску подумайте, как работает WiFI и SPIFFS при записи :)
 
Последнее редактирование:

psyduck

New member
Здравствуйте, я с вопросом. Использую по wifi версию 0.6.2. В какой-то момент настройка ip слетает в none. Кто-то может подсказать в связи с чем это происходит? И как от такого избавиться?
 

osnwt

New member
Возникло желание задействовать валяющийся ESP8266 для подключения к "умному дому" на базе OpenHAB электросчетчика "Энергомера". Счетчик имеет полудуплексный RS-485 интерфейс с собственным протоколом (не MODBUS). Сейчас показания снимаю своим скриптом, работающим на Linux через USB2RS485 адаптер. Хочется сделать счетчик автономным TCP сервером с WiFi, к которому можно слать команды по TCP в его RS-485 и получать ответы. Позже планирую дописать опрос нужных данных счетчика прямо в ESP8266 с выдачей результатов в виде JSON или через WS. Но сначала хочется что-то с него получить.

Насколько я вижу, вариант TCP2UART мне не подходит - в нем нет драйвера RS-485 с управлением направлением передачи. А вариант RS485 содержит MODBUS, который мне не нужен. Итого, вопрос: можно ли штатно сконфигурировать второй вариант (RS485) в режиме TCP2RS485 на отдельном порту, запретив MODBUS? Если нет, то тогда, видимо, нужно делать свой вариант, используя драйвер RS485 без MODBUS, для чего придется править основной код (например, он вызывает init_mdbtab() при включении RS485DRV даже, если MODBUS отключен в конфигурации).
 
Последнее редактирование:

osnwt

New member
Последняя версия с github не собирается в режиме rs485. Используется функция из файла tcp2uart, который в конфигурации rs485 не включен в трансляцию:
Код:
web_int_callbacks.c: In function 'web_int_callback':
web_int_callbacks.c:497:7: error: implicit declaration of function 'tcp2uart_ajax_rx' [-Werror=implicit-function-declaration]
       tcp2uart_ajax_rx(ts_conn, tmo);
EDIT: Рекомендацию закомментировать ветку с uart_data я видел. Но с учетом того, что мелкие исправления из RTL варианта, как пишется, попадают и в ESP, было бы логичным поправить код так, чтобы стандартные варианты проектов (0, 1, 2) исходно транслировались.
 
Последнее редактирование:
Сверху Снизу