Pull to refresh

Управление домашними электроприборами («умный дом») через чат бот на Raspberry Pi

Development for iOS *Development for Android *
Tutorial
В данном проекте запускаем своё iOS, Android или Web приложение, а также пишем (вернее, чуть дописываем) чат бот на питоне, который управляет розетками через радио модуль, подключенный к Raspberry Pi.

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

Интересно?

А зачем?


Вопрос “а зачем это нужно?” не всегда остро стоит для проектов из серии «умный дом» и всяческих Internet of Things, здесь часто тратится куча времени и денег на автоматизацию чего-то, что на практике удобнее переключать по старинке обычным настенным выключателем :-) Но при этом получаешь кучу удовольствия и полезного опыта в процессе и далее радуешься исправной работе механизма, который сделал сам.

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

  • Человеческий язык — довольно легко заставить чат бот общаться с вами на человеческом языке, что довольно удобно, особенно для менее технических членов семьи. Также это позволяет в перспективе подключить голосовое управление.
  • Универсальный удаленный доступ — к XMPP чат серверу можно подключаться откуда угодно и из любого Jabber совместимого IM клиента. Людям удобно, а как подключить устройства описано в данной статье.
  • Удобное управление для всей семьи — подключите домашних в единый групповой чат, где сидят боты, отвечающие за дом или приборы в доме. Вы можете обсуждать свои семейные вопросы и одновременно управлять домом. Все видят, кто какие команды подал приборам, можно видеть их (ботов) ответы и отчеты, просмотреть предыдущую историю и т.п. Это удобно.
  • Система независимых распределенных агентов. Каждый прибор или набор датчиков, которые имеют представительство (по сути, пользователя) в чате, соответственно являются независимыми агентами и могут общаться с другими приборами и быть управляемыми ими или вами напрямую. Единый сервер не обязателен. Можно поднять свой чат бот для каждого важного прибора или датчика, а также настроить главного бота с элементами AI, такой себе “дворецкий” или “majordomo”, который будет всеми девайсами управлять, причем они будут общаться в доступном вам и другим членам семьи чате на понятном вам языке, так что вы всегда можете отследить что происходило или вмешаться в процесс.


Реквизит


Для данного мини-проекта нам потребуются следующие компоненты:

1. Raspberri P.
У меня модель B, заказал буквально за день до объявления о выходе B+, но в принципе, любая модель тут подойдет, главное смотрите, чтоб GPIO пины были совместимы с управляющим модулем, который вы выберете. Об этом ниже.
Ну а так, главное требование — запустить чат бот на питоне.



2. Аксессуары к вашему Pi.
WiFi модуль, простые USB клавиатура и мышь, карточка SD памяти с дистрибутивом Raspbian, блок питания, по желанию — пластиковый корпус.
Это стандарт для “малинки”, но т.к. я покупал её впервые, специально под этот проект, то не знал, что WiFi и SD карта не входят в стандартный комплект, и пришлось дозаказывать, так что имейте в виду. Также для настройки вам потребуется монитор или телевизор с HDMI кабелем.



3. Управляющий модуль (RF transmitter) и розетки или другие приборы с приёмником (RF receiver).
Здесь нужно сказать, что я пошел по быстрому или ленивому пути, и заказал готовый RF модуль для Pi и набор радиоуправляемых розеток от Energenie. В комплекте идет готовый RF передатчик, который подключается на GPIO пины вашей малинки. Кому этот путь не по душе, есть альтернативы, в инете куча гайдов о том, как к существующим радиоуправляемым приборам подобрать код и управлять ими через простой дешевый китайский RF передатчик. В качестве альтернативы можно через Pi управлять приборами непосредственно прямым проводным подключением с GPIO, а также через WiFi и по другим каналам.

Вот фото моего Energenie комплекта:




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. Создаем приложение в админке.


3. Создаем пользователя для нашего чат бота (Users -> Add new user)


4. Создаем MUC комнату для общения (Chat -> New dialog)


Всё, ваш собственный 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 статусами с сервером:



Всё, бот готов и ждет ваших указаний в чат-комнате.

Кстати, вы могли обратить внимание, что функции реакции на команды продублированы одновременно в
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.


4. Компилируем, билдуем на девайс.
По желанию кастомизируем интерфейс и прочее, тут более подробный мануал.

5. PROFIT!!!

Демонстрация


Скрины:


свой билд Q-municate я назвал гордо «Q-Power»


находим бота в френдах или групповом чате


общаемся с ботом


Видео управления лампой через чат:



Спасибо за внимание, надеюсь пригодится, а еще лучше если данный «proof of concept» сподвигнет кого-то реализовать идею до конца, и микроволновка вдруг заговорит с тостером, а давать им всем команды будет жена голосом через вашу домашнюю Siri :-)

Успехов!
Tags:
Hubs:
Total votes 26: ↑23 and ↓3 +20
Views 64K
Comments Comments 32