26 января 2014 г.

Тестируем жесткие диски в debian/ubuntu

Чтобы не забыть.

# apt-get install smartmontools
# fdsik -l
# smartctl -A /dev/sda
# smartctl -t conveyance /dev/sda 
//через две минутки:
# smartctl -a /dev/sda
# smartctl -t long /dev/sda
//через пару часов
# smartctl -a /dev/sda


Проверим kern.log , позиции связанные с ata рассмотреть.

Быстрый опрос диска на предмет живучести, с предсказанием отказа диска в ближайшие 24 часа
sudo smartctl -H /dev/sda
Лучшее описание параметров здесь. На что стоит обратить внимание:
Attribute 04 (4) Start/Stop Count (Количество циклов запуск/останов шпинделя)
Attribute 05 (5) Reallocated Sector Count (Количество переназначенных секторов)
Attribute 09 (9) Power On Hours Count (Количество отработанных часов)
Attribute 0C (12) Power Cycle Count (Количество полных циклов запуска/останова)
Attribute C2 (194) Temperature (Температура диска)
Spin Up Time и Spin Retry Count - изменение значения может означать проблемы с питанием или с мотором.
Current Pending Sector Count - число "кандидатов" в ремапы.
Offline Scan Uncorrectable Count - число ошибок, обнаруженных при Offline самотесте (запускается автоматически, когда нет обращений к диску)
UltraDMA CRC Error Rate - изменение значения может означать плохой контакт в сигнальном кабеле (между MB и HDD).

На остальное смотреть не обязательно, в поле raw может быть написано все что угодно и для каждого производителя по своему (в разных системах исчисления и т.д.).

"Следует отметить, что в винчестерах отдельных производителей Raw_Read_Error_Rate и Seek_Error_Rate параметры достигают максимума и обнуляютя несколько раз в день. Это связанно с политикой некоторых производителей в отношении SMART: в эти параметры пишутся все ошибки, а остальные производители только те, что не смог отловить контроллер." (с)

Current_Pending_Sector - число кандидатов на Reallocate, если сектор успешно читается повторно, то он убирается из списка «плохих» секторов, параметр Current_Pending_Sector уменьшается а Reallocate не происходит.
Изменение счётчика Current_Pending_Sector без Reallocate может быть из-за неправильного температурного режима накопителя.

24 января 2014 г.

Лев Толстой. Воскресение

Ближе же всех стоявший у перил невысокий лохматый старик, которого Нехлюдов сначала не заметил, не перекрестился, а, подняв голову, уставился на Нехлюдова. Старик этот был одет в заплатанный озям, суконные штаны и разношенные, заплатанные бродни. За плечами была небольшая сумка, на голове высокая меховая вытертая шапка.

- Ты что же, старый, не молишься? - сказал нехлюдовский ямщик, надев и оправив шапку. - Аль некрещеный?

- Кому молиться-то? - решительно наступающе и быстро выговаривая слог за слогом, сказал лохматый старик.

- Известно кому, богу, - иронически проговорил ямщик.

- А ты покажи мне, игде он? Бог-то?

Что-то было такое серьезное и твердое в выражении старика, что ямщик, почувствовав, что он имеет дело с сильным человеком, несколько смутился, но не показывал этого и, стараясь не замолчать и не осрамиться перед прислушивающейся публикой, быстро отвечал:

- Игде? Известно - на небе,

- А ты был там?

- Был - не был, а все знают, что богу молиться надо.

- Бога никто же не видел нигде же. Единородный сын, сущий в недре отчем, он явил, - строго хмурясь, той же скороговоркой сказал старик.

- Ты, видно, нехрист, дырник. Дыре молишься, - сказал ямщик, засовывая кнутовище за пояс и оправляя шлею на пристяжной.

Кто-то засмеялся.

- А ты какой, дедушка, веры? - спросил немолодой уже человек, с возом стоявший у края парома.

- Никакой веры у меня нет. Потому никому я, никому не верю, окроме себе, - так же быстро и решительно ответил старик.

- Да как же себе верить? - сказал Нехлюдов, вступая в разговор. - Можно ошибиться.

- Ни в жизнь, - тряхнув головой, решительно отвечал старик.

- Так отчего же разные веры есть? - спросил Нехлюдов.

- Оттого и разные веры, что людям верят, а себе не верят. И я людям верил и блудил, как в тайге; так заплутался, что не чаял выбраться. И староверы, и нововеры, и субботники, и хлысты, и половцы, и беспоповцы, и австрияки, и молокане, и скопцы. Всякая вера себя одна восхваляет. Вот все и расползлись, как кутята {Кутята - щенки. (Прим. Л. Н. Толстого.)} слепые. Вер много, а дух один. И в тебе, и во мне, и в нем. Значит, верь всяк своему духу, и вот будут все соединены. Будь всяк сам себе, и все будут заедино.

Старик говорил громко и все оглядывался, очевидно желая, чтобы как можно больше людей слышали его.

- Что же, вы давно так исповедуете? - спросил его Нехлюдов.

- Я-то? Давно уж. Уж они меня двадцать третий год гонят.

- Как гонят?

- Как Христа гнали, так и меня гонят. Хватают да по судам, по попам - по книжникам, по фарисеям и водят; в сумасшедший дом сажали. Да ничего мне сделать нельзя, потому я слободен. "Как, говорят, тебя зовут?" Думают, я звание какое приму на себя. Да я не принимаю никакого. Я от всего отрекся: нет у меня ни имени, ни места, ни отечества, - ничего нет. Я сам себе. Зовут как? Человеком. "А годов сколько?" Я, говорю, не считаю, да и счесть нельзя, потому что я всегда был, всегда и буду. "Какого, говорят, ты отца, матери?" Нет, говорю, у меня ни отца, ни матери, окроме бога и земли. Бог - отец, земля - мать. "А царя, говорят, признаешь?" Отчего не признавать? он себе царь, а я себе царь. "Ну, говорят, с тобой разговаривать". Я говорю: я и не прошу тебя со мной разговаривать. Так и мучают.

- А куда же вы идете теперь? - спросил Нехлюдов.

- А куда бог приведет. Работаю, а нет работы - прошу, - закончил старик, заметив, что паром подходит к тому берегу, и победоносно оглянулся на всех слушавших его.

Паром причалил к другому берегу. Нехлюдов достал кошелек и предложил старику денег. Старик отказался.

- Я этого не беру. Хлеб беру, - сказал он.

- Ну, прощай.

- Нечего прощать. Ты меня не обидел. А и обидеть меня нельзя, - сказал старик и стал на плечо надевать снятую сумку. Между тем перекладную телегу выкатили и запрягли лошадей.

21 января 2014 г.

