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

Общие вопросы, пожелания

valeraba

Moderator
Команда форума
Внимание, сайт переехал на новый домен mgt24.ru

Вводная информация.

Этот конструктор предназначен для создания панелей управления с их последующим встраиванием на собственные сайты. Хорошо подходит для реализации проектов, где требуется управление устройствами в реальном времени. Если вся система будет находиться в локальной сети, время отклика составит несколько десятков миллисекунд. При удалённом управлении через интернет, время отклика сильно зависит от провайдера, но как правило это будут доли секунды. Транспортный протокол включает в себя авторизацию, поточное шифрование, проверку целостности пакетов. Все данные по сети передаются в бинарном виде, в максимально упакованной форме.

Принцип взаимодействия веб-страницы и ESP8266.
Веб-приложение через веб-сокет подключается к посреднику.
ESP8266 через Wi-Fi подключается к посреднику.
В качестве посредника выступает консольная программа запущенная на Windows машине (MgtBroker.exe).

Отмечу, что такое взаимодействие имеет много общего с популярным протоколом MQTT. Но есть некоторые моменты, которые не позволили мне применить этот стандарт в своей реализации.
1) Необходимость шифрования данных при ограниченных ресурсах платформы.
2) Возможность передавать непрерывные потоки данных (звуковой поток).
3) Возможность передавать большие файлы (изображения, видеофайлы).
4) Нужна была регистрация данных.
То есть основной акцент был направлен на создание универсального транспортного протокола для платформ с малыми ресурсами (4кб оперативной памяти). А встроенный модуль регистрации позволил бы применить более простые схемы взаимодействия (ESP8266, программа посредника, web-браузер).

Регистрация данных.
Основные моменты в текущей реализации.
1) Способность сохранять как числовые и строковые параметры, так и JPEG изображения.
2) Данные хранятся в сжатом виде, экономя дисковое пространство.
3) Время каждой записи хранится в миллисекундах.
4) Простое javascript API для работы с хранилищем данных.
Если система запускается в автономном режиме, то кроме программы MgtBroker.exe на компьютере должна быть запущена база данных MongoDB.


Инструкции.
Вся разработка программы для устройства, сведётся к тому, что нужно будет модифицировать уже готовую программу под конкретную прикладную задачу. Шаблон этой программы, предоставляется в виде скетча, он будет несколько избыточен, так как рассчитан для разных целевых платформ (ESP8266, Arduino, Windows, FreeBSD).

Среда разработки Arduino IDE для ESP8266, язык разработки C++.
Общее описание http://esp8266.ru/arduino-ide-esp8266/
Способ установки http://esp8266.ru/forum/threads/obschie-voprosy-po-arduino-ide-dlja-esp8266.224/

В качестве простейшей инструкции по созданию веб-панелей, можно использовать мою статью Создаём свой сайт для управления Ардуиной
Здесь ознакомительная статья о сервисе Удалённое управление для Arduino, проба пера
Как работать с регистратором http://geektimes.ru/post/272694/
//Здесь демонстрация работы модуля ESP8266 (к нему подключены три светодиода и один датчик //температуры) This domain is for sale!

Текущие недостатки и планы на будущее.

Проект на этапе бета-тестирования.

Примечания.
Проект в поиске своего конечного облика, и то, каким он может быть, зависит и от пожеланий пользователей.
 
Последнее редактирование:

valeraba

Moderator
Команда форума
можна ли обеденить несколько esp8266 в mesh сеть?
Нет, в моей реализации все сообщения проходят только через посредника. Да и то, мне ещё нужно дописать транспортную библиотечку, чтобы устройство не только выставляло бы наружу свои параметры, но и могло бы привязаться к чужим. Если это потребуется, то я сделаю этот функционал.
 

pvvx

