Наш канал в telegram

Микрокомпьютер Omega2. Часть 6. Установка, настройка и использование php для интерактивного взаимодействия

Как вы знаете, я являюсь сторонником внедрения web-технологий в автоматизацию систем управления (вот здесь можно почитать подробнее о том, как я это себе представляю). В то же время современные web-технологии невозможно представить без php, — языка серверных сценариев, на котором генерируется подавляющая часть динамических web-страниц.

Давайте посмотрим, а что же предлагает микрокомпьютер Omega2 в плане web? Можно ли на него установить php? Как можно использовать php для организации web-управления?

Сразу отвечу на первый вопрос. Под OpenWRT, на базе которого собрана прошивка для наших омег, обычно используется довольно лёгкий и отлично работающий с php web-сервер под названием uhttpd (но можно поставить и другой). Установка и настройка web-сервера — тема отдельная и сегодня мы её рассматривать не будем, поэтому переходим к php.

Установка и настройка php на Omega2

Тут всё просто. Сначала подключаемся в консоль через Serial0 или по ssh и обновляем список пакетов:

root@Omega-XXXX:/# opkg update

Мы будем устанавливать самую новую версию, то есть php7. Смотрим, какие в плане php7 предлагаются варианты:

Список найденных вариантов под катом

list interpreter ".php=/usr/bin/php-cgi"
option index_page 'index.php'

[свернуть]

Как видите, php7 присутствует. При желании можно установить и php5, но в родном репозитории эта версия уже недоступна. Убедиться в этом можно выполнив команду root@Omega-XXXX:/# opkg list | grep php5 или просто root@Omega-XXXX:/# opkg list | grep php.

Итак, чтобы поставить php7, — выполняем в консоли:

opkg install php7 php7-cgi

Теперь нужно настроить наш web-сервер для работы с php. Оригинальная дока советует делать это с помощью встроенного текстового редактора vi. Я, однако, предпочитаю скачивать файлы к себе на комп, редактировать их в привычном notepad++ и заливать обратно. Ещё один вариант — воспользоваться редактором, встроенным в файловый менеджер Midnight Commander, если конечно этот менеджер у вас установлен (про установку Midnight Commander и обмен файлами с омегой я ранее уже писал).

В общем, — редактируем файл конфигурации сервера (/etc/config/uhttpd), дописывая в раздел config uhttpd ‘main’ две строчки, которые содержат место расположения интерпретатора php, а также имя страницы по-умолчанию:

<?php
echo phpinfo();
?>

Далее нужно перезапустить web-сервер, чтобы наши правки вступили в силу:

root@Omega-XXXX:/# /etc/init.d/uhttpd restart

Осталось только проверить работоспособность. Создаём для тестов какой-нибудь файл, например вот такой:

<?php
$result = shell_exec('omega2-ctrl gpiomux get 2-->&amp;1');
echo "&lt;pre&gt;".$result."&lt;/pre&gt;";
?>

Закачиваем его куда-нибудь внутрь папки /www (например, в папку /www/phptest/), запускаем браузер и переходим по адресу http://[your-omega-ip]/phptest/. Если всё работает правильно, то вы увидите информацию о версии и настройках вашего php.

Кстати, если бы мы загрузили нашу страничку прямо в папку /www, то она загружалась бы прямо при переходе по адресу http://[your-omega-ip], а для запуска штатной страницы настройки, которая запускалась раньше, пришлось бы в явном виде набирать http://[your-omega-ip]/index.html. Помните, мы ранее установили имя страницы по-умолчанию опцией index_page? Это относится ко всем папкам, в том числе и к корню web-сервера (только не забывайте перезапускать web-сервер и удалять кэш браузера).

Вообще, опцией index_page, можно определять не только имя одной единственной страницы по умолчанию, но и задать целый список таких страниц, установив приоритеты (кто первый в списке — тот и более приоритетный).

Изменить настройки самого php можно в файле конфигурации, который по-умолчанию находится здесь -> /etc/php.ini

Работа с модулями Omega2 из php

Для управления модулем Omega2 через php можно воспользоваться встроенными в php функциями выполнения внешних программ и команд в оболочке shell. Подробности обо всех подобных способах можно нагуглить запросом «функции исполнения системных команд в php», но главные из таких способов, это конечно же функции, перечисленные ниже:

  • shell_exec — выполняет команду shell и возвращает полный вывод в виде строки
  • exec — выполняет внешнюю программу и возвращает последнюю строку вывода. Может заполнить строками вывода указанный массив, а также вернуть статус возврата выполненной команды в указанную переменную.
  • system — выполняет внешнюю программу и возвращает последнюю строку вывода или false в случае неудачи. Может дополнительно вывести статус возврата выполненной команды в указанную переменную.

