Вступление
Когда я впервые увидел статью на хабре «Народный мониторинг температуры (vs прогноз) в различных городах. Нужен ли?», я как-то скептически отнесся к такой затее и забыл про нее. Перед новым годом у меня появилась Raspberry Pi и какое-то время ушло на ее освоение и обзор возможностей, в итоге что-бы малинка не простаивала, да и так для общего развития по статье «История взаимодействия «чайника» и DS18B20 посредством Raspberry Pi» сделал тоже самое, но с учетом исходников первоисточника, в который уже внесены изменения по мотивам вышеприведенной статьи с ссылкой на хабр. Температура измерялась, графики строились, но как-то скучно стало за этим наблюдать, да и применение малинки в этих целях это как из пушки по воробьям, и в один прекрасный день я вспомнил про «Народный мониторинг». Начал искать и нашел статью «Лучшая реализация реализация UART => 1-wire и I2C/SPI на базе роутеров». Тут я и загорелся идеей сделать такое устройство, правда в надежде на то, что кто-то уже это сделал, а я только повторю, благо роутер TL-MR3020 уже имелся в хозяйстве, и над ним уже ставились бесчеловечные опыты по привинчиванию его к «самокатной телеге» с камерой по мотивам статьи «Простой wifi бот для мониторинга помещений или «кухонное» роботостроение».
Итак, приступим
Начал я с опытов над роутером, на нем на тот момент была прошивка OR-WRT 0.70, основанная на OpenWRT. Опытом удачного подключения и получения показаний с датчика DS16B20 я поделился на форуме http://cyber-place.ru. Там же Вы найдете всю необходимую информацию по подключению датчика к роутеру. Если коротко, то датчик подключается к роутеру через USB-UART переходник. При попытке подключения и считывания данных через родной UART роутера выяснилось, что сделать с наскока это не получится. На одном буржуйском форуме была найдена информация о том, что ограничение это аппаратное и накладывает его сам роутеровский порт, который заточен под 8 бит данных, а в digitemp (пакет для считывания данных с датчиков 1-wire) используется только 6. Решено – придется ставить переходник USB-COM на FT232 или PL2303, возможен еще вариант на CP2102, но его у меня в наличии нет, а посему буду использовать то что есть. После этого я решил попробовать силы в написании скрипта отправки полученных данных на «Народный мониторинг». На данный сервис отправка данных должна осуществляться двумя методами на выбор, либо telnet TCP/UDP (рекомендуемый), либо HTTP POST. Примеры отправки данных на PHP имеются на сайте. PHP для меня темный лес, но все же это лучше чем ничего. После первой же попытки установить PHP на роутер стало ясно, что имеющихся в нем 4МБ памяти маловато, и фокус не удастся. Тогда я начал думать об увеличении объема флеш-памяти и наткнулся на том-же cyber-place.ru на тему «Замена и восстановление Flash ROM в роутере MR3020 и WR703n». Но после некоторых раздумий пришел к выводу что это не по фэн-шую, для меня и для большинства это довольно трудоемко, плюс требуется программатор, который не у всех есть, и забил на это дело. Решил написать на bash необходимый скрипт, но советы с гуглом не принесли результата, и пара дней прошло зря. В итоге было решено поставить USB-HUB (видел в сети благополучные опыты по вживлению оных во внутренности роутера), и к нему подключить внешний накопитель и USB-UART мост. Сказано – сделано, но в будущем, после удачного завершения опытов с Raspberry Pi и PHP, а в тот момент я как раз перекинулся на эти опыты. Перенесемся в будущее, задуманные опыты над малинкой и ПХП благополучно закончены, о чем я напишу ниже, продолжим опыты с роутером. Для увеличения объема памяти используется ее перенос на внешнюю флешку, а это значит что тот роутер который у меня был настроен на работу с «самокатной телегой» будет окончательно и бесповоротно переведен на использование с дополнительной памятью, чего делать категорически не хотелось. На следующий день был куплен еще 1 роутер и самый маленький USB-HUB, так-как потерять достигнутые результаты было жалко, тем более что это все же должны быть разные устройства.
Для «термометра» я решил использовать чистую OpenWRT. Скачав ее при попытке установки в поле выбора имени файла поиском по первым буквам обнаружил что у меня там целых 3 прошивки с одинаковым размером и именем файла, отличался только порядковый номер закачки файла. Я решил что когда-то уже качал эту прошивку и выбрал на угад одну из трех. После прошивки мне не удавались ни какие первичные действия из мануала на OpenWRT. Думал уже что что-то пошло не так во время прошивки и начал изучать методы извлечения роутера из кирпича через TFTP. Весь вечер на это положил, благо до практики руки не дошли, в теории было много не понятного. И под конец вечера что-то меня дернуло попробовать выполнить первоначальные настройки как для OR-WRT 0.70. Мне повезло, оказалось что я залил именно ее. Потом при сравнивании имен скачиваемых файлов оказалось что и OpenWRT и OR-WRT имеют одинаковые названия. Далее я потратил энное количество времени на попытку расширить память на внешнюю флешку, после чего было принято решение о заливке другой прошивки OR-WRT 0.75 alpha с уже имеющейся поддержкой флешек. Без проблем прошил и настроил по инструкции свой роутер и приступил к дальнейшим действиям.
По накатанной в /etc/opkg.conf изменил адрес репозитория на downloads.openwrt.org/snapshots/trunk/ar71xx/packages/, обновил список пакетов
opkg update
установил пакеты digitemp-a
opkg install digitemp-usb
opkg install digitemp
После этого командой dmesg
выяснил куда подключен адаптер FTDI, у меня оказался ttyUSB0. Выполняем поиск устройств 1-wire
digitemp_DS9097 -i -s /dev/ttyUSB0
если нашлись, то считываем показания температуры и пишем в файл
digitemp_DS9097 -a -A -l /tmp/1wire_log
что бы посмотреть результат вводим
cat /tmp/1wire_log
Все работает. Далее устанавливаем пакеты для работы PHP
opkg install php5
opkg install php5-cgi
И начинаем заниматься написанием скриптов. В этом деле я не мастак, поэтому прошу сильно не пинать за кривость кода и огромные костыли, подставленные, чтобы это все заработало. Написано было два скрипта, один на bash, другой на php. Вернее тот, что на php был сделан на основе исходников с сайта «Народный мониторинг». Первый скрипт выуживает данные полученные от пакета digitemp и записанные в файл 1wire_log, и подгоняет их в удобоваримый вид. После чего передает управление второму скрипту на php для отправки данных на сервер.
rm /temperatura/1wire_log
rm /temperatura/temp
rm /temperatura/temper
cd /
digitemp_DS9097 -i -s /dev/ttyUSB0
sleep 1s
digitemp_DS9097 -a -A -l /temperatura/1wire_log
sleep 2s
cd /temperatura
cut -c29-33 1wire_log | sed 's/$//' > temp
cat temp | tr -d 'n' > temper
php-cgi /temperatura/send.php
echo «OKn»
Второй скрипт берет данные из файла, подготовленного первым скриптом, и отправляет их на сервер.
$file_name="/temperatura/temper";
$file=fopen("$file_name", «r»);
$gradus_out=fread($file, filesize($file_name));
echo "$gradus_outn";
fclose($file);
$fp = @fsockopen(«tcp://narodmon.ru», 8283, $errno, $errstr);
if(!$fp) exit(«ERROR(».$errno."): ".$errstr);
fwrite($fp, "#01-23-45-67-89-AFn# 0123456789ABCDEF#$gradus_outn##");
fclose($fp);
echo «OKn»;
?>
где 01-23-45-67-89-AF – mac-адрес сетевой карты wlan (Wi-Fi), а 0123456789ABCDEF – серийный номер датчика температуры DS16(x)20
Для обоих реализаций устройства я использовал mac-адрес wlan для привязки устройства на сайте «Народный мониторинг». Что-бы найти этот адрес можно ввести команду ifconfig
.
Далее нам необходимо автоматизировать получение и отправку данных на сервер с помощью cron. На момент отладки скриптов я отправлял данные на сервер с периодичностью 5 минут, но как только они были отлажены, период увеличился до 10 минут. Для этого создаем простенький crontab для пользователя root с содержимым
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0,10,20,30,40,50 * * * * sh /temperatura/get_send.sh
По данному заданию опрос датчика и отправка данных осуществляется каждые 10 минут. Последняя строка скрипта вполне может быть вида
*/10 * * * * sh /temperatura/get_send.sh
Так как на данный момент у меня включены два устройства для отправки данных о температуре, а на сайте игнорируются данные приходящие чаще чем раз в пять минут, данные от одного из моих устройств игнорируются. По этому, для каждого из устройств было четко задано в кроне время отправки данных с интервалом между устройствами в 5 минут. Скачать скрипты и crontab можно здесь. Далее копируем crontab пользователя root в /etc/crontabs и папку temperatura в / (корень файловой системы).
Для запуска и включения cron надо выполнить в терминале
/etc/init.d/cron start
/etc/init.d/cron enable
Переходим на сборочный участок
После того как все было проверено в работе пора приступать к сборке всего хозяйства в единое устройство. После вскрытия USB-хаба и роутера начал прикидывать компоновку устройств внутри корпуса советуясь с гуглом и подглядывая на страничку по моддингу роутера. Оказалось что USB-HUB я купил такой же как и у автора первого варианта доработок. Уже хорошо, раз ему удалось это сделать значит и у меня получится. После первичной компоновки внутренностей устройства стало ясно, что можно попробовать уместить туда же и USB-UART переходник. В качестве USB-UART переходника был опробован и принесен в жертву датакабель от какого-то старого телефона на микросхеме PL2303, появившийся у меня из ниоткуда с целью использования как мост USB-UART. До этого он кем-то дорабатывался, были напаяны не самые маленькие детали, которые задавали толщину самой плате. После изучения схем на телефонные шнурки эти габаритные детали были удалены. Так же был удален переключатель питания и откусаны торчащие ноги выводных элементов. Платка сразу похудела. Можно было бы воспользоваться и платкой на FTDI, габариты которой минимум в 2 раза меньше примененной платы, но ее было жалко т.к. в ней есть полезный сигнал DTR, применяемый для сброса Arduino, а в PL2303 он инверсный и для его использования пришлось бы городить инвертор. А для наших целей этот сигнал совершенно не важен.
После доработки USB-UART переходника пришла очередь и USB-хаба, торчащие выводы которого так же были срезаны. Для него это похудение оказалось почти не заметным, но в целом для конструкции думаю стало полезным. Опираясь на опыт людей которые уже делали это начал повторную примерку. Те варианты что были предложены меня не устраивали т.к. пришлось бы удалять световод. Перекинул на противоположную от световода сторону, уже лучше. Но все равно имеющейся флешкой будет закрываться часть светодиодов и придется так же удалять часть световода.Но по прикидкам можно обойтись без крайних мер купив флешку покороче. Начал искать по компьютерным магазинам и нашел достойный вариант по адекватной цене, которую купил на следующий день. Как оказалось такую же модель флешки уже использовал автор еще одного варианта моддинга. Получается что ввыбор применяемых деталей не так велик, раз я 2 раза случайно попал на такие же, совершенно не зависимо от опередивших меня авторов.
Далее я начал думать как наиболее элегантно расположить порт UART на корпусе роутера для подключения внешнего датчика. Оказалось что не используемый отныне USB порт, выводы питания которого так и продолжают исполнять возложенные на них функции, а отрезанные от схемы выводы +D и -D вполне можно приспособить под Rx и Tx. Отлично. Спаял все воедино, проверил.
Для фиксации плат между собой использовал обычный 2х сторонний скотч. При сборке надо быть предельно осторожным, что-бы ничто нигде не коротнуло и не продавить скотч острыми паяными выводами. При приклейке хаба я использовал два слоя скотча для увеличения расстояния между платами, по 2 полоски на слой сложенные «паленицей». Для тестов использовал оставшийся хвост от того же хаба. Вот что получилось в итоге
Результат порадовал, даже места еще немного осталось, и остался неиспользуемый встроенный UART. В закромах был найден Bluetooth модуль HC-04 и примерен на возможное место установки. Встал как родной. Сразу же был припаян и приклеен на тот же скотч на USB порт роутера.
Зачем мне это? Как уже сказал выше, жалко что пропадает место и UART. Плюс роутер ничего не будет делать целых 10 минут, не порядок. Можно навешать еще каких функций. Например, первое из-за чего я это сделал – в интернете на градусник смотреть хорошо, но не всегда удобно. Вот и думаю поставить простейшую ардуину с 7-сегментным индикатором. А может и знакосинтезирующий, чтоб еще и время/дату показывать. Вообще вариантов масса.
Закрыть крышку мешал только один штырь на ней, который должен упираться в плату, а упирается в USB разъем хаба. Примерил на глаз да и срезал половину.
После чего крышка нормально встала на место. Правда так же плотно поставить ее не удалось и она немного выдается вверх. Но это нормальное явление и ей не мешают все мои доработки. Тоже самое у меня на первом не доработанном роутере. В итоге получил внешне почти девственно новый роутер, не считая следов не аккуратного вскрытия.
Для выноса датчика на улицу я использовал разборный USB разъем на кабель и шнур от комовской мышки, он мягче остальных шнуров которые у меня были, с напаянным небольшим отрезком плоского кабеля что-бы пропустить его между оконными уплотнителями при закрывании окна.
.
Цена вопроса при использовании роутера
Роутер TL-MR3020 910р.
USB-HUB Ginzzu 210р.
Флешка Sandisk Cruzer Fit 8 ГБ 248р.
Переходник USB-UART на FT232 из китая ~5$ = 150р.
Bluetooth модуль HC-04 из китая ~7$ = 210р.
Датчик температуры DS16(x)20 ~60р.
Итого ~1788р.
Естественно Bluetooth модуль можно выкинуть, и тогда цена приблизится к планке ~1600р.
Варианты усовершенствования
Первое – оптимизация скриптов приведенных в статье
Второе – если удастся избавиться от скрипта на PHP и перейти на bash полностью, то получится избавиться от флешки и USB-хаба, что существенно сократит трудоемкость и стоимость конечного устройства.
Третье (просто предположение) – возможно, если почистить прошивку удалив не используемые модули, получится освободить место для PHP, достигнем тех же результатов что и во втором варианте.
Четвертое – заставить работать аппаратный UART, еще сократит стоимость, но немного повысит трудоемкость. Все что я смог найти на эту тему это непонятный мне скрипт на pastebin-е без комментариев, и ссылку на лежачий сайт, откуда идет ссылка на pastebin. Пробовал запустить этот скрипт безрезультатно.
Пятое – задействовать вывод GPIO написав соответствующий драйвер.
Отправка с Raspberry Pi
Как я уже упоминал, у меня уже была малинка настроенная должным образом на измерение температуры на двух датчиках и составление графиков. Таким образом, дело осталось за малым, выдернуть данные о температуре и отправить их на сервер.
Дальнейшее описание процесса будет с учетом того, что Вы уже настроили малинку на получение данных с датчиков и построение графиков. Однако коротко расскажу принцип действия тех скриптов, а желающие смогут скачать полностью мои скрипты для быстрой настройки. В варианте, который я повторил и предлагаю Вам повторить, имеется 3 скрипта на bash, один на perl и один файл базы данных для RRDTool. Первый скрипт на bash запускается однократно и создает файл базы данных. Второй скрипт на bash добавляется в cron и все что он делает, это запускает выполнение остальных скриптов. Первым делом он запускает скрипт get_temp.pl, который отвечает за считывание показаний с датчиков температуры и укладывание этих показаний в базу данных. Второй строкой он запускает скрипт create_graphs.sh, который берет значения температуры из базы данных и по ним строит графики. Отталкиваясь от того что моя малинка все это уже умеет делать приступаю к реализации оставшейся части задуманного. Здесь уже используется один скрипт на PHP для отправки данных на сервер. Плюс к этому добавляется несколько строк обработки полученных от датчиков данных в уже имеющийся скрипт get_temp.pl и одна строчка в скрипт get.sh.
Мой скрипт получения данных с датчиков с добавлением обработки показаний температуры выглядит так
Здесь прошу меня простить, то ли в скрипте что-то мешает, то ли глюк какой, но нормально вставить его под спойлер у меня не получилось, по этому привожу кусок оригинального кода с вставленными моими доработками.
#######################################################################
foreach $device (@deviceIDs)
{
$reading = &read_device($device);
if ($reading == 9999) {
$reading = «U»;
}
push(@temp_readings,$reading);
}
if ($temp_readings[0] ne 'U') {$temp_readings[0] -= $in_correction;}
if ($temp_readings[1] ne 'U') {$temp_readings[1] -= $out_correction;}
#update the database
`/usr/bin/rrdtool update /home/pi/temperature/multirPItemp.rrd N:$temp_readings[0]:$temp_readings[1]`;
print «Temp 1 = $temp_readings[0] Temp 2 = $temp_readings[1]n»;
#######################################################################
#Мои дополнения
open(FILE, ">/home/pi/temperature/temp_out");
print FILE "$temp_readings[0]";
close (FILE);
open(FILE, ">/home/pi/temperature/temp_in");
print FILE "$temp_readings[1]";
close (FILE);
#######################################################################
Суть моих дополнений заключается в вылавливании данных о температуре, которые заносятся в базу данных, и записи их в отдельные файлы для каждого датчика.
После того как все это заработало можно заняться скриптом отправки данных на сервер. Для этого нам понадобится установить PHP.
sudo apt-get install php5-cgi
Скрипт отправки данных сделан из примера, представленного на сайте «Народный мониторинг». Он обращается к файлам созданным предыдущим скриптом, берет из них данные о температуре и отправляет их.
Мой скрипт send.php выглядит так
<?
$file_name="/home/pi/temperature/temp_out";
$file=fopen("$file_name", «r»);
$gradus_out=fread($file, filesize($file_name));
echo "$gradus_outn";
fclose($file);
$file_name="/home/pi/temperature/temp_in";
$file=fopen("$file_name", «r»);
$gradus_in=fread($file, filesize($file_name));
echo "$gradus_inn";
fclose($file);
$fp = @fsockopen(«tcp://narodmon.ru», 8283, $errno, $errstr);
if(!$fp) exit(«ERROR(».$errno."): ".$errstr);
fwrite($fp, "#01-23-45-67-89-AFn#0123456789ABCDEF#$gradus_outn#0123456789ABCDEF#$gradus_inn##");
fclose($fp);
?>
где так же как и в варианте с роутером 01-23-45-67-89-AF – mac-адрес сетевой карты wlan (Wi-Fi) или lan, если малинка подключена через него, а 0123456789ABCDEF – серийный номер датчика температуры DS16(x)20.
Затем добавляем строчку в скрипт get.sh, указывающую на исполнение скрипта send.php.
/home/pi/temperature/get_temp.pl
/home/pi/temperature/create_graphs.sh
#######################################################################
#Мое дополнение
/home/pi/temperature/send.php
echo «OKn»
#######################################################################
В кроне я изменил расписание на отправку данных каждые 10 минут с четкой привязкой ко времени, не пересекающимся с временем отправки данных роутером.
Задание в кроне выглядит так
5,15,25,35,45,55 * * * * /home/pi/temperature/get.sh
После этого должно все заработать. Скачать данные скрипты можно здесь
Цена вопроса при использовании Raspberry Pi
Здесь уже посчитать так однозначно не получится. Дело в том, что стоимость самой малинки и дополнительных комплектующих к ней может сильно отличаться от человека к человеку.
Заключение
На мой взгляд при не имении ни того ни другого наиболее рациональным является использование роутера. Использование малинки имеет смысл только в том случае, если у Вас уже она есть, постоянно включена и выполняет какие либо задачи.
А в целом в полку устройств отправляющих данные на сервис «Народный мониторинг» прибыло, и это хорошо.
Автор: Serenya