• Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

Уроки

  • записей
    9
  • комментариев
    14
  • просмотров
    6 280

Авторы блога:

9. Управление светодиодом через браузер и Omega2

Админ

73 просмотра

Всем привет!

Сегодня я расскажу, как сделать простую 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/ и видим следующее:

1.JPG

Если нет, возможно вы допустили ошибку где-то здесь:

  1. Не сделали рестарт сервера (описано выше)
  2. Не туда дописали код в файле uhttpd (надо писать не в конец файла, а в конец первого блока)
  3. По каким-то причинам выставлены не те права доступа на папку test, они должны быть 755 (можно задавать в том же WinSCP либо через терминал)

Поздравляю, PHP успешно установлено и функционирует на вашей омеге. Теперь переходим к практическому применению.

4. Управляем светодиодом через PHP

Для начала соберем супер сложнейшую схему:

2.jpg

Как видите, плюс светодиода подключили на первый 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

Должно получиться так:

3.JPG

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 и молимся :)

После нажатия кнопки должно получиться так:

5.JPG 

4.jpg

Таким образом, go.html при нажатии кнопки вызывает knopka.php, а та в свою очередь инициализирует запуск test.py, получает от нее ответ и передает его обратно в go.html (текст “LED Status = …”). 

Для закрепления результата еще приконектился с телефона:

На этом все! Надеюсь у вас все получилось!




0 комментариев


Нет комментариев для отображения

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас