LINUX.ORG.RU

История изменений

Исправление Moisha_Liberman, (текущая версия) :

Ну, положим, как бы я решал эту задачу.

По железу. Во-первых и сразу я бы оставил роутер в покое. Роутит и файерволлит, вот и пусть себе спокойно роутит и файерволлит без дерготни. Иначе это называется «Чем мы занимаемся? Да седьмую шапку шьём…» (Поговорка, распространённая в ряде дружественных контор по мотивам одной древней побасёнки.

Лучше бы «контроллер» вынести на отдельную малинку, как уже посоветовали в треде неоднократно. Если этого не сделать, то формально ничего плохого не случится, но… зачем? Ресурсов вычислительной системы всегда может не хватить и всё откажется работать в самый неприятный момент. К тому же, в ядре Linux совсем не зря есть параметр IP_ADVANCED_ROUTER, который имеет смысл включать именно на «роутере», на «хосте» незачем. Там ещё от него ряд параметров ядра зависит, но нафиг нам на «сервере» таблица маршрутизации (routing table), например?

В общем, я могу написать как было бы на мой взгляд лучше, но считайте что я Вас предупредил – лучше бы отдельную малинку прикрутить и не париться. Хотя, в принципе, предлагаемый мною вариант может и на малинке и на роутере пойти.

По решению. Во-вторых, я бы вспомнил о такой незаслуженно забытой технологии как CGI. Веб-сервер отдаёт клиенту html, css, javascript в самом простейшем виде. От клиента он получает http(s) запрос к CGI (common gateway interface) вида

http://.../cgi-bin/test.cgi?имя=значение&имя1=значение1&...

Ваша задача – получить веб-сервером строку от браузера и передать её на вход «скрипта» CGI. Исторически такие «скрипты» писались на perl, C, хотя ни кто не запрещает хоть на bash писать. Например:

#!/bin/bash
	echo "Content-type: text/html"
	echo ""
	echo '<html>'
	echo '<head>'
	echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
	echo '<title>Environment Variables</title>'
	echo '</head>'
	echo '<body>'
	echo 'Environment Variables:'
	echo '<pre>'
	/usr/bin/env
	echo '</pre>'
	echo '</body>'
	echo '</html>'
	exit 0

Этот скрипт выдаст в документ html все нужные переменные окружения. Важным моментом является то, что от веб-сервера скрипт их получает через эти самые environment variables, дальше он парсит нужное (QUERY_STRING, методы GET/POST/PUT), делает какую-то магию и возвращает результат бразеру. Браузер уже отображает что там вернулось. По сути дела, эти «скрипты» это не более чем стандартные unix-процессы со своими stdin, stdout, stderr каждый. И, отсюда, следует вторая проблема с ними – каждый процесс при каждом обращении запускается заново. Если у Вас есть логин в некую БД, то всё может оказаться очень печально. Нет, ни php, ни python, ни ruby с рельсами ничего нового, к сожалению, не привнесли в дело обработки запросов. FastCGI не в счёт, но об этом ниже.

Но как вариант для встраиваемок этот вариант вполне пойдёт. Например, если я хочу сделать для такого же роутера как у Вас, это называется CPE или Customer Premises Equipment, конфигурационную панель, то неужели Вы думаете что я поволоку туда всю инфраструктуру php? Ну Вы же не серьёзно! =))) Именно на cgiшках и делают… Я Вам это гарантирую. =)))

