• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Общие баги/глюки/проблемы в пакете Sming

Добрый день!

Во-второй раз поднимаю вопрос проблемы реализации встроенного веб-сервера. Симптомы такие, что в локальной сети, встроенный веб-сервер нормально отдает странички, отдает файлы иже с ним. Но стоит попробовать получить доступ из-за нат-а, через проброс портов - веб-сервер нормально отдает только маленькие странички или небольшие json-ответы. То есть даже страницы из примера Meteocotrol уже НЕ отдаются. Как верно в прошлый раз заметил тов pvvx, это может быть из-за сырости реализации HTTP-протокола встроенным веб-сервером. А именно он не отдает заголовок Content-Length и/или не умеет отправлять поток данных в "нарезку" используя Transfer-Encoding: chuncked. Я пробовал "хачить" TcpConnection::write
Код:
int TcpConnection::write(IDataSourceStream* stream, bool chunked)
{
    // Send data from DataStream
    bool repeat;
    bool space;
    int available;
    int total = 0;
    char buffer[NETWORK_SEND_BUFFER_SIZE];

    do
    {
        space = (tcp_sndqueuelen(tcp) < TCP_SND_QUEUELEN);
        if (!space)
        {
            debugf("WAIT FOR FREE SPACE");
            flush();
            break; // don't try to send buffers if no free space available
        }

        // Join small fragments
        int pushCount = 0;
        do
        {
            pushCount++;
            int read = min(NETWORK_SEND_BUFFER_SIZE, getAvailableWriteSize());
            if (read > 0)
                available = stream->readMemoryBlock(buffer, read);
            else
                available = 0;

            if (available > 0)
            {
                if (chunked)
                {
                    char cbuf[16];
                    unsigned int len = os_sprintf(cbuf,"%X\r\n", available);
                    write(cbuf, len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
                }
                int written = write(buffer, available, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);

                if (chunked)
                {
                    write("\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
                }

                total += written;
                stream->seek(max(written, 0));
                repeat = written == available && !stream->isFinished() && pushCount < 25;
            }
            else
                repeat = false;
        } while (repeat);

        space = (tcp_sndqueuelen(tcp) < TCP_SND_QUEUELEN);// && tcp_sndbuf(tcp) >= FILE_STREAM_BUFFER_SIZE;
    } while (repeat && space);
    if (chunked)
    {
        write("0\r\n\r\n", 5, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
    }
    flush();
    return total;
}

приблизительно таким методом, и из HttpResponse выставлять заголовок TransferEncoding: chuncked и оно даже почти работать стало в ЛОКАЛКЕ, но через нат+портфорвардинг+инет - те же грабли. Грязные попытки анализа трафика привели к тому, что стало ясно, что не смотря на нарезку, пакеты сперва заполняют весь MSS 1460, а только потом шлются..А надо, чтоб каждый HTTP-кусок шел своим пакетом как я понимаю.

Вообщем может есть кто, кто более хорошо въезжает в тонкости LWIP+Sming+HTTP чтоб пофиксить это и довести реализацию HTTP до минимально рабочего через инет состояния? или хотя бы пните КАК сделать так, чтоб не дожидаясь заполнения ПОЛНОГО MSS 1460 отправлять пакет??

Спасибо!
 

anakod

Moderator
Команда форума
В посл строке вы зацикливаетесь, возможно моя точка доступа от этого ложится? Может стоит сначала от нее отключиться?
Не думаю что это связано. Зацикливание идет чтобы произошла перезагрузка по WatchDog.

Так понимаю виной всему вот это: makefile:20: c:\tools\sming\Sming: Permission denied Но я на всю папку изменял права на "Полный доступ" для всех. В чем косяк? На двух машинах (дом, работа) такая бяка)
Вероятно проблема в переменной Path. Каково ее содержимое?

Я уменьшать delay уже пробывал пробывал , все равно перезагружается.
Похоже что дело в изменениях связанных с новым SDK. Кто-нибудь еще пробовал выполнить подобный тест?

не умеет отправлять поток данных в "нарезку" используя Transfer-Encoding: chuncked.
Это не может влиять, у HTTP много расширений но никакие из них не являются обязательными. Можно и в GZIP жать и т.д., но это точно не поможет.

Очень похоже что проблема в TCP уровне и/или размерах отправляемых пакетов. Было бы интересно услышать больше информации по этому поводу.
 
Вероятно проблема в переменной Path. Каково ее содержимое?
C:\MentorGraphics\7.9.5EE\SDD_HOME\common\win32\bin;C:\MentorGraphics\7.9.5EE\SDD_HOME\common\win32\lib;C:\MentorGraphics\7.9.5EE\MGC_HOME.ixn\bin;C:\MentorGraphics\7.9.5EE\MGC_HOME.ixn\lib;C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\WinAVR-20100110\bin;C:\WinAVR-20100110\utils\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files (x86)\Common Files\Acronis\SnapAPI\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files\TortoiseSVN\bin;C:\ProgramData\chocolatey\bin;C:\Program Files\Eclipse Foundation\4.4.2\eclipse;C:\tools\mingw64\bin;C:\tools\mingw64\msys\1.0\bin;

C:\MentorGraphics\7.9.5EE\SDD_HOME\common\win32\lib;C:\tools\mingw64\bin;
 

anakod

Moderator
Команда форума
C:\WinAVR-20100110\utils\bin
Судя по всему winavr перекрывает.

чтобы узнать точно запустите в командной строке:
Код:
whereis make
 

pvvx

Активный участник сообщества
Очень похоже что проблема в TCP уровне и/или размерах отправляемых пакетов. Было бы интересно услышать больше информации по этому поводу.
Поиск в инете рулит :) Ифа что надо уменьшать MTU у российских провайдеров GSM = 100%. Толи забили всё древним оборудованием, то-ли что-то другое у них... 4G в Питере не пролазит c mss = 1460. с 1420 - пролазит.
А большей инфы вы не дождетесь. Считанные единицы включают ESP в сеть или вообще что-то делают через сеть. Остальные, соединив с компом, на макетке и помигав светодиодом кидают ESP в "дальний угол" :)
 

