Raspberry PiとPythonでsakura.ioを使ってみる(中編)
はじめに
さくらのナレッジ編集部の法林です。
さくらインターネットが提供するIoTプラットフォームサービスsakura.ioをRaspberry Piにつないで、Pythonのプログラムで操作する方法を紹介します。先日公開した前編では、IoTデバイスとしてRaspberry PiとFaBoを使用し、それらとsakura.ioモジュールの接続、sakura.ioの設定、Raspberry PiやサーバにおけるPython環境の構築、サンプルプログラムの実行と結果の確認を行いました。
続いてこれからは、sakura.ioと通信するプログラムをPythonで書くために必要な情報や、実際に作成したプログラムの中身を説明します。なお、当初はこの部分を1本の記事でご覧いただく予定でしたが、書いてみたらとても長くなってしまったので2本に分割し、この記事を中編、3本目の記事を後編として公開します。
プログラム作成に必要な情報
筆者はこれまでRaspberry PiもPythonもほとんど使ったことがなかったので、どうすればsakura.ioと接続できるのか、いろいろ調べながら開発を進めていきました。結果的に、およそ以下の情報が必要でした。
- Raspberry Piでsakura.ioを操作する方法
- FaBoおよびセンサーを扱う方法
- PythonでWebSocketによる通信を実装する方法
- sakura.ioと外部ホストの間でやりとりするJSONデータの形式
- PythonでJSON形式のデータを扱う方法
これらについて調べたことを書き、それから実際に作成したプログラムを説明します。記事としては、1-2をこの記事で紹介し、3-5と最終的に作成したプログラムの説明は次の記事で紹介します。
なお、今回の記事群で使用するPythonはVer3とします。
Raspberry Piでsakura.ioを操作する方法
Raspberry Piでsakura.ioを操作する方法はいくつかありますが、今回はRaspberry PiにPythonとsakura.ioのPythonライブラリをインストールし、それらを使ってプログラムを書く方法を採ります。sakura.ioにどんなライブラリがあるかは、ライブラリ一覧のページをご覧ください。
今回使用するPythonライブラリもここに掲載されています。ソースコードなどはGitHubで公開されています。ドキュメントも英語ですが存在します。
これらのページによると、動作環境はPython 2.7、あるいは3.4以上となっています。
インストールやテスト方法は、ドキュメントのInstallationやGetting Startedページ、および前編でも参照した「HAT for Raspberry Piスタートガイド」に書いてありますが、まとめるとこんな感じになるようです。
インストール
Raspberry PiにPythonと関連ライブラリをインストールし、さらにsakura.ioのPythonライブラリをインストールします。手順としては以下のようになります。(前編でダウンロードしたsakura.io体験ハンズオンのサンプルプログラム集にinstall-devtools.shとして収録しています)
Raspberry Piにインストールされているソフトウェアを最新にします。 % sudo apt update Python3およびパッケージ管理ツールをインストールします。 % sudo apt install python3 python3-pip Pythonでハードウェアを制御するためのライブラリをインストールします。 % sudo apt install python3-smbus python3-rpi.gpio i2c-tools pipを使用してsakura.ioライブラリをインストールします。 % sudo pip3 install sakuraio pyserial
sakura.ioモジュールの動作テスト
Raspberry Piの上にsakura.ioモジュールおよびHATを接続してから、Pythonのインタラクティブシェルにて以下を実行します。(もしくは、サンプルプログラム集に収録しているsakuraio-test.pyを実行します)
import sakuraio from sakuraio.hardware.rpi import SakuraIOSMBus sakuraio = SakuraIOSMBus() print(sakuraio.get_unique_id())
実行結果はこのようになります。
$ python3 Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170124] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sakuraio >>> from sakuraio.hardware.rpi import SakuraIOSMBus >>> sakuraio = SakuraIOSMBus() >>> print(sakuraio.get_unique_id()) 16X00000000 >>>
sakuraio.get_unique_id()は、個々のsakura.ioモジュールに割り当てられたIDを返す関数で、このプログラムではそれが出力されます。
sakura.ioへのデータ送信
Pythonのインタラクティブシェルにて以下を実行します。(あるいは、サンプルプログラム集に収録しているsakuraio-send.pyを実行します)
from sakuraio.hardware.rpi import SakuraIOSMBus sakuraio = SakuraIOSMBus() sakuraio.enqueue_tx(0, 1) sakuraio.send()
Pythonライブラリで使える関数は、ドキュメントの「Hardware API」ページに載っています。それを見ると、sakuraio.enqueue_tx(ch,val)でchチャンネルにvalという値をセットし、sakuraio.send()でsakura.ioに送信することがわかります。上記のプログラムでは0チャンネルに1を入れて送っています。
sakuraio-send.pyを実行したら、sakura.ioのコントロールパネルを表示します。下図のようなデータが到着していたら、正常に送信されています。
sakura.ioからのデータ受信
一方、sakura.ioからデータを受信するときは、以下のようなプログラムを実行します。(サンプルプログラム集ではsakuraio-recv.py)
# ライブラリのインポートと初期化 from sakuraio.hardware.rpi import SakuraIOSMBus sakuraio = SakuraIOSMBus() # sakura.ioのキューからデータを受信 dict_data = sakuraio.dequeue_rx_raw() # 取得したデータ全体を表示 print(dict_data) # 0チャンネルにセットされたデータを取得しledに代入して表示 led = dict_data['data'][0] print("led = %i" % (led))
sakuraio.dequeue_rx_raw()がsakura.ioからデータを受信する関数です。受信したデータは、dataというキーの中身が配列になっていて、0番目の要素が0チャンネルの値というように対応しているので、ここでは0チャンネルにセットされたデータを取り出して表示しています。
これをテストするには、まずsakura.ioからデータを送信します。sakura.ioのコントロールパネルにはメッセージ送信機能があるので、これを使って、図のように送信先のsakura.ioモジュールを設定し、0チャンネルに1という値をセットして送信します。
その後、Raspberry Piでsakuraio-recv.pyを実行すると、データを受信して表示します。実行例を示します。
pi@raspberrypi:~ $ python3 sakuraio-recv.py {'channel': 0, 'type': 'i', 'data': [1, 0, 0, 0, 0, 0, 0, 0], 'offset': 7369} led = 1 pi@raspberrypi:~ $
FaBoおよびセンサーを扱う方法
FaBoおよびそれに接続するセンサー類を取り扱うプログラムは、FaBoのGitHubサイトに情報があります。今回使用する#101 LED Brick(LED)や#108 Temperature Brick(温度センサー)のサンプルコードも掲載されています。幸いなことにPythonで書かれているので、そのまま応用できそうです。
それぞれのサンプルコードから得られる情報を記します。
#101 LED Brick
このLEDは、FaBoのGPIO端子のいずれかに接続します。そして、GPIOから1が送られると発光し、0が送られると消えるという動作をします。以下はサンプルコードの抜粋です。
import RPi.GPIO as GPIO import time LEDPIN = 4 GPIO.setup( LEDPIN, GPIO.OUT ) GPIO.output( LEDPIN, True ) time.sleep( 1.0 ) GPIO.output( LEDPIN, False )
LEDPIN=4でGPIOの端子番号を設定した後、GPIO.output(LEDPIN,True)でGPIO4に1を送っています。よって、FaBoのGPIO4という端子にLEDを接続しておけば、ここでLEDが点灯します。そして、1秒休んだ後に実行されるGPIO.output(LEDPIN,False)でGPIO4に0が送られ、LEDが消灯します。
#108 Temperature Brick
こちらは温度センサーで、FaBoのアナログ端子(A0-A7)のいずれかに接続します。動作としては、センサーからはアナログ値(0-1023)を取得し、これを変換することで−30度から100度までの温度を算出するというものです。こちらもサンプルコードから抜粋します。
import spidev import time TEMPPIN = 0 def readadc(channel): adc = spi.xfer2([1,(8+channel)<<4,0]) data = ((adc[1]&3) << 8) + adc[2] return data def arduino_map(x, in_min, in_max, out_min, out_max): return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min spi = spidev.SpiDev() spi.open(0,0) spi.max_speed_hz = 5000 data = readadc(TEMPPIN) volt = arduino_map(data, 0, 1023, 0, 5000) temp = arduino_map(volt, 300, 1600, -30, 100) sys.stdout.write("\rtemp = %f" % (temp)) sys.stdout.flush()
TEMPPIN=0で端子番号を設定した後、data=readadc(TEMPPIN)でアナログ値を読み出します。よって、このプログラムでは温度センサーをA0端子につなげば動作します。読み出した値はarduino_map()で電圧を経て温度に変換され、出力されます。
なお、FaBoのサンプルコードのページに書かれていないこととして、spi.max_speed_hz=5000を指定しないと正しい値が取得できませんでした。これは温度センサーとRaspberry Piの通信で使うSPIの最大周波数の設定で、最近のRaspbian(Raspberry Piの公式OS)では必要なようです。
続きは次の記事で
この記事では、Raspberry PiにPythonとsakura.ioのPythonライブラリを導入し、sakura.ioとの間でデータの送受信をする方法、それからFaBoとセンサーをRaspberry Piに接続し、PythonのプログラムでLEDのON/OFFや温度センサーのデータを取得する方法を紹介しました。
次の記事では、sakura.ioとWebの世界をつなぐ方法として、WebSocketによるプログラミングやJSONデータの扱い方を説明し、最後に今回実装したプログラムの説明をします。