Активный участник сообщества
Веб-страница через веб-сокеты подключается к посреднику.
Веб-сокет очень просто реализуется на ESP8266.
ESP8266 через Wi-Fi подключается к посреднику.
В качестве посредника выступает консольная программа запущенная на Windows машине (standalone.exe).
Т.е. посредник требует много ресурсов и его не реализовать на стандартном дешевом роутере за ~600 рупь с OpenWRT?
1) Необходимость шифрования данных при ограниченных ресурсах платформы.
Шифрование данных во внешнюю сеть должен осуществлять роутер на OpenWRT, к которому подключаются модули. На модулях устанавливается ограничение мощности передачи и их протоколы идут в нестандартных форматах, которые сложно декодировать как и любую современную шифрацию (т.е. требуется столько-же времени на "вскрытие").
2) Возможность передавать непрерывные потоки данных (звуковой поток).
ESP8266 запросто передает/принимает 1 мегобайт в секунду по TCP.
3) Возможность передавать большие файлы (изображения, видеофайлы).
Если роутер меснтный, как и описано выше - то никаких сложностей не возникает. Роутер с OpenWRT держит буфер для малого местного клиента в несколько мегабайт для каждого потока запросто - у него обычно памяти от 64 мегобайта...
То есть основной акцент был направлен на создание универсального транспортного протокола для платформ с малыми ресурсами (кроме совсем маленьких, как Arduino Uno с 2кб оперативной памяти).
В распределенной по уровням защиты и ресурсами сети (множество мелких клиентов <-> роутер-мамка [<-> другая группа с роутером-мамкой]<-> глобальная сеть <-> внешний ресурс отображения и ...) кодированием/переводом протоколов занимается "роутер-мамка". На ней и происходит зашита внутренней сети и разграничение разрешенных внешних запросов и она должна предоставлять логирование, настройку внутренних подключений (только от внутренних местных запросов) и прочую статистическую информацию (на то у всех дешевых роутеров есть возможность подключения USB-диска/флешки) и обеспечивать полную обработку в случае нарушения внешнего доступа. В такой структуре всё равно на сколько времени "засыпает" клиент - роутер-мамка держит и предоставляет его актуальные данные всегда и они не теряются, как в случае с вашей системой при временном отказе внешней сети... Пока ваш проект от этой картины уходит и не позволяет создавать обычную распределенную иерархическую систему... и не будет востребован. Нет никакого смысла каждому мелкому клиенту иметь ресурсы с шифрацией и прочими защитами для связи через глобальную сеть инет. Ни один из имеющихся на сегодня проектов на ESP8266 не готов к работе напрямую через глобальную сеть инет. Им необходим хоть брандмауэр и прочие защиты... А нафига им они, если в большинстве случаев связь всё равно идет через тот-же роутер, на который можно и нужно поставить ПО для обеспечения таких сетей. И оно скоро будет - глобальные корпорации уже его готовят и в скором встроят в каждый роутер хоть для концепции "умного дома"...
Необходима сборка ПО на стандартные роутеры... Если оно "выростет", то сможет повлиять на развитие системы в дальнейшем, а не оставаться только на поводу у корпораций и чисто коммерческих систем клиент<->внешний сервер созданных, как и ваш проект (пока вы готовите им инструмент) для дальнейшего обдирания народу путем привязке к внешнему серверу :).
 
Последнее редактирование:

valeraba

Moderator
Команда форума
Веб-сокет очень просто реализуется на ESP8266.
К посреднику можно связываться либо через веб-сокеты либо через TCP сокеты. Я сделал как проще.
Т.е. посредник требует много ресурсов и его не реализовать на стандартном дешевом роутере за ~600 рупь с OpenWRT?
Программа посредника для windows 124кБ, просто у меня нет версии под linux.
Шифрование данных во внешнюю сеть должен осуществлять роутер на OpenWRT, к которому подключаются модули. На модулях устанавливается ограничение мощности передачи и их протоколы идут в нестандартных форматах, которые сложно декодировать как и любую современную шифрацию (т.е. требуется столько-же времени на "вскрытие").
Для домашней сети OpenWRT хороший подход.
Нет никакого смысла каждому мелкому клиенту иметь ресурсы с шифрацией и прочими защитами для связи через глобальную сеть инет.
Не знаю, просто техническая возможность была, я это и реализовал.
Ни один из имеющихся на сегодня проектов на ESP8266 не готов к работе напрямую через глобальную сеть инет.
Наверное это так, и моя реализация является первым таким случаем.
Необходима сборка ПО на стандартные роутеры...
Это серебренная пуля?

В целом, вы правы, чего-то не хватает моему проекту, буду переосмысливать.
 

pvvx

Активный участник сообщества
@valeraba : "Здесь ознакомительная статья о сервисе http://habrahabr.ru/post/251589/"
- Стандартный SCADA и OPC-сервер скоро заработают с EPS8266... "сетевой бридж Modbus TCP" в качестве ESP8266. К нему можно будет подключать стандартные исполнительные устройства и всё что работает через Modbus RTU c RS-485... Внешнее шифрование можно обеспечить через включение на роутере VPN...
Простейший клиент Modbus TCP уже встроен в Web-свалку, но не 'размаплен' - не назначено в таблице адресов modbus что делать и какие переменные куда (т.к. это базовый пример).
 
Последнее редактирование:

valeraba

Moderator
Команда форума
Стандартный SCADA и OPC-сервер скоро заработают с EPS8266... "сетевой бридж Modbus TCP" в качестве ESP8266.
У вас интересные проекты. Подскажите пожалуйста, как повысить скорость передачи данных от esp8266 во внешний мир.
У меня такая ситуация, я использую библиотечный WiFiClient. Когда в "loop()" я вызываю функцию "write" для отправки очередной порции данных, происходит блокирование на достаточно длительное время. В итоге скорость передачи по WiFi много меньше скорости UART на 115200. И отправка данных большими порциями ситуацию не спасает. Одним словом, вызов функции "write" библиотечного WiFiClient стопорит работу всей программы.
Вы же говорите об 1 МБайт в секунду. Что я делаю не так?
 