anakod

Moderator
Команда форума
Да, я думаю Вы правы, наверняка дело именно в этом. А возможно ли отрегулировать мсу без пересборки lwip? Просто т.к. OpwnLWIP похоже больше не поддерживается автором, Sming временно переведен на сборку от Espressif.
 

pvvx

Активный участник сообщества
А возможно ли отрегулировать мсу без пересборки lwip? Просто т.к. OpwnLWIP похоже больше не поддерживается автором, Sming временно переведен на сборку от Espressif.
А это я и хотел узнать, как сменить на ходу для всех соединений. Но на первый взгляд никак. Там везде прописывается MSS из множественных define, а менять при открытии соединения уже в pcb мне кажется поздно. Если при создании pcb, то может и пройдет. У меня в "свалке web" OpenLwIP 1.4.0 в SDK 1.2.0. и при смене на 1420 всё работает, а при 1460 не проходят большие пакеты, если путь через GSM (4G/LTE/...)
Вам для опытов может подойти liblwip_536.a от китайцев...
 
Последнее редактирование:
C:\WinAVR-20100110\utils\bin
Судя по всему winavr перекрывает.

чтобы узнать точно запустите в командной строке:
Код:
whereis make
Да, винавр перекрывал. Все исправил. По умолчанию в папке C:\Espressif\ESP8266_SDK\include в файле ip_addr.h ошибки типа как здесь: http://esp8266.ru/forum/threads/smi...j-razrabotki-proshivok-esp8266.167/#post-3183
Проблема решена копированием с заменой всех файлов из папки ESP8266_SDK_095. Но до конца не компилит:
02:58:35 **** Build of configuration Sming for project SmingFramework ****
make all
AS system/irq_check.s
CC system/flashmem.c
CC Services/SpifFS/spiffs.c
CC Services/SpifFS/spiffs_cache.c
CC Services/SpifFS/spiffs_check.c
CC Services/SpifFS/spiffs_gc.c
CC Services/SpifFS/spiffs_hydrogen.c
CC Services/SpifFS/spiffs_nucleus.c
CC Services/libemqtt/libemqtt.c
CC Libraries/Adafruit_GFX/glcdfont.c
CC Libraries/Adafruit_ILI9341/hspi.c
CC Libraries/cWebsocket/websocket.c
C+ system/esp_cplusplus.cpp
C+ system/stringconversion.cpp
C+ Wiring/FakePgmSpace.cpp
C+ Wiring/I2cMaster.cpp
C+ Wiring/IPAddress.cpp
C+ Wiring/Print.cpp
C+ Wiring/SplitString.cpp
C+ Wiring/Stream.cpp
C+ Wiring/WMath.cpp
C+ Wiring/WShift.cpp
C+ Wiring/WString.cpp
C+ SmingCore/Clock.cpp
C+ SmingCore/DataSourceStream.cpp
C+ SmingCore/Digital.cpp
C+ SmingCore/ESP8266EX.cpp
C+ SmingCore/FileSystem.cpp
C+ SmingCore/HardwareSerial.cpp
C+ SmingCore/Interrupts.cpp
C+ SmingCore/PWM.cpp
C+ SmingCore/SPI.cpp
C+ SmingCore/SystemClock.cpp
C+ SmingCore/Timer.cpp
C+ SmingCore/Wire.cpp
C+ appinit/user_main.cpp
C+ SmingCore/Network/FTPServer.cpp
C+ SmingCore/Network/FTPServerConnection.cpp
C+ SmingCore/Network/HttpClient.cpp
C+ SmingCore/Network/HttpFirmwareUpdate.cpp
C+ SmingCore/Network/HttpRequest.cpp
C+ SmingCore/Network/HttpResponse.cpp
C+ SmingCore/Network/HttpServer.cpp
C+ SmingCore/Network/HttpServerConnection.cpp
C+ SmingCore/Network/MqttClient.cpp
C+ SmingCore/Network/NetUtils.cpp
C+ SmingCore/Network/NtpClient.cpp
C+ SmingCore/Network/TcpClient.cpp
C+ SmingCore/Network/TcpConnection.cpp
C+ SmingCore/Network/TcpServer.cpp
C+ SmingCore/Network/URL.cpp
C+ SmingCore/Network/UdpConnection.cpp
C+ SmingCore/Network/WebSocket.cpp
C+ SmingCore/Platform/AccessPoint.cpp
C+ SmingCore/Platform/Station.cpp
C+ SmingCore/Platform/System.cpp
C+ SmingCore/Platform/WDT.cpp
C+ Services/ArduinoJson/ArduinoJson.cpp
C+ Services/DateTime/DateTime.cpp
C+ Services/WebHelpers/base64.cpp
C+ Services/WebHelpers/escape.cpp
C+ Libraries/Adafruit_GFX/Adafruit_GFX.cpp
C+ Libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp
C+ Libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp
C+ Libraries/Adafruit_SSD1306/Adafruit_SSD1306.cpp
C+ Libraries/BH1750FVI/BH1750FVI.cpp
C+ Libraries/BMP180/BMP180.cpp
C+ Libraries/Bounce/Bounce.cpp
C+ Libraries/DHT/DHT.cpp
C+ Libraries/HMC5883L/HMC5883L.cpp
C+ Libraries/I2Cdev/I2Cdev.cpp
C+ Libraries/LiquidCrystal/FastIO.cpp
C+ Libraries/LiquidCrystal/I2CIO.cpp
C+ Libraries/LiquidCrystal/LCD.cpp
C+ Libraries/LiquidCrystal/LiquidCrystal.cpp
C+ Libraries/LiquidCrystal/LiquidCrystal_I2C.cpp
C+ Libraries/LiquidCrystal/LiquidCrystal_SR.cpp
C+ Libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp
C+ Libraries/LiquidCrystal/LiquidCrystal_SR3W.cpp
C+ Libraries/MMA_7455/MMA_7455.cpp
C+ Libraries/OneWire/OneWire.cpp
C+ Libraries/TFT_ILI9163C/TFT_ILI9163C.cpp
C+ Libraries/Ultrasonic/Ultrasonic.cpp
C+ Libraries/WS2812/WS2812.cpp
AR out/build/app_app.a
Installing libsming
Done

