RaspberryPiからObnizを使用してみる

とても久しぶりにエントリーを書いているような感じです。5月から6月はリアルな仕事で異動関連のイベントがあったのでなかなか時間がとれなかったり、 大阪で行われたデジットハッカソンに参加したりと割と忙しい感じでした。最近、本当に体力が落ちた実感があります。

その中で、ObnizRaspberryPiでエッジデバイスとして使用したいなと思うことがありました。Obnizはピンが5V出るのでArduinoUnoのような使い方ができるところとHTMLでUIを作ることができるのが結構気に入っています。あと、RaspberryPiだとGPIOが3.3Vなのでたまに電圧変換を何とかしないといけないのが面倒に感じてしまいます。回路組めばいいんだけど…、最近は老眼が進んでしまって抵抗値のカラーコードが全く見えず泣きそうです。そこで、Obnizをエッジデバイスとして使えないかなというアイデアに行きつきました。その場合にはシリアル接続かWiFiでの接続になる感じですが、コスト的にはもったいない気もしますw

折角だから、Python経由で動かそうと思っていたのですが、ObnizPythonでの利用はPython3.6以上である必要があり、RaspberryPiPythonバージョンはver3.5なので解決が必要という感じです。そこで、RaspberryPiPythonのバージョンを上げて使用してみようという実験を行いました。

手法として考えられるのは

  • pyenvを使用する
  • ソースからPython3.6をインストールする