Резервная копия в сети, запуск по расписанию, шифрование (debian)

В общем, опять. Надо сделать бекап сайта (debian) или чего угодно, вcтречаем:

Резервная копия в сети, запуск по расписанию, шифрование. А теперь по-английски: Backup, mysqldump, yandex-disk, cron, gpg.

1. Устанавливаем клиент yandex-disk.

2. Скрипт сохранения и шифрования.

#!/bin/sh
# get the current timestamp for filename #
NOWDATE=`date +%d.%m.%y_%H%M`

echo 'zipping ...'

BACKUP="/path/to/yadisk"
TMPBACKUP="/path/to/temp"

tar -cz /path/to/site/ | gpg --batch --yes -c --passphrase _passwordhere_ -o "$BACKUP/$NOWDATE-site_files.tgz.gpg"

echo 'mysql_dump ...'

DB_USER="dbuser"
DB_PASSWD="dbpassword"
DB_BASE="dbname"

mysqldump --user=$DB_USER --password=$DB_PASSWD --opt $DB_BASE > "$TMPBACKUP/$NOWDATE-db_backup"
gpg --batch --yes --passphrase _passwordhere_  -o "$BACKUP/$NOWDATE-db_backup.gpg" -c "$TMPBACKUP/$NOWDATE-db_backup" && rm -f "$TMPBACKUP/$NOWDATE-db_backup"


--batch --yes может даже лишнее. Но пригодится, если у вас одно и тоже имя для файла бекапа.

3. Пишем правило для crontab. Если вы путаетесь в параметрах crontab есть отличная вещь под названием cronWTF. :)

4. gpg для windows здесь.

Удаления старых файлов пока нет, так как после удаления на клиенте файлы остаются в корзине на сервере яндекс диска и занимают место и их надо все равно удалять вручную.

20 января 2014 г.

Получение данных через интернет или сеть в OpenHAB. Использование Oracle Java 1.7

Температура дома у нас есть. Пока у меня нет внешней температуры, ее можно получить в интернете. Сделать это очень просто используя http binding. В демо есть пример.

Итак, для начала попробуем использовать пример с демо. Ищем свой yahoo woeid.

Пишем в sitemap :

Frame label="Погода" {
  Text item=Yahoo_Temperature {
   Frame {
    Text item=Yahoo_Temp_Max
    Text item=Yahoo_Temp_Min
   }
   Frame {
    Chart item=Yahoo_Chart period=h refresh=10000
   }
  }
 }


Пишем в items :

Group Yahoo_Chart   (Weather)
Number Yahoo_Temperature   "Температура на улице yahoo [%.1f °C]" <temperature> (Yahoo_Chart) { http="<[http://weather.yahooapis.com/forecastrss?w=_тут ваш woeid_&u=c:60000:XSLT(yahoo_weather_temperature.xsl)]" }
Number Yahoo_Temp_Max   "Сегодня максимум [%.1f °C]" <temperature> (Yahoo_Chart)
Number Yahoo_Temp_Min   "Сегодня минимум [%.1f °C]" <temperature> (Yahoo_Chart)


Загляните в yahoo_weather_temperature.xsl - это шаблон для извлечения данных из возращенного xml.

Сейчас мы видим, что item Yahoo_Temp_Max и Yahoo_Temp_Min не привязаны к источнику данных. Откуда же их брать? Смотрим demo.rules, а также документацию здесь и прописываем себе тоже в файл home.rules:

             
import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*

rule "Update max and min temperatures"
when
    Item Yahoo_Temperature changed or
    Time cron "0 0 0 * * ?" or
    System started
then
    postUpdate(Yahoo_Temp_Max, Yahoo_Temperature.maximumSince(now.toDateMidnight).state)
    postUpdate(Yahoo_Temp_Min, Yahoo_Temperature.minimumSince(now.toDateMidnight).state)
end


Ну и последнее, сохранение. Добавим в rrd4j.persist:
Weather*, PersistTemp* : strategy = everyMinute, restoreOnStartup
Перезапускаем сервер и я получил ошибку в логах:
 Executing startup rule 'Startup'
22:32:27.859 ERROR o.e.x.x.s.XbaseScopeProvider[:189]- error during scoping
com.google.inject.ProvisionException: Guice provision errors:

1) Error injecting constructor, java.lang.NullPointerException: null key


Ошибка решается установкой Oracle Java.

Удаляем OpenJDK, устанавливаем Oracle Java (инсталлер качает oracel java с интеренета).

# /etc/init.d/openhab stop
# apt-get remove icedtea-6-jre-jamvm
# apt-get autoremove
# echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
# echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu precise main" | tee -a /etc/apt/sources.list
# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886
# apt-get update
# apt-get install oracle-java7-installer
# java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) Client VM (build 24.51-b03, mixed mode)


Вчера настроил yahoo, а сегодня сервер мне уже показывает вместо -20C реальных: -2C. Поэтому я решил не использовать погоду от yahoo. Решил добавить gismeteo, openweathermap.org и worldweatheronline.net и вычислить среднее арифметическое с показаний. Забирать температуру буду раз в полчаса, чтобы не нагружать сервер.

В общем-то, имея демо, несложно написать следующий сценарий, который пришел мне в голову (в скобках, какая часть конфигурации отвечает за действие).

  1. Запрашиваем данные раз в полчаса с трех источников (чаще нет смысла - их обычно обновляют раз в три часа). (items)
  2. Сохраняем данные раз в полчаса с каждого ресурса. (persist)
  3. Вычисляем среднюю температуру после обновления хотя бы одного источника (rules)
  4. Вычисляем максимальную и минимальную температуру после обновления средней температуры (rules)
  5. Сохраняем среднюю, максимальную и минимальную температуру при их обновлении (everyChange в persist)
  6. Выводим среднюю температуру, а также график средней, минимальной и максимальной (аналогично как в демо)