02:59:07 Build Finished (took 31s.598ms)

02:59:07 **** Build of configuration Sming for project Basic_Interrupts ****
make all
make: *** c:/tools/sming/Sming: Invalid request code. Stop.

02:59:07 Build Finished (took 90ms)
 

SamGold

New member
Небольшой баг при компиляции в регистрозависимых системах:

В ./Sming/Services/CommandProcessing/CommandDelegate.h
Заменить [HASHTAG]#include[/HASHTAG] "../Wiring/Wstring.h" на [HASHTAG]#include[/HASHTAG] "../Wiring/WString.h"

В ./Sming/Services/CommandProcessing/CommandDelegate.h
Заменить [HASHTAG]#include[/HASHTAG] "../Wiring/Whashmap.h" на [HASHTAG]#include[/HASHTAG] "../Wiring/WHashMap.h"
 

pvvx

Активный участник сообщества
@anakod - зачем такое выравнивание?
cfg.phys_addr += 0x3000;
Не жалко 12 килобайт?
Устраните ошибку тут:
s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
Замените на:
s32_t *cand_scores = (s32_t *)(fs->work + (((max_candidates * sizeof(spiffs_block_ix) + 3)>>2)<<2));
Причина в получении (256-8)/6 = 41 или нечетного max_candidates от размера fs->block_count и соответственно Fatal exception (9) в строке тут.
И ставьте любые размеры и начальные адреса диска, да размер cfg.log_block_size и cfg.log_page_size...
Да учтите, что реальная скорость работы spiffs при полной "оптимазе" на запись, когда заполнено более половины пространства диска составляет менее 1 килобайта в секунду (при этом он стирает несколько секторов - приближает кончину flash), а открытие файла на большом диске - более нескольких секунд :)
 