という2つの方向性があるのですが、できればソースからのインストールは勘弁という感じです。 では、やってみたいと思います。(この実験を行ったのは2019/06/20頃です。そのため、このエントリーを書き終えた時点では壮大なオチがありますが気にしてはいけません

pyenvを使用してPython3.6系に上げる

pyenvpythonのバージョン管理を容易にするものと考えてもらっていいかなと。 詳細はこちら…

pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.

Node.jsでいうところのnと同じようなものだという考えでいいと思います。

事前に必要なものをインストール

pyenvはインストールにライブラリが必要なものがあるので事前にaptでパッケージインストールを行います。

$ sudo apt update
$ sudo apt install -y git openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev

pyenvgithubから取得

github.com

githubからクローンします。

$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv

.bash_profileファイルに設定を追加、反映。

pyenvはそのまま使用できるのですが、PATH環境変数PYENVを設定していないと毎回設定する必要があるので、 ~/.bash_profileに設定を追記しておくのが楽です。

$ vi ~/.bash_profile

以下の内容を末尾追記します。(デフォルトではpiユーザには~/.bash_profileは存在しないので、そのまま書き込めばOKです)

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

~/.bash_profileに設定を追記したら、以下のコマンドで有効化しましょう。

$ source ~/.bash_profile

これでpyenvは使用可能になりました。

pyenvで利用できるバージョンの確認

では、pyenvで利用できるバージョンの確認してみます。以下のように実行すると使用可能なバージョンのリストが出力されます。

【コマンド】

$ pyenv install --list

【ログ】

$ pyenv install --list
Available versions:
(中略)
  2.7.0
  2.7-dev
  2.7.1
  2.7.2
  2.7.3
  2.7.4
  2.7.5
  2.7.6
  2.7.7
  2.7.8
  2.7.9
  2.7.10
  2.7.11
  2.7.12
  2.7.13
  2.7.14
  2.7.15
  2.7.16
(中略)
  3.5.0
  3.5-dev
  3.5.1
  3.5.2
  3.5.3
  3.5.4
  3.5.5
  3.5.6
  3.5.7
  3.6.0
  3.6-dev
  3.6.1
  3.6.2
  3.6.3
  3.6.4
  3.6.5
  3.6.6
  3.6.7
  3.6.8
  3.7.0
  3.7-dev
  3.7.1
  3.7.2
  3.7.3
  3.8-dev
  3.9-dev
  activepython-2.7.14
  activepython-3.5.4
  activepython-3.6.0
(中略)
  stackless-3.4-dev
  stackless-3.4.1
  stackless-3.4.2
  stackless-3.4.7
  stackless-3.5.4

出力している中に3.6.6があったので、今回はこれをインストールしていきます。

pyenvを使用してPython3.6をインストール

pyenvを使ってPython3.6.6をインストールします。

$ pyenv install 3.6.6
$ pyenv global 3.6.6

インストール時間は長いので、気長に待ちましょう。 globalの設定は全てのシェルでそのバージョンを利用できるようにしています。

インストールが完了したら、さっそくバージョン確認してみます。

$ python3 -V
Python 3.6.6

$ python -V
Python 3.6.6

$ pip3 -V
pip 10.0.1 from /home/pi/.pyenv/versions/3.6.6/lib/python3.6/site-packages/pip (python 3.6)

$ pip -V
pip 10.0.1 from /home/pi/.pyenv/versions/3.6.6/lib/python3.6/site-packages/pip (python 3.6)

上手くインストールされていました。 pipもインストールされていました。 ただ、Python コマンドは2系も含めて今回インストールしたバージョンに塗り替えられています。

要約準備ができたのでObnizのライブラリをインストールしてみましょう。

obniz-python-sdkをインストール

以下のドキュメントと同様にインストールを行います。

github.com

【コマンド】

$ sudo pip install obniz

【ログ】

$ sudo pip install obniz
Collecting obniz
  Downloading https://files.pythonhosted.org/packages/91/33/540c6504add677965294db2149962c3a1a843ac0fc2346f19179b1db1b92/obniz-0.3.0.tar.gz (42kB)
    100% |████████████████████████████████| 51kB 793kB/s 
Collecting attrdict==2.0.1 (from obniz)
  Downloading https://files.pythonhosted.org/packages/ef/97/28fe7e68bc7adfce67d4339756e85e9fcf3c6fd7f0c0781695352b70472c/attrdict-2.0.1-py2.py3-none-any.whl
Collecting pyee==6.0.0 (from obniz)
  Downloading https://files.pythonhosted.org/packages/ad/d8/5608d571ffad3d7de0192b0b3099fe3f38d87c0817ebff3cee19264f0bc2/pyee-6.0.0-py2.py3-none-any.whl
Collecting semver==2.8.1 (from obniz)
  Downloading https://files.pythonhosted.org/packages/21/18/a0de8cda637ba3efee1b3617ded00601507ce15bd70a39399740e0fd415f/semver-2.8.1-py2.py3-none-any.whl
Collecting websockets==7.0 (from obniz)
  Could not find a version that satisfies the requirement websockets==7.0 (from obniz) (from versions: 1.0, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 4.0.1, 5.0, 5.0.1)
No matching distribution found for websockets==7.0 (from obniz)

エラー…エラーメッセージを確認してみると、websocketsの依存関係がうまく行っていないようです。

【ログ抜粋】

Collecting websockets==7.0 (from obniz)
  Could not find a version that satisfies the requirement websockets==7.0 (from obniz) (from versions: 1.0, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, 3.4, 4.0.1, 5.0, 5.0.1)
No matching distribution found for websockets==7.0 (from obniz)

ということなので、pipで別途websocketsをインストールしておきます。

$ sudo pip install websockets

websocketsインストール後にもう一度、obnizのインストールを行うと問題なく完了します。

ただ、REPLでテストしてみると

$ python 
Python 3.6.6 (default, Jun  6 2019, 23:09:21) 
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from obniz import Obniz
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'obniz'

やっぱりエラー。うーむ。ネットを検索してみると似たようなエラーはあるので、

forum.obniz.io

できそうな感じなんですけど…解決できないので別の手段を考えてみます。


ソースコードからPython3.6系をインストールしてみる

できればこちらの手は使いたくなかった…

パッケージのアップデート

まずは必要なパッケージをインストールします。

ビルドに必要なパッケージのインストール

$ sudo apt update
$ sudo apt-get upgrade
$ sudo apt-get install build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev libc6-dev

こちらの方が必要になるライブラリが多いです。

Pythonのダウンロードとインストール(例:Python 3.6.6)

※任意のPythonバージョンをインストールする場合は以下の公式サイトを参考にファイル名を調整してください。

www.python.org

$ wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz
$ tar -zxvf Python-3.6.6.tgz
$ cd Python-3.6.6
$ ./configure --prefix=/usr/local
$ sudo make
$ sudo make install

久々にソースコードからmakeしましたが、無事に終わった感じ。

pipのアップデート

pythonのインストールが終わったのでpip3もインストールしておきます。

$ sudo pip3 install -U pip
$ sudo pip3 install -U setuptools

動作確認(今回の例:Python 3.6.6)

今回のインストールはPython3のみがバージョンアップされたので、実行するのはPython3pip3になります。

$ python3 -V
Python 3.6.6

$ pip3 -v
pip 19.1.1 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)

