IoT プラットホームとしてのXMPP

XMPPは主に人間・対・人間のコミュニケーション手段として発展してきたプロトコルですが、通信対象は人間に限定されているわけではありません。

XMPPでの通信相手は、自動応答するボットであったり、センサーであったり、様々な機器とリアルタイムに通信することも想定して設計されています。 そのような人間・対・機器、機器・対・機器の通信のことを最近ではIoT(Internet of Things)と呼び、たいそう人気を博しているようです。

IoTのための通信プロトコルといえばMQTTも有名ですが、 もちろんここではXMPPを利用して簡単なIoTプラットホームを実装してみたいと思います。

IoTと言われると大規模な工業用途を想像してしまい、私達の日常生活にどんな風に関わってくるかピンとこないかもしれません。

そこで今回はRaspberry Piと温度センサーを利用して自宅の室温をXMPP経由でスマートフォンに通知する簡単なIoTシステムを作ってみます。

システム構成

システム図

用意するのはRaspberry Pi 2と温度センサー(DS18B20)です。 DS18B20は安価で手に入る1-Wireの温度センサーで、Linux用のKernelモジュールが用意されているため取り扱いが非常に簡単です。

まず、このセンサーとRaspberry Pi 2を以下の回路図のように接続します。

回路図

回路図

VDDと信号線の間には2.2kΩ〜4.7kΩ程度のプルアップ抵抗を入れ、信号線をGPIOの4番ポートと接続します。

実装例

実装例

続いてRaspberry Pi側で以下のコマンドをrootで実行し、1-Wire接続のセットアップを行います。最後に再起動を行うと1-Wire温度センサーのカーネルモジュールが有効になります。

# echo w1-gpio >> /etc/modules
# echo w1-therm >> /etc/modules
# echo dtoverlay=w1-gpio-pullup,gpiopin=4 >> /boot/config.txt
# reboot

再起動を行うと、以下のディレクトリにセンサーが認識されているはずです。

$ ls /sys/bus/w1/devices/
28-000005cf6989 w1_bus_master1

28-000005cf6989というのがセンサーのデバイスIDとなりますが、このIDは部品によって異なりますので適時読み替えてください。

このディレクトリのw1_slaveというファイルを参照することでセンサーの温度を読み取ることができます。

$ cat /sys/bus/w1/devices/28-000005cf6989/w1_slave
7f 01 4b 46 7f ff 01 10 33 : crc=33 YES
7f 01 4b 46 7f ff 01 10 33 t=23937

t=23937を1000で割った値がセンサーで実際の温度となります。

続いて、センサーで読み取った温度をXMPPプロトコルで配信するXMPPボットを実装してみましょう。 XMPPボットの実装にはPythonライブラリのSleekXMPPがオススメです。 以下のソースコードは10秒毎にセンサーから読み取った温度をPresenceとして通知するXMPPボットです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sleekxmpp

JID = "アカウント名@xmpp.jp"
PASSWORD = "XXXXXXXX"
DEVICE_ID='28-000005cf6989'
DEVICE_FILE='/sys/bus/w1/devices/%s/w1_slave' % (DEVICE_ID)

def read_temp():
    try:
        file = open(DEVICE_FILE)
        lines = file.readlines()
        temp = lines[1].split('t=')[1]
        return float(temp) / 1000
    except e:
        return -1

class TempBot(sleekxmpp.ClientXMPP):
    def __init__(self, jid, password):
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
        self.add_event_handler("session_start", self.start)

    def start(self, event):
        self.send_temp_presence()
        self.scheduler.add("timer", 10, self.send_temp_presence, repeat=True)

    def send_temp_presence(self):
        self.makePresence(pstatus='室温 %.1f ℃' % read_temp()).send()

if __name__ == '__main__':
    xmpp = TempBot(JID, PASSWORD)
    if xmpp.connect():
        xmpp.process(block=True)
    else:
        print('接続失敗')

XMPPにはIoT向けにXEP-0323という仕様が定義されていますが、今回はこれを利用せず単純にPresenceとして温度データを配信するようにしました。

Presenceとして配信することで、データを受信するクライアント側では特別なアプリケーションは必要ありません。 従来のXMPPクライアントを利用し、友達のステータスがコンタクトリストに表示されるのと同様に、自宅の室温をコンタクトリストに表示する事が出来ます。

XMPPクライアント

いかがだったでしょうか。IoT化が発達した未来ではXMPPクライアントで自宅のエアコンを制御したり、ご飯を炊いたり出来るようになるかも知れませんね。