さくらのIoT

さくらのモノプラットフォーム(モノプラ)に接続するデバイス向けのPythonライブラリ「py-monopla」を公開しました。本記事ではpy-monoplaの簡単な説明と実際にRaspberry Pi 4で付属のサンプルプログラムを動作させるまでの手順をご紹介します。

py-monoplaとは?

py-monoplaはRaspberry PiなどのLinuxが動作するデバイス向けのクライアントライブラリです。MITライセンスの元に公開されたオープンソースプログラムですので商用利用など利用用途による制限はありません。「さくらのモノプラットフォーム」で提供している以下の機能のクライアントを提供します。

プラットフォーム機能

現在のところプロジェクトに登録されているセキュアモバイルコネクトSIM経由の接続でのみ使用可能です。インターネット経由の場合API呼び出しがエラーとなります。

Raspberry Pi 4で動かしてみる

ここからは実際にRaspberry Pi 4でpy-monopla付属のサンプルプログラムを動作させるまでの手順をご紹介します。
※2023年9月現在の手順となります。将来、各デバイスの入手状況やセットアップ方法の変化、OSのバージョンアップ等で再現できなくなる可能性があります。ご了承ください。

用意するもの

今回は以下のデバイスを用意しpy-monoplaのインストールとサンプルプログラムの実行を行いました。

SORACOM Onyxは個人でも1つから購入できること、技適の心配が無いこと、モバイルルータータイプでは無くOSからモデムとして見えコントロールしやすいことから採用しました。
今回は未確認ですがセキュアモバイルコネクト経由でデバイスアダプタへの接続が可能であれば他のLTEデバイスでも動作するのではと思います。

Raspberry Pi 4インストール

Raspberry Pi 4の準備

公式サイトのGetting startedなどを参考にRaspberry Pi OSをインストールし動作するようにしてください。また、インストール中にインターネットへの接続が必要になりますので接続できるようにしておいてください。

SIMの準備

セキュアモバイルコネクトSIMを「さくらのモノプラットフォーム」から使用できるようにします。

以上を参考にSIMをプロジェクトに登録してください。

LTEドングルの準備

SORACOM Onyxのセットアップ手順を元にセキュアモバイルコネクト向けの調整をしながら進めます。

SIM

SORACOM Onyxのカバーを外しセキュアモバイルコネクトのSIMを挿します。
参考: IoT SIM の挿入 / 取り出し

Raspberry Piへ接続

SORACOM OnyxをRaspberry Pi 4のUSBポートに挿します。
Raspberry Pi OSが認識しているか確認します。

pi@monoplapi:~ $ ls /dev/ttyUSB*
/dev/ttyUSB0  /dev/ttyUSB1  /dev/ttyUSB2  /dev/ttyUSB3

/dev以下にデバイスファイルttyUSB0、ttyUSB1、ttyUSB2、ttyUSB3が見えていれば正しく認識しています。一旦、SORACOM OnyxをUSBポートから取り外します。

LTE接続設定

SORACOM Onyxのセットアップスクリプトをダウンロードします。

pi@monoplapi:~ $ curl -O https://soracom-files.s3.amazonaws.com/setup_air.sh

ダウンロードしたセットアップスクリプトsetup_air.shを実行します。

pi@monoplapi:~ $ sudo bash setup_air.sh sakura sakura sakura

APNにsakuraを指定します。セキュアモバイルコネクトではユーザー名とパスワードは任意のもので良いので双方ともsakuraを指定します。
スクリプトの実行が完了すると、/etc/udev/rulesにUSBドングルの認識に必要な設定、/etc/networks/interfacesにネットワークインターフェスの設定、/etc/wvdial.confにPPP接続の設定が追加されます。
キャリア自動選択ではなくSoftBankを選択するように/etc/wvdial.confの初期化スクリプトを編集します。(AT+COPS=1,2,"44020"を最初に追加する)

/etc/wvdial.conf

[Dialer Defaults]
Init1 = AT+COPS=1,2,”44020”
Init2 = AT+CFUN=1
Init3 = ATZ
Init4 = AT+CGDCONT=1,”IP”,”sakura”
Dial Attempts = 0
Stupid Mode = 1
Modem Type = Analog Modem
Dial Command = ATD
Stupid Mode = yes
Baud = 460800
New PPPD = yes
ISDN = 0
APN = sakura
Phone = *99***1#
Username = sakura
Password = sakura
Carrier Check = no
Auto DNS = 1
Check Def Route = 1