По серверам. Из существующих серверов напрямую и без проблем CGI поддерживаются lighttpd, apache, thttpd (на последний я бы обратил внимание особо, т.к. это сервер для кофемашин и газонокосилок.

Таким образом, у Вас получается две части проекта – опрос данных с устройств и складирование в какую-нибудь базу и отображение данных в веб-интерфейсе, котрые вытягиваются из базу по запросу. CGI позволяет отдавать любой формат – json, xml, html, кроче, что угодно. Отображать в браузере Вы можете тоже как угодно – хоть single page web-appication создать.

Если нужно обрабатывать большое число запросов или база на back end тяжёлая, то имеет смысл задуматься о применении FastCGI. По сути, это почти те же CGI, но стартующие уже при загрузке системы и общающиеся по сокету, т.е., их можно размещать на удалённой машине и запросы от веб-сервера будут передаваться через сокет. Т.е., все те же переменные окружения будут пересылаться на удалённую машину (можно и на локальную, само собой) и тут же парситься, обрабатываться, через веб-сервер клиенту в браузер будет возвращаться ответ. Несомненный плюс – приложение будет отрабатывать запросы пока жив хост, на котором оно работает. Есил есть СУБД, то раз залогинились при старте и дальше этого делать не нужно. Тот fastcgi что есть в php так и работает, кстати. Хотя, в том что CGI запускается при каждом запросе и завершается после отработки запроса, есть и плюс – не будет фрагментации памяти, проблемы, которая по временам здорово подбешивает, особенно при «длинных» запросах и на скромных ресурсах системы. Система сама должна зачистить использованные ресурсы после завершения процесса. С FastCGI можно нарваться на неприятности. В особенности если памяти немного. FastCGI офигенно поддерживается тем же nginx, хотя по размерам он и больше thttpd.

Почему я рекомендую не драть мозг, а использовать «стандартный» веб-сервер? Потому что в принципе можно взять ту же libevent (чтобы не париться с парсингом http-запросов и получить всё и сразу) и написать с её помощью некий веб-сервер (дадада, в 40 строк, ага). Но я бы предпочёл взять мелкий сервер типа thttpd и сконцентрироваться на логике приложения и веб-интерфейса (тот же ajax там реализовать или ещё что, чтобы приложение было бы более-менее современным, технологии это позволяют). Кроме того, использование сервера позволяет не сильно заниматься реализацией поддержки SSL/TLS и аутентификации. Сомневаюсь чтобы Вы хотели поделиться содержимым Вашего умного дома с соседями, ну, например, home video с камер видеонаблюдения. Так что, эти вопросы либо самостоятельно решать, либо пусть ими сервер занимается.

По языкам. Я бы рекомендовал воспользоваться С, благо дело тема эта проработанная годами и существует море библиотек. Например, https://github.com/rafaelsteil/libcgi для построения самих по себе CGI и FastCGI (разница в коде буквально на пяток строк). И https://github.com/ac000/libctemplate если нужны templates для веб-страничек. Хотя, можно и без них, если понимаете что делаете. В результате сторона чтения из СУБД и отображения этой информации в веб-интерфейсе будет плёвая по запрашиваемым ресурсам. Сторона сбора информации и размещения её в СУБД по идее, тоже, если опять же на С. =) Т.е., проект должен получиться максимально лёгким в части требуемых ресурсов. Счёт идёт на килобайты, даже не на сотни килобайт. Да, даже на роутере такое можно сгородить и даже будет работать, но… смысл?

В принципе, конечно, на python тоже можно поднять веб-сервер с поддержкой CGI, но чего-то не втыкает меня вся инфраструктура питона (сам питон, да ещё потом гуано всякого потребуется вагон и маленькая тележка).

По СУБД. Рекомендовали sqlite3. Можно, конечно, но я бы рекомендовал посмотреть в сторону Berkeley DB (теперь это Oracle Embedded). Это именно что встраиваемая СУБД. SQL там нет (точнее, есть, но считайте что нет, он там через зад). В код на С/С++ она добавляется именно как бибилотека, позволяет хранить данные в виде key-value, в общем, если загуглите, то с лёгкостью найдёте. Душевно рекомендую.

Ну вот, как-то вот так, в общем и целом.

P.S. И да, в зависимости от того, что именно Вы хотите, возможно что я бы даже и не стал бы городить огород со всем этим, а просто снимал бы данные с устройств и обрабатывал бы их посредством MQTT (гуглите mosquitto) на телефоне/планшете. Если там планируется сбор телеметрии и только (типа, показания счётчиков, температура, простейшие действия типа открыть-закрыть шторы), то в принципе, этого должно хватить. В каком-нибудь там IoTManager. Тогда вообще всё просто. Должно быть приложение (пусть будет номер 1), читающее данные с устройств и/или записывающее команды на устройства, должен быть «сервер» mosquitto, где для устройств созданы топики, с которыми работает приложение номер 1 (как публикует там данные, так и получает публикации), ну и IoTManagerом мы читаем-пишем данные на пользовательском устройстве. В разы проще. Ну и см. libmosquitto (хоть там и С, да).

Исходная версия Moisha_Liberman, :

Посмотерл на требования, сказал про себя "ого"... =)))