Последнее редактирование:
Добрый день!
Возникла проблема при портировании софтинки с ардуино в плане работы со сдвиговыми регистрами через SPI.
Дано: 2х 74hc165 + 2x 74hc595
Включено практически 1-в-1 как на картинке, только кондеров нет и входы входных регистров подтянуты через 11К сопротивления к +VCC (5 | 3.3V).
есть ардуино про мини и модуль на основе esp-07.
есть простой как двери код, который через "ардуиновское" SPI читает-пишет за один SPI.transfer регистры. Так вот на ардуино железо-код работают ожидаемо хорошо. На esp-07 + последний sming + sdk 1.2.0 выходные регистры вроде как нормально работают (те, ктоорые 74hc595), а вот входные (74hc165) как будто сдвинуты на один БИТ (не байт, а именно всего лишь БИТ) влево. в состоянии покоя с входных регистров должно вычитываться два байта едениц (REG0 = 0b11111111 = 255, REG1 = 0b11111111 = 255) при замыкании соотв выхода на землю ноль в соотв. бите меняется на 1. Но на esp-07 в состоянии покоя имеем (REG0 = 0b11111111 = 255, REG1 = 0b11111110 = 254) и соотв вся логика работы как бы "сдвинута на один бит влево" то есть 8 битом второго входного (REG1) регистра мы управляем ПЕРВЫМ битом первого выходного (REG0) регистра, а на 8 бит первого (REG0) регистра нету вообще никкакой реакции)
Кто виноват и что делать? Код идентичный до разницы в "оформлении" на setup + loop vs init & timer task железо рабочее на 100% меняю esp на ардуинку и все ожидаемо пашет. При этом вроде как ВЫХОДНЫЕ регистры отрабатывают без сдвига.. пишешь в них по SPI.transfer два байта и ссответственно устанавливаются выходы регистров. Чего можно докрутить в сминговском SPI чтоб и там работало?