Update. Тут обнаружилась проблема (версия openHAB 1.4 - графики не выводятся, если данные сохранены реже, чем раз в минуту. Поэтому сохраняем раз в минуту пока. В общем, это не проблема, а фича. rrd имеет шаг (step) и сердцебиение (heartbeat). Шаг - время обновления базы rrd, сердцебиение - время в течении которого данные сохраняются. То есть, если мы не попадаем в heartbeat (сохраняем реже) - данные не сохраняются! heartbeat в openhab забит жестко (по крайней мере, пока) - и составляет 60 секунд. Поэтому лучше всего сохранять не реже 1 минуты. Шаг, насколько я понял, это параметр во время которого rrd принимает решение о хранении данных. В openhab оно настроено так:

 rrdDef.addArchive(function, 0.5, 4, 360); // one day (granularity 4 min)
                rrdDef.addArchive(function, 0.5, 15, 644); // one week (granularity 15 min)
                rrdDef.addArchive(function, 0.5, 60, 720); // one month (granularity 1 hour)
                rrdDef.addArchive(function, 0.5, 720, 730); // one year (granularity 12 hours)
                rrdDef.addArchive(function, 0.5, 10080, 520); // ten years (granularity 7 days)


То есть, после первого дня хранения, точность данных меняется на 4 минуты, после одной недели на 15 минут, одного месяца на на 1 час и так далее...

В принципе, все шаги очевидны, единственно, я немного затормозил на этапе вычисления средней температуры. Значения надо предварительно перевести в DecimalType:
rule "Update average temp"
when
    Item Owm_Temperature changed or
    Item Gismeteo_Temperature changed or
    Item Wwo_Temperature changed or
    System started
then
    var Number owm = Owm_Temperature.state as DecimalType
    var Number gismeteo = Gismeteo_Temperature.state as DecimalType
    var Number wwo = Wwo_Temperature.state as DecimalType
    postUpdate( Average_Temperature, ( owm + gismeteo + wwo ) / 3  )
end






ps. Заодно поменяем ntp сервер для даты в файле конфигурации. Я люблю pool.ntp.org.

17 января 2014 г.

Now Playing (сейчас играет) в связке foobar2000 и блога (сайта и др.)

Продолжу тему оповещения всех о вашей музыке. Теперь мы будем встраивать информацию на сайт, блог или любой ресурс поддерживающий http. Половина информации отсюда.
1. Ставим и настраиваем dropbox.
2. Качаем плагин Foobar2000:Now Playing Simple.
Прописываем путь к файлу C:\Users\_User_\Dropbox\Public\out.html (_User_ - меняем на ваш профиль). Строчка форматирования такая:

%artist% - %title% / 


3. Качаем два файла отсюда или прямо из моего блога: раз и два. Заливаем к себе в dropbox. Чтобы получить публичную безвременную ссылку в дропбокс замените 'www.dropbox.com' на 'dl.dropboxusercontent.com' в ней.
4. Прописываем виджет в блогспоте (или на сайте, поменяйте пути к dropbox на свои):
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8" src="http://dl.dropboxusercontent.com/s/gnhdeg1bt5gih4v/date.to_relative_time.jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="http://dl.dropboxusercontent.com/s/g87i4ss1odc8jeh/date.extensions.js"></script>
 
<script>
$(function(){

   $.get("https://dl.dropboxusercontent.com/sh/abo4xjbtappf8fp/2lHB9SZoe2/out.html", function(data) {
      $("#nowPlayingInfo").html(data);

 var now = new Date(); //"now"
        var play_Time = new Date(play_Time_str); // Date/Time formatting with %stamps as per AMIP functions and variables. (more info on their website)
        var diff = Math.abs(now-play_Time); //difference between the current time and the time the song was changed or started playing.
        var diff_minutes = Math.round(diff / (1000*60)); //difference in minutes.

        $("#now_playing_txt").text(new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes() - diff_minutes).toString());
         $("span.rel_").toRelativeTime();

   });
});
</script>

<div class="box">
<p>♫ <span id="nowPlayingInfo"></span><span style="font-size:80%;"><span class="rel_" id="now_playing_txt"></span></span></p>
</div>

Пример - справа вверху.

16 января 2014 г.

Сохранение данных OpenHAB. Графики

Отлично, температура у нас есть.

Кстати, теперь можно протестировать и android приложение, тут самая последняя версия. У меня на планшете заработало сразу, единственный момент, надо указывать не полный url, а вида http(s)://server:port/ , выбор sitemap происходит в самом приложении, а если он один, то и запускается сразу. К сожалению, работает на android только начиная с версии 4.0.3.

Переходим к теме. Для того чтобы заиметь график температуры ее надо сначала сохранить.

Изучаем документацию по Persistence (сохранение состояния) и rrd4j. Процитирую слова разработчика: "As said above, I would recommend rrd4j", тем не менее OpenHAB поддерживает больше число мест сохранения данных (db4o, sql и др.), которые могут работать одновременно. Для начала нам нужен org.openhab.persistence.rrd4j-1.3.1.jar в папке addons.

Конфигурация.

Для редактирования конфигурации советуют использовать openHAB Designer, так как там есть проверка и автодополнение синтаксиса. Основная идея файла конфигурации, сообщить OpenHAB, какие данные и когда сохранять. Для для того, чтобы определить "когда" сохранять данные используют слово "strategies" в файле конфигурации. Синтаксис:

Strategies {
    <strategyname1> : "<cronexpression1>"
    <strategyname2> : "<cronexpression2>"
    ...
    
    default = <strategynamex>, <strategynamey>
}


Следующие "стратегии" предварительно сконфигурированы, их можно не описывать, но можно прописать в default:

  • everyChange: сохранять состояние при его изменении
  • everyUpdate: сохранят состояние при его обновлении, даже если значение не изменилось
  • restoreOnStartup: если состояние не определено при запуске, последнее сохраненное значение будет загружено и элемент будет проинициализирован им. Это очень удобно для всех "виртуальных" устройств, которые не имеют связи с реальным железом. (например "Presence").

Структура описания элементов для сохранения.

Items {
    <itemlist1> [-> "<alias1>"] : [strategy = <strategy1>, <strategy2>, ...]
    <itemlist2> [-> "<alias2>"] : [strategy = <strategyX>, <strategyY>, ...]
    ...
}


где <itemlist> разделенный запятыми список следующих опций:
  • * - эта линия должна применяться для всех элементов в системе. Пример:
    // persist all items once a day and on every change and restore them from the db at startup      
    * : strategy = everyChange, everyDay, restoreOnStartup
  • <itemName> - одиночный элемент (его имя). Это может быть группа, но в таком случае сохранится только значение группы, не значения элементов.
  • <groupName>* - все члены группы будут сохранены, но не сама группа. если стратегия не предоставлена, используется стратегия по умолчанию, описанная в первой в используемой секции. Как опция, может быть предоставлен псевдоним, если сервис сохранения требует специального имени (например таблица в БД и т.п.).

Ну что же попробуем сохранить температуру. Создадим группу. Назовем ее PersistTemp. Добавляем в Items:

Group PersistTemp (All)
/* Indoor Temperatures */
Number Temperature_Hall "Температура [%.1f °C]" <temperature> (Hall, PersistTemp) { onewire="28.1A821E040000#temperature" }

Пишем rrd4j.persist (не забудьте про addons/org.openhab.persistence.rrd4j-1.3.1.jar ):

// persistence strategies have a name and a definition and are referred to in the "Items" section
Strategies {
 // for rrd charts, we need a cron strategy
 everyMinute : "0 * * * * ?"
}