Ну, положим, как бы я решал эту задачу.

По железу. Во-первых и сразу я бы оставил роутер в покое. Роутит и файерволлит, вот и пусть себе спокойно роутит и файерволлит без дерготни. Иначе это называется «Чем мы занимаемся? Да седьмую шапку шьём…» (Поговорка, распространённая в ряде дружественных контор по мотивам одной древней побасёнки.

Лучше бы «контроллер» вынести на отдельную малинку, как уже посоветовали в треде неоднократно. Если этого не сделать, то формально ничего плохого не случится, но… зачем? Ресурсов вычислительной системы всегда может не хватить и всё откажется работать в самый неприятный момент. К тому же, в ядре Linux совсем не зря есть параметр IP_ADVANCED_ROUTER, который имеет смысл включать именно на «роутере», на «хосте» незачем. Там ещё от него ряд параметров ядра зависит, но нафиг нам на «сервере» таблица маршрутизации (routing table), например?

В общем, я могу написать как было бы на мой взгляд лучше, но считайте что я Вас предупредил – лучше бы отдельную малинку прикрутить и не париться. Хотя, в принципе, предлагаемый мною вариант может и на малинке и на роутере пойти.

По решению. Во-вторых, я бы вспомнил о такой незаслуженно забытой технологии как CGI. Веб-сервер отдаёт клиенту html, css, javascript в самом простейшем виде. От клиента он получает http(s) запрос к CGI (common gateway interface) вида

http://.../cgi-bin/test.cgi?имя=значение&имя1=значение1&...

Ваша задача – получить веб-сервером строку от браузера и передать её на вход «скрипта» CGI. Исторически такие «скрипты» писались на perl, C, хотя ни кто не запрещает хоть на bash писать. Например:

#!/bin/bash
	echo "Content-type: text/html"
	echo ""
	echo '<html>'
	echo '<head>'
	echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
	echo '<title>Environment Variables</title>'
	echo '</head>'
	echo '<body>'
	echo 'Environment Variables:'
	echo '<pre>'
	/usr/bin/env
	echo '</pre>'
	echo '</body>'
	echo '</html>'
	exit 0

Этот скрипт выдаст в документ html все нужные переменные окружения. Важным моментом является то, что от веб-сервера скрипт их получает через эти самые environment variables, дальше он парсит нужное (QUERY_STRING, методы GET/POST/PUT), делает какую-то магию и возвращает результат бразеру. Браузер уже отображает что там вернулось. По сути дела, эти «скрипты» это не более чем стандартные unix-процессы со своими stdin, stdout, stderr каждый. И, отсюда, следует вторая проблема с ними – каждый процесс при каждом обращении запускается заново. Если у Вас есть логин в некую БД, то всё может оказаться очень печально. Нет, ни php, ни python, ни ruby с рельсами ничего нового, к сожалению, не привнесли в дело обработки запросов. FastCGI не в счёт, но об этом ниже.

Но как вариант для встраиваемок этот вариант вполне пойдёт. Например, если я хочу сделать для такого же роутера как у Вас, это называется CPE или Customer Premises Equipment, конфигурационную панель, то неужели Вы думаете что я поволоку туда всю инфраструктуру php? Ну Вы же не серьёзно! =))) Именно на cgiшках и делают… Я Вам это гарантирую. =)))