Давайте не будем углубляться в детали различий между этими тремя командами, а лучше попробуем вместо этого что-нибудь сделать, например, проанализировать настройки мультиплексированных выводов при помощи инструмента omega2-ctrl.

Создаём файл test.php, содержащий следующий код:

команда 1&gt;/tmp/stdout.txt 2&gt;/tmp/stderr.txt

Загружаем этот файл в омегу, в папку /www/phptest/, открываем браузер и переходим по адресу http://[your-omega-ip]/www/phptest/test.php. Если ошибок нет, то вы увидите на экране вывод, аналогичный выводу команды omega2-ctrl gpiomux get в консоли.

То есть, при формировании нашей страницы была запущена внешняя команда, результаты работы которой мы получили в переменную и поместили на сгенерированную web-страницу.

Запись 2>&1 в конце команды означает, что вывод результатов работы команды, отправляемый в stderr, нужно перенаправить в stdout. Дело в том, что результаты работы нашей команды по-умолчанию отправляется в stderr (так часто делают с диагностическими сообщениями), а shell_exec возвращает нам вывод, отправленный в stdout, поэтому нужно использовать перенаправление. Если бы мы выполняли команду из консоли, то в результате оба потока вывода (stdout и stderr) были бы отправлены в консоль, мы в любом случае увидели бы ответ и нам по-сути было бы без разницы как они в консоль попали, через stdout или через stderr.

По умолчанию 0 — устройство ввода (stdin), 1 — устройство вывода (stdout), 2 — устройство вывода (stderr). Если вы хотите протестировать, куда отправляется результат выполнения команды, можно запустить из командной строки:

root@Omega-XXXX:/# opkg list | grep php7

В результате выполнения такой конструкции вывод отправляемый в устройство stdout будет записан в файл /tmp/stdout.txt, а вывод, отправляемый в stderr будет записан в файл stderr.txt.

Хотелось бы отметить ещё один момент. Не смотря на то, что ответ можно анализировать средствами самого php, не стоит пренебрегать таким мощным встроенным инструментом самого линуха, как команда grep.

Эта команда позволяет организовать фильтрацию вывода и работает следующим образом: она анализирует ответ предыдущей команды и выводит только те его строки, которые содержат заданную подстроку.

Командой grep мы уже пользовались выше, когда в общем списке доступных пакетов искали те, которые имеют отношение к php7. Помните, наша команда выглядела вот так:

root@Omega-XXXX:/# opkg list | grep php7

Таким образом мы фильтровали вывод команды opkg list, которая выводит список вообще всех доступных для установки пакетов, и задавали условие, что хотим видеть не весь ответ, а только те строки, которые содержат подстроку php7

Следует учесть, что команда grep имеет много разных дополнительных опций, позволяющих, например, не учитывать регистр букв при анализе ответа (опция -i) или выводить номера строк, в которых найдена заданная подстрока (опция -n). Кроме того, эта команда умеет искать в файлах (и даже не в одном, а сразу во всех файлах каталога), рекурсивно обходить все вложенные каталоги и много чего ещё.

Ладно, не будем сильно отвлекаться, вернёмся к php.

Интерактивное взаимодействие с Omega2, вызов php-скриптов через Ajax

Динамическое формирование страниц — это конечно здорово, но для хорошего современного проекта мало. Рано или поздно хочется, чтобы страница не просто динамически формировалась, но и могла динамически изменяться, взаимодействуя при этом с пользователем, то есть была интерактивной.

А есть у нас что-то для динамического изменения содержимого web-страницы, не перегружая при этом полностью саму страницу? Конечно, для этого у нас есть Ajax.

Как это работает покажу на реальном примере. Нам понадобятся две страницы: 1) test.html — web-страница с кнопкой, нажатие на которую будет с помощью технологии Ajax запускать расположенный на сервере php-скрипт, на этой же странице будет отображаться возвращённый скриптом результат работы; 2) test_push.php — скрипт, который будет запускаться кликом по кнопке на странице test.html и возвращать обратно на эту страницу результаты своей работы.

Листинг страницы test.html

 
<title>Omega2 Ajax Test</title>
 
<script type="text/javascript">
function getXmlHttpRequestObject()	// функция создания нового объекта XMLHttpRequest
{	var x;
if (window.XMLHttpRequest)	// мы в нормальном браузере?
{	// если в нормальном (IE7+, Firefox,Chrome, Opera, Safari) - создаём объект
x=new XMLHttpRequest();	// создаём объект XMLHttpRequest
}
else x=false;	// если в ненормальном - болт
return x;	// возвращаем указатель на созданный объект
}
 