Items {
 // let's only store temperature values in rrd
 PersistTemp* : strategy = everyMinute, restoreOnStartup
}


Обратите внимание, что крон тут не стандартный и начинается с секунд - подробнее здесь. Если все ок, смотрим директорию openHAB/etc/rrd4j/ . Там лежат файлы с данными.

Данные мы сохранили, а что делать с ними дальше? Изучаем демо, там есть график температуры.

Меняем sitemap. Группа в sitemap по умолчанию синхронизируется с элементами в группе в Items (довольно не очевидно и не очень понятно вначале, тем более в документации об этом не написано вроде). Теперь у нас группа в sitemap Hall будет состоять из Item и Chart, поэтому будет перезаписана правилами sitemap. В примере в демо такие "вручную описанные" блоки имеют вид "Text label="Widget Overview" icon="chart" {}". Но я оставил группу - и так работает, добавляем (пояснение по параметрам ниже):

Group item=Hall label="Зал" icon="office"
   {
   Frame {
         Text item=Temperature_Hall
         Chart item=Temperature_Hall period=D refresh=10000
         Chart item=Temperature_Hall period=W refresh=10000
         }
   }


Заходим и не работает график. Копируем url изображения и переходим на него в новой вкладке. Ошибка 500 Probable fatal error:No fonts found.

# apt-get install ttf-bitstream-vera ttf-dejavu ttf-liberation ttf-linux-libertine xfonts-terminus ttf-inconsolata
# /etc/init.d/openhab restart


Кстати, напоминаю, у меня OpenHAB и 1-wire сеть, которые работают на cubietruck.

Небольшая информация по графикам. Параметры, которые можно передавать:

w: ширина, опция, по умолчанию 480 пикселей
h: высота, опция, по умолчанию 240
period: время по оси X. Значения могут быть h,4h,8h,12h,D,3D,W,2W,M,2M,4M,Y - параметр опциональный, по умолчанию "D", то есть за последние 24 часа.
items: разделенные запятыми элементы (items).
или
groups: разделенные запятыми группы.


14 января 2014 г.

Знакомство с OpenHAB

В прошлой заметке я решил сменить платформу для управления умным домом.

Архитектура OpenHAB:



OpenHAB состоит из двух частей райнтайма (аналог контроллера в openremote, ну или просто сервер) и дизайнера. В принципе, дизайнером некоторые не пользуются - правят конфигурацию вручную.

Удаляем скрипт OpenRemote из автозагрузки.

# update-rc.d openremote remove

Java у нас уже стоит.

Runtime

Качаем runtime (проверьте версию, у меня на данный момент 1.3.1).

# wget http://openhab.googlecode.com/files/openhab-runtime-1.3.1.zip
# wget https://openhab.googlecode.com/files/openhab-addons-1.3.1.zip
# unzip openhab-runtime-1.3.1.zip -d /srv/openHAB
# unzip openhab-addons-1.3.1.zip -d oh-addons

Копируем необходимые addons в одноименную /srv/openHAB/addons. Я скопировал пока такие:

# ls -l
-rw-rw-r-- 1 root root   38725 Sep 19 00:25 org.openhab.action.mail-1.3.1.jar
-rw-rw-r-- 1 root root 1246014 Sep 19 00:26 org.openhab.action.xmpp-1.3.1.jar
-rw-rw-r-- 1 root root   31270 Sep 19 00:29 org.openhab.binding.http-1.3.1.jar
-rw-rw-r-- 1 root root   23164 Sep 19 00:31 org.openhab.binding.ntp-1.3.1.jar
-rw-rw-r-- 1 root root   29468 Sep 19 00:36 org.openhab.binding.onewire-1.3.1.jar
-rw-rw-r-- 1 root root   18734 Sep 19 00:46 org.openhab.persistence.exec-1.3.1.jar
-rw-rw-r-- 1 root root   19373 Sep 19 00:46 org.openhab.persistence.logging-1.3.1.jar
-rw-rw-r-- 1 root root  630764 Sep 19 00:46 org.openhab.persistence.rrd4j-1.3.1.jar
-rw-rw-r-- 1 root root     126 Aug 31 03:03 README

Обратите внимание, org.openhab.binding.owserver-1.3.1.jar используется для железки под названием EDS OWServer . Нам же нужен org.openhab.binding.onewire-1.3.1.jar .
Не забудьте, у нас уже установлен owfs с его owserver.

Копируем файл configurations/openhab_default.cfg в configurations/openhab.cfg и правим.

Из чего состоит openHAB Runtime?

1. Асинхронная шина событий.

Все узлы, которые не сохраняют свое состояние, должны информировать другие узлы о событиях, а также обновляться другими узлами реакцией на внешние события.
Существуют преимущественно два типа событий:

  • Команды, которые вызывают действие или изменение состояния некоторого элемента/устройства.
  • Обновления статусов, которые информируют об изменении статуса некоторых элементов/устройств (часто в ответ на команду).

2. Что такое элементы шины? Это items. Кто может запускать события?  Это sitemap и rules.

Items - это представление наших устройств, их значения можно менять с помощью правил или через Sitemap. Sitemap - графическое представление и структура. Rules, соответственно правила.

Вот еще одна красивая картинка шины событий openHAB:



Дизайнер

Так как у нас сервер без иксов и графики, то дизайнер мы будем использовать на машине с windows.
Качаем дизайнер, запускаем и получаю ошибку Failed to load the JNI shared library "c:\soft\jdk1.7\\bin\..\jre\bin\server\jvm.dll". Это потому, что Дизайнер (основанный на eclipse) работает в 32 битной среде. Качаем 32 (x86) битную яву и ставим.

Меняем конфиг (openHAB-Designer.ini) дизайнера.

-vm C:/soft/jdk1.7_32/bin/javaw.exe

И запускаем. Также скачаем папку configuration с сервера (напомню, я использую winscp). Укажем ее, как папку конфигурации (например c:\temp\openhab-demo-configuration-1.3.1\configurations\). Теперь скачем демо конфигурацию с сайта на рабочую машину, чтобы было на что ориентироваться.





Поковырявшись немного в дизайнере, кроме всплывающих подсказок (Ctrl+Space), ничего не нашел. Поэтому для начала им воспользуемся, а потом в принципе нужно будет прикрутить подсветку синтаксиса для mc.

Начнем. Создаем файл sitemap, например home.sitemap . Честно говоря, в дизайнере даже этого нет. :) Но создать можно нажав ctrl+N (там проблема с директориями - они не отображаются - но разобраться можно). Пишем в файле "sitem" и нажимаем Ctrl+Space. Выбираем шаблон sitemap. И у нас появляется нечто вроде этого:

sitemap name label="label" {
 
}