в приложении два файла - код от ардуино и код от esp.


собственно полезная работа по SPI идет в куске
Код:
digitalWrite(reg_in_latch, LOW);
 
  delayMicroseconds(100);
 
  digitalWrite(reg_in_latch, HIGH);
 
  digitalWrite(reg_out_latch, LOW);

  for(int i = 0; i < num_reg; i++)
  {
    in_reg.bytes[i] = SPI.transfer(out_reg.bytes[num_reg - 1 - i]);

    Serial.print("REG-IN"); Serial.print(i);Serial.print(" ");
    Serial.println(in_reg.bytes[i], BIN);
    Serial.print("REG-OUT"); Serial.print(i);Serial.print(" ");
    Serial.println(out_reg.bytes[i], BIN);
  }
  digitalWrite(reg_out_latch, HIGH);
вот как бы так. Повторюсь, код под ардуино давно и исправно работает.

application.txt = esp-07 code
SPI_16ch+tester_from_esp07.txt = код от ардуино, специально "бекпортированый" с кода от esp
 

Вложения

verzi

New member
Да, я думаю Вы правы, наверняка дело именно в этом. А возможно ли отрегулировать мсу без пересборки lwip? Просто т.к. OpwnLWIP похоже больше не поддерживается автором, Sming временно переведен на сборку от Espressif.
Уважаемый Anakod, не подскажете как вернуть обратно OpenLWIP? Просто теперь большие веб странички не отдаются до конца, прям как в Lua :(
 
Уважаемый Anakod, не подскажете как вернуть обратно OpenLWIP? Просто теперь большие веб странички не отдаются до конца, прям как в Lua :(
Буду рад ошибаться, но ИМХО пока выход только менять liblwip.a на liblwip_536.a которая рядом лежит. Но с той либой с угребным мту тож проблемы.. странички вроде начинают отдаваться, но вот POST в хроме отваливается... в общем все не по-людски :(
 
Последнее редактирование:

verzi

New member
Буду рад ошибаться, но ИМХО пока выход только менять kb,e liblwip.a на liblwip_536.a которая рядом лежит. Но с той либой с угребным мту тож проблемы.. странички вроде начинают отдаваться, но вот POST в хроме отваливается... в общем все не по-людски :(
Сделал как Вы сказали. Вроде помогло, страницы грузятся до конца, но потом случилось это. 1.png
Раньше, когда версия SDK только перевалила за единичку, я кажется просто менял в make файле lwip на openlwip и все работало. Но теперь это не помогает, впрочем как и использование старых версий SDK.

Поторопился я. Выяснилось что этот злосчастный network.html просто не залился в esp с первого раза (у меня такое постоянно случается). Исправил, но он все равно не до конца загружается. Хотя в общем с этой библиотекой все бодрее работает.
 
Последнее редактирование:

verzi

New member
Разобрался. Хотя лучше сказать вернул все как было. Версия SDK 1.0.1_b1_15_04_02. Sming тоже старый. Файлы в SmingCore датированы 15.05.2015. В make файле у меня прописан openlwip. И все снова заработало. Ощущения такие что на другой стороне не копеечная esp а нормальный сервак. Страницы открывает просто мгновенно, хотя у меня там и css и js и картинка на 90кб. С тем что сейчас просто не сравнимо, даже без учета глюков. Может быть стоит вернуться к старому SDK в котором китайцы еще не все успели сломать?
 

pvvx

Активный участник сообщества
Уважаемый Anakod, не подскажете как вернуть обратно OpenLWIP? Просто теперь большие веб странички не отдаются до конца, прям как в Lua :(
Передавайте пакеты с ограничением по длине (не по 1460 байт, а к примеру по 1400, но поставьте tcp_nagle_disable(pcb)) и всё будет пучком.
Общий алго самой скоростной TCP передачи на ESP8266 описан.
MTU (MSS=1460) не лезет только в случае если линия инет идет через кривых российских GSM провайдеров... :) Тогда проще пересобрать LwIP с опцией mss к примеру в 1420.
Мой OpenLwIP 1.4.0 работает на SDK 1.3.0.
Даже есть максимально Open на базе SDK 1.3.0 - meSDK https://github.com/pvvx/MinEspSDKLib, но 100% не тестирован на все случаи жизни... :)
 
Последнее редактирование:

verzi

New member
pvvx Вы очень круты, я думаю что всем кто читает данный форум это понятно. Но представьте на секунду что не все такие же продвинутые как Вы. Я попробую переформулировать свой вопрос. Дано: SDK 1.2, последний sming. Где именно писать это tcp_nagle_disable(pcb))? Что еще подправить для того что бы странички отдавались до конца? И у меня обычный провайдер, не GSM. И вообще я обращаюсь к esp с соседнено компа который в одной локальной сети.
 

pvvx

Активный участник сообщества
tcp_nagle_disable в Sming должен быть уже включен:
https://github.com/anakod/Sming/blob/master/Sming/SmingCore/Network/TcpConnection.cpp#L234

По локальной сети подобных проблем я не наблюдал никогда, поэтому это довольно странно.
Странно у российских GSM провайдеров (используют какое-то древнее оборудование, даже на новых протоколах). Попробуйте передать полные пакеты с mss по умолчанию на телефон или другой комп с GSM :)
В инет пишут, что данная проблема в других странах давно решена... путем увеличения MTU.
У нас вроде MTU = TCP_MSS + 40 = 1460 + 40 = 1500. При этом не работает.
Для наших GSM надо минус 40 (с MSS=1420 проверял - работает).
 
Последнее редактирование:

LuckyFIA

New member
По поводу Transfer-Encoding:chunked

я слегка подправил вариант предложенный Alexander V. Ribchansky
Код:
int TcpConnection::write(IDataSourceStream* stream, bool chunked)
{
// Send data from DataStream
    bool repeat;
    bool space;
    int available;
    int total = 0;
    char buffer[NETWORK_SEND_BUFFER_SIZE];

    do
    {
        space = (tcp_sndqueuelen(tcp) < TCP_SND_QUEUELEN);
        if (!space)
        {
            debugf("WAIT FOR FREE SPACE");
            flush();
            break; // don't try to send buffers if no free space available
        }

        // Join small fragments
        int pushCount = 0;
        do
        {
            pushCount++;
            int read = min(NETWORK_SEND_BUFFER_SIZE, getAvailableWriteSize());
            if(chunked)    read -= 7;

            if (read > 0)
                available = stream->readMemoryBlock(buffer, read);
            else
                available = 0;

            if (available > 0)
            {
                if (chunked)
                {
                    char cbuf[6];
                    unsigned int len = os_sprintf(cbuf,"%X\r\n", available);
                    write(cbuf, len, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
                }

                int written = write(buffer, available, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);

                if (chunked)
                {
                    write("\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
                }

                total += written;
                stream->seek(max(written, 0));
                repeat = written == available && !stream->isFinished() && pushCount < 25;
            }
            else
                repeat = false;
        } while (repeat);

        space = (tcp_sndqueuelen(tcp) < TCP_SND_QUEUELEN);// && tcp_sndbuf(tcp) >= FILE_STREAM_BUFFER_SIZE;
    } while (repeat && space);

    if (chunked && stream->isFinished())
        write("0\r\n\r\n", 5, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);

    flush();
    return total;
}

и увеличил NETWORK_SEND_BUFFER_SIZE до 2*MSS
Результатом вполне доволен, в локалке работает отлично.
 
Сверху Снизу