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

Нужна помощь Хранение картинки в ESP для cnhfybws web servera

Tantra

New member
Здравствуйте уважаемые форумчане.
Видит Бог, искал, но не нашел, так что прошу сильно не пинать.
Вопрос такой. Как хранить картинку в ESP так, что бы можно было ее вставить в HTML страничку, когда ESP работает в режиме web servera?
т.е. <img src="? картинка ?">
Варианты - держать картинку на web ресурсе не подходят, нужно хранить ее именно на ESP .
И второе, работу с файловой системой хотелось бы избежать.
 

Сергей_Ф

Moderator
Команда форума
@Tantra либо крестик снять, либо трусы надеть. Либо файл в файловой системе, либо base64 - вроде ничего другого не придумали.
 

Алексей.

Active member
И второе, работу с файловой системой хотелось бы избежать.
храните в массиве байтов, используйте директивы progmem,
картинки (которые в прошивке в ввиде массива байтов) отправляю броузеру, не раздувая их в base64.
в теге img как обычно устанавливаем атрибут src и броузер методом get запрашивает картинку, я в заголовке ответа устанавливаю соответствующий тип и отгружаю контент без каких либо преобразований на есп.
 

Алексей.

Active member
andrik_zp,
Пример получения данных погоды с openweathermap, там статика от веб морды уже конвертнутая в код в файле memcontent.h чем отправляется смотрим WebIface.cpp, там где обработчик server.onNotFound, ну а преобразование статики в memcontent.h на лету - скрипт prebuild.

п.с.
Собирал на ардуине 1.8.5 с пакетом "esp8266 by ESP8266 Community" версия 2.4.1
Проверял на ноде мсу и есп-01, броузер хром фф эдж.
 

Сергей_Ф

Moderator
Команда форума
@Алексей. Вы на каждую картинку обработчик запроса вешаете или как то изящнее вопрос множества картинок решаете? Из приведенного примера не понял.
 

Алексей.

Active member
Сергей_Ф,
Всё проще, точнее совсем просто.
Перед билдом я скриптом конвертирую файлы в си-шный код, если есть смысл жать, то и пережимаю gzip-ом
в результате получаю кучу массивов байтов и массив описателей
Код:
static unsigned char _index_html[] PROGMEM = {..}
static unsigned char _404_html[] PROGMEM = {..}
static unsigned char _favicon_ico[] PROGMEM = {..}
static unsigned char _jquery_2_2_4_min_js[] PROGMEM = {..}
static unsigned char _bootstrap_min_js[] PROGMEM = {..}
static unsigned char _blank_png[] PROGMEM = {..}
static unsigned char _01d_png[] PROGMEM = {..}
static unsigned char _02d_png[] PROGMEM = {..}

struct content_info {char* uri; char* dataType; char* content; size_t size; int gzip;};
static struct content_info _ci[8] = {
  {"/index.html", "text/html", (char*)_index_html, sizeof(_index_html), 1},
  {"/404.html", "text/html", (char*)_404_html, sizeof(_404_html), 0},
  {"/favicon.ico", "image/x-icon", (char*)_favicon_ico, sizeof(_favicon_ico), 0},
  {"/jquery-2.2.4.min.js", "application/javascript", (char*)_jquery_2_2_4_min_js, sizeof(_jquery_2_2_4_min_js), 1},
  {"/bootstrap.min.js", "application/javascript", (char*)_bootstrap_min_js, sizeof(_bootstrap_min_js), 1},
  {"/blank.png", "image/x-icon", (char*)_blank_png, sizeof(_blank_png), 0},
  {"/01d.png", "image/x-icon", (char*)_01d_png, sizeof(_01d_png), 1},
  {"/02d.png", "image/x-icon", (char*)_02d_png, sizeof(_02d_png), 1}
};
Нулевой элемент - корневой контент, первый элемент - контент возвращаемый для кода 404, всё остальное - контент который может быть запрошен со страниц.
В обработчике server.onNotFound если запрошен корень - возвращаем в контенте _ci[0].content длиной _ci[0].size
иначе ищем запрошенный ресурс в _ci
Код:
for (n = 0; n < sizeof(_ci) / sizeof(_ci[0]) && i == 0; n++) {
  if (this->server.uri().endsWith(_ci[n].uri)) {
    i = &_ci[n];
  }
}
если не нашли - возвращаем в контенте _ci[1].content длиной _ci[1].size
ну а если нашли то возвращаем то что найдено :)
 

Сергей_Ф

Moderator
Команда форума
@Алексей. фактически, сделали аналог простейшей файловой системы с фиксированным набором файлов :)

честно говоря, не понял условия [inline]n < sizeof(_ci) / sizeof(_ci[0])[/inline]
получается вы сравниваете индекс с размером структуры, деленным на размер нулевого элемента ? Зачем?
вроде надо сравнивать с конечным индексом[inline] len(_ci)[/inline], нет?
И как вы выходите из цикла, когда элемент найден? Или обработку внутри него делаете?​
 
Последнее редактирование:

Алексей.

Active member
Сергей_Ф,
Пока загрузишь на этот spiffs сотню кило, заснуть можно, а тут всё в памяти уже.
Именно скорость загрузки была причиной переноса файлов в код.
 

Сергей_Ф