pvvx

Активный участник сообщества
Вы же говорите об 1 МБайт в секунду.
Отключите опцию NAGLE в LwIP -> tcp_nagle_disable(pcb) и предоставляйте данные для отправки LwIP в кол-ве 2-х полных пакетов (2*MSS).
Размер передаваемого "куска" перед передачей LwIP-у узнается через pcb->snd_buf (больше он всё равно не сожрет в данный промежуток времени). При нормальной последовательности передачи там всегда свободно 2*MSS - вот такими кусками и давайте ему данные для передачи.
Тогда Chrome принимает сразу 2 пакета и отправляет на них один ACK. Иначе он будет выдерживать задержку до отправки ACK (TCP, подтверждение приема). На Explorer это не влияет - он не делает задержки перед передачей ACK.
Что я делаю не так?
- "использую библиотечный WiFiClient. "
В ардуино и прочих "либах" доступа к pcb и задачи параметров практически нет. Не используйте их или пишите их авторам, чтобы устранили глупые опции заданные LwIP китацами и сменили алгоритмы.
Эти либы написаны чтобы мигать одним светодиодом и имеют паузы в сотни ms, перед отправкой пару байт раз в несколько минут. Они всегда закрывают соединение первыми, вызывая на себя TIME_WAIT (условие хранения ещё 60..120 секунд структуры pcb, приводящее к кончине "heap" при частых TCP соединениях).

В итоге алго прост:
1) По соединению ставите tcp_nagle_disable(pcb)
2) Смотрите сколько можно передать байт по переменной u16_t snd_buf; /* Available buffer space for sending (in bytes). */ в struct tcp_pcb LwIP и даете ему их на передачу (передачу можно даже не проверять, т.к. LwIP сожрет указанное число байт на 100% если есть свободный "heap"). И так в цикле, если у вас многозадачка или SDK работает в другом потоке. Если у вас кусок данных меньше, чем указано snd_buf, то передаете меньше за раз. LwIP всё сам разрулит - мешать ему не надо какими-то кривыми насадками-либами :).
3) Если у вас WEB сервер, то формируете правильные заголовки, чтобы клиент первым закрывал соединение и выдерживаете паузу (к примеру в 5 сек) до принудительного закрытия соединения (можно даже обрыва соединения c удалением pcb, если клиент нарушает протокол).
 
Последнее редактирование:

valeraba

Moderator
Команда форума
Я использую Arduino IDE для ESP8266. Я отключал NAGLE, но это не помогает, впрочем это и не должно помочь (ведь скорость реакции не важна, важен общий размер трафика). У меня esp8266 является клиентом и открывает соединение с удалённым сервером (esp8266 никогда не отсоединяется от сервера). Через UART небольшими порциями esp8266 выкачивает изображения с JPEG камеры и тут же отправляет по WiFi на сервер. И каждый раз, при отправке очередного куска изображения, функция "write" очень долго исполняется. Когда я использую обычную ардуинку(Atmega) и ethernet shield, то 30кб фотки отправляются на сервер за 3 секунды. В тоже время, esp8266 на отправку одной фотки тратит несколько минут. То есть, мой случай самый что ни на есть тривиальный, но такие жуткие тормоза, как такое возможно. Может функцию "write" из WiFiClient не следует использовать?
 

pvvx

Активный участник сообщества
Я использую Arduino IDE для ESP8266. Я отключал NAGLE, но это не помогает, впрочем это и не должно помочь (ведь скорость реакции не важна, важен общий размер трафика).
Важна.
Помочь c Arduino IDE не могу. Я его не использую, т.к. не вижу в нем смысла, кроме ловли доп. багов.
Единственная беда с UART в том, что он жрет ресурсы CPU (падает общая производительность модуля). Как итог, добиться работы приема/передачи TCP (в режиме полудуплекса непрерывным потоком) сильно выше 3 мегабита через UART не удается. Но у вас 115200 :)
Связано с частыми обращениями в драйвере UART к регистрам UART находящемся на низкоскоростной шине. Fifo у неё всего на 8 обращений и на 8 записей в регистры уже fifo UART или чтения его состояния тратятся несколько сотен тактов CPU ESP8266 на 160 Mhz, а DMA для UART не открыто китайцами (его может и нет для UART, но для SPI и I2S есть).
Спрашивайте у anakod, может он исправит ситуацию с TCP в sming. А то данный вопрос уже часто всплывает...
 
Последнее редактирование:

valeraba