LTE接続の確認

SORACOM OnyxをRaspberry Pi 4のUSBポートに挿します。認識するまで10秒ほど時間がかかります。あわてずに待ちましょう。ip aコマンドでppp0で認識していることを確認します。

pi@monoplapi:~ $ ip a
        :
      省略
        :
6: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1464 qdisc pfifo_fast state UNKNOWN group default qlen 3
    link/ppp
    inet 10.xxx.xxx.xxx peer 10.xxx.xxx.xxx/32 scope global ppp0
       valid_lft forever preferred_lft forever

ping connector.sipf.iot.sakura.ad.jpで疎通を確認します。

pi@monoplapi:~ $ ping connector.sipf.iot.sakura.ad.jp

PING edge.gslb.prod.iot.sakura.ad.jp (xxx.xxx.xxx.xxx) 56(84) bytes of data.
64 bytes from xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx): icmp_seq=1 ttl=62 time=67.5 ms
64 bytes from xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx): icmp_seq=2 ttl=62 time=108 ms
64 bytes from xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx): icmp_seq=3 ttl=62 time=66.9 ms
64 bytes from xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx): icmp_seq=4 ttl=62 time=86.9 ms
^C
— edge.gslb.prod.iot.sakura.ad.jp ping statistics —
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 66.871/82.432/108.438/17.039 ms

SORACOM OnyxをRaspberry Pi 4のUSBポートから取り外します。

py-monoplaのインストール

GitHubからpy-monoplaのリポジトリをクローンします。

pi@monoplapi:~ $ sudo apt install git
pi@monoplapi:~ $ git clone https://github.com/sakura-internet/py-monopla.git

TLS(SSL)のルート証明書をインストールします。

pi@monoplapi:~ $ cd py-monopla/
pi@monoplapi:~/py-monopla $ sudo ./install_crt.sh
 
Updating certificates in /etc/ssl/certs…
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d…
done.
lrwxrwxrwx 1 root root     71 Sep 27 15:56 Sakura_Iot_SIPF_Root_CA_1.pem -> /usr/share/ca-certificates/SakuraInternet/Sakura_Iot_SIPF_Root_CA_1.crt

venvでPythonの環境を作ります。

pi@monoplapi:~/py-monopla $ sudo apt-get install python3-venv
pi@monoplapi:~/py-monopla $ python3 -m venv venv

作成したPython環境を有効にした後、pipでpy-monoplaをインストールします。

pi@monoplapi:~/py-monopla $ source venv/bin/activate
(venv) pi@monoplapi:~/py-monopla $ pip install .
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing /home/pi/py-monopla
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Building wheels for collected packages: py-monopla
  Building wheel for py-monopla (PEP 517) ... done
  Created wheel for py-monopla: filename=py_monopla-0.1-py3-none-any.whl size=5655 sha256=213b6d85c28bfd07913b771710db49ff6ed4fa06add7aa000a1fc77a25dd8389
  Stored in directory: /home/pi/.cache/pip/wheels/74/53/ec/ba62fdf7483117fcd6665b66ecc0e1bb95086e75ad87a63896
Successfully built py-monopla
Installing collected packages: py-monopla
Successfully installed py-monopla-0.1

以上で、py-monoplaのインストールは完了です。

サンプルプログラムの実行

py-monoplaのsamplesディレクトリのサンプルプログラムを動かしてみます。
SORACOM OnyxをRaspberry Pi 4のUSBポートに挿し「さくらのモノプラットフォーム」に接続した状態にします。続いてインストール時に作成したPython環境を有効にします。

pi@monoplapi:~/py-monopla $ source venv/bin/activate
(venv) pi@monoplapi:~/py-monopla $ cd samples/
(venv) pi@monoplapi:~/py-monopla/samples $

オブジェクト送信

このサンプルプログラムでは以下のオブジェクトを送信します。

タグ タイプ
00 uint8 0
01 int8 1
02 uint16 2
03 int16 3
04 uint32 4
05 int32 5
06 uint64 6
07 int64 7
10 float32 1.4142135
11 float64 2.2360679775
20 float64 0102030405(HEX)
21 string.utf8 Hello

object_tx.pyを実行します。
送信に成功するとOTIDを表示します。