無事にインストールされたようです。

obniz-python-sdkをインストールしてテスト

先ほどと同様にインストールを行います。

【コマンド】

$ sudo pip install obniz

インストール後のテストですが、REPL環境では特にエラーなども発生していなかったので以下のようなソースを実行させてみます。

【obnizConnect.py】

import asyncio
from obniz import Obniz

async def onconnect(obniz):
    pass

obniz = Obniz('****-****') # ここには使用するobnizのIDを入力してください
obniz.onconnect = onconnect

asyncio.get_event_loop().run_forever()

【実行】

$ python3 obnizConnect.py 
WebSocket connection is closed: code = 1000 (OK), no reason
_call_on_connect

特にエラーは発生しませんでした!やったー!

f:id:ueponx:20190625202020j:plain

動作するとObnizの本体はこのような表示になっているので、実行がされているのも画面でわかります。

このサンプルは何もしないものなので更にテストを行っていきます。


以下のサンプルのソースコードを実行してみます。3Vと5VのGPIOやUARTなどを使用しています。

【ObnizSample.py】

import asyncio
from obniz import Obniz
    
async def onconnect(obniz):
    obniz.io0.drive("5v")
    obniz.io0.output(True)
    obniz.io1.pull("3v")
    obniz.io1.drive("open-drain")
    obniz.io1.output(False)
    obniz.io2.drive("3v")
    obniz.io2.output(True)

    def callback(voltage):
        print("change to {} v".format(voltage))

    obniz.ad3.start(callback)

    pwm = obniz.get_free_pwm()
    pwm.start({"io": 4})
    pwm.freq(1000)
    pwm.duty(50)

    uart = obniz.getFreeUart()
    uart.start({"tx": 5, "rx": 6, "baud": 9600})

    def onreceive(data, text):
        print(data)

    uart.onreceive = onreceive

    uart.send("Hello")

obniz = Obniz('****-****') # ここには使用するobnizのIDを入力してください
obniz.onconnect = onconnect

asyncio.get_event_loop().run_forever()

【実行】

$ python3 ObnizSample.py 
WebSocket connection is closed: code = 1000 (OK), no reason
_call_on_connect
Task exception was never retrieved
future: <Task finished coro=<onconnect() done, defined at ObnizSample.py:4> exception=AttributeError("'Obniz' object has no attribute 'getFreeUart'",)>
Traceback (most recent call last):
  File "ObnizSample.py", line 23, in onconnect
    uart = obniz.getFreeUart()
AttributeError: 'Obniz' object has no attribute 'getFreeUart'
change to 0.215 v
change to 0.205 v
change to 0.215 v
change to 0.196 v
change to 0.22 v
change to 0.205 v

UART系がエラーを出していますが、基本的には期待した動作が確認できました。

f:id:ueponx:20190625202004j:plain

動作するとObnizの本体はこのような表示になっているので、実行がされているのも画面でわかります。 GPIOの状態も変化してますのでわかりやすいです。

おわりに

なんとか、‘‘‘RaspberryPi‘‘‘から‘‘‘Python SDK‘‘‘を使用して‘‘‘Obniz‘‘‘をエッジデバイスとして使用できそうです。 もしかしたら、‘‘‘pyenv‘‘‘の場合も一度インストール済みの‘‘‘python3‘‘‘環境をクリーンにしてしまえば、うまく実行できるのかもしれません。(そこまでやりませんが)

さて、オチになりますが。 2019/06/20にリリースされた新しいRaspbianである2019-06-20-raspbian-busterではPythonのバージョンは3.7.3になっているのでこの作業は不要です。

/* -----codeの行番号----- */