По серверам. Из существующих серверов напрямую и без проблем CGI поддерживаются lighttpd, apache, thttpd (на последний я бы обратил внимание особо, т.к. это сервер для кофемашин и газонокосилок.

Таким образом, у Вас получается две части проекта – опрос данных с устройств и складирование в какую-нибудь базу и отображение данных в веб-интерфейсе, котрые вытягиваются из базу по запросу. CGI позволяет отдавать любой формат – json, xml, html, кроче, что угодно. Отображать в браузере Вы можете тоже как угодно – хоть single page web-appication создать.

Если нужно обрабатывать большое число запросов или база на back end тяжёлая, то имеет смысл задуматься о применении FastCGI. По сути, это почти те же CGI, но стартующие уже при загрузке системы и общающиеся по сокету, т.е., их можно размещать на удалённой машине и запросы от веб-сервера будут передаваться через сокет. Т.е., все те же переменные окружения будут пересылаться на удалённую машину (можно и на локальную, само собой) и тут же парситься, обрабатываться, через веб-сервер клиенту в браузер будет возвращаться ответ. Несомненный плюс – приложение будет отрабатывать запросы пока жив хост, на котором оно работает. Есил есть СУБД, то раз залогинились при старте и дальше этого делать не нужно. Тот fastcgi что есть в php так и работает, кстати. Хотя, в том что CGI запускается при каждом запросе и завершается после отработки запроса, есть и плюс – не будет фрагментации памяти, проблемы, которая по временам здорово подбешивает, особенно при «длинных» запросах и на скромных ресурсах системы. Система сама должна зачистить использованные ресурсы после завершения процесса. С FastCGI можно нарваться на неприятности. В особенности если памяти немного. FastCGI офигенно поддерживается тем же nginx, хотя по размерам он и больше thttpd.

Почему я рекомендую не драть мозг, а использовать «стандартный» веб-сервер? Потому что в принципе можно взять ту же libevent (чтобы не париться с парсингом http-запросов и получить всё и сразу) и написать с её помощью некий веб-сервер (дадада, в 40 строк, ага). Но я бы предпочёл взять мелкий сервер типа thttpd и сконцентрироваться на логике приложения и веб-интерфейса (тот же ajax там реализовать или ещё что, чтобы приложение было бы более-менее современным, технологии это позволяют). Кроме того, использование сервера позволяет не сильно заниматься реализацией поддержки SSL/TLS и аутентификации. Сомневаюсь чтобы Вы хотели поделиться содержимым Вашего умного дома с соседями, ну, например, home video с камер видеонаблюдения. Так что, эти вопросы либо самостоятельно решать, либо пусть ими сервер занимается.

По языкам. Я бы рекомендовал воспользоваться С, благо дело тема эта проработанная годами и существует море библиотек. Например, https://github.com/rafaelsteil/libcgi для построения самих по себе CGI и FastCGI (разница в коде буквально на пяток строк). И https://github.com/ac000/libctemplate если нужны templates для веб-страничек. Хотя, можно и без них, если понимаете что делаете. В результате сторона чтения из СУБД и отображения этой информации в веб-интерфейсе будет плёвая по запрашиваемым ресурсам. Сторона сбора информации и размещения её в СУБД по идее, тоже, если опять же на С. =) Т.е., проект должен получиться максимально лёгким в части требуемых ресурсов. Счёт идёт на килобайты, даже не на сотни килобайт. Да, даже на роутере такое можно сгородить и даже будет работать, но… смысл?

В принципе, конечно, на python тоже можно поднять веб-сервер с поддержкой CGI, но чего-то не втыкает меня вся инфраструктура питона (сам питон, да ещё потом гуано всякого потребуется вагон и маленькая тележка).

По СУБД. Рекомендовали sqlite3. Можно, конечно, но я бы рекомендовал посмотреть в сторону Berkeley DB (теперь это Oracle Embedded). Это именно что встраиваемая СУБД. SQL там нет (точнее, есть, но считайте что нет, он там через зад). В код на С/С++ она добавляется именно как бибилотека, позволяет хранить данные в виде key-value, в общем, если загуглите, то с лёгкостью найдёте. Душевно рекомендую.

Ну вот, как-то вот так, в общем и целом.