В данной теме я опишу принцип интеграции исполняемых файлов в родной веб-интерфейс, передача данных между веб-интерфейсом и исполняемыми данными, а так же работу с некоторыми устройствами.Для работы необходимы:
-подключение по локальной сети
-включенный FTP сервер
-Notepad++ или что то подобноеФайлы веб-сервера находятся в /www/
Можете скопировать файлы которые там находятся и сохранить их на память, они нам не понадобятся.
Я буду писать веб страницу с нуля, чтобы все было понятно, и без кучи лишней красоты.
Сначала создадим главную страницу index.htmlКод:
<html><head> <meta http-equiv=Content-Type content=text/html>
<title>Test page</title> </head>
<body>
<body bgcolor="#AAAAAA">
<table width="300" align="center" cellpadding="0">
<tr>
<td width="100">
<p align="center"><a href="index.html">Home</a>
</td>
<td width="100">
<p align="center"><a href="input.cgi">Input</a>
</td>
<td width="100">
<p align="center"><a href="output.html">Output</a>
</td>
</tr>
<tr>
<td colspan=3><p align="center">MINI 2440 TEST PAGE by Z_Z_Z</td>
</tr>
</table>
</body></html>
Вверху страницы три ссылки Home (заглавная страница), Input (работа с вводом), Output (работа с выводом).
Теперь создаем файл input.cgi, вообще файлы cgi
могут быть написаны на любом языке программирования, и они являются шлюзами между веб-сервером и остальной системой.
Этот файл будет у нас представлять обычный исполняемый файл шела (/bin/sh) Но если кому то более удобно это может быть файл perl'a (/usr/bin/perl) (если он установлен), можно использовать даже откомпилированный ELF..
При нажатии на ссылку Input этот файл .cgi выполнится, и если не хотим смотреть на пустой экран или ошибки, он должен вывести страницу.
Наш файл input.cgi будет опрашивать АЦП с переменным резистором, установленным на плате, и кнопки, находящиеся там же, и выводить на экран веб-страничку с данными.Код:
#!/bin/sh //указываем с помощью чего надо это открывать
echo "Content-type: text/html; charset=utf-8" //начинаем выводить страницу
echo
/bin/cat temp.template //берем заготовку веб-страницы из файла
echo "<p align=center>" //выравнивание по центру
echo
/root/adctest //запускаем программу опроса АЦП и выводим результат
echo
/root/buttonstest //запускаем программу опроса кнопок и выводим результат
echo "</p><p align="center"><a href="input.cgi">Refresh</a></body>" //дописываем ссылку Refresh и завершаем страницу
exit 0
Чтобы не мучаться с выводом страницы, я создал файл заготовки веб страницы: temp.templateКод:
<html><head>
<title>Input test</title>
<style type="text/css">
<!--
body {
background-color: #AAAAAA;
}
-->
</style>
</head>
<table width="300" align="center" cellpadding="0">
<tr>
<td width="100">
<p align="center"><a href="index.html">Home</a>
</td>
<td width="100">
<p align="center"><a href="input.cgi">Input</a>
</td>
<td width="100">
<p align="center"><a href="output.html">Output</a>
</td>
</tr>
</table>
Заготовка - немного измененная заглавная страница. В общем то все готово.. Осталось только упомянуть использованые программы adctest и buttonstest.
Они были взяты из исходников на диске (linux/examples) и были немного откорректированны, для работы с веб интерфейсом. Это то что осталось от обработки АЦП:
Код:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int fd = open("/dev/adc", 0); //открываем файл АЦП
if (fd < 0) {
perror("open ADC device:"); // ошибка при открытии
return 1;
}
{
char buffer[30];
int len = read(fd, buffer, sizeof buffer -1);
if (len > 0) {
buffer[len] = '\0';
int value = -1;
sscanf(buffer, "%d", &value);
printf("ADC Value: %d\n", value);
} else {
perror("read ADC device:");
return 1;
}
}
close(fd);
}
А это от кнопок:
Код:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
int main(void)
{
int buttons_fd;
buttons_fd = open("/dev/buttons", 0); //открываем файл обработки кнопок
if (buttons_fd < 0) {
perror("open device buttons"); //если ошибка-выводим ошибку
exit(1);
}
char current_buttons[6]; //массив из состояния 6 кнопок
int i;
if (read(buttons_fd, current_buttons, sizeof current_buttons) != sizeof current_buttons) { //читаем состояния кнопок
perror("read buttons:"); //если ошибка-выводим ошибку
exit(1);
}
printf("<br>");
for (i = 0; i < 6; i++) {
printf("Key %d is %s\n <br>", i+1, current_buttons[i] == '0' ? "up" : "down"); //выводим состояния кнопок
}
close(buttons_fd); //закрываем файловую переменную
return 0;
}
Особенностью является, что обе программы выполняются не в цикле, а один раз, и в проге кнопок пришлось добавить в некоторые места
<br> для перевода строки в HTML'е (иначе все в одну строку).
После копирования файлов на девайс обязательно сделать
chmod +x adctest
chmod +x buttonstest
chmod +x input.cgiВот результат с получившейся страницы input:
ADC Value: 404
Key 1 is up
Key 2 is up
Key 3 is down
Key 4 is up
Key 5 is down
Key 6 is up Подведем итог:
Для запуска файлов достаточно сделать исполняемый файл .cgi, и вызывать его по ссылке из html'а.
Файл .cgi может быть написан как на любом скриптовом языке, так и на нормальном C++.
Файл .cgi может вызывать любые исполняемые файлы в ОС.
Файл .cgi может обмениваться данными с помощью стандартного вывода, а так же через сторонние файлы с приложениями ОС, а затем выводить их на веб-страницуРабота с выводом:Принцип тот же самый, только необходимо знать некоторые особенности.
Для ввода данных в HTML используются формы: Код:
<FORM ACTION="output.cgi" METHOD="get">...</FORM>
В форме может быть несколько разных элементов INPUT различных типов.
Помещаем на страницу элементы ввода:Код:
<form method="get" action="output.cgi" name="PWM-TEST">
<input type="radio" value="on" checked name="type">On</td>
<input type="radio" name="type" value="off">Off</td>
<input type="submit" value="OK" name="submit"></td>
</form>
Переключатель On/Off и кнопка ОК.
При нажатии кнопки ОК сформируется строка такого вида:
Код:
action?name=value&name=value&name=value
В нашем случае будет выглядеть так:Код:
output.cgi?type=on&submit=ok
в результате запустится output.cgi :Код:
#!/bin/sh
case $QUERY_STRING in
*on*)
/usr/bin/nohup /root/pwmtest >/dev/null &
;;
*off*)
/bin/kill -9 `/bin/pidof pwmtest`
;;
esac
//здесь должен быть вывод страницы после выполнения команды
exit 0
Строка передается в .cgi в виде переменной QUERY_STRING.Проверка на содержание этой строки в данном примере - халтурная, разборка строки на составляющие не происходит, просто проверяется, есть ли в строке слово On и Off.
а это исходник pwmtest:Код:
#include <stdio.h>
#include <stropts.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#define PWM_IOCTL_SET_FREQ 1
#define PWM_IOCTL_STOP 0
static int fd = -1;
static void close_buzzer(void);
static void open_buzzer(void)
{
fd = open("/dev/pwm", 0);
if (fd < 0) {
perror("open pwm_buzzer device");
exit(1);
}
// any function exit call will stop the buzzer
atexit(close_buzzer);
}
static void close_buzzer(void)
{
if (fd >= 0) {
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -1;
}
}
static void set_buzzer_freq(int freq)
{
// this IOCTL command is the key to set frequency
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
if(ret < 0) {
perror("set the frequency of the buzzer");
exit(1);
}
}
static void stop_buzzer(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < 0) {
perror("stop the buzzer");
exit(1);
}
}
int main(int argc, char **argv)
{
int freq = 400 ;
bool upe = true;
open_buzzer();
if (argc==2) {
sscanf(argv[1], "%d", &freq);
set_buzzer_freq(freq);
while (true) sleep(1000);
} else {
while( true )
{
if (upe) {
if (freq<3000) {
freq+=100;}
else upe = false;
} else {
if (freq>500) {
freq-=100;}
else upe = true;
}
set_buzzer_freq(freq);
usleep(20000);
}
}
}
Ну вот собственно и все. Как видно в исходнике pwmtest, если его запускать без команды, то будет сирена, если запускать с цифрой - будет воспроизводить звук с той частотой что установлена в командной строке, проверки на валидность введенного числа нет.
Если есть желание можно дополнить веб страницу полем ввода частоты воспроизведения. Но тогда придется разбирать строку на составляющие.
В архиве adctest, buttonstest с исходниками, index.html, input.cgi, temp.template