(venv) pi@monoplapi:~/py-monopla/samples $ ./object_tx.py
OTID:abaeb782c7394fef805909708f6e3153

受信確認

SIMが所属しているプロジェクトに関連付けられている「さくらのモノプラットフォーム」のサービスアダプタ(WebSocket)の画面で受信を確認します。

受信内容は以下のようになります。

{
  “id”: “abaeb782-c739-4fef-8059-09708f6e3153”,
  “device_id”: “xxxx”,
  “timestamp_src”: “1970-01-01T00:00:00.000Z”,
  “timestamp_platform_from_src”: “2023-09-27T08:10:47.473Z”,
  “timestamp_platform_to_dst”: “2023-09-27T08:10:47.919Z”,
  “type”: “object”,
  “payload”: [
    {
      “type”: “uint8”,
      “tag”: “00”,
      “value”: 0
    },
    {
      “type”: “int8”,
      “tag”: “01”,
      “value”: 1
    },
    {
      “type”: “uint16”,
      “tag”: “02”,
      “value”: 2
    },
    {
      “type”: “int16”,
      “tag”: “03”,
      “value”: 3
    },
    {
      “type”: “uint32”,
      “tag”: “04”,
      “value”: 4
    },
    {
      “type”: “int32”,
      “tag”: “05”,
      “value”: 5
    },
    {
      “type”: “uint64”,
      “tag”: “06”,
      “value”: 6
    },
    {
      “type”: “int64”,
      “tag”: “07”,
      “value”: 7
    },
    {
      “type”: “float32”,
      “tag”: “10”,
      “value”: 1.4142135
    },
    {
      “type”: “float64”,
      “tag”: “11”,
      “value”: 2.2360679775
    },
    {
      “type”: “binary”,
      “tag”: “20”,
      “value”: “AQIDBAU=“
    },
    {
      “type”: “string.utf8”,
      “tag”: “21”,
      “value”: “Hello”
    }
  ]
}

オブジェクト受信

このサンプルプログラムは「さくらのモノプラットフォーム」にデバイス宛のオブジェクトが存在する場合、受信し内容を表示します。存在しない場合は「Empty」と表示します。

オブジェクトが存在する場合

コントロールパネルのSIMが所属しているプロジェクトに関連付けられている「さくらのモノプラットフォーム」のサービスアダプタ(WebSocket)の画面の「メッセージ送信」からデバイスへ送信します。

※タグ: 0x10、タイプ: uint32、値: 12345678を送信

Raspberry Pi 4でobject_rx.pyを実行します。

(venv) pi@monoplapi:~/py-monopla/samples $ ./object_rx.py
OTID: 8dd6ce978dd4459cb6ad9ea0ff80fe18
 
tag: 0x10
type: SipfObjectType.UINT32
value_len: 4
value: 12345678

受信したオブジェクトの内容が表示されます。

オブジェクトが複数存在する場合

WebSocket簡易UI等からJSON形式で複数オブジェクトを送信した場合、受信に含まれるオブジェクトを列挙して表示します。以下のJSONを送信します。

{
    “device_id”: “xxxxxx”,
    “type”: “object”,
    “payload”: [
        {
            “type”: “uint8”,
            “tag”: “00”,
            “value”: 0
        },
        {
            “type”: “int8”,
            “tag”: “01”,
            “value”: 1
        },
        {
            “type”: “uint16”,
            “tag”: “02”,
            “value”: 2
        },
        {
            “type”: “int16”,
            “tag”: “03”,
            “value”: 3
        },
        {
            “type”: “uint32”,
            “tag”: “04”,
            “value”: 4
        },
        {
            “type”: “int32”,
            “tag”: “05”,
            “value”: 5
        },
        {
            “type”: “uint64”,
            “tag”: “06”,
            “value”: 6
        },
        {
            “type”: “int64”,
            “tag”: “07”,
            “value”: 7
        },
        {
            “type”: “binary”,
            “tag”: “09”,
            “value”: “AQIDBAU=“
        },
        {
            “type”: “string.utf8”,
            “tag”: “10”,
            “value”: “Hello”
        }
    ]
}

Raspberry Pi 4でobject_rx.pyを実行します。

(venv) pi@monoplapi:~/py-monopla/samples $ ./object_rx.py
OTID: e8039b6928c041d891183537a50f4370
 
