Веб-сервер на базе модуля Wiznet W5100S-EVB-Pico. Часть 1. Знакомство с HTML, CSS и JavaScript
17 Февраль, 2022
- Wiznet
- Ethernet
- Перспективные Ethernet-мосты Wiznet и модули на их базе
- Микроконтроллеры W7500 и W7500p с аппаратным блоком Ethernet и модули на их базе
- Ethernet-модули Wiznet для платформы Raspberry Pi RP2040
Веб-сервер на базе модуля Wiznet W5100S-EVB-Pico.
Часть 1. Знакомство с HTML, CSS и JavaScript
Сергей Долгушин, dsa@efo.ru
Продолжаем знакомиться с новым модулем Wiznet W5100S-EVB-PICO на базе микроконтроллера Raspberry Pi RP2040 и Ethernet-моста Wiznet W5100S. Темой статьи будет пример реализации веб-сервера. Мы пока рассмотрим базовые основы, необходимые для начала работы. Данная публикация рассчитана на тех разработчиков, кто еще не знаком с HTML, CSS и JS, но рассматривает возможность использования в своих изделиях веб-интерфейса.
Современные возможности HTML, CSS и JavaScript (JS) дают очень интересные возможности для реализации интерфейса для встраиваемых устройств тем, кто уже использует решения компании Wiznet на уровне передачи по TCP/IP, но хотел бы познакомиться и с другими возможностями, которые предлагает компания Wiznet. В частности, речь идет о библиотеках WIZnet к своим Ethernet-мостам и микроконтроллерам W7500/W7500P.
Библиотека Wiznet для реализации HTTP-сервера, с которой мы предлагаем познакомиться далее, представляет собой готовый базовый проект. В него достаточно добавить свои обработчики и базовые HTML-страницы, чтобы получить полностью рабочий веб-интерфейс. Эта библиотека входит и в состав примеров для работы с новым недорогим модулем W5100S-EVB-PICO, а сам модуль интересен своим двухъядерным микроконтроллером (МК) RP2040. Для приложения, в котором присутствует веб-сервер, два ядра МК могут дать дополнительные преимущества. Например, на одном можно запустить веб-сервер, а на другом - прикладные задачи. В предыдущей статье "Новый модуль Wiznet W5100S-EVB-Pico – Raspberry Pi Pico с аппаратной поддержкой Ethernet" мы начинали рассказ о данном модуле, в этой статье продолжим использовать его в качестве тестовой платформы. Все, что мы расскажем далее, будет применимо и к реализации веб-сервера на базе контроллера W7500/7500P, а также при использовании других мостов Wiznet.
Рис.1 Модуль Wiznet W5100S-EVB-PICO
Веб-сервер, в общем виде, это некое устройство, принимающее HTTP-запросы от клиентов и выдающее им HTTP-ответы. Клиентом в повседневной жизни, чаще всего, является веб-браузер, а HTTP-ответом является HTML-страница.
В рамках встраиваемых приложений веб-сервер может служить для решения ряда полезных задач. Например, для удаленного управления устройством, получения от него информации о состоянии и т.п., выбора и настройки режимов работы. Кроме этого, можно предоставлять пользователю вызов подсказок по режимам работы и любой другой информации в удобном для восприятия виде. При этом есть возможность реализовать современный графический интерфейс без добавления в проект дисплеев, сенсорных панелей и т.п. Графический интерфейс будет отображаться на экране клиентского устройства, смартфона, ноутбука и т.п. В ряде случаев такой подход к реализации графического интерфейса может оказаться проще в реализации, чем добавление дисплея с сенсорной панелью в изделие.
Одним из важных плюсов веб-интерфейса является его кросс-платформенность. Он в меньшей степени зависит от того, какое и чье “железо” находится на клиентской стороне, и какая ОС установлена на данном “железе”. Пользователь может управлять устройством с компьютера или смартфона, а из специализированного ПО ему необходим только веб-браузер. Современный инструментарий, который предоставляет разработчику HTML и CSS, позволяет реализовать масштабируемую веб-страницу, которая будет одинаково удобна при работе на ПК или мобильном устройстве. А JS поможет реализовать интерактивность при работе с контентом на странице, а также организовать взаимодействие с веб-сервером.
Новый модуль Wiznet W5100S-EVB-PICO хорошо подходит для первого знакомства с данной темой. Первой причиной для этого является то, что компания Wiznet дает полностью готовый шаблон проекта, который и будем использовать для работы. А методика и принципы работы, которые покажем ниже, будут идентичны для всех мостов и Ethernet-контроллеров W7500/7500P. Второй причиной для тех, кто работает под ОС Windows, является то, что среда разработки VS Code, рекомендуемая для работы с Raspberry PI RP2040, подходит и для работы с HTML, CSS и JavaScript. Весь проект можно будет реализовать в рамках данной среды разработки.
Библиотека WIZnet для W5100S-EVB-PICO доступна по следующим ссылкам [3,4], соответственно, на языках С/С++ и CursuitPyton. Для тех, кто только начинает знакомство с микросхемами Wiznet и модулем W5100S-EVB-PICO, рекомендуем начать с предыдущих статей: в статье [1] рассказаны общие принципы работы с Ethernet-мостами на примере моста W5500; cтатья [2] знакомит с началом работы с модулем W5100S-EVB-PICO.
В примере, который входит в состав библиотеки для модуля W5100S-EVB-PICO, производитель показывает работу веб-сервера в статическом режиме. При вводе в адресную строку браузера IP-адреса модуля, последний отправляет в браузер страницу index.html, на которой выводится одна текстовая строка. Мы же дополним данный проект более сложным функционалом. В пример войдет реализация на HTML и CSS нескольких вкладок на веб-странице с возможностью переключения между ними. Также рассмотрим отправку с помощью JS “GET” запроса на сервер и покажем, как формируется ответ на данный запрос на сервере.
Начнем с кода, отвечающего в проекте HTTP-сервера за верхний уровень - это файл “..\examples\http\server\w5x00_http_server.c”. В этом файле производится инициализация микроконтроллера RP2040, инициализация моста W5100S и установка сетевых параметров. Не забудем, для начала, скорректировать сетевые параметры таким образом, чтобы наш модуль был доступен в текущей локальной сети, у автора настройки выглядят следующим образом (MAC-адрес оставлен в исходном виде, как в примере у производителя):
/* Network */
static wiz_NetInfo g_net_info =
{
.mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, // MAC address
.ip = {192, 168, 100, 150}, // IP address
.sn = {255, 255, 255, 0}, // Subnet Mask
.gw = {192, 168, 100, 1}, // Gateway
.dns = {8, 8, 8, 8}, // DNS server
.dhcp = NETINFO_STATIC // DHCP enable/disable
};
Затем необходимо привязать нашу будущую html-страницу и файл style.css с переменными в С-коде проекта. Это делается при помощи следующей функции:
/* Register web page */
reg_httpServer_webContent("index.html", index_page);
reg_httpServer_webContent("style.css", style_css); // добавляем самостоятельно
Файлы веб-страницы и стилей в рабочем приложении представлены в проекте в виде строковых переменных, которые определены в файлах web_page.h и style_css.h, как index_page и style_css. Функция reg_httpServere_webContent выполняет служебные функции, например, связывает имена страниц с переменными и осуществляет выделение памяти при обращении к данным переменным. В исходном проекте производителя уже существует файл web_page.h с тестовой страницей index.html и, соответственно, нам потребуется добавить по аналогии только один новый файл - style_css.h и вторую строчку кода.
На данном этапе все подготовительные операции сделаны, других изменений в коде файла w5x00_http_server.c не требуется. Далее, в основной функции проекта main() в цикле запускается веб-сервер httpServer_run(). В httpServer_run() происходит установление соединения, прием запросов от клиента и передача запрошенных данных, обработка ошибок и закрытие соединения. Ответы формируются в зависимости от того, какие данные запрашивает клиент. Для того, чтобы протестировать работу сервера в режиме выдачи статичной веб-страницы этого достаточно.
Шаблоны функций-обработчиков запроса на получение каких-либо динамических данных сведены в файле “…\libraries\ioLibrary_Driver\Internet\httpServer\httpUtil.c”. Через них можно прописать необходимый нам функционал взаимодействия с сервером. Например, если наш веб-интерфейс предназначен для установки сетевых параметров, то через эти функции будем получать их текущие значения и, при необходимости, менять их. Как это сделать - покажем чуть позже, а пока вернемся к созданию целевой веб-страницы, на которой и будет размещаться наш будущий веб-интерфейс (рис 2).
2 Внешний вид страниц (а – первая вкладка, б – вторая вкладка, в – третья вкладка)
Как работает страница можно посмотреть по ссылке: https://sergeydolgushin.github.io/Example-for-article-web-server-based-W5100S-PICO-EVB-/
Наша страница будет содержать три блока, переключение между которыми будет осуществляться по щелчку на нужном заголовке. Первые два блока будут выводить статичную информацию, в третьем будет отображаться служебная информация о сетевых настройках нашего отладочного модуля, которую мы будем получать от модуля по запросу. В исходном файле проекта style.css, который приложен к статье, также включен блок кода, который отвечает за адаптивность нашей страницы к размерам экрана (рис. 3). В этой статье из-за большого объема материала не успеем рассмотреть данный функционал, вернемся к нему в наших следующих публикациях. А желающие смогут разобрать данный момент самостоятельно на примере блока @media (max-width: 480px) в файле style.css.
Рис.3 Вид страницы при выводе на экран смартфона
Базовый код, который реализует функционал переключения между вкладками на странице, взят из примера с сайта: https://dbmast.ru/blok-akkordeon-na-css3-eksperimenty-prodolzhayutsya. По ключевым доработкам добавлен только js-скрипт, который при открытии закрытой вкладки закрывает уже открытую. Таким образом, в каждый момент времени, в окне браузера мы видим информацию в одной, на данный момент открытой, вкладке (рис.2).
Код HTML-страницы прост и выглядит следующим образом:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Веб-сервер</title>
</head>
<body>
<div class="accordion">
<input class="toggle-box" id="block-1" type="checkbox">
<label for="block-1">НАСТРОЙКИ МОДУЛЯ W5100S-EVB-PICO</label>
<div class="box">
</div>
<input class="toggle-box" id="block-2" type="checkbox" >
<label for="block-2">Продукция компании Wiznet</label>
<div class="box2">
<img class="product" src="https://efo.ru/storage/images/wiznet/Vendors%20page/mostec.jpg" alt="">
<img class="product" src="https://efo.ru/storage/images/wiznet/Vendors%20page/control.jpg" alt="">
<img class="product" src="https://efo.ru/storage/images/wiznet/Vendors%20page/mod.jpg" alt="">
</div>
<input class="toggle-box" id="block-3" type="checkbox" checked>
<label for="block-3">Компания ЭФО - официальный дистрибьютор Wiznet в России</label>
<div class="box3">
<h2 class="box3-header">Простой веб-сервер</h2>
<h2 class="box3-header">на базе модуля Wiznet W5100S-EVB-PICO.</h2>
<h3 class="box3-header">Использование HTML, CSS и JavaScript</h3>
<h3 class="box3-header">для создания веб-интерфейса.</h3>
<div class="image3">
<img class = "img-box3" src="https://efo.ru/storage/Products/Wiznet%20(pictures)/w5100s-evb-pic-pinout_v1-0b6175173e9620025ef8d641a9521bfc.png" alt="">
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Если создаем файл index.html «с нуля», то заготовку страницы, в которой будет вся необходимая служебная информация и базовые разделы, в MS Code можно создать путем ввода в новом документе знака “!”, и удерживая его, нажать “TAB”. В документ будет добавлен следующий код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
В заголовке head, кроме стандартной служебной информации, нам еще потребуется добавить ссылку на файл со стилями CSS, который и будет отвечать за итоговый внешний вид нашей страницы. Еще нужно изменить текст в теге title, данное название будет отображаться на вкладке страницы в браузере.
В элементе body хранится весь отображаемый контент страницы. Для данного раздела мы рассмотрим только ключевые моменты нашего проекта, а именно: как реализован механизм разворачивания/сворачивания вкладки, и как выводится получаемая от модуля W5100S информация на страницу. Как работают остальные элементы и стили рассматриваемого примера, можно посмотреть с помощью ресурса [6], который содержит много полезной информации, касающейся веб-технологий.
Итак, основная разметка страницы реализована с помощью универсальных блочных элементов div. В нашем проекте их четыре, основной div class = “accordion”, который является общим контейнером, и три div class = “box/2/3”, содержащие в себе контент разворачивающихся вкладок. В один момент времени в окне браузера мы видим контент только одной из вкладок. В тегах, кроме элемента, также присутствует атрибут class. Он нужен для идентификации элементов на странице. С его помощью можно назначать свои стили нужному элементу и изменять его поведение на странице с помощью JS. Атрибут class может содержать более, чем одно, имя. Каждое дополнительное имя отделяется от предыдущего пробелом.
Каждый из трех блочных элементов div класса box предваряется элементами input и label. Эти два элемента формируют кликабельные заголовки вкладок.
<input class="toggle-box" id="block-1" type="checkbox">
<label for="block-1">НАСТРОЙКИ МОДУЛЯ W5100S-EVB-PICO</label>
Элемент input задан в виде флажка (checkbox) и связан с элементом label с помощью уникального идентификатора id через атрибут for. Сам флажок не отображается на странице, мы видим только заголовок с текстом, за которые отвечает label. Связь этих элементов через атрибут for позволяет управлять состоянием флажка, кликая на заголовке.
<input class="toggle-box" id="block-3" type="checkbox" checked>
Т.к. при открытии веб-страницы в браузере мы хотим видеть одну из вкладок открытой, то один из флажков имеет предустановленный атрибут “checked”, т.е. флажок установлен.
Но данный HTML-код бесполезен без применения к нему стилей, который описываются с помощью языка CSS . CSS (Cascading Style Sheets) — это язык иерархических правил или таблиц стилей, используемый для представления внешнего вида документа, написанного на HTML. Управлять элементами на странице мы можем с помощью различных селекторов, в роли которых выступают имена тегов, классов, идентификаторов. Например, в нашем проекте в начале файла style.css мы задаем внешний вид блока body с помощью указания наименования тега, а div-контейнера – с помощью селектора класса .accordion:
body{
background-color: #c9cace;
}
.accordion{
width: 700px;
padding: 0;
margin: 0 auto;
background-color: #fcfcff;
}
С помощью селектора элемента body{} в CSS мы выбираем элемент body на нашей html-странице и задаем ему цвет фона. Этот цвет будет отображаться на неактивной области окна браузера, см рис 2 А.
С помощью селектора класса .accordion{} мы выбираем наш базовый блок div, в котором размещается основной контент страницы. В данном правиле мы прописываем общие параметры для отображения контента в браузере. В данном случае мы задаем фиксированную ширину рабочей области в 700 пикселей, отступы и базовый цвет фона.
Теперь рассмотрим, какие правила в файле style.css отвечают за работу нашего базового интерфейса страницы. Следующий листинг содержит только те блоки, которые отвечают за сворачивание/разворачивание вкладок и отображение элементов:
.toggle-box {
display: none;
}
.toggle-box + label + div {
display: none;
}
.toggle-box:checked + label + div {
display: block;
}
С помощью селектора класса .toggle-box мы запрещаем отображение на странице флажка - элемента input class=” toggle-box”.
Затем, с помощью комбинаторов следующего соседнего элемента, т.е. записи .toggle-box + label + div, выбираем следующий за указанным классом и следующим за ним элементом label элемент div, и устанавливаем для него свойство display: none, т.е. он не будет отображаться на странице.
Аналогичным образом выбираем элемент div, который следует за выбранным флажком с атрибутом checked, и отображаем его на экране.
Теперь веб-страница будет вести себя следующим образом, см. рис.
Рис. 4 Вид страницы без JS-скрипта
Т.е. при открытии закрытой вкладки, ранее открытая не закрывается. Происходит это потому, что мы не снимаем атрибут cheсked у открытой вкладки, кликая на заголовок другой вкладки. Соответственно, по установленным правилам отображения элементов в CSS, все элементы с селектором .toggle-box:checked + label + div будут отображаться. Чтобы закрыть ранее открытую вкладку, надо еще раз кликнуть по ее заголовку, чтобы снять с флажка атрибут checked. Т.е. открытие и закрытие вкладки происходит после нажатия на ее заголовок, при этом устанавливается или снимается флажок.
Чтобы реализовать механизм автоматического скрытия ранее открытой вкладки при выборе следующей, напишем небольшой скрипт на JS. С его помощью будем снимать атрибут checked с ранее установленного флажка и назначать его тому, который выбираем в данный момент.
// выбор вкладки
const labelcheck = document.querySelectorAll('.toggle-box');
labelcheck.forEach((labelcheck) => {
labelcheck.addEventListener('click', () => {
console.log(labelcheck); \\ тестовый вывод в консоль браузера
deselectall();
labelcheck.checked = true;
})
})
// снятие "checked" со всех вкладок
function deselectall() {
labelcheck.forEach(labelcheck => {
labelcheck.checked = false;
});
}
Данный скрипт устанавливает обработчик события addEventListener “click”, т.е. щелчка мышью на панели, для каждого элемента input с типом checkbox. При его срабатывании снимаются галки (статус checked) для всех чекбоксов и устанавливается галка на текущем, на котором произошло событие ‘click’. Надо понимать, что обработчик addEventListener не выполняется в тот момент, когда интерпретатор JS браузера доходит до этой строчки кода. Обработчик ведет себя по аналогии с прерыванием в МК, т.е. браузер отслеживает появление события для указанного элемента, и функция в обработчике начинает работу после того, как событие будет происходить или произойдет.
Теперь основной интерфейс нашей веб-страницы готов. Следующим шагом добавим функционал, с помощью которого будем получать данные от модуля и выводить их на страницу.
Перед тем, как реализовать запрос некоей информации от сервера, нам необходимо подготовить данную информацию. Мы предполагаем выводить на страницу текущие сетевые настройки модуля W5100S-EVB-PICO. Они будут отображаться на вкладке “ НАСТРОЙКИ МОДУЛЯ W5100S-EVB-PICO” нашего веб-интерфейса. Для получения данных от сервера используем HTTP-метод GET. В общем виде данный метод предназначен для чтения данных с сервера, с его помощью мы запрашиваем веб-страницы целиком или какой-то особый набор данных, которые хотим получить от сервера.
Как уже упоминали ранее, функции проекта HTTP-сервера, отвечающие за подготовку ответов на клиентские запросы, описываются в файле “httpUtil.c”. Функции, предназначенные для ответа на GET-запросы, включают в свое имя “get”, например, http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len). Это основной обработчик, в котором осуществляется поиск запрошенной клиентом информации. Поиск осуществляется по имени запроса – uri_name. По своей сути, данное имя представляет собой идентификатор URI, или иначе - унифицированный идентификатор ресурса. Например, веб-адрес или URL (унифицированный локатор ресурса) является одним из типов идентификатора URI.
Ответ на запрос веб-сервер возвращает в виде текстовой строки. Наиболее популярным ее представлением сейчас является формат JSON (JavaScript Object Notation), построенный на основе синтаксиса объекта JavaScript. Объект (в некоторых языках – словарь) хранит данные в виде пар ключ: значение. Ключ или имя – это строка, а значение может включать в себя различные типы данных. Для того, чтобы передать сетевые настройки модуля W5100S-EVB-PICO в наш веб-интерфейс, нам надо подготовить ответ в формате JSON следующим образом:
void make_json_netinfo(uint8_t * buf, uint16_t * len)
{
wiz_NetInfo netinfo;
ctlnetwork(CN_GET_NETINFO, (void*) &netinfo);
// DHCP: 1 - Static, 2 - DHCP
*len = sprintf((char *)buf, "[{\"mac\":\"%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\",\
\"ip\":\"%d.%d.%d.%d\",\
\"gw\":\"%d.%d.%d.%d\",\
\"sn\":\"%d.%d.%d.%d\",\
\"dns\":\"%d.%d.%d.%d\",\
\"dhcp\":\"%d\"\
}]",
netinfo.mac[0], netinfo.mac[1], netinfo.mac[2], netinfo.mac[3], netinfo.mac[4], netinfo.mac[5],
netinfo.ip[0], netinfo.ip[1], netinfo.ip[2], netinfo.ip[3],
netinfo.gw[0], netinfo.gw[1], netinfo.gw[2], netinfo.gw[3],
netinfo.sn[0], netinfo.sn[1], netinfo.sn[2], netinfo.sn[3],
netinfo.dns[0], netinfo.dns[1], netinfo.dns[2], netinfo.dns[3],
netinfo.dhcp
);
В данной функции мы обращаемся к Ethernet-мосту W5100S через функцию ctlnetwork(CN_GET_NETINFO, (void*) &netinfo). Параметр CN_GET_NETINFO указывает, что мы хотим получить текущие сетевые настройки моста. В соответствии с этим выполняется чтение всех требуемых регистров W5100S. С помощью функции sprintf() создаем JSON-ответ в виде строкового представления массива [], который, в свою очередь, содержит один элемент - объект. Таким образом, мы можем собрать всю информацию по текущим настройкам моста W5100S в одну строку и передавать ее клиенту по запросу. На стороне клиента данная строка в консоли браузера будет выглядеть таким образом (рис 5):
Рис. 5 JSON-ответ в консоли браузера
Отвлечемся от нашего проекта и скажем несколько слов про консоль. Она входит в состав инструментов разработчика, и в браузере Chrome вызывается через “F12” или меню, как показано на рисунке 6.
Рис. 6 Вызов инструментов разработчика в Chrome
Если вернуться к JS-скрипту выше, где реализуется переключение активных вкладок, то можно увидеть строку следующего вида: console.log(labelcheck); \\ тестовый вывод в консоль браузера. С помощью данной команды можно вывести информацию в консоль. Это очень полезно при отладке скрипта.
JS-cкрипт для отправки запроса и преобразования полученного ответа в информацию на веб-странице, как показано на рисунке 2 В, будет выглядеть следующим образом:
<script>
const request = new XMLHttpRequest();
request.open('GET', 'http://192.168.100.150/get_netinfo.cgi');
request.send();
request.addEventListener('load', function() {
const data = JSON.parse(this.responseText);
console.log(data[0]); \\ вывод в консоль первого элемента массива принятого JSON
console.log(data[0].mac); \\ вывод в консоль мас-адреса
\\ формируем HTML-блок для вывода на страницу с полученными параметрами
let div = document.getElementsByClassName('box');
console.log(div);
const html = `<h4 class=""box2-header"">MAC-адрес: ${data[0].mac}</h4>
<h4 class=""box2-header"">IP-адрес: ${data[0].ip}</h4>
<h4 class=""box2-header"">Шлюз: ${data[0].gw}</h4>
<h4 class=""box2-header"">DNS-сервер: ${data[0].dns}</h4>
`;
div[0].insertAdjacentHTML('afterBegin', html);
})
</script>
Данный скрипт состоит из трех основных блоков: формирование запроса на сервер и его отправка; ожидание ответа от сервера и обработка его после получения; вывод полученной информации на страницу.
В данном проекте рассмотрим старый, но еще широко используемый метод XMLHttpRequest. Например, его использует и Wiznet в своем проекте [5] для модуля WIZ550web.
Первым делом создаем новый запрос. С помощью метода open инициализируем его, задав тип запроса и URL с указанием требуемой информации. По имени “get_netinfo.cgi” наш веб-сервер определит, что нам требуется информация о настройках модуля (см файл httpUtil.c).
По умолчанию, запрос XMLHttpRequest является асинхронным, т.е. при его отправке с помощью метода send дальнейшая работа скрипта не останавливается до момента получения данных от сервера, а продолжает выполняться. И для того, чтобы отследить окончание процесса приема данных нам потребуется уже знакомый обработчик, который мы реализуем с помощью addEventListener. С помощью указания события load мы определяем момент начала выполнения обработчиком определенной в нем функции. Т.к. событие load происходит, когда данные закончили загружаться, то и функция в обработчике будет вызвана только после загрузки данных. После приема данных запускается метод JSON.parse, который преобразует строку в объект JS. С помощью вывода в консоль показан принцип работы с данными, содержащимися в итоговом объекте. Обращение к объекту в виде data[0].mac говорит, что в консоль надо вывести значение с ключем “mac” из первого элемента массива объекта data (см.рис 5).
И, наконец, остается вывести полученные данные на вкладку “НАСТРОЙКИ МОДУЛЯ W5100S-EVB-PICO” нашего веб-интерфейса. Для этого нам надо найти с помощью JS место размещения данных и поместить их туда. Для этого найдем все блоки div с классом “box” с помощью метода getElementsByClassName. Вернувшись к листингу с HTML-кодом нашей страницы, увидим, что такой класс есть только у одного блока div, пустого на момент загрузки страницы в браузер. Соответственно, метод вернет нам объект с описанием элемента, который представляет на HTML-странице первую вкладку.
Сформируем html-код, который и будем добавлять на требуемую вкладку. Он определен в виде строки, заключенной в обратные кавычки (``) – клавиша “Ё” в русской раскладке. Обратные кавычки нам нужны в обязательном порядке, чтобы можно было добавить в строку внешние данные. Добавление их в строку осуществляется следующим образом: ${data[0].ip. В данном случае добавляем IP-адрес. Такой вызов допустим, если строка «обернута» в обратные кавычки.
Теперь сформированную строку с помощью метода insertAdjacentHTML вставляем в выбранный ранее элемент div. Место размещения определяет параметр 'afterBegin' – он указывает, что код нужно поместить после открывающего тега выбранного элемента. В нашем случае - это элемент div[0], а код будет размещен сразу после открывающего тега выбранного элемента. В нашем случае - это элемент div[0], а код будет размещен сразу после div, (см. листинг с html-кодом страницы).
Рассмотренный вариант добавления информации - не единственный. Например, можно добавить заголовки h4, которые используются для вывода настроек на страницу, сразу в блок div. Затем у каждой из них менять содержание с помощью скрипта. Тут зависит от предпочтений и знания HTML и JS, а также от того, как должна выглядеть страница при ее вызове. В нашем примере вкладка открывается, если пользователь ее выбирает. На данном этапе скрипт выше уже должен полностью отработать, поэтому информация на вкладке будет присутствовать. Если же вкладка изначально активна, то пользователь должен видеть не пустой фон, а некую информацию, которая позволит ему понять, что страница “живая”. Некоторую оценку можно получить с помощью панели “Network” в инструментах разработчика (рис.7) По диаграмме видно, какие ресурсы загружаются дольше всего по времени. Обращаем внимание, что данная диаграмма будет зависеть от текущей нагрузки на сеть и на веб-серевер, т.е. она справедлива для данного конкретного момента. В нашем случае, запрос сетевых параметров “get_netinfo.cgi” имеет самый короткий интервал выполнения. А разница между полной загрузкой HTML и CSS кода и выполнением данного запроса составляет порядка 25 мс.
Рис.7 Диаграмма загрузки ресурсов нашей страницы в панели инструментов разработчика
На стороне модуля W5100S-EVB-PICO также можно посмотреть, как отвечает модуль на наши запросы. Для этого в коде производителя предусмотрен вывод служебной информации в UART, ее можно посмотреть через терминал (рис 8)
Рис.8 Вывод служебной информации в терминал Tera Term
Итак, на этом завершаем первый этап работы над проектом. Сама по себе тема достаточно обширна, и в данной части мы успели рассказать только о базовых вещах. В принципе, их уже достаточно, чтобы решить, имеет ли смысл закладывать веб-интерфейс в свои приложения. Если проводной Ethernet не подходит для вашей задачи, то на сайте https://wless.ru/technology/?tech=7 можно найти подходящий беспроводный вариант. А верхний уровень, о котором шла речь в данной статье, будет одинаков и для проводных, и для беспроводных вариантов реализации.
Все файлы, которые были созданы или изменены в исходном примере Wiznet, а также исходные файлы html, css и js, доступны в репозитории автора на Github: https://github.com/SergeyDolgushin/Example-for-article-web-server-based-W5100S-PICO-EVB-
Стоимость (со склада ЭФО):
WIZnet Ethernet HAT 4,95$ + НДС
W5100S-EVB-Pico 9,95$ + НДС
Микросхемы и модули Wiznet на складе
Литература
- Долгушин С “ Перспективные Ethernet-мосты компании Wiznet ”
- Долгушин С “Новый модуль WIZNET W5100S-EVB-PICO – RASPBERRY PI PICO с аппаратной поддержкой ETHERNET”
- Примеры и библиотека Wiznet на С/С++: https://github.com/Wiznet/RP2040-HAT-C
- Примеры и библиотека Wiznet на CircuitPyton: https://github.com/Wiznet/RP2040-HAT-CircuitPython
- Проект веб-сервера на базе модуля WIZ550web: https://github.com/Wiznet/WIZ550web/tree/master/WIZ550web_Webpages
- Справочная информация по веб-технологиям: https://webref.ru/