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と接続できるのか、いろいろ調べながら開発を進めていきました。結果的に、およそ以下の情報が必要でした。

  1. Raspberry Piでsakura.ioを操作する方法
  2. FaBoおよびセンサーを扱う方法
  3. PythonでWebSocketによる通信を実装する方法
  4. sakura.ioと外部ホストの間でやりとりするJSONデータの形式
  5. 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以上となっています。

インストールやテスト方法は、ドキュメントのInstallationGetting 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からのデータ受信

一方、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データの扱い方を説明し、最後に今回実装したプログラムの説明をします。