オムロン環境センサ（2JCIE-BU）をラズパイで使ってみた。（３）

センサーのオムロン 2JCIE-BUとデータを格納するPostgreSQLの準備ができたので、実際にテーブルを作成してデータを格納していく。

# 格納テーブルの作成

## 今回格納するデータ

|格納するデータ|説明|
|---|---|
|Time measured|計測時刻|
|Temperature|温度　-10～60℃|
|Relative humidity|湿度　30～85%RH|
|Ambient light|照度　10～2000lx|
|Barometric pressure|大気圧　700～1100hPa|
|Sound noise|騒音　40～94dB|
|eTVOC|総揮発性有機化学物量相当値 0～29206ppb|
|eCO2|CO2 濃度相当値|
|Discomfort index|不快指数|
|Heat stroke|熱中症警戒度|
|Vibration information|振動|
|SI value|スペクトル強度|
|PGA|最大加速度値|
|Seismic intensity|計測震度相当値|

詳細は、以下のページの製品カタログやユーザマニュアルを参照するとよい。

https://www.omron.co.jp/ecb/product-detail?partNumber=2JCIE-BU


## PostgreSQLのテーブルの作成

上の表にした項目を登録するテーブルを作成。

```shell-session:
pi@raspberrypi:~ $ psql -U pgadmin -d sample_db -h localhost -p 5432
ユーザ pgadmin のパスワード: 
psql (11.13 (Raspbian 11.13-0+deb10u1))
SSL 接続 (プロトコル: TLSv1.3、暗号化方式: TLS_AES_256_GCM_SHA384、ビット長: 256、圧縮: オフ)
"help" でヘルプを表示します。

sample_db=# create table t_omron_sensor( id serial NOT NULL,
sample_db(#                     TimeMeasured timestamp,
sample_db(#                     Temperature numeric,
sample_db(#                     RelativeHumidity numeric,
sample_db(#                     AmbientLight integer,
sample_db(#                     BarometricPressure numeric,
sample_db(#                     SoundNoise numeric,
sample_db(#                     eTVOC integer,
sample_db(#                     eCO2 integer,
sample_db(#                     DiscomfortIndex numeric,
sample_db(#                     HeatStroke numeric,
sample_db(#                     VibrationInformation integer,
sample_db(#                     SIValue numeric,
sample_db(#                     PGA numeric,
sample_db(#                     SeismicIntensity numeric,
sample_db(#                     PRIMARY KEY(id) );
CREATE TABLE
```

作成したテーブルの確認

```shell-session:
sample_db=# \d t_omron_sensor
                                              テーブル "public.t_omron_sensor"
          列          |             型              | 照合順序 | Null 値を許容 |                 デフォルト                 
----------------------+-----------------------------+----------+---------------+--------------------------------------------
 id                   | integer                     |          | not null      | nextval('t_omron_sensor_id_seq'::regclass)
 timemeasured         | timestamp without time zone |          |               | 
 temperature          | numeric                     |          |               | 
 relativehumidity     | numeric                     |          |               | 
 ambientlight         | integer                     |          |               | 
 barometricpressure   | numeric                     |          |               | 
 soundnoise           | numeric                     |          |               | 
 etvoc                | integer                     |          |               | 
 eco2                 | integer                     |          |               | 
 discomfortindex      | numeric                     |          |               | 
 heatstroke           | numeric                     |          |               | 
 vibrationinformation | integer                     |          |               | 
 sivalue              | numeric                     |          |               | 
 pga                  | numeric                     |          |               | 
 seismicintensity     | numeric                     |          |               | 
インデックス:
    "t_omron_sensor_pkey" PRIMARY KEY, btree (id)

sample_db=# 
```

## サンプルプログラムの修正

https://qiita.com/Toshiaki0315/items/aa43e78c024bb900ef53

で使用した、オムロンのサンプルを改造してPostgreSQLに登録するように修正してみる。

https://github.com/omron-devhub/2jciebu-usb-raspberrypi


オムロンのサンプルプログラムの最初の方でpsycopg2をインポートする記載を追記します。

```python:
import psycopg2
```

サンプルプログラムのprint_latest_data()メソッドの後ろあたりに、データベースへ登録するメソッドを作ります。
前半の値を作るところはほぼ同じ（サンプルの表示のところでは、str()で囲んで全て文字列にしていた部分を削除しています）になります。
後半は、データベースに接続してデータを追加する処理になります。

```python:
def insert_latest_data(data):
    """
    insert measured latest value.
    """
    time_measured = "'" + datetime.now().strftime("%Y/%m/%d %H:%M:%S") + "'"
    temperature = s16(int(hex(data[9]) + '{:02x}'.format(data[8], 'x'), 16)) / 100
    relative_humidity = int(hex(data[11]) + '{:02x}'.format(data[10], 'x'), 16) / 100
    ambient_light = int(hex(data[13]) + '{:02x}'.format(data[12], 'x'), 16)
    barometric_pressure = int(hex(data[17]) + '{:02x}'.format(data[16], 'x') + '{:02x}'.format(data[15], 'x') + '{:02x}'.format(data[14], 'x'), 16) / 1000
    sound_noise = int(hex(data[19]) + '{:02x}'.format(data[18], 'x'), 16) / 100
    eTVOC = int(hex(data[21]) + '{:02x}'.format(data[20], 'x'), 16)
    eCO2 = int(hex(data[23]) + '{:02x}'.format(data[22], 'x'), 16)
    discomfort_index = int(hex(data[25]) + '{:02x}'.format(data[24], 'x'), 16) / 100
    heat_stroke = s16(int(hex(data[27]) + '{:02x}'.format(data[26], 'x'), 16)) / 100
    vibration_information = int(hex(data[28]), 16)
    si_value = int(hex(data[30]) + '{:02x}'.format(data[29], 'x'), 16) / 10
    pga = int(hex(data[32]) + '{:02x}'.format(data[31], 'x'), 16) / 10
    seismic_intensity = int(hex(data[34]) + '{:02x}'.format(data[33], 'x'), 16) / 1000

    con = psycopg2.connect( database='sample_db', user='pgadmin', password='xxxxx', host='localhost', port=5432)

    cur = con.cursor();

    print(temperature)
    cur.execute("INSERT INTO t_omron_sensor(timemeasured,
                                        temperature,\
                                        relativehumidity,\
                                        ambientlight,\
                                        barometricpressure,\
                                        soundnoise,\
                                        etvoc,\
                                        eco2,\
                                        discomfortindex,\
                                        heatstroke,\
                                        vibrationinformation,\
                                        sivalue,\
                                        pga,\
                                        seismicintensity) \
                                        VALUES (\
                                        %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);", \
                                        (time_measured,\
                                        temperature,\
                                        relative_humidity,\
                                        ambient_light,\
                                        barometric_pressure,\
                                        sound_noise,\
                                        eTVOC,\
                                        eCO2,\
                                        discomfort_index,\
                                        heat_stroke,\
                                        vibration_information,\
                                        si_value,\
                                        pga,\
                                        seismic_intensity) \
                                        )

    con.commit()

    cur.close()
    con.close()

```

最後にサンプルプログラムのprint_latest_data()メソッドを繰り返し呼び出していたところを、insert_latest_data()メソッドに変更すると、定期的にセンサーデータを取得してきてDBに登録します。

サンプルプログラムの表示が１秒になっていて、DBに登録するデータ量と頻度が多くなるので、適切な感覚に調整することをお勧めします。
僕は60秒間隔でデータを登録するようにしました。

※サンプルプログラムで、デバッグで使っていた処理（INSERT後にSELECTでデータを取得して表示していた処理）を削除。