http сервер на макросах своими руками (MT серия)

Отправку http сообщений уже рассматривали тут.
А можно ли реализовать http сервер НА панели, чтобы она отвечала на запросы обычного веб-браузера ?
Оставим за рамками вопросы применимости. Каждый сам на него может ответить.
Рассмотрим саму возможность реализовать свой собственный web сервер на самых простых моделях панелей Weintek.
Для этого нам понадобятся:
1) панель MT серии (в примере использована MT8071iE)
1) устройство Free Protocol Server (Ethernet)
2) EasyBuilder Pro
Условимся, что:
1) наш web сервер будет на все запросы (парсить ничего не будем, на макросах это весьма трудоёмко)
2) отвечать одинаково, жестко заданным ответом (мы будем возвращать значения четырех локальных регистров панели LB-1, LB2, LW-1, LW-2)
3) автоматическое обновление данных на html странице реализуем через тег <meta>
4) общий объеём всех переменных в одном макросе не мбодет быть более 4 килобайт.
Реализация:
1) создадим проект для нужной модели
2) в Системных настройках проекта добавим устройство Free Protocol Server (Ethernet)
3) TCP порт для устройства Free Protocol Server (Ethernet) укажем отличный от 80 (даже на MT серии этот порт оказался занят системой), в нашем примере это 8080
4) создадим макрос, дадим ему имя server, поставим флажок "Период вып." и укажем 1*100 ms
5) в тело макроса добавим следующий код:
В строке 25 макроса мы оформили html страницу по всем правилам, но если вам надо покорочи и понагляднее, то закомментируйте 25 строку и раскомментируйте 26.
В конце макроса мы добавили вывод некоторой отладочной информации (текст запроса, кол-во символов в запросе и т.п.). Когда макроса отлажен всё это можно не выводить.
5) Загружаем проект в панели и в браузере обращаемся к ней по IP адресу и порту 8080
Естественно такое же можно реализовать и в cMT/cMT_X серии.
А можно ли реализовать http сервер НА панели, чтобы она отвечала на запросы обычного веб-браузера ?
Оставим за рамками вопросы применимости. Каждый сам на него может ответить.
Рассмотрим саму возможность реализовать свой собственный web сервер на самых простых моделях панелей Weintek.
Для этого нам понадобятся:
1) панель MT серии (в примере использована MT8071iE)
1) устройство Free Protocol Server (Ethernet)
2) EasyBuilder Pro
Условимся, что:
1) наш web сервер будет на все запросы (парсить ничего не будем, на макросах это весьма трудоёмко)
2) отвечать одинаково, жестко заданным ответом (мы будем возвращать значения четырех локальных регистров панели LB-1, LB2, LW-1, LW-2)
3) автоматическое обновление данных на html странице реализуем через тег <meta>
4) общий объеём всех переменных в одном макросе не мбодет быть более 4 килобайт.
Реализация:
1) создадим проект для нужной модели
2) в Системных настройках проекта добавим устройство Free Protocol Server (Ethernet)
3) TCP порт для устройства Free Protocol Server (Ethernet) укажем отличный от 80 (даже на MT серии этот порт оказался занят системой), в нашем примере это 8080
4) создадим макрос, дадим ему имя server, поставим флажок "Период вып." и укажем 1*100 ms
5) в тело макроса добавим следующий код:
- Код: Выделить всё
macro_command main()
unsigned char http_request[400] = {0} // http запрос GET, POST и т.д.
FILL(http_request[0], 0x0, 400)
unsigned short http_request_len = 0 // длина http запроса
unsigned short read_count = 100
unsigned short input_result = 0
unsigned short requests_count = 0
unsigned short wait_time = 50 // время ожидания завершения запроса в OUTPORT
unsigned char http_header[300] // http заголовок
FILL(http_header[0], 0x0, 300)
unsigned char http_status[17] = "HTTP/1.1 200 OK" // http заголовок: статус
unsigned char http_date[13] = "Date: Monday"
unsigned char http_srv[16] = "Server: Weintek"
unsigned char http_len[30] = "Content-Length: "
unsigned char http_type[50]= "Content-Type: text/html; charset=windows-1251"
unsigned char html_start[200]= "<!DOCTYPE html><html><head><title>Weintek HMI</title><link rel=\"icon\" type=\"image/png\" href=\"data:image/png;base64,iVBORw0KGgo=\"><meta http-equiv=\"refresh\" content=\"1\"></head><body>"
//unsigned char html_start[200]= "<!DOCTYPE html><meta http-equiv=\"refresh\" content=\"1\"><body>"
unsigned char html_end[14]= "</body></html>"
unsigned char html_body[200] // тело страницы , всё что между <body>...</body>
FILL(html_body[0], 0x0, 1000)
unsigned char html_page[500] // html страницы
FILL(html_page[0], 0x0, 500)
unsigned char http_response[800] // тело ответа = http_заголовок + html_страница
FILL(http_response[0], 0x0, 8000)
unsigned int http_response_len = 0 // кол-во символов в ответе сервера - числом
unsigned char http_response_len_txt[5] // кол-во символов в ответе сервера - текстом
FILL(http_response_len_txt[0], 0x0, 5)
unsigned int html_len = 0 // кол-во символов в html странице - числом
unsigned char html_len_txt[5] // кол-во символов в html странице - текстом
FILL(html_len_txt[0], 0x0, 5)
//unsigned char text6_doc[200]= "<!DOCTYPE html><head><link rel=\"icon\" type=\"image/png\" href=\"data:image/png;base64,iVBORw0KGgo=\"></head><html>HMI works!</html>"
//unsigned char text6[100]= "<!DOCTYPE html><html><head><link rel=\"icon\" href=\"data:,\"></head><body>HMI works !</body></html>"
//unsigned char no_favicon[50] = "<link rel=\"icon\" href=\"data:;base64,=\">"
//unsigned char text7[80]= "<!DOCTYPE html><html><head><link rel=\"icon\" href=\"data:,\"></head></html>"
unsigned char new_line[2] = {0x0D, 0x0A} // ASCII коды перехода на новую строку
// получаем http запрос
INPORT2(http_request[0], "Free Protocol Server (Ethernet)", http_request_len, wait_time)
// если запрос не 0 длины, то формируем ответ
if http_request_len > 0 then
// объявляем переменные панели, которые надо мониторить
short lw_1 // размер в регистр
unsigned short lw_2 // размер в регистр
bool lb_1, lb_2 // размером в бит
char lw_1_txt[6] = {0,0,0,0,0,0} // для текстового представления числа
char lw_2_txt[6] = {0,0,0,0,0,0} // для текстового представления числа
char lb_1_txt[2] = {0,0} // для текстового представления числа
char lb_2_txt[2] = {0,0} // для текстового представления числа
char thml_br[5] = "<br>" // html переход на новую строку
// считываем значение тегов
GetData(lw_1, "Local HMI", LW, 1, 1)
GetData(lw_2, "Local HMI", LW, 2, 1)
GetData(lb_1, "Local HMI", LB, 1, 1)
GetData(lb_2, "Local HMI", LB, 2, 1)
// преобразуем числовые значение тегов в текст
StringBin2DecAsc(lw_1, lw_1_txt[0])
StringBin2DecAsc(lw_2, lw_2_txt[0])
StringBin2DecAsc(lb_1, lb_1_txt[0])
StringBin2DecAsc(lb_2, lb_2_txt[0])
// формируем блок <body>
StringCopy("LB-1: ", html_body[0])
StringCat(lb_1_txt[0], html_body[0])
StringCat("<br>", html_body[0])
//StringCat(new_line[0], html_body[0])
StringCat("LB-2: ", html_body[0])
StringCat(lb_2_txt[0], html_body[0])
StringCat("<br>", html_body[0])
//StringCat(new_line[0], html_body[0])
StringCat("LW-1: ", html_body[0])
StringCat(lw_1_txt[0], html_body[0])
StringCat("<br>", html_body[0])
//StringCat(new_line[0], html_body[0])
StringCat("LW-2: ", html_body[0])
StringCat(lw_2_txt[0], html_body[0])
StringCat("<br>", html_body[0])
//StringCat(new_line[0], html_body[0])
// формируем html страницу
StringCat(html_start[0], html_page[0])
StringCat(html_body[0], html_page[0]) // приклеиваем к началу html документа блок <body>
StringCat(html_end[0], html_page[0])
// считаем размер html страницы
unsigned int html_page_len = 0
char html_page_len_txt[10]
FILL(html_page_len_txt[0], 0x0, 8)
html_page_len = StringLength(html_page[0])
StringBin2DecAsc(html_page_len, html_page_len_txt[0]) // преобразуем длину html страницы в текст
// формируем http заголовок
StringCat(http_status[0], http_header[0])
StringCat(new_line[0], http_header[0]) // добавляем символы перехода на новую строку
StringCat(http_date[0], http_header[0])
StringCat(new_line[0], http_header[0])
StringCat(http_srv[0], http_header[0])
StringCat(new_line[0], http_header[0])
StringCat(http_type[0], http_header[0])
StringCat(new_line[0], http_header[0])
StringCat(html_page_len_txt[0], http_len[0])
StringCat(http_len[0], http_header[0])
StringCat(new_line[0], http_header[0])
StringCat(new_line[0], http_header[0])
// формируем http ответ: склеиваем заголовк с html страницей
StringCat(http_header[0], http_response[0])
StringCat(html_page[0], http_response[0])
// определяем размер ответа
http_response_len = StringLength(http_response[0])
// отправляем http ответ в порт
OUTPORT(http_response[0], "Free Protocol Server (Ethernet)", http_response_len)
// диагностическая информация по запросам-ответам
http_request_len = StringLength(http_request[0])
SetData(http_request_len, "Local HMI", LW, 999, 1) // выводим кол-во символов в запросе
SetData(http_request[0], "Local HMI", LW, 300, http_request_len) // выводим текст запроса
SetData(http_response_len, "Local HMI", LW, 340, 1) // выводим кол-во символов в ответе
SetData(http_response[0], "Local HMI", LW, 500, http_response_len) // выводим текст ответа
// счетчик http запросов
GetData(requests_count, "Local HMI", LW, 888, 1) // считываем кол-во запросов
requests_count = requests_count + 1
SetData(requests_count, "Local HMI", LW, 888, 1) // выводим кол-во запросов
end if
end macro_command
В строке 25 макроса мы оформили html страницу по всем правилам, но если вам надо покорочи и понагляднее, то закомментируйте 25 строку и раскомментируйте 26.
В конце макроса мы добавили вывод некоторой отладочной информации (текст запроса, кол-во символов в запросе и т.п.). Когда макроса отлажен всё это можно не выводить.
5) Загружаем проект в панели и в браузере обращаемся к ней по IP адресу и порту 8080
Естественно такое же можно реализовать и в cMT/cMT_X серии.