MonowirelessのTWELITE PalからのデータをRaspiで受け取って、DBへ格納→Streamlitで表示する

#背景
タイトルの通りのことを実現したい。
イメージ図は以下の通り。
![システム構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714168/211018e6-f2c4-2bcf-c3eb-568146e961b3.png)


#準備するもの
PC：TWELITE pal および　Monostick設定変更
Raspberry pi：今回はRaspi 4(4GB)にRasbian OS を導入したものを用いました
TWILITER2：センサへの設定書き込み用
センサデータ送受信関係
TWELITE PAL(Blue or red)：センサ側の通信部分(データ送信)
Ambient pal:環境センサモジュール
MONOSTICK(Blue or red):Raspi側の通信部分(データ受信)

#環境設定
Raspbian OS GNU/Linux 10 (buster)
Python 3.7.3
mariadb 10.3
Streamlit 0.62.0: Raspberry piでstreamlitを導入しようとするとpyarrowのインストールでコケたので0.62.0を指定しました。
mysql-connector-python 8.0.23

#センサのデータ送受信テスト
MONOWIRELESSさんから提供されている種々ソフトウェアを用いてセンサの送受信テストを行います。
##受信側MONOSTICK(親機)およびセンサ側(子機)の設定
子機から送信されたデータを親機で受信するためには、チャンネルなどを適切に設定する必要があります。MONOWIRELESSさんが提供している[TWELITESTAGE SDK](https://mono-wireless.com/jp/products/stage/)に含まれるMWSTAGEを用いて子機と親機の設定をしていきます。
今回は、Windowsにてセンサの設定を行います。続いて、DLしたTWILITESTAGE SDKを解凍します。TWILITER2をPCへと接続し、センサとTWILITER2も接続した状態で、解凍フォルダ内に含まれるTWELITESTAGE.exeを立ち上げます。
TWILITER2→アプリ書き換え→BINから選択→MONO WIRELESS APP_PAL(Endevice) V1-00-2
の順に選択するとセンサ側のファームウェアが書き込まれます。続いてインタラクティブモードへ移行するので、適宜設定します。ここでの設定の詳細は公式の解説([PALアプリインタラクティブモード](https://mono-wireless.com/jp/products/TWE-APPS/App_pal/interactive.html))に譲ることとしますが、わからなければチャンネルをメモして、データ送信間隔を好みの感覚にいじっておけばいいでしょう。(tを入力後、好みの数字を入力)
続いて、MONOSTICKをPCへと接続し、TWELITESTAGE.exeを立ち上げます。
MONOSTICK→アプリ書き換え→BINから選択→APP_PAL-PARENT
の順に選択すると親機側のファームウェアが書き込まれます。続いてインタラクティブモードモードへ移行します。ここでは、センサ側とチャンネル設定の数字があっていることが確認できれば問題ありません。もし異なっていれば、先ほどメモした数字に書き換えましょう。

##Raspiを用いたデータ取得テスト
[MONOWIRELESSさんによるPython用のデータ取得スクリプト](https://mono-wireless.com/jp/products/TWE-APPS/App_pal/palscript.html)を用いてセンサで取得したデータを通信によってRaspiに取得し表示するテストを行います。Raspi側では、Python3を使用するので、pyserialを導入しておきます。

```
>pip3 install pyserial
```
続いて、まず、ソースコード(PAL_Script.py)と実行に必要なライブラリ(MNLib)をRaspiへと移します。
この時PAL_Script.pyとライブラリは同一のディレクトリ内に存在する必要があります。それさえ気をつけておけば、PAL_Script.pyが存在するディレクトリにおいて、

```
>python3 PAL_Script.py
```


と実行しその後、子機に電池を挿入することで受信したデータが表示されます。

```
*** MONOWIRELESS App_PAL_Viewer 1.0.1 ***
{'ArriveTime': datetime.datetime(2021, 2, 6, 21, 19, 6, 51703), 'LogicalID': 1, 'EndDeviceSID': '82014DC1', 'RouterSID': '80000000', 'LQI': 132, 'SequenceNumber': 10, 'Sensor': 128, 'PALID': 2, 'PALVersion': 1, 'Power': 2790, 'ADC1': 2373, 'Temperature': 26.85, 'Humidity': 49.06, 'Illuminance': 4}
```
ちなみに子機側のデータ送信間隔を長く設定してしまった場合、子機のLEDの隣にあるボタンを押すと、データ送信間隔を待たずして強制的にデータが送信されます。強制送信によってもデータの送受信が確認できます。

#センサのデータのMariaDBへの格納
##MariaDBの導入
RaspiにMariaDBを導入します。

```
>sudo apt-get install mariadb-server
```
設定周りは[P.H (id:raspberrypi)さんのブログ](https://www.raspberrypirulo.net/entry/mariadb-install)を参考に**rootのパスワード設定**までを実行しておきましょう。

##データベースの作成
PALアプリから得られたデータを格納するためのtableを作成します。上記の通り多くのデータが無線で送信されてきますが、ここでは、センサデータとして最低限必要なものとして、

1. time：受信日時(datetime)　主キーとして指定
2. sensorid:センサーID(varchar(128))
3. humidity:湿度(float)
4. temperature:気温(float)
5. lqi:受信強度(int)

を登録することとします。(カッコ内は指定する型)

```
>mysql -u root -p
Enter password: #パスワードを入力
>create database monowireless;
>create table monowireless.amb (time datetime not null primary key, sensorid varchar(128), humidity float, temperature float,lqi int);
```

以上で必要なデータを格納するためのテーブルの作成が完了しました。

##センサで取得したデータをデータベースへ登録
データ取得テストで使用したPAL_Script.pyを書き換えて取得データをデータベースへ登録します。pythonからのDB操作にはmysql-connector-pythonを用いることとします。使い方等は[こちら](https://qiita.com/valzer0/items/2f27ba98397fa7ff0d74)を参考にさせていただきました。

```
>pip install mysql-connector-python
```
まずPAL_Script.pyの冒頭のライブラリインポート部分に以下を追記します。

```python
import mysql.connector
```

続いて、取得したデータを記録するために、PAL_Script.py下部の「# なにか処理を記述する場合はこの下に書く」以降に、次の内容を追記します。ここに記述することでデータを取得、書き込みごとにデータベースと接続して得られたセンサデータを記録する形式となります。

```python
conn = mysql.connector.connect(
    host='localhost',
    port='3306',
    user='root',
    password='password',#パスワード設定を変えた場合はその通りに変更
    database='monowireless'
)
cur = conn.cursor()
cur.execute("INSERT INTO amb VALUES (%s,%s,%s,%s,%s)",(Data["ArriveTime"],Data["EndD    eviceSID"] ,Data["Humidity"], Data["Temperature"],Data["LQI"]))
conn.commit()
cur.close()
conn.close()
```

ここまで修正したうえでPAL_Script.pyを実行し、強制送信によってデータの送受信を確認します。

```
>python3 PAL_Script.py
```
受信したデータはMariaDBへ直接記録されていくので表示は出てきません。記録されたデータを確認してみます。

```
>mysql -u root -p
Enter password: #パスワードを入力
>select * from monowireless.amb;
#以下に格納されたデータが表示される
```

データが確認できれば、データの格納までは完了です。


#MariaDBへ格納したデータをStreamlitで表示
最後にDBに格納されたデータをStreamlitで表示しましょう。グラフ等様々な出力がありますが、ここではひとまず表形式のデータを出力することとします。
まず、streamlitの動作確認をしてみます。

```
>streamlit hello 
```

すると、以下のようなエラーメッセージが出て怒られます。

```
Original error was: libf77blas.so.3: cannot open shared object file: No such file or directory
```

調べてみると[こういう記述](https://github.com/numpy/numpy/issues/14772)にぶち当たりました。どうやらライブラリが足りない模様です。

```
>sudo apt-get install libatlas-base-dev
```

として必要なライブラリを導入します。これでいけるはずなので再度動作確認。

```
>streamlit hello 
  RequestsDependencyWarning)

  Welcome to Streamlit. Check out our demo in your browser.

  Network URL: http://xxx.xxx.xxx.xxx:8501
  External URL: http://yyy.yyy.yyy.yyy:8501

  Ready to create your own Python apps super quickly?
  Just head over to https://docs.streamlit.io

  May you create awesome apps!
```

ラズベリーパイには別のPCからsshで接続している状況を想定しています。ラズベリーパイ上で構築されたwebアプリにアクセスするにはNetwork　URLに記されているURLを任意のブラウザに入力します。すると、streamlitのアプリサンプルが表示されるかと思います。確認出来たらアプリを停止して、DBからデータを取得して表示する処理を記述していきます。

```python:amb_steamlit.py
import mysql.connector
import pandas as pd
import streamlit as st

def get_df_by_sql():
        conn = mysql.connector.connect(
        host='localhost',
        port='3306',
        user='root',
        password='password',#パスワード設定を変えた場合はその通りに変更
        database='monowireless'
        )
        sql = 'SELECT * FROM amb'
        df = pd.io.sql.read_sql(sql,conn)
        conn.close
        return df

st.table(get_df_by_sql())
```

上記をsteramlitで実行します。

```
>streamlit run amb_steamlit.py
```

テスト時と同様に得られたURLに接続すると以下のような画面になります。

![スクリーンショット 2021-02-20 200928.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714168/2b5135c6-e0f5-b6fa-6992-c20e2245a626.png)

無事streamlitで取得データを表示することができました。

#まとめ
以上で、「MonowirelessのTWELITE PalからのデータをRaspiで受け取って、DBへ格納→Streamlitで表示する」ことができました。グラフ等にしたければStreamlitの書式に従って適宜作っていきましょう。


#参考
[MONOWIRELESS](https://mono-wireless.com/jp/index.html)
[Raspberry Pi & Python 開発ブログ ☆彡](https://www.raspberrypirulo.net/entry/mariadb-install)
[DBOnline MySQLの使い方](https://www.dbonline.jp/mysql/)
[Qiita Python + mysql-connector-python の使い方まとめ](https://qiita.com/valzer0/items/2f27ba98397fa7ff0d74)