Moderator
Команда форума
Сергей_Ф,
Пока загрузишь на этот spiffs сотню кило, заснуть можно, а тут всё в памяти уже.
Именно скорость загрузки была причиной переноса файлов в код.
это точно.
Вот бы ещё это всё оформить библиотекой - цены бы не было.
я там выше вопросы накидал, если не сложно - объясните чайнику.
 

Алексей.

Active member
Вот бы ещё это всё оформить библиотекой - цены бы не было.
Библиотека для трех строчек кода? Излишество.
Большую часть времени заняло подключение своего скрипта к "Скетч->Проверить/Компилировать" ардуино иде.
Документации мало, такое впечатление, что никому это не интересно.
 

Сергей_Ф

Moderator
Команда форума
Библиотека для трех строчек кода? Излишество.
позвольте возразить. Во-первых, "чайникам" труднее сделать ошибку, во-вторых, можно будет оперативно сделать добавление очередного элемента для загрузки, типа [inline]progmem_fs.add("/my_pic.png", _my_pic_png, GZIP_ON)[/inline]
 

Алексей.

Active member
Про добавлять тут я немножко не понял, лежат файлы себе в папочке, нажали кнопку "Проверить/Компилировать" - они уже в прошивке, в progmem (области данных если хотите), spiffs тут совсем ни причем. Куда добавлять то? В прошивку по живому?
Если нужна супер оперативность то проще вынести файлы связанные с http в отдельную папку и поправить скрипт, чтоб всю эту помойку конвертировал в код.

И если уж говорить об установке библиотек, подскажите как в процессе установки, определить версию пакета "esp8266 by ESP8266 Community" и запустить установочный скрипт который обработает platform.local.txt если он создан или создаст его.

П.С.
Забыл про версию смой ide, её тоже нужно знать в процессе установки.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
Добавлять не файлы, а обработчик этого файла в код. Файлы, естественно надо будет готовить вашим скриптом, как и раньше.
Просто перенесем формирование структуры с данными в библиотеку и немного упростим добавление элементов.
Конечно, никто вас не заставляет делать библиотеку, просто высказываю мысли почему так будет удобнее на мой взгляд.
Если нужна супер оперативность то проще вынести файлы связанные с http в отдельную папку и поправить скрипт, чтоб всю эту помойку конвертировал в код.
Хм. Тоже вариант.

По поводу установки библиотек не подскажу, не знаю.
Вы наверное не заметили пару вопросов, если не трудно поясните
честно говоря, не понял условия n < sizeof(_ci) / sizeof(_ci[0])
получается вы сравниваете индекс с размером структуры, деленным на размер нулевого элемента ? Зачем?
вроде надо сравнивать с длинной массива len(_ci), нет?
И как вы выходите из цикла, когда элемент найден? Или обработку внутри него делаете?
 
Последнее редактирование:

Алексей.

Active member
Сергей_Ф, Прощу прощения, упустил
честно говоря, не понял условия n < sizeof(_ci) / sizeof(_ci[0])
получается вы сравниваете индекс с размером структуры, деленным на размер нулевого элемента ? Зачем?
сравниваю n с количеством элементов массива структур
например структура содержит два указателя void*, на 32-х битной архитектуре размер структуры равен 8 (опустим всякие прагма-паки и т.п.), размер массива структур предположим 256 байт, рассчитаем количество элементов в массиве 256 / 8 = 32

И как вы выходите из цикла, когда элемент найден? Или обработку внутри него делаете?
Перед циклом потерялся
struct content_info* i = 0;
for (n = 0; n < sizeof(_ci) / sizeof(_ci[0]) && i == 0; n++) {
если нашли ресурс - прекращаем цикл

По поводу установки библиотек не подскажу, не знаю.
И я не знаю, получается давайте сделаем то, пока не знаю что. Вернее не знаю как.
 

Сергей_Ф

Moderator
Команда форума
сравниваю n с количеством элементов массива структур
понял, но всё же проще будет[inline] len(_cli)[/inline] или, как у вас, но корректнее/нагляднее [inline]sizeof(_ci) / sizeof(content_info)[/inline]. Если не ошибаюсь, компилятор в этом случае даже сделает предварительные вычисления и подставит в сравнение уже константу.

Перед циклом потерялся
struct content_info* i = 0;
теперь понял :)
 

Сергей_Ф

Moderator
Команда форума
подскажите как в процессе установки, определить версию пакета "esp8266 by ESP8266 Community"
версию смой ide, её тоже нужно знать в процессе установки
а точно нужно знать в процессе установки? Вроде обычно это возлагается на препроцессор при компиляции?
 

Алексей.

Active member
а точно нужно знать в процессе установки? Вроде обычно это возлагается на препроцессор при компиляции?
Какой препроцессор?
Если вы знаете как при выполнении "Проверить/Компилировать" выполнить скрипт (или какое то приложение) передав ему путь к проекту (к директории со скетчем) и не плохо ещё путь ко временной директории которую создает ide, подскажите как?
Основная задача - преобразовать статику в код, а обработка этого кода умещается в несколько строк.
Мне как раз и нужно знать при установки библиотек, куда сохранять platform.local.txt
Писать инструкцию - пойдите туда, скопируйте то, сделайте исполняемым это и т.д. - не прокатит. Установка должна быть исчерпывающей, чтоб вопросов не возникало.
 
Сверху Снизу