Moderator
Команда форума
Понял вас. Можете тогда дать ссылку на проект самого простейшего TCP/IP клиента? Я как понимаю, нужно использовать SDK от производителя.
 

pvvx

Активный участник сообщества
Понял вас. Можете тогда дать ссылку на проект самого простейшего TCP/IP клиента (Web клиента) ? Я как понимаю, нужно использовать SDK от производителя.
Ситуация то сложная. Надо досконально знать и оперировать UART по прерываниям. Простого примера с UART нет. Задачи слишком разные...
А прием по TCP в низко-скоростное устройство требует оперировать "Окном TCP", чтобы передающий не перелил выше возможности буферизации в модуле...
В итоге TCP2UART и выходит монстром...
 
Последнее редактирование:

valeraba

Moderator
Команда форума
Вот-вот, а в Arduino IDE это "Serial.begin(115200);" и все дела.
Но я же попросил пример TCP/IP клиента а не UART, или в SDK вообще нет примера работы с UART, я правильно понял?
 

pvvx

Активный участник сообщества
Вот-вот, а в Arduino IDE это "Serial.begin(115200);" и все дела.
Но я же попросил пример TCP/IP клиента а не UART, или в SDK вообще нет примера работы с UART, я правильно понял?
serialEvent() то нету. Опрашивать в цикле - плохой тон. Тем более Arduino IDE не RTOS.
Нужен обычный автомат, работающий по событиям.
Принялcя буфер UART - сработало событие, обработали если надо и передали данные в TCP стек. И это практически всё. :)
 
Последнее редактирование:

valeraba

Moderator
Команда форума
Нашёл обсуждение этой проблемы, люди даже сделали костыль и получили хороший результат, но в официальные исходники эта правка не вошла, так как костыль чреват вызвать другие проблемы.
http://www.esp8266.com/viewtopic.php?f=28&t=2672
Наверняка вы лучше поймёте, о чём там говориться.
Вот текущий код функции, которая вызывает длительные задержки:
Код:
size_t write(const char* data, size_t size) {
            if(!_pcb) {
                DEBUGV(":wr !_pcb\r\n");
                return 0;
            }

            if(size == 0) {
                return 0;
            }

            size_t room = tcp_sndbuf(_pcb);
            size_t will_send = (room < size) ? room : size;
            err_t err = tcp_write(_pcb, data, will_send, 0);
            if(err != ERR_OK) {
                DEBUGV(":wr !ERR_OK\r\n");
                return 0;
            }

            _size_sent = will_send;
            DEBUGV(":wr\r\n");
            tcp_output( _pcb );
            _send_waiting = true;
            delay(5000); // max send timeout   /* люди убирали эту строчку, хотя это не корректно, но проблема решалась (сегодня вечером я тоже попробую это сделать) */
            _send_waiting = false;
            DEBUGV(":ww\r\n");
            return will_send - _size_sent;
}
 

pvvx

Активный участник сообщества
Нашёл обсуждение этой проблемы, люди даже сделали костыль и получили хороший результат, но в официальные исходники эта правка не вошла, так как костыль чреват вызвать другие проблемы.
По общим прикидкам вызовет другие проблемы (не ясна реализация многозадчки... пока исполняется пользовательский код, сколько времени отдается на процессы SDK/WiFi?)
Не ясно одно - что так сложно проверить pcb->snd_buf (оно-же макрос tcp_sndbuf(_pcb)) и понять что можно уже ещё передавать? Горе ардуинописатели :)

В цикле приема данных с UART или при передаче файла, опрашиваете pcb->snd_buf, и если 1) набрали с UART столько-же символов, то передаете их 2) если вышло время ожидания набора буфера отправки, но ещё не набрано pcb->snd_buf, то передаете то, что есть (если не нуль). Но обязательно, сразу при TCP соединении выключаете nagle.

Вчера копал Lua (правил немного куски net. модуля NodeMCU) - процесс открытия, передачи сотни байт, закрытие TCP в EspLua.ru занимает ~ 250 ms на Lua, а трансфер в уже открытом ТСP соединении зависит исключительно от куда берутся данные для передачи (Lua и особенно файловая система SPIFFS = ужасный тормоз). При этом в Lua-подобных используется ещё espconn от китайцев, но и они сделали отключение nagle в espconn_set_opt()...
 
Последнее редактирование:

valeraba

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

valeraba

Moderator
Команда форума
Добавил регистрацию данных, теперь подключаемое устройство может сохранять свои текущие значения в базу данных.
При запуске системы в автономном режиме можно сохранять до сотни тысяч значений в секунду, вся записанная информация будет хранится в сжатом виде.
Для каждого регистрируемого параметра можно настроить собственное прореживание, чтобы ограничить объём сохраняемой информации.
 
Сверху Снизу