Всем привет!
Сегодня я расскажу, как сделать простую PHP-страницу, закинуть ее на Omega2, и управлять на этой странице подключенным светодиодом (а по сути GPIO пинами).
Для начала обязательно расширьте память омеги, если вы это еще не сделали, инструкция здесь. Также рекомендую установить какой-нибудь файл-менеджер по типу WinSCP, инструкция здесь.
Итак, приступим.
Для чистоты эксперимента, я сделал полный сброс омеги до системных настроек, для этого я через терминал выполнил поочередно три команды (либо можно было зажать на 10 секунд кнопку перезагрузки на док-станции):
firstboot -y
sync
reboot
1. Устанавливаем PHP на Omega2
Я постараюсь написать все понятно, но если что, вот официальная документация: https://docs.onion.io/omega2-docs/installing-and-using-php.html
Для начала обновляем список пакетов:
opkg update
И за тем устанавливаем необходимые пакеты:
opkg install php7 php7-cgi
2. Настраиваем PHP на Omega2
Отлично, теперь идем и открываем файл /etc/config/uhttpd (еще раз напоминаю про файловый менеджер WinSCP из начала статьи). Добавляем в раздел config uhttpd ‘main’ две строчки, которые содержат адрес расположения PHP-интерпретатора, а также имя страницы по-умолчанию.
list interpreter ".php=/usr/bin/php-cgi"
option index_page 'index.php'
Должно получиться примерно так:
config uhttpd 'main'
list listen_http '0.0.0.0:80'
list listen_http '[::]:80'
list listen_https '0.0.0.0:443'
list listen_https '[::]:443'
option redirect_https '1'
option home '/www'
option rfc1918_filter '1'
option max_requests '3'
option max_connections '100'
option cert '/etc/uhttpd.crt'
option key '/etc/uhttpd.key'
option cgi_prefix '/cgi-bin'
option script_timeout '60'
option network_timeout '30'
option http_keepalive '20'
option tcp_keepalive '1'
option ubus_prefix '/ubus'
list interpreter ".php=/usr/bin/php-cgi"
option index_page 'index.php'
config cert 'defaults'
option days '730'
option bits '2048'
option country 'ZZ'
option state 'Somewhere'
option location 'Unknown'
option commonname 'LEDE'
Сохраняем файл и перезапускаем WEB-сервер Omega2 через консоль следующей командой:
/etc/init.d/uhttpd restart
3. Тестируем
Если вы знакомы с серверами, хостингами и прочими словами, то знаете, что все файлы хранятся в папке www. Omega2, как маленький сервер не стал исключением.
Заходим в папку /www , создаем там папку test, и в ней файл index.php cо следующим содержимым:
<?php
echo "Hello, World!";
?>
Все, теперь открываем браузер, переходим по адресу http://192.168.3.1/test/ и видим следующее:
Если нет, возможно вы допустили ошибку где-то здесь:
-
Не сделали рестарт сервера (описано выше)
-
Не туда дописали код в файле uhttpd (надо писать не в конец файла, а в конец первого блока)
-
По каким-то причинам выставлены не те права доступа на папку test, они должны быть 755 (можно задавать в том же WinSCP либо через терминал)
Поздравляю, PHP успешно установлено и функционирует на вашей омеге. Теперь переходим к практическому применению.
4. Управляем светодиодом через PHP
Для начала соберем супер сложнейшую схему:
Как видите, плюс светодиода подключили на первый GPIO-контакт Omega 2, а минус на землю (GND). Соответственно включать/выключать светодиод мы будем устанавливая логические 0 и 1 на первом пине омеги.
4.1 Создаем Python файл для вкл/выкл светодиода
Если вы ранее не устанавливали питоновский интерпретатор, то сделайте это последовательно введя 3 команды в консоль (посмотреть установленные пакеты можно командой opkg list-installed):
opkg update
opkg install python
opkg install pyOnionGpio
Заходим в папку /root и в ней создаем файл text.py. Пишем в него следующий код:
import onionGpio
# define pins
PIN_NUMBER = 1
# define states
ON = 1
OFF = 0
# instantiate gpio objects
NASH_PIN = onionGpio.OnionGpio(PIN_NUMBER)
# initialize to output
status = int(NASH_PIN.getValue())
NASH_PIN.setOutputDirection(status)
# body
if status == 1:
status = OFF
else:
status = ON
NASH_PIN.setValue(status)
print "LED Status = "+str(status)
Сохраняем файл.
Краткое описание кода: подключаем библиотеку onionGpio, затем устанавливаем 3 константы (номер пина и статусы ON, OFF), обзываем объект третьего пина как NASH_PIN, считываем уровень третьего пина, указываем OUTPUT направление третьего пина (в скобках указано значение по-умолчанию, если не указать будет ошибка). Ну и на последок узнаем статус пина (0 или 1) и устанавливаем обратное.
Распространенные ошибки:
-
Иногда требуется добавлять str() и int(), чтобы преобразовать переменные в текстовые и числовые. Если это не сделать, в чем ошибка, иногда можно не понять.
-
В языке Python условия и циклы создаются не с помощью символов { } или begin end, а с помощью равных отступов, то есть если внутри IF’а будет одна строка с отступом в 4 пробела, а другая в 1 таб (что визуально выглядит одинаково), то условие работать не будет.
Чтобы проверить код, открываем консоль и пишем:
python /root/test.py
Должно получиться так:
4.2 Создаем HTML и PHP файлы
Отлично, научились включать светодиод скриптом. Теперь открываем папку /www и создаем там 2 файла go.html – по сути оболочка, и knopka.php – файл, который будет связывать «оболочку» и файл test.py. Сразу скажу, что в JavaScript я не силен, поэтому заимствовал код с просторов интернета и подкорректировал под свои нужды.
Содержимое go.html:
<title>Omega2 Control</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 stat; // эта переменная нужна чтобы опознать, что ответ получен и обработан
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; // проверяем следующий элемент
}
stat=1; // меняем статус (1 - ответ получен и обработан)
}
}
}
function sendTop() // В этой функции мы формируем запрос и отправляем его на сервер
{ stat=0; // сбрасываем статус (0 - ответ не получен и не обработан)
top_http = getXmlHttpRequestObject(); // вызываем функцию создания объекта XMLHttpRequest
top_http.onreadystatechange = handleTop;// цепляем на onreadystatechange обработчик ответа
// (когда он придёт - автоматически запустится функция handle_top)
var url='/knopka.php'; // строка запроса (запустить на сервере файл /knopka.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: #CF12F1;
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()">Omega2 LED Click</td>
<td id="result"></td>
</tr>
</tbody>
</table>
Содержимое knopka.php:
<?php
$result = shell_exec('python /root/test.py');
$answer = "1;result;".$result; // записываем в переменную строку ответа
echo $answer; // вывод ответа (он будет отправлен обратно на страницу, с которой вызван скрипт)
?>
Сохраняем файлы.
5. Запуск!
Теперь открываем браузер, переходим по адресу http://192.168.3.1/go.html и молимся
После нажатия кнопки должно получиться так:
Таким образом, go.html при нажатии кнопки вызывает knopka.php, а та в свою очередь инициализирует запуск test.py, получает от нее ответ и передает его обратно в go.html (текст “LED Status = …”).
Для закрепления результата еще приконектился с телефона:
На этом все! Надеюсь у вас все получилось!