// глобальные переменные
var top_http;		// здесь будем хранить указатель на объект XMLHttpRequest
var status;		// эта переменная нужна чтобы опознать, что ответ получен и обработан
var elements_col;	// количество переменных, которые мы будем запрашивать/получать
 
function handleTop()	// обработчик ответа сервера
{	if(top_http.readyState == 4)	// если запрос выполнен (4 - состояние complete)
{	if(top_http.status == 200)	// если статус ответа - 200 ( Ok! )
{	var value = top_http.responseText;	// получаем в переменную текст ответа
var ArrVal=value.split(';');		// разделяем ответ на массив параметров (параметры пришли через ;)
var obj_tag;				// здесь будет указатель на контейнер
var i=0;				// это просто счётчик
elements_col=ArrVal[0];	// количество элементов, которые нужно обработать 
// первый переданный элемент - это общее кол-во параметров
// (пар id/значение), а далее сами пары id/значение
while(i<elements_col)
{	// проверяем, есть ли на странице контейнер с нужным id?
obj_tag=document.getElementById(ArrVal[2*i+1]);
if(obj_tag)					// если есть
{	// меняем текст внутри него на принятый от сервера
obj_tag.innerHTML = ArrVal[2*i+2];
}
i=i+1;	// проверяем следующий элемент
}
status=1;	// меняем статус (1 - ответ получен и обработан)
}
}
}
 
function sendTop()	// В этой функции мы формируем запрос и отправляем его на сервер
{	status=0;	// сбрасываем статус (0 - ответ не получен и не обработан)
top_http = getXmlHttpRequestObject();	// вызываем функцию создания объекта XMLHttpRequest
top_http.onreadystatechange = handleTop;// цепляем на onreadystatechange обработчик ответа
// (когда он придёт - автоматически запустится функция handle_top)
var url='/test_push.php';		// строка запроса (запустить на сервере файл /test_push.php)
 
top_http.open('GET', url, true);	// настраиваем асинхронный запрос с адресом url
// (это url от корня того сервера, с которого загружена страница)
top_http.setRequestHeader('If-Modified-Since','0');	// добавляем заголовки
top_http.setRequestHeader('Cache-Control','no-cache');	
top_http.send(null);	// отправляем пустой запрос (поскольку у GET запроса
// нет тела, всё, что нужно, - запихано в url)
}
</script>
 
<!-- добавим глобальный стиль для таблиц и для кнопок -->
<style type="text/css">
td	{	border: 1px solid blue; 
padding: 10px; 
}
td.button
{	background-color: #40C781;
box-shadow: 0 -3px #35A76E inset;
}
td.button:hover
{	background-color: #35A76E;
}
td.button:active
{	background-color: #21935A;
box-shadow: 0 3px #21935A inset;
}
</style>
 
<table style="border: 1px solid blue">
<tbody>
<tr>
<td class="button" onclick="sendTop()">Push Button</td>
<td id="result"></td>
</tr>
</tbody>
</table>

[свернуть]
Листинг страницы test_push.php

<?php
$answer = "1;result;Yu-hu!";	// записываем в переменную строку ответа
echo $answer;	// вывод ответа (он будет отправлен обратно на страницу, с которой вызван скрипт)
?>

[свернуть]

Загружаем эти страницы в омегу, в папку www и перезапускаем веб-сервер. Теперь переходим по адресу http://[your_omega2_ip_address]/test.html и нажимаем кнопку «Push Button». Если всё работает правильно — справа должна появиться переданная нам скриптом информация (в данном случае текст «Yu-hu»).

Как эти страницы работают я думаю вы разберетесь сами, оба листинга достаточно подробно прокомментированы.

Итак, что мы теперь умеем? 1) Мы умеем запускать из php-скриптов внешние программы и команды. 2) Мы умеем запускать с web-страницы php-скрипты. Собственно, это всё, что нам нужно для управления микрокомпьютером Omega2 через web. Однако, более подробно мы займёмся темой управления (и красивой визуализации) как-нибудь в другой раз, а пока — пока.

  1. Часть 1. Первое знакомство
  2. Часть 2. Использование GPIO
  3. Часть 3. Док-плата
  4. Часть 4. Работа с файлами
  5. Часть 5. Работа с USB flash-дисками
  6. Часть 6. Установка, настройка и использование php для интерактивного взаимодействия
  7. Часть 7. Выполнение задач по расписанию с помощью планировщика Cron
  8. Часть 8. Подключаем проводной Ethernet.
  9. Часть 9. Сборка альтернативной прошивки на базе OpenWRT.

Добавить комментарий