Читаем документацию по sitemap, чтобы понять, что же нам делать дальше. Удобно сравнивать, что у нас в demo.sitemap и в онлайн демо. Быстро понимаешь, что к чему.
Разобьем по комнатам (у меня, к сожалению, этажей нет).

sitemap name label="Дом" {
 Frame {
  Group item=Hall label="Зал" icon="office"
  }
 Frame label="Дата" {
  Text item=Date
 }
}


Иконки хранятся тут openHAB/webapps/images. Скачать дополнительные можно тут.

Создадим новый файл: Items/home.items, прочитав документацию по Items. Так как у нас 1-wire, читаем документацию по связи с openHAB тут, и правим файл конфигурации в секции OneWire Binding (собственно говоря я только прописал ip - onewire:ip=127.0.0.1). Формат записи item:
itemtype itemname ["labeltext"] [<iconname>] [(group1, group2, ...)] [{bindingconfig}]

Group All
Group Hall   (All)

/* Indoor Temperatures */
Number Temperature_Hall  "Температура [%.1f °C]" <temperature> (Hall) { onewire="28.1A821E040000#temperature" }

/* NTP binding demo item */
DateTime  Date   "Дата [%1$tA, %1$td.%1$tm.%1$tY]" <calendar> { ntp="Europe/Moscow:ru_RU" }


Копируем созданные файлы, исправленный openhab.cfg на сервер.
Меняем владельца папки с сервером на обычного пользователя и запускаем:

$/srv/openHAB$ ./start.sh
UnknownHostException: 


И получаем ошибку. Ну я получил. :) Прописать надо имя хоста в /etc/hosts на 127.0.0.1. Запускаем еще раз.

$ ./start.sh
Launching the openHAB runtime...
osgi> 23:20:46.100 INFO  o.o.c.internal.CoreActivator[:92] - openHAB runtime has been started (v1.3.1).
.........
23:21:17.223 INFO  o.o.u.w.i.s.WebAppServlet[:99] - Started Classic UI at /openhab.app
23:21:29.349 INFO  o.o.c.s.AbstractActiveService[:189] - NTP Refresh Service has been started
23:21:29.655 INFO  o.o.c.s.AbstractActiveService[:189] - HTTP Refresh Service has been started

Довольно долгий запуск таки. Заходим http://openhab-srv:8080/openhab.app?sitemap=home .



Дата на английском. Смотрим локали:

# locale -a
C
C.UTF-8
en_US.utf8
POSIX
Запускаем, выбираем там ru_RU.UTF-8 UTF-8 и перезапускаем сервер.:
$ sudo dpkg-reconfigure locales 
$ export LANG=ru_RU.UTF-8
или
$ sudo echo "LANG=en_US.UTF-8" > /etc/default/locale


Ну вот немного обрусевший вид.



Если что-то не работает, можно посмотреть более детальные логи, прописав в logback.xml <logger level="INFO" name="org.openhab"> на <logger level="DEBUG" name="org.openhab"> и <logger level="DEBUG" name="org.openhab.binding.onewire"> (для примера смотрите logback_debug.xml). Или просто запустив start_debug.sh - в этом случае сообщения смотрим прямо в консоли.

Запускаем сервер и смотрим.




Скрипт управления и автозагрузки здесь (меняем пользователя и путь).

Продолжение следует!

12 января 2014 г.

Безопасность в Elastix (дистрибутив Asterisk)

Пост для заметки. Во-первых, прочитать это. В принципе, пост наполовину оттуда - спасибо нужно говорить там :). У меня все за фаерволом, открыты только нужные upd порты (5060 и 10000-20000).
1. Закрываем доступ через web! Я сделал это внешним фаеролом. Если вы хотите попасть в web конифгуратора elastix создайте ssh туннель с другого хоста.
2. Запретим гостевые вызовы, для этого в файле sip_general_custom.conf пропишем allowguest=no
3. Баним всяких подборщиков паролей и сохраняем для восстановления правил после перезагрузки:

iptables -I INPUT -j DROP -p udp --dport 5060 -m string --string "friendly-scanner" --algo bm
iptables -I INPUT -j DROP -p udp --dport 5060 -m string --string "sipcli" --algo bm
iptables -I INPUT -j DROP -p udp --dport 5060 -m string --string "iWar" --algo bm
iptables -I INPUT -j DROP -p udp --dport 5060 -m string --string "sipsak" --algo bm
# /sbin/service iptables save
Правила брандмауэра сохраняются в /etc/sysconfig/iptables: [  OK  ]
4. Запускаем fail2ban.

touch /etc/fail2ban/filter.d/asterisk.conf

Правила скопипастены (нажмите view plain, чтобы скопировать по-нормальному):