tag: 0x00
type: SipfObjectType.UINT8
value_len: 1
value: 0
 
tag: 0x01
type: SipfObjectType.INT8
value_len: 1
value: 1
 
tag: 0x02
type: SipfObjectType.UINT16
value_len: 2
value: 2
 
tag: 0x03
type: SipfObjectType.INT16
value_len: 2
value: 3
 
tag: 0x04
type: SipfObjectType.UINT32
value_len: 4
value: 4
 
tag: 0x05
type: SipfObjectType.INT32
value_len: 4
value: 5
 
tag: 0x06
type: SipfObjectType.UINT64
value_len: 8
value: 6
 
tag: 0x07
type: SipfObjectType.INT64
value_len: 8
value: 7
 
tag: 0x09
type: SipfObjectType.BIN_BASE64
value_len: 5
value: b’\x01\x02\x03\x04\x05’
 
tag: 0x10
type: SipfObjectType.STR_UTF8
value_len: 5
value: Hello

オブジェクトが存在しない場合

受信すべきオブジェクトが存在しない場合object_rx.pyを実行すると

(venv) pi@monoplapi:~/py-monopla/samples $ ./object_rx.py
Empty

Emptyと表示されます。

ファイル送信

「さくらのモノプラットフォーム」にファイルを送信します。
送信するファイルを作成します。(内容がランダムな100kBのファイル)

(venv) pi@monoplapi:~/py-monopla/samples $ dd if=/dev/urandom of=~/random_100k.bin bs=1k count=100
100+0 records in
100+0 records out
102400 bytes (102 kB, 100 KiB) copied, 0.00608402 s, 16.8 MB/s

file_upload.pyを実行します。
random.binというFileID(ファイル名)で先程作成したrandom_100k.binをアップロードします。

(venv) pi@monoplapi:~/py-monopla/samples $ ./file_upload.py random.bin ~/random_100k.bin
upload /home/pi/random_100k.bin to random.bin
upload successful.

アップロードしたファイルの確認

SIMが所属しているプロジェクトの「ファイル送受信」タブを選択します。
random.binという名前で100kBのファイルがアップロードされていることを確認します。

ファイル受信

「さくらのモノプラットフォームから」ファイルをダウンロードします。
ファイル送信でアップロードしたrandom.binをダウンロードします。
FileID(ファイル名)にrandom.binをrandom_download.binという名前でダウンロードします。

(venv) pi@monoplapi:~/py-monopla/samples $ ./file_download.py random.bin ~/random_download.bin
download random.bin from /home/pi/random_download.bin
download successful.

ダウンロードしたファイルの確認

ファイル送信に使用したrandom_100k.binとダウンロードしたrandom_download.binを比較し、一致するか確認します。

(venv) pi@monoplapi:~/py-monopla/samples $ diff ~/random_100k.bin ~/random_download.bin
(venv) pi@monoplapi:~/py-monopla/samples $ sha1sum ~/random_100k.bin ~/random_download.bin
151cc43da9b4d3e85cbc586c2b73e2fb7f78a3bb  /home/pi/random_100k.bin
151cc43da9b4d3e85cbc586c2b73e2fb7f78a3bb  /home/pi/random_download.bin

diffコマンドで差分が表示されないこと、SHA1のハッシュ値が一致することからダウンロードしたファイルの内容が正しいことが確認できました。

まとめ

以上、「py-monopla」とRaspberry Pi 4で実際に動かす手順のご紹介でした。
「さくらのモノプラットフォーム」を利用するデバイスの例として「開発キット」を提供してきましたが、今回あらたな選択肢を提供することができました。
開発キットと比較してLinux + Pythonで使用できるためマイコンに不慣れな方でも「さくらのモノプラットフォーム」を使いやすくなります。
py-monoplaはまだ生まれたてですので、是非使っていただいてフィードバックをいただければと思います。
特にGitHubへのプルリクエストをいただければ大変うれしく思います。
今回のpy-monoplaを始め、様々なデバイスから「さくらのモノプラットフォーム」をご利用いただけるような発信を続けていきますのでこれからもよろしくお願いいたします。

構成・執筆・編集
DX事業部

IoTコラムでは、さくらのIoTに関係するビジネス向けの内容や身近な例、通信技術の説明や当社エンジニアが取り組んだ開発サンプルなどを掲載しています。

2023年10月公開