![](https://habrastorage.org/files/b6e/e84/273/b6ee8427395447e5bbe9ee34338e463e.jpg)
В итоге, можем управлять домашними приборами и получать от них статусы удаленно и совместно с другими пользователями через общий чат.
Интересно?
А зачем?
Вопрос “а зачем это нужно?” не всегда остро стоит для проектов из серии «умный дом» и всяческих Internet of Things, здесь часто тратится куча времени и денег на автоматизацию чего-то, что на практике удобнее переключать по старинке обычным настенным выключателем :-) Но при этом получаешь кучу удовольствия и полезного опыта в процессе и далее радуешься исправной работе механизма, который сделал сам.
Но кроме вышеупомянутых удовольствий, мне кажется, управление домом и общение устройств через чат, конкретнее XMPP протокол, имеет право на жизнь по следующим причинам:
- Человеческий язык — довольно легко заставить чат бот общаться с вами на человеческом языке, что довольно удобно, особенно для менее технических членов семьи. Также это позволяет в перспективе подключить голосовое управление.
- Универсальный удаленный доступ — к XMPP чат серверу можно подключаться откуда угодно и из любого Jabber совместимого IM клиента. Людям удобно, а как подключить устройства описано в данной статье.
- Удобное управление для всей семьи — подключите домашних в единый групповой чат, где сидят боты, отвечающие за дом или приборы в доме. Вы можете обсуждать свои семейные вопросы и одновременно управлять домом. Все видят, кто какие команды подал приборам, можно видеть их (ботов) ответы и отчеты, просмотреть предыдущую историю и т.п. Это удобно.
- Система независимых распределенных агентов. Каждый прибор или набор датчиков, которые имеют представительство (по сути, пользователя) в чате, соответственно являются независимыми агентами и могут общаться с другими приборами и быть управляемыми ими или вами напрямую. Единый сервер не обязателен. Можно поднять свой чат бот для каждого важного прибора или датчика, а также настроить главного бота с элементами AI, такой себе “дворецкий” или “majordomo”, который будет всеми девайсами управлять, причем они будут общаться в доступном вам и другим членам семьи чате на понятном вам языке, так что вы всегда можете отследить что происходило или вмешаться в процесс.
Реквизит
Для данного мини-проекта нам потребуются следующие компоненты:
1. Raspberri P.
У меня модель B, заказал буквально за день до объявления о выходе B+, но в принципе, любая модель тут подойдет, главное смотрите, чтоб GPIO пины были совместимы с управляющим модулем, который вы выберете. Об этом ниже.
Ну а так, главное требование — запустить чат бот на питоне.
![](https://habrastorage.org/files/495/0d6/00e/4950d600e7d348a7a115303c73552e60.jpg)
2. Аксессуары к вашему Pi.
WiFi модуль, простые USB клавиатура и мышь, карточка SD памяти с дистрибутивом Raspbian, блок питания, по желанию — пластиковый корпус.
Это стандарт для “малинки”, но т.к. я покупал её впервые, специально под этот проект, то не знал, что WiFi и SD карта не входят в стандартный комплект, и пришлось дозаказывать, так что имейте в виду. Также для настройки вам потребуется монитор или телевизор с HDMI кабелем.
![](https://habrastorage.org/files/b2d/ce7/d2f/b2dce7d2f64f40c5bc4c95c873ae7fb9.jpg)
3. Управляющий модуль (RF transmitter) и розетки или другие приборы с приёмником (RF receiver).
Здесь нужно сказать, что я пошел по быстрому или ленивому пути, и заказал готовый RF модуль для Pi и набор радиоуправляемых розеток от Energenie. В комплекте идет готовый RF передатчик, который подключается на GPIO пины вашей малинки. Кому этот путь не по душе, есть альтернативы, в инете куча гайдов о том, как к существующим радиоуправляемым приборам подобрать код и управлять ими через простой дешевый китайский RF передатчик. В качестве альтернативы можно через Pi управлять приборами непосредственно прямым проводным подключением с GPIO, а также через WiFi и по другим каналам.
Вот фото моего Energenie комплекта:
![](https://habrastorage.org/files/ba5/494/6c9/ba54946c952e4686ac2802f55333020a.jpg)
![](https://habrastorage.org/files/d22/dc3/1eb/d22dc31eb7eb4487a27f0869c388257c.jpg)
4. Чат-клиент.
В данном туториале используется Q-municate, это мессенджер с открытым исходным кодом от нашей платформы QuickBlox, который можно скачать с github и забилдить под iOS, Android или запустить Web версию на десктоп и других платформах. Преимущество использования Q-municate в том, что вы можете кастомизировать интерфейс под себя и сделать своё собственное приложение, например, только для своей семьи.
Но это совершенно не обязательно. Вы можете использовать любой Jabber/XMPP совместимый клиент, например Adium.
Итак, начнем.
Устанавливаем дистрибутивы / dependencies для Raspbian
Логинимся на малинку и ставим следующие вещи под рутом:
apt-get install python-dev
pip install sleekxmpp
pip install dnspython
pip install pyasn1 pyasn1-modules
apt-get install python-rpi.gpio
Нам собственно нужен sleekxmpp, это базовый проект для чат бота, а остальное решает вопросы с различными зависимостями для этого проекта. Ну и плюс python-rpi.gpio позволит контролировать GPIO пины малинки из нашего питон скрипта.
Подключаем и проверяем модуль радиоуправления
Если вы используете другой модуль, не от Energenie, то эту часть вам придется исследовать самостоятельно.
При использовании же готового Pi-mote модуля всё просто и хорошо описано в официальной инструкции от производителя: energenie4u.co.uk/res/pdfs/ENER314%20UM.pdf
Лично я потратил непозволительно много времени пытаясь определить, работает ли мой комплект радиоуправляемых розеток, меряя напряжение на малинке, пробуя неофициальные скрипты и т.п., так как розетки Energenie почему-то никак не хотели управляться скриптом, как это описано у производителя и на нескольких блогах. Не сразу дошло еще раз заглянуть в мануал и прочитать на этот раз внимательно, а там английским по белому говорится, что сокеты нужно запустить сначала в обучающем режиме. Логично. В своё оправдание могу только сказать, что проект делал рано по утрам в выходные, пока семья спит, видимо, сказался недосып :-)
Итак, обучаем. Согласно инструкции, запускаем скрипт
sudo python ENER002.py
вставляем розетки в розетки ) и если лампочки на них не мигают, то переводим в режим обучения нажатием кнопки выключения в течение 5 секунд. Лампочки замигали, нажимаем “Enter” на клавиатуре чтобы подать сигнал из скрипта и видим быстрое мигание лампочки, это значит что обучение прошло успешно. Повторяем то же самое с остальными розетками. Один Pi-mote модуль может подавать 4 разных кода, т.е. управлять можно 4 разными наборами Energenie розеток, при этом никто не мешает использовать один код для нескольких розеток одновременно.
Поднимаем чат сервер
Нам нужен XMPP / Jabber совместимый чат сервер с возможностью создания MUC (группового чата или чат комнаты) в нём, чтобы подключить туда наш чат бот и человеков-пользователей.
В принципе, на Pi можно поднять свой чат сервер, например вот здесь http://box.matto.nl/raspberryjabberd.html описывается установка ejabberd на Raspberri Pi.
В данной статье мы опять идем по пути наименьшего сопротивления и используем готовый бесплатный чат сервер от QuickBlox. Вам нужно просто создать аккаунт, чтобы получить свой собственный чат сервер и веб админку к нему.
Шаги ниже описывают регистрацию и заодно создание пользователя для нашего чат бота и MUC комнаты для общения.
1. Регистрируемся на http://quickblox.com/signup/ или логинимся через GitHub / Google
2. Создаем приложение в админке.
![](https://habrastorage.org/files/00f/5d1/464/00f5d1464063494799542cbad8ec7d70.png)
3. Создаем пользователя для нашего чат бота (Users -> Add new user)
![](https://habrastorage.org/files/8eb/2f1/181/8eb2f1181f254960a0583adc34371139.png)
4. Создаем MUC комнату для общения (Chat -> New dialog)
![](https://habrastorage.org/files/b45/fc8/900/b45fc89002c344c9b47e0ea7271a6fc2.png)
Всё, ваш собственный XMPP чат сервер готов к приёму граждан и ботов, 24 часа в сутки, без перерывов на обед.
Пишем и настраиваем чат бот
Мы уже установили библиотеку SleekXMPP, которая реализует XMPPшный чат бот на питоне.
На сайте проекта есть хороший пример по MUC чат боту: http://sleekxmpp.com/getting_started/muc.html
а исходник можно взять здесь: https://github.com/fritzy/SleekXMPP/blob/develop/examples/muc.py
Дальше нам нужно взять и модифицировать это под свои нужды.
Если вы тоже используете Energenie для управляемых розеток и QuickBlox для чат сервера, то вы можете взять мой готовый скрипт здесь: https://github.com/QuickBlox/sample-powerbot-python-rpi.
Вам нужно будет только поменять credentials в начале скрипта, прописав туда свои ключи приложения и пользователя (того, что мы создали выше).
Ниже мы пройдемся более детально по внесённым изменениям, но вкратце, что было сделано (заранее прошу прощения за уровень питон кода — давно не программист и тем более не питонщик — буду благодарен за любые улучшения и пулл реквесты):
1. Добавлено авто-присоединение по приглашению в другие чат комнаты.
2. Подправлена совместимость с QuickBlox и Q-municate (мелочи типа формата названия чат комнат и т.п.)
3. Добавлен собственно парсинг команд для управления приборами — в нашем случае это «lamp on», «lamp off», «all on» и «all off» — и вызов функций switch_on / switch_off из питон модуля energenie, который уже отдает команды на плату радиопередатчика через GPIO.
Кто работает напрямую с GPIO, посмотрите в energenie.py как реализована работа с GPIO.
Авто-присоединение в другие чат комнаты
Опциональная фича, но лично мне этого не хватало, например, когда в мессенджере у вас в друзьях висит этот бот-дворецкий и вы можете создавать новые чаты и приглашать его туда. Без этого работать будет, но тогда бот будет привязан к тому чату, в который вы его запустили.
Как реализовать авто-присоединение — парсим станзы входящих XML сообщений, т.к. нам обязательно прийдет сообщение о том, что создан такой-то MUC чат, если данный пользователь был туда приглашен.
В нашем случае мы используем платформу QuickBlox и конкретное приложение Q-municate, в нём приглашение в новый групповой чат выглядит примерно так:
RECV: <message to="1265350-7232@chat.quickblox.com" from="1234040-7232@chat.quickblox.com/098CA696-A60A-480D-B744-BE7DFC4FE6D3" id="1404538064.385079" type="chat"><body>Taras Filatov created new chat</body><extraParams><_id>53b78c0c535c12798d005055</_id><occupants_ids>1234040,1258466,1265350</occupants_ids><type>2</type><date_sent>1404538064</date_sent><name>Yanus Poluektovich, Sergey Fedunets</name><xmpp_room_jid>7232_53b78c0c535c12798d005055@muc.chat.quickblox.com</xmpp_room_jid><notification_type>1</notification_type></extraParams></message>
Отслеживаем фразу “created new chat” в XMPP станзах, и если она встречается, то парсим оттуда xmpp_room_jid, это и будет id вновь созданной комнаты.
Дальше запускаем процесс с этим же скриптом
Имейте в виду, для того чтоб это работало, нужно сделать скрипт исполняемым:
chmod +x powerbot.py
Код реализации представлен ниже:
if msg['mucnick'] != self.nick and "Create new chat" in msg['body']:
from bs4 import BeautifulSoup
y = BeautifulSoup(str(msg))
roomToJoin = y.xmpp_room_jid.string
print ("Got an invite to join room")
botId = subprocess.Popen([selfPath + " -d -j " + qbChatLogin + " -r " + str(roomToJoin) + " -n " + qbChatNick + " -p " + qbUserPass], shell=True)
print "spawned new bot ID="
print botId
self.send_message(mto=msg['from'].bare,
mbody="Thank you for your kind invitation, joining your new room now!",
mtype='groupchat')
Приветствие + инструкции
Определяем кодовое слово, в данном случае “powerbot”, и выдаем в ответ приветствие и подсказку о том, как пользоваться / общаться с нашим ботом.
Проверка “if msg['from'] != self.nick” нужна чтобы бот не реагировал на сообщения от себя самого.
#
# Reply to help request (any message containing "powerbot" in it)
#
if msg['mucnick'] != self.nick and "powerbot" in msg['body']:
reply_test_message = self.make_message(mto=msg['from'].bare,
mbody="Powerbot is greeting you, %s! Usage: [powerbot] lamp [on|off] to control socket 1, [powerbot] all [on:off] to control all sockets. Example: 'lamp on' switched socket 1 on." % msg['mucnick'],
mtype='groupchat')
self.copy_dialog_id(msg, reply_test_message)
reply_test_message.send()
print "Sent help text: " + str(reply_test_message)
Включение / выключение лампы и других приборов
Отслеживаем команду “lamp on” (включить лампу), если команда получена, то включаем розетку switch_on(lampSocket) и отчитываемся о выполнении.
#
# Handle "lamp on" command
#
if msg['mucnick'] != self.nick and "lamp on" in msg['body']:
switch_on(lampSocket)
confirmation_message = self.make_message(mto=msg['from'].bare,
mbody="Lamp has been switched on, %s." % msg['mucnick'],
mtype='groupchat')
self.copy_dialog_id(msg, confirmation_message)
confirmation_message.send()
print "Lamp switched on, sent confirmation: " + str(confirmation_message)
Аналогичным образом реализованы “lamp off”, “all on” и “all off” (последние отвечают за включение или выключение всех управляемых розеток).
Запускаем чат бот
Из bash на малинке выполняем нехитрую команду:
sudo python powerbot.py -d -r <адрес начальной MUC комнаты>
Sudo нужно для доступа к GPIO. Если вы использовали QuickBlox, то в качестве адреса MUC комнаты просто скопируйте JID адрес из таблички Chat Dialogs.
В результате на экране появятся логи аутентификации и обмена XMPP статусами с сервером:
![](https://habrastorage.org/files/9af/47b/e3e/9af47be3e7fa49eb85a4987f8614a6c3.jpg)
Всё, бот готов и ждет ваших указаний в чат-комнате.
Кстати, вы могли обратить внимание, что функции реакции на команды продублированы одновременно в
def message(self, msg):
и
def muc_message(self, msg):
первый блок обрабатывает приватные сообщения 1:1, а второй — групповые.
То есть управлять ботом можно и в приватном чате, хотя на мой взгляд, это менее интересно.
Собираем чат клиент под iOS (варианты: Android, Web)
Как я писал выше, можно общаться с ботом через любой Jabber / XMPP — совместимый чат клиент.
Мы легких путей не ищем, поэтому собираем своё приложение — клиент для управления ботом ну и заодно для общения с домашними и друзьями.
Свой собственный мессенджер с ботом и групповыми чатами :-)
Однако, как вы увидите, мы здесь тоже идем по быстрому и ленивому пути и берем готовый open-source проект нашей собственно разработки,
который называется Q-municate.
1. Тянем с гита проект для соответствующей платформы:
iOS: bitbucket.org/quickblox/qmunicate-ios
Android: github.com/QuickBlox/q-municate-android
Web: github.com/QuickBlox/q-municate-web
2. Открываем в IDE.
3. Правим креденшелы — меняем стандартные константы с ключами приложения на скопированные из админки QuickBlox. В iOS это меняется в AppDelegate.m, в Android в Consts.java.
![](https://habrastorage.org/files/119/324/b5c/119324b5c3e44b4d88ea9213a3f7952a.png)
4. Компилируем, билдуем на девайс.
По желанию кастомизируем интерфейс и прочее, тут более подробный мануал.
5. PROFIT!!!
Демонстрация
Скрины:
![](https://habrastorage.org/files/561/2ef/f6a/5612eff6ad5a42a4ae77a50a70764a12.jpg)
свой билд Q-municate я назвал гордо «Q-Power»
![](https://habrastorage.org/files/757/c6c/ceb/757c6cceb01d44fabf5e727bdc926cc0.png)
находим бота в френдах или групповом чате
![](https://habrastorage.org/files/a6f/960/f07/a6f960f07ceb4db8b1096ae58d327c2d.jpg)
общаемся с ботом
Видео управления лампой через чат:
Спасибо за внимание, надеюсь пригодится, а еще лучше если данный «proof of concept» сподвигнет кого-то реализовать идею до конца, и микроволновка вдруг заговорит с тостером, а давать им всем команды будет жена голосом через вашу домашнюю Siri :-)
Успехов!