# Fail2Ban configuration file
#
#
# $Revision: 251 $
#
[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf
[Definition]
#_daemon = asterisk
# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile. The
#          host must be matched by a group named "host". The tag "<host>" can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P<host>\S+)
# Values:  TEXT
#
# Asterisk 1.8 uses Host:Port format which is reflected here
failregex = NOTICE.* .*: Registration from '.*' failed for ':.*' - Wrong password
      NOTICE.* .*: Registration from '\".*\".*' failed for '' - Wrong password
     NOTICE.* .*: Registration from '\".*\".*' failed for '' - No matching peer found
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - No matching peer found
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - No matching peer found
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - Username/auth name mismatch
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - Device does not match ACL
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - Peer is not supposed to register
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - ACL error (permit/deny)
    NOTICE.* .*: Registration from '.*' failed for '<host>:.*' - Device does not match ACL
    NOTICE.* .*: Registration from '\".*\".*' failed for '<host>:.*' - No matching peer found
    NOTICE.* .*: Registration from '\".*\".*' failed for '<host>:.*' - Wrong password
    NOTICE.* <host> failed to authenticate as '.*'$
    NOTICE.* .*: No registration for peer '.*' \(from <host>\)
    NOTICE.* .*: Host <host> failed MD5 authentication for '.*' (.*)
    NOTICE.* .*: Failed to authenticate user .*@<host>.*
    NOTICE.* .*: <host> failed to authenticate as '.*'
    NOTICE.* .*: <host> tried  to authenticate with nonexistent user '.*'
    VERBOSE.*SIP/<host>-.*Received incoming SIP connection from unknown peer
    NOTICE.* .*: Sending fake auth rejection for device.* \(<host>:.*\)
    NOTICE.* .*: Failed to authenticate device.* \(<host>:.*\)
# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =

Добавляем в конфиг /etc/fail2ban/jail.conf (изменил немного, в почту слать ничего не надо, добавлены ip адреса игнорирования - внешняя статика и локальная сеть, бан изменен на пожизненный).

[asterisk-iptables]
enabled = true
filter = asterisk
action = iptables-allports[name=ASTERISK, protocol=all]
#sendmail-whois[name=ASTERISK,dest=ваш_емаил_куда_слать_сообщения_о_бане, sender=fail2ban@local]
logpath = /var/log/asterisk/full
maxretry = 10
bantime = -1
ignoreip = 127.0.0.1 XXX.XXX.XXX.XXX 192.168.0.1/24

/etc/init.d/fail2ban start

Статус смотрим командой fail2ban-client status asterisk-iptables или # iptables -L -n (уже забанил :) )

# fail2ban-client status asterisk-iptables
Status for the jail: asterisk-iptables
|- filter
|  |- File list:        /var/log/asterisk/full
|  |- Currently failed: 1
|  `- Total failed:     16
`- action
   |- Currently banned: 1
   |  `- IP list:       50.30.35.55
   `- Total banned:     1

Для автостарта fail2ban в файл /etc/rc.d/rc.local добавим строчку /etc/rc.d/init.d/fail2ban start

После рестарта fail2ban или после перезагрузки все адреса сбрасываются. Поэтому можно добавить /sbin/service iptables save в крон. Я думаю раз в час будет достаточно ( /etc/crontab ):

0 * * * * root /sbin/service iptables save
Правда командой fail2ban-client status asterisk-iptables после перезагрузки забаненных мы уже не увидим. Если вы все-таки захотите видеть и чтобы fail2ban рулил сам iptables после перезагрузки, то прочитайте вот этот пост. Защита от SIP флуда описана тут.

8 января 2014 г.

Безопасный доступ к OpenRemote

Мы создали первое приложение в OpenRemote в локальной сети. Но ясное дело , что управлять то мы хотим не только из локальной сети, а еще и через интернет. Это означает, что нам надо обеспокоиться нашей безопасностью. Ну и самые элементарные вещи это - внедрение парольной защиты и шифрование трафика между клиентом и контроллером.

1. Зашифрованное соединение.

Очевидно, что для шифрования трафика надо использовать https. Подготовим самоподписанные сертификаты в директории /home/openremote/.keystore:

$ keytool -genkey -alias tomcat -keyalg RSA -validity 3600 -keystore ~/.keystore

Когда спросят про второй пароль его вводить не надо - вы обязаны оставить прежний (по умолчанию). Далее переходим в файл /srv/openremote/conf/server.xml и правим следующий кусок:

    
<connector clientauth="false" keystorepass="changeit" 
maxthreads="150" port="8443" protocol="HTTP/1.1" scheme="https" 
secure="true" sslenabled="true" sslprotocol="TLS">

Внимание, мы не только его раскомментировали, но и добавили keystorePass="changeit" - пароль, который вводили при генерации сертификатов. Пробуем запускать скрипт с параметром run - так видно логи сервера. Заходим https://192.168.xx.xx:8443/webconsole/ - должно работать. Теперь закомментируем небезопасный порт 8080, чтобы протестировать клиентов.

Пробуем андроид клиент - в нем адрес контроллера оставляем, только нажимаем на кнопочку SSL в самом низу настроек. Порт указан там же. Теперь пробуем онлайн webconsole, тут по-другому. Удаляем старый адрес контроллера, вводим новый https://192.168.xx.xx:8443/controller/

2. Авторизация.

Хорошо, с шифрованным соединением решили. Авторизация тоже заложена в системе, но немного не явным образом. Для начала правим файл: /security/users.xml:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="openremote"/>
  <user username="vermus" password="test" roles="openremote"/>
</tomcat-users>


Потом открываем файл webapp/controller/WEB-INF и расскоментируем следующие строки:
<!-- Constraint resource: /rest/control/* -->
  
    <security-constraint>
      <web-resource-collection>
        <web-resource-name>Control command RESTful service of Openremote Controller</web-resource-name>
        <description>Control command RESTful service of Openremote Controller</description>
        <url-pattern>/rest/control/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
        <role-name>openremote</role-name>
      </auth-constraint>
    </security-constraint>
  

  <!-- Constraint resource: /rest/panel/* -->
  
    <security-constraint>
      <web-resource-collection>
        <web-resource-name>Panel identity RESTful service of Openremote Controller</web-resource-name>
        <description>Panel identity RESTful service of Openremote Controller</description>
        <url-pattern>/rest/panel/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
      </web-resource-collection>
      <auth-constraint>
        <role-name>openremote</role-name>
      </auth-constraint>
    </security-constraint>
  

  
   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Status command RESTful service of Openremote Controller</web-resource-name>
       <description>Status command RESTful service of Openremote Controller</description>
       <url-pattern>/rest/status/*</url-pattern>
       <http-method>GET</http-method>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       <role-name>openremote</role-name>
     </auth-constraint>
   </security-constraint>
   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Polling command RESTful service of Openremote Controller</web-resource-name>
       <description>Polling command RESTful service of Openremote Controller</description>
       <url-pattern>/rest/polling/*</url-pattern>
       <http-method>GET</http-method>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       <role-name>openremote</role-name>
     </auth-constraint>
   </security-constraint>
  
 
    <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>OPENREMOTE_Controller</realm-name>
    </login-config>
    <security-role>
      <role-name>openremote</role-name>
    </security-role>
</pre>


Заходим в webconsole и при клике на выбранной панели система спросит нас логин с паролем. Приложение для андроид (кстати, качайте последнее с сайта, в google play на данный момент 2.0.0 , который даже не поддерживает https).

Итак, мы неплохо обезопасили нашу систему, жаль что для новичков эти шаги были бы не очевидными. Плюс меня еще смущает: древняя версия openremote под андроид в гугл плей, отсутствие внятной документации, онлайновый дизайнер, отсутствие сбора данных, ориентированность на платный продукт и т.п....
В общем, я решил испробовать другую систему openhab, которая лишена всех этих недостатков, хоть в ней вроде бы и есть проблема с 1-wire. Я думаю ее можно как-то решить, кроме owserver же есть еще и owhttpd (может http binding сработает) и owfs (может можно писать в файлы локально). Хоть ее и начали писать позже openremote кстати! Но по моим наблюдениям она гораздо динамичнее развивается. В общем, будем смотреть!

5 января 2014 г.

Платформа умного дома OpenRemote. Знакомство. Подключаем 1-wire через owfs.

Пока я жду DS2406P+ и DS2408S+ занялся серверной и клиентской стороной умного дома.

OpenRemote представляет из себя сервер, который получает команды от мобильного или веб приложения и дальше транслирует их другому контроллеру или серверу.

OpenRemote это:

1) Сервер умного дома, работает на десятке платформ, даже на NAS Synology и Windows.

2) Онлайн-cреда для разработки приложения.

3) Мобильное приложение, которое загружает данные для своей работы из среды для разработки.




Поддерживаемые технологии.
AMX, KNX, Lutron, Z-Wave, 1-Wire, EnOcean, xPL, Insteon, X10, Infrared, Russound, GlobalCache, IRTrans, XBMC, VLC, panStamps, Denon AVR, FreeBox, MythTV и другие.

У нас есть owfs с показаниями термометра. Давайте посмотрим как нам связать все это дело воедино.

Установка.

Сubietruck похож на Raspberry Pi, поэтому мы воспользуемся следующим мануалом.

Процессор в Cubietruck версии ARMv7, который поддерживает операции с плавающей точкой на аппаратном уровне (Hard-float). Наш Debian ( ARMv7 (EABI hard-float ABI, «armhf») ) также поддерживает.

Вообще пишут, что использование java машины с плавающей точкой на аппаратном уровне может иметь проблемы со стабильностью и совместимостью. Посмотрим, что у нас в дебиане. Перед тем как ставить java я немного изучил возможные проблемы и какую все таки версию ставить. Читаем комментарий ANDREAS DROLLINGER по ссылке - в нем написано:

OpenJDK (IcedTea6 Zero VM) is slower than Oracle Java, but it is available for hard float installation and the Drools rule engine 5.1.1 works.


В общем-то рекомендует нам использовать OpenJDK 6 с IcedTea6 (с поддержкой таки hard float), оно немного помедленней, ну и ладно, у нас нагрузка не высокая, будет критично - переустановим. Смотрим, что есть у нас в наличии.

root@debtruck:~# apt-cache search icedtea-6-jre
icedtea-6-jre-cacao - Alternative JVM for OpenJDK, using Cacao
icedtea-6-jre-jamvm - Alternative JVM for OpenJDK, using JamVM


Судя по довольно интересным статье сравнения JamVM немного получше, чем Cacao, поэтому буду пробовать его. Ставим:

# apt-get install icedtea-6-jre-jamvm
root@debtruck:~# which java
/usr/bin/java
# java -version
java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1~deb7u1)
root@debtruck:~# which java
/usr/bin/java
# java -jamvm -version
java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1~deb7u1)
JamVM (build 1.6.0-devel, inline-threaded interpreter with stack-caching)
# export JAVA_HOME=/usr

Редактируем /etc/java-6-openjdk-armhf/jvm-armhf.cfg перенеся -jamvm KNOWN в начало списка.

# java -version
java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1~deb7u1)
JamVM (build 1.6.0-devel, inline-threaded interpreter with stack-caching)

Видим, что у нас JamVM используется по умолчанию.

Качаем контроллер.
# cd /usr/src/
# wget http://download.openremote.org/

У меня скачался OpenRemote-Controller-2.1.0_SNAPSHOT-2013-06-17.zip.

Настройка и использование OpenRemote

Теперь давайте создадим пользователя под которым будет запускаться контроллер. ( #adduser openremote , #su openremote ). Создадим под root директорию /srv/or/ дадим chown openremote на нее. Распакуем архив в нее.
$ cd /srv/or/bin
$ chmod +x openremote.sh
$ ./openremote.sh run
....
INFO: Server startup in 19386 ms
Регистрируемся на сайте. Заходим в online редактор. Я обычно не доверяю таким онлайн штукам. Но да ладно, в принципе есть исходники - пишут, что можно и оффлайн устанавливать дизайнер, но пока я смысла в этом не вижу. Создаем новый Device.



Теперь создаем команду (тут можно не прописывать хост и порт каждый раз в версии 2.2, там есть config for controller onewire. В версии 2.1. пока его нет).



Теперь создаем сенсор.



Теперь перейдем во вкладку "Дизайн". Создадим новую панель Android (у меня только андроид :) ). Добавим в нее пару Label - один просто текст, во втором выберем наш сенсор. Ну вот вроде и готово. Перейдем по адресу http://openremoteserver:8080/controller/ и нажмем Sync with Online Designer, тем самым загрузим созданное приложение на контроллер OpenRemote (Что интересно, можно делать это и оффлайн, тем самым сохранив бекап с приложением - в онлайн редакторе есть возможность сохранить приложение как zip файл, а на контроллере импортировать). После синхронизации заходим на веб-консоль ( http://192.168.xx.xx:8080/webconsole/ ) и нажимаем найти контроллер, после этого вебконсоль находит наш локальный контроллер, нажимаем на него и видим наше созданное приложение. И опять не работает. :)

Проблема вот в чем, по умолчанию owserver отвечает только по адресу localhost:4304 , то есть контроллер по имени благополучно подключается, а вот по ip (127.0.0.1) нет. Поэтому пропишем так server: port = 127.0.0.1:4304 (для доступа из сети просто пишем server: port = 4304) в owfs.conf. Перезапускаем сервер owserver: #service owserver restart . Работает:



Для установки приложения на мобильный телефон, устанавливаем приложение для андроид и оно само находит контроллер в локальной сети - подключаемся, работает.
Добавляем строчку cd /srv/openremote/bin в openremote.sh, иначе при запуске из другого места могут вылезти косяки. Скрипт init.d для контроллера

#!/bin/sh
### BEGIN INIT INFO
# Provides:          openremote
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

#!/bin/sh

User=openremote
orpass=/srv/openremote/bin

case "$1" in

stop)
        echo "Stopping OpenRemote Controller..."
        su -l $User -c "$orpass/openremote.sh stop" > /dev/null 2>&1 &
        ;;

start)
        # start OpenRemote in background mode
        su -l $User -c "$orpass/openremote.sh start" > /dev/null 2>&1 &
        echo "OpenRemote Controller started..."
        ;;

restart)
        $0 stop
        sleep 5
        $0 start
        ;;
*)
        echo "usage: $0 { start | stop | restart}" >&2
        exit 1
        ;;

esac

Ну и автозапуск update-rc.d.

ps. Вообще для доступа через интернет ip адрес контроллера должен быть внешним.

Now Playing (сейчас играет) в связке foobar2000 и pidgin

Отображение в строке статуса pidgin трека, играющего в foobar2000. Пишу для памяти. :)

1. Ставим плагин http://code.google.com/p/pidgin-musictracker/ . К сожалению, поддержка foobar2000 у меня не заработала (хотя ее и удалить собираются вскоре). Поэтому:
2. Ставим foo_winamp_spam в foobar2000 (копируем в папку components, перезапускаем foobar).
3. Заходим в pidgin в "средства-модули", включаем winamp. Чтобы увидеть свой статус либо качаем плагин http://vayurik.ru/wordpress/toobars , либо добавляем себя в ростер (список контактов).
4. Если что-то пошло не так, открываем "помощь-окно отладки". У меня например Status format: пустой, поэтому в статус ничего не выводилось. Это происходило потому, что плагин думал, что проигрывание остановлено (поле "остановлено" в настройках по умолчанию пусто). Плюс %t - берет полное название (%t настраивается в foobar2000-tools-winamp api emulation). В pidgin-musictracker вообще какое-то мутное определение плеера, без foo_winamp_spam плагин таки определяет заголовок, но при парсинге возвращает -1. Похоже сначала сканируются заголовки окон, а потом решается какой API использовать)

В общем, я настраиваю второй раз, на win 7 определение того, что трек "играет" работало, сейчас пока оставляю так.

Шаблон: np: %t
Результат:
Состояние: Не беспокоить: np: Samurai - Four Seasons

Update. Если у вас на срастется с плагином winamp API под foobar2000, его можно заменить плагином WLM Notifier, его надо скопировать в components, включить в foobar2000, после чего поменять в настройках pidgin-musictracker плеер на Messenger compatible interface. У меня он работает гораздо лучше (понимает "стоп" и "паузу"):

Состояние: Не беспокоить: ♫: Roxy Music - Avalon

2 января 2014 г.

Создание термометра в сети 1-wire

Итак, мы научились подключать устройство 1-wire к контроллеру.

Оффтопик. Давайте-ка я все-таки расскажу что и где покупал.
1. Cubietruck - здесь.
2. Контроллер DS9490R, термометр DS18B20 - здесь.
3. Прототипные платы - здесь.
4. Проводочки :) - 30 ft Kynar wire wrap wire 30 awg 4 modding 10 color.
5. 100 штук RJ11\12 - 100× Modular Lan Network Connector Plug RJ11 6P6C CAT5
6. Остальное в местном радио магазине (включая внешние телефонные розетки и некоторые разъемы по питанию).

Для создания термометра используем схему с сайта Бенукс (сайт вообще отличный, самое лучшее и доступное описание 1-wire сети и устройств).

Травить плату я не умею (хотя в инете полно видео технологии ЛУТ - может быть в скором времени и попробую), поэтому решил делать на прототипных платах - схема в принципе не такая сложная:



По схеме: в принципе ничего сложного даже для такого новичка, как я. 78L05 - стабилизатор, преобразует 12 вольт на нашей шине в 5 вольт для датчика. Кстати! Мы приведем сеть 1-wire в порядок и пустим по ней 12 вольт, не будем использовать паразитное питание. Остальные элементы описаны разработчиком схемы (обсуждение немного другой платы, поэтому 5 пункт можно не читать и обозначения не все совпадают - но я думаю догадаться можно о чем речь):

1. Диод D6 - для каких целей он служит и почему выбран именно КД521?
Этот диод уменьшает влияние "просадок" по общей шине питания на данный модуль. Здесь допускается применение любого маломощного выпрямительного диода. КД521 взят только потому, что был под рукой.

2. Конденсатор C2 - для каких целей он служит? Ведь в datasheet к 7805 указаны только 2 конденсатора, по 0,33 и 0,1 соответственно.
Во время "просадок" питания по общей шине этот конденсатор поддерживает питание данного модуля.

3. Сопротивление R2 - почему именно 100 Ом?
Оптимальный номинал, который с одной стороны является элементом защиты, а с другой стороны не оказывает большого влияния на полезные сигналы 1-wire.

4. Стабилитрон D3 - почему выбран именно КС156?
Этот элемент совместно с резистором R2 является цепочкой защиты модуля от импульсных помех по микросети. Выбран с несколько большим напряжением, чтобы не влиять на полезный сигнал 1-Wire и Pullup, а "срезать" случайные импульсные помехи превышающие 5,6 В.

5. Действительно ли так нужна опторазвязка на схеме между DS2413 и реле, или можно обойтись транзистором + реле?

Можете исключить опторазвязку, но тогда при работе через USB-адаптер может быть подвисание порта.

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



Теперь надо сделать саму шину. Для этого я купил 6 контактные телефонные разъемы (RJ12 в простонародии - почитайте вики, чтобы не купить что-нибудь не то) по цене примерно 200 рублей за 100 штук (см. пункт 5 в закупках). Я решил обжимать по схеме B в RJ45 (без оранжевого и светло-оранжевого) ибо уже привык к ней :) , запишем распиновку. Теперь обжимаю все шесть проводов, а не как в прошлом посте, так обжимка получается качественнее.



У меня вид с обратной стороны по B (то есть контакты от 8 до 3 включительно)



1. Светло-зелёный - не используется.
2. Синий - черный в розетку - +12 вольт.
3. Светло-синий - красный в розетке - Data.
4. Зелёный - зелёный в розетке - земля.
5. Светло-коричневый - жёлтый в розетке - +18 вольт.
6. Коричневый - свободный.

"Организатор" шины

Теперь я подумал как же мы будем подключать 18 и 12 вольт? Ну и решил взять еще одну розетку и сделать из нее некий переходник-организатор (дурацкое название, что-то сейчас лучше в голову не пришло :) ).



Смотрим распиновку. Нам нужны только 3 и 4 контакты. Обжимаем как хотим один конец (советую выщипать лишние контакты), а второй оставляем - его будем впаивать в макетплату.

Разбираем розетку, паяем. У меня получилось вот так вот



Обжимаем еще один провод. Мультиметром проверяем работу схемы и правильность соединений. Проверяем 12 вольт на шине. 18 вольт у меня пока нет. Чтобы было удобнее пользоваться мультиметром - подключаем по розетке на оба конца:



Пробуем вставлять наш термометр, пока без DS18B20. Проверим напряжение 5 вольт.



Последний шаг - впаиваем DS18B20 в плату под термометр. Распиновка:



У меня заработало не сразу. :) Вышла небольшая заминка по проводам. Поэтому прежде чем обжимать коннектор в DS9490R выщипайте лишние контакты в коннекторе, оставьте два посередине и только после этого обжимайте.
В итоге, у нас есть первое устройство в "нормальной" сети 1 wire, которую можно расширять не боясь. Еще я понял, что лучше все-таки травить плату, это наверное быстрее (если конечно есть работающий макет), чем использовать такие вот прототипные платы (хотя может их надо как-то по другому использовать, я честно говоря не знаю. :) ) и качественее.

Кусочек информации с моего термометра:

power YES (1)
r_address 710000041E821A28
r_id 0000041E821A
r_locator FFFFFFFFFFFFFFFF
temperature  26.3125
temperature10  26.25
temperature11  26.375
temperature12  26.3125
temperature9  26.5


Система в сборе



ps. Кстати, неплохо бы в наш дебиан еще поставить системные логи:
#apt-get install rsyslog