Если у Вас это установленно (Lighttpd и т.д.), то ничего удалять не нужно, просто пропустите установку uHTTPd.
Теперь для работы системы, достаточно легкого сервера uHTTPd (используется в OpenWrt для работы Web-интерфейса) и двух маленьких программ. Благодаря этому нет необходимости использовать флешку.
Как это работает?
Ардуина два раза в секунду отправляет данные роутеру (по USB или UART), на роутере программа arduread получает эти данные и записывает их в файл. Клиент подключённый к роутеру, раз в секунду считывает данные из этого файла.
Когда клиент отправляет команду (например включить свет), то её принимает другая программа — arduserver, которая слушает TCP-порт и отправляет ардуине принятые от клиента команды. Ардуина выполняет команду и продолжает отправлять данные, которые опять таки считывает arduread и записывает в файл. Клиент, при следующем запросе, читает из файла уже новые данные и они отображаются на страничке.
Функционально, система может включать/отключать устройства подключённые к ардуине и считавать информацию с датчиков.
Ардуина
Всё что делает ардуина — это принимает команды и два раза в секунду отсылает серверу информацию.
Заливаем скетч:
PHP код:
#include <DHT.h>
#include "CyberLib.h"
#define MAXMILLIS 4294967295
#define DHTPIN 9 // пин для подключения датчика
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
int hum = 110; // влажность
int thum = 110; // температура
byte d2 = 0; // флаг состояния
byte d3 = 0;
byte d4 = 0;
byte d5 = 0;
byte d6 = 0;
byte d7 = 0;
byte d8 = 0;
byte d9 = 0;
byte d10 = 0;
byte d11 = 0;
byte d12 = 0;
byte d13 = 0;
byte pir1 = 0;
byte knop1 = 0;
byte knop2 = 0;
byte knop3 = 0;
byte descript[5]; // массив
unsigned long time; // время
long timelapsed = 0;
int count=0; // счетчик минут
void setup()
{
Serial.begin(57600);
D2_Out;
D3_Out;
D4_Out;
D5_Out;
D6_Out;
D7_Out;
D8_Out;
//D9_Out; // DHT
D10_Out;
D11_Out;
D12_Out;
D13_Out;
thum = dht.readTemperature(); // считываем температуру, сначала делаем это в сетапе, так как следующее чтение будет только через минуту
hum = dht.readHumidity(); // считываем влажность
}
void loop()
{
if (Serial.available()>4) // ждём дескриптор и нужный символ
{
if (Serial.read()=='Y') // проверяем первый символ, если это 'Y', то продолжаем принимать, если нет, то выходим из цикла чтения
{
for (byte i=0; i < 5; i++)
{
descript[i] = Serial.read(); // добавляем символы в массив
}
if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='Z')) // проверяем дескриптор
{
switch (descript[3])
{
case 'o': // обновление
glavnaia(); // отправка ответа
break;
////////////// Кнопки ///////////////////
case 'A': // d2 вкл
D2_High;
d2 = 1; // флаг вкл
break;
case 'a':
D2_Low;
d2 = 0; // флаг откл
break;
case 'B': // d3
D3_High;
d3 = 1;
break;
case 'b': // d3
D3_Low;
d3 = 0;
break;
case 'C': // d4
D4_High;
d4 = 1;
break;
case 'c': // d4
D4_Low;
d4 = 0;
break;
case 'D': // d5
D5_High;
d5 = 1;
break;
case 'd': // d5
D5_Low;
d5 = 0;
break;
case 'E': // d6
D6_High;
d6 = 1;
break;
case 'e': // d6
D6_Low;
d6 = 0;
break;
case 'F': // d7
D7_High;
d7 = 1;
break;
case 'f': // d7
D7_Low;
d7 = 0;
break;
case 'G': // d8
D8_High;
d8 = 1;
break;
case 'g': // d8
D8_Low;
d8 = 0;
break;
case 'H': // d9
//D9_High; // DHT
//d9 = 1;
break;
case 'h': // d9
//D9_Low; // DHT
//d9 = 0;
break;
case 'I': // d10
D10_High;
d10 = 1;
break;
case 'i': // d10
D10_Low;
d10 = 0;
break;
case 'J': // d11
D11_High;
d11 = 1;
break;
case 'j': // d11
D11_Low;
d11 = 0;
break;
case 'K': // d12
D12_High;
d12 = 1;
break;
case 'k': // d12
D12_Low;
d12 = 0;
break;
case 'M': // d13
D13_High;
d13 = 1;
break;
case 'm': // d13
D13_Low;
d13 = 0;
break;
default:
glavnaia();
}
}
else // если дескриптор ложный, то очищаем буфер
{
for(byte i=0; i < 255; i++)
{
Serial.read();
}
}
} // конец if (Serial.read()=='Y')
} // конец чтение порта
unsigned long currtime = millis();
if(currtime > time) timelapsed = (currtime - time);
else timelapsed = (MAXMILLIS - time + currtime);
if(timelapsed >= 440) // функция будет выполняться раз в 2 минуты
{
time = currtime;
count++;
if(count == 120) thum = dht.readTemperature();
if(count == 240) hum = dht.readHumidity();
if(count > 239) count=0;
glavnaia(); // отправка данных серверу
} // конец включения по температуре
} // конец loop
void glavnaia() // отправка данных серверу
{
// сумма проверяется на сервере, на предмет целостности пакета
int summa = d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + d11 + d12 + d13 + thum + hum + pir1 + knop1 + knop2;
Serial.print('A');
Serial.print(" ");
Serial.print(summa);
Serial.print(" ");
Serial.print(d2);
Serial.print(" ");
Serial.print(d3);
Serial.print(" ");
Serial.print(d4);
Serial.print(" ");
Serial.print(d5);
Serial.print(" ");
Serial.print(d6);
Serial.print(" ");
Serial.print(d7);
Serial.print(" ");
Serial.print(d8);
Serial.print(" ");
Serial.print(d9);
Serial.print(" ");
Serial.print(d10);
Serial.print(" ");
Serial.print(d11);
Serial.print(" ");
Serial.print(d12);
Serial.print(" ");
Serial.print(d13);
Serial.print(" ");
Serial.print(thum);
Serial.print(" ");
Serial.print(hum);
Serial.print(" ");
Serial.print(pir1); // не используется
Serial.print(" ");
Serial.print(knop1); // не используется
Serial.print(" ");
Serial.print(knop2); // не используется
Serial.print(" ");
Serial.print(knop3); // не используется
Serial.print(" ");
Serial.print(0); // не используется
Serial.print(" ");
Serial.print(0); // не используется
Serial.print(" ");
Serial.println('Z');
}
В скетче используются две библиотеки DHT и CyberLib.
Ардуина получает команду включить/выключить пин, выполняет действие и устанавливает соответствующий флаг (d2 = 1; — вкл, d2 = 0; — откл), по этим флагам клиент определяет что включено или выключено.
Сервер
На роутере будут установлены следующие программы:
uHTTPd — легковесный сервер, написанный разработчиками OpenWrt для работы на встраиваемых устройствах, он будет отдавать клиенту основной контент.
Если установлен Lighttpd, то устанавливать uHTTPd не нужно.
arduread — получает данные присланные ардуиной и записывает их в файл file.db. Клиент подключенный к роутеру, раз в секунду считывает данные из этого файла, тем самым получая актуальную информацию.
arduserver — это маленький TCP-сервер, который ожидает соединение на порту 3490 (порт можно указать любой). Когда от клиента прилетает какая-либо команда, arduserver ловит её и отправляет в ардуину.
То есть, на роутере работает arduread — «слушающая» ардуину, и два HTTP-сервера — uHTTPd для отдачи контента и arduserver — принимающий команды для ардуины.
Устанавливаем
PHP код:
opkg install uhttpd
В автозагрузку и стартуем:
PHP код:
/etc/init.d/uhttpd enable
/etc/init.d/uhttpd start
Устанавливаем драйвера для ардуины (если знаете какой из них используется в Вашей, то другие ставить не нужно, если нет, то ставьте все).
Если подключаете ардуину к UARTу роутера, то пропустите этот пункт.
PHP код:
opkg install kmod-usb-serial-ftdi kmod-usb-acm kmod-usb-serial-pl2303 kmod-usb-serial-cp210x libftdi
После этих операций, на роутере без флешки, останется 372Кб.
Подключите ардуину и убедитесь что она определилась.
Arduino Nano —
ttyUSB0
Arduino Mega —
ttyACM0
UART —
ttyATH0
Переходим в каталог
/tmp
Скачиваем пакеты arduread и arduserver:
PHP код:
wget http://istarik.ru/file/arduread_1-1_ar71xx.ipk
PHP код:
wget http://istarik.ru/file/arduserver_1-1_ar71xx.ipk
Устанавливаем их:
PHP код:
opkg install arduread_1-1_ar71xx.ipk
PHP код:
opkg install arduserver_1-1_ar71xx.ipk
Редактируем файл /etc/rc.local и вставляем нижеследующие строчки (до exit 0).
PHP код:
vi /etc/rc.local
PHP код:
(sleep 20 && /arduread /dev/ttyUSB0 /www/ymdom/file.db )&
(sleep 1 && /arduserver 3490 /dev/ttyUSB0 )&
exit 0
Создаём папку ymdom в корневой папке сервера
/www
PHP код:
mkdir /www/ymdom
Переходим в неё:
И загружаем необходимые файлы:
PHP код:
wget http://istarik.ru/file/ymdom/index.html
wget http://istarik.ru/file/ymdom/knopki.css
wget http://istarik.ru/file/ymdom/style.css
Проверим свободное место:
Умный дом занял 24Кб.
Теперь нужно подкорректировать файл index.html, вписав в него ip-адрес роутера (если у Вас выделенный ip и планируете заходить извне, то впишите соответствующие имя или айпишку).
PHP код:
vi /www/ymdom/index.html
Строка
№31
Менять нужно только адрес 192.168.5.222, порт (3490) трогать не надо.
Если всё же решите поменять порт, то не забудте поменять его в аргументах для запуска программы arduserver, в файле /etc/rc.local (sleep 1 && /arduserver 3490 /dev/ttyUSB0).
Опять же, если будете заходить извне, и «умный дом» подключён к интернету не напрямую, а через другой роутер, то на нём нужно пробросить порт.
Перегружаем:
Заходим в браузере по
адрес/ymdom/ и видим…
Строка сверху, это «служебная» информация, пояснения содержатся в комментариях в файле
index.html.
Если что-то пошло не так, то в корневой папке появятся файлы Error.log и/или ErrorServer.log:
PHP код:
ls /
vi /Error.log
vi /ErrorServer.log
Расшифровку логов можно подсмотреть в исходниках arduread и arduserver, которые находятся
здесь.