SCM-LTE-01 + Raspi HAT で sakura.io にデータ送信


# 概要
Python の SakuraIOSMBus というライブラリを使用して「SCM-LTE-01(sakura.io)」+「Raspi HAT(SCO-RPI-01)」+「RaspberryPi 3 model B+」の組み合わせで、sakura.ioプラットフォーム（sakura.ioインターネットデータセンタ、クラウド）に**データを送信**することにトライしてみました。

Python3.6を使った実行環境のセットアップについては「[sakura.io + Raspi HAT のセットアップと動作確認 Python3.6](https://qiita.com/code0327/items/a5fa302bf2a67e4a6f72)」にメモを残しています。

# 実行環境
- Python 3.6.7
- SakuraIO 0.1.7 (pipで追加したPythonパッケージ）

# 準備 

はじめに、準備としてデバイスのIDや接続状態を確認するプログラムを作成しました。各関数のリファレンスは、https://python-sakuraio.readthedocs.io/en/latest/ に置かれています

```Python
from sakuraio.hardware.rpi import SakuraIOSMBus
sakuraio = SakuraIOSMBus()

# 製品名の取得(戻値：str)
print(f'ProductName:{sakuraio.get_product_name()}')

# デバイスデバイスのユニークIDの取得(戻値：str)
print(f'DeviceID   :{sakuraio.get_unique_id()}')

# ファームウェアバージョンの取得(戻値：str)
print(f'FirmwarVer.:{sakuraio.get_firmware_version()}')

# 接続ステータスの取得(戻値：int)
cs = sakuraio.get_connection_status()
print(f'ConnectionStatus:{cs} ({bin(cs)})')

# オンライン状態の取得(戻値:bool)
isOnline = sakuraio.get_is_online()
if isOnline :
  
  # 信号強度(戻値:int) 0:圏外　5:良好
  print(f'SignalQuality   :{sakuraio.get_signal_quality()}')

  # ここに、なんからの受信・送信処理を記述していく
```

## 実行結果

```
ProductName:SCM-LTE-01
DeviceID   :17xxxxxx30
FirmwarVer.:v1.2.1-170425-cd8cace
ConnectionStatus:128 (0b10000000)
SignalQuality   :4
```

### get_connection_status
接続ステータスを8ビットで示したものを10進数の整数値にしたものが戻値となります。

最上位ビットの 1 は「接続OK」を意味します。つまり、128 (=b10000000) が戻ってくればLTE回線に問題なく接続できている状態といえます。一方、最上位ビットが 0 ならば「接続NG」で、残りの下位7ビットによりエラーの詳細を表します。例えば、`0b00000001`なら「圏外」のようです。

### get_signal_quality
信号強度、電波状態を取得します。戻値は0～5の整数値で、0が圏外レベル、5が最良の状態となります。

私の環境では「4」でした。ちなみに、アンテナの先端を取り外すと「3」になりました。
![_20190209_084106.jpg](https://qiita-image-store.s3.amazonaws.com/0/152805/25e2d946-3cfc-0e81-3c68-c6f855e9783d.jpeg)

# sakura.ioプラットフォームにデータ送信

デバイス（SCM-LTE-01）から、sakura.ioプラットフォーム（以下、クラウド）にデータを送信すると、**1回につき1ポイント（=0.05円）を消費**しまします。1回に送信で送ることができる最大データ量は、8バイト×16チャンネル（=128バイト）となります。

データは各チャンネルごとに、整数型や浮動小数点数型、バイト配列型などを与えることができます。

ここでは、チャンネル1に「符号付き32ビット整数型」として -51、チャンネル2に「64ビット浮動小数点数型」として 3.2、チャンネル3に「バイト型配列」として 0x4e(='N'=78)、0x65(='e'=101)、0x6b(='k'=107)、0x6f(='o'=111) をセットして、これをまとめて1回の送信でクラウドに送ってみたいと思います。

```Python
from sakuraio.hardware.rpi import SakuraIOSMBus
sakuraio = SakuraIOSMBus()

if sakuraio.get_is_online() :
  sakuraio.enqueue_tx(1, -51)
  sakuraio.enqueue_tx(2, 3.2)
  sakuraio.enqueue_tx(3, b'Neko')
  sakuraio.send()

else :
  print(f'デバイスがLTE回線に接続できていません。')
```


## 実行結果

実行結果は、sakura.ioのコントールパネルから確認することができます（連携サービス：WebSocket）。次のようにしっかりとデータが届いていました。また、ポイントについても、しっかりと1ポイント分がカウントされていました。

![2019-02-09_09h24_48.png](https://qiita-image-store.s3.amazonaws.com/0/152805/9a64cfeb-d7d6-1263-4b0d-379317ea7431.png)

なお、`enqueue_tx`の第一引数に与えるチャンネル番号は0から127まで任意の値を設定できます。次のように連番で使用する必要もありません。

```Python
  sakuraio.enqueue_tx(0,   1)
  sakuraio.enqueue_tx(127, 1)
  sakuraio.enqueue_tx(64,  1)
```

## 16個を超えるデータをキューにセットすると

公式HPの[よくある質問](https://sakura.io/docs/pages/questions/questions_technical.html#id5)によれば「`1回で送受信できるデータとしては、最大で8バイト×16チャンネル=128バイトのデータを送受信でき、1ポイントを消費します。`」ということですが、17個以上の送信データをキューにセットしてsendするとどうなるかを確認してみました。

次のプログラムでは、まずキューをクリアして空にしてから、ループを使ってチャンネル0から19の合計20個のデータをキューにセットし、`send`を実行しています。

```Python
from sakuraio.hardware.rpi import SakuraIOSMBus
sakuraio = SakuraIOSMBus()

if sakuraio.get_is_online() :
  sakuraio.clear_tx()
  for i in range(0,20) :
    sakuraio.enqueue_tx(i, i*10)
  sakuraio.send()

else :
  print(f'デバイスがLTE回線に接続できていません。'
```

### 実行結果

最初にキューにセットしたチャンネル1から、最後にセットしたチャンネル19のデータまで、すべてのデータがちゃんと届いていました。ただし、ポイントは2ポイント消費され、以下のようなログとなっていることから、16個を超えるデータをキューにセットした場合は複数回に分けて送信されるようです。

![2019-02-09_10h05_37.png](https://qiita-image-store.s3.amazonaws.com/0/152805/c7546a88-8d40-346b-c78d-e11ee9369a09.png)

## 32個を超えるデータをキューにセットすると

`get_tx_queue_length`を利用すると送信データを溜めておくキューの状態を確認することができます。

```Python
from sakuraio.hardware.rpi import SakuraIOSMBus
sakuraio = SakuraIOSMBus()

if sakuraio.get_is_online() :
  sakuraio.clear_tx()
  print(f'TxQueue:{sakuraio.get_tx_queue_length()}')
  sakuraio.enqueue_tx(0, 128)
  print(f'キューにデータを1個セットしました')
  print(f'TxQueue:{sakuraio.get_tx_queue_length()}')
```

### 実行結果

`enqueue_tx`を実行すると、`available`が1個減って、`queued`が1個増えています。キューの最大容量は32個のようです。

```
TxQueue:{'available': 32, 'queued': 0}
キューにデータを1個セットしました
TxQueue:{'available': 31, 'queued': 1}
```

32個を超えるデータをキューにセットしようとするとどうなるのでしょうか？

・・・例外が発生しました。