API 経由での Measurement 格納
投稿日 / 投稿者名
2018.8.1 / 竹村 直也
はじめに
本レポートは、Things Cloud の利用例をより知っていただくための実利用レポートとして作成したものです。
Things Cloud は極力後方互換性を持つよう開発されていますが、今後のリリースにより、一部画面やコマンド、手順などが変更となったり、利用できない可能性があることをあらかじめご了承ください。
なお、作成にあたり、以下バージョンを用いています。
- ver.8.15.8(backend/UI)
難易度 ★★
概要
本レポートでは、API 経由で Measurement データを格納する方法についてご紹介します。
Thins Cloud では Measurement を格納するための API が用意されており、それを利用することでプログラム Measurement データを格納することが可能です。
本レポートを読むことで、CSV で取得したデータを Python を用いて JSON 形式の Measurement に変換して、API 経由で Measurement データを格納する方法を理解することができます。
前提条件
- 次の言語/フレームワーク/パッケージ管理システムを扱えること
- Python3 (3.7)
- pip3
- requests (2.19.1)
- テナント内にデバイスが登録済みであること(シミュレーターでも可)
シミュレーターの作成方法は SCADAウィジェットによるデータの可視化 をご参考ください
所要時間(目安)
この手順に沿って、「API 経由で Measurement データ格納」を実現するまでの所要時間。
- 約30分
つくるもの
今回は、post_measurement.py
という Python プログラム の作成を通して、「CSV で取得した温度データを TemperatureMeasurement に変換して、Things Cloud にデータを格納」する基礎を学びます。
1. 関係ファイル
本レポートでは,以下のファイルを利用します.
sample
├── post_measurement.py
└── data.csv
2. サンプルの概要
まず、本レポートで作成したサンプル post_measurement.py
の概要は以下のようになっています。
- CSV ファイルから1行読み込む
- データを Measurement に変換する
- 作成した Measurement を Things Cloud に POST
また、Measurement を格納する方法は以下の2つの方法があります。
- Measurement を1つずつ格納
- Measurement Collection としてまとめて格納
Measurement を格納する際には API を利用するため、API call としてカウントされます。 大量のデータを格納するケースでは、 Measurement Collection の利用を推奨します。
本レポートで作成したサンプルは、以下の通りです。
詳細については、3. サンプルスクリプトの解説 で説明します。
post_measurement.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
########################################################################
## /**
## * [Sample code to create and post Measurement]
## * @param {String} <<CSV_ROW[0]>> temperature
## * @param {String} <<CSV_ROW[1]>> time
## * @return HTTP status code
## */
########################################################################
### import library
import csv
import json
from datetime import datetime
import requests # pip3 install --user requests
### YOUR OWN ACCOUNT INFORMATION
USER = "USER_NAME"
PASSWORD = "PASSWORD"
TENANT_NAME = "TENANT_NAME"
GLOBAL_ID = "DEVICE_GLOBAL_ID"
DOMAIN = "https://" + TENANT_NAME + ".je1.thingscloud.ntt.com"
ENDPOINT = "measurement/measurements"
URL = DOMAIN + "/" + ENDPOINT
FILE_NAME = "data.csv"
### Measurement format
measurement = {
"c8y_TemperatureMeasurement": {
"T": {
"value": 0,
"unit": "C"
}
},
"time": "",
"source": {
"id": GLOBAL_ID
},
"type": "c8y_TemperatureMeasurement"
}
### Object for Measurement Collection
measurements = {
"measurements": []
}
### Header for Measurement
headers_1 = {
"content-type": "application/json",
"accept": "application/vnd.com.nsn.cumulocity.measurement+json"
}
### Header for Measurement Collection
headers_2 = {
"content-type": "application/json",
"accept": "application/vnd.com.nsn.cumulocity.measurementCollection+json"
}
### Read CSV
with open(FILE_NAME, "r") as f:
reader = csv.reader(f)
header = next(reader)
print("Measurement")
for row in reader:
measurement["c8y_TemperatureMeasurement"]["T"]["value"] = int(row[0])
# set time_value to time in CSV
measurement["time"] = row[1]
# # set time_value to current time
# measurement["time"] = datetime.utcnow().isoformat()
##################################################
# POST Measurement (Sequential transmission)
##################################################
r = requests.post(URL, auth=(USER, PASSWORD), headers=headers_1, data=json.dumps(measurement))
print("status : " + str(r.status_code))
measurements["measurements"].append(measurement)
##################################################
# POST Measurement Collection (Bulk transmission)
##################################################
r = requests.post(URL, auth=(USER, PASSWORD), headers=headers_2, data=json.dumps(measurements))
print("Measurement Collection")
print("status : " + str(r.status_code))
data.csv
temperature,time
-10,2018-07-04T01:15:38.144343+09:00
-5,2018-07-04T01:25:39.017374+09:00
0,2018-07-04T01:35:39.814033+09:00
5,2018-07-04T01:45:41.088180+09:00
10,2018-07-04T01:55:41.088180+09:00
3. サンプルスクリプトの解説
必要なライブラリ
スクリプトの冒頭で以下のライブラリをインポートします。
### import library
import csv
import json
from datetime import datetime
import requests # pip3 install --user requests
requests
はデフォルトでは利用できないため、下記のコマンドでインストールします。
$ pip3 install --user requests
テナント情報の設定
次に、ユーザーのアカウント情報を設定します。
### YOUR OWN ACCOUNT INFORMATION
USER = "USER_NAME"
PASSWORD = "PASSWORD"
TENANT_NAME = "TENANT_NAME"
GLOBAL_ID = "GLOBAL_ID"
DOMAIN = "https://" + TENANT_NAME + ".je1.thingscloud.ntt.com"
ENDPOINT = "measurement/measurements"
URL = DOMAIN + "/" + ENDPOINT
FILE_NAME = "data.csv"
今回指定したエンドポイント measurement/measurements
に対して POST リクエストを行うことで、新規 Measurement を格納することができます。
また、2つの格納方法は共に、同じエンドポイント measurement/measurements
を利用します。
Measurement フォーマットの作成
以下は、(Temperature)Measurement のフォーマットです。
格納したい Measurement の種類やデバイスに応じて、以下を変更してください。
変更項目 | 参照方法 |
---|---|
取り扱う Measurement | measurement[“Measurement の フラグメント”] |
デバイスの Global ID | measurement[“source”][“id”] |
取得時間 | measurement[“type”] |
### Measurement format
measurement = {
"c8y_TemperatureMeasurement": {
"T": {
"value": 0,
"unit": "C"
}
},
"time": "",
"source": {
"id": GLOBAL_ID
},
"type": "c8y_TemperatureMeasurement"
}
また、センサーが所得したデータを格納する際に、データごとに変更する項目は以下の2つです。
変更項目 | 参照方法 |
---|---|
センサー取得値 | measurement[“c8y_TemperatureMeasurement”][“T”][“value”] |
取得時間 | measurement[“time”] |
以下は、Measurement Collection 用の配列です。
Measurement をまとめて格納するために利用します。
### Object for Measurement Collection
measurements = {
"measurements": []
}
Header の設定
本レポートでは、2つの方法による Measurement の格納方法をご紹介します。
それぞれ設定する Header が異なる点に注意してください。
Measurement を1つずつ格納
accept
が ***measurement+json
となっていることにご注意ください。
### Header for Measurement
headers_1 = {
"content-type": "application/json",
"accept": "application/vnd.com.nsn.cumulocity.measurement+json"
}
Measureent Collection としてまとめて格納
accept
が ***measurementCollection+json
となっていることにご注意ください。
### Header for Measurement Collection
headers_2 = {
"content-type": "application/json",
"accept": "application/vnd.com.nsn.cumulocity.measurementCollection+json"
}
CSV からデータ取得
Measurement のフォーマットに対して、CSV から取得した 温度
と 取得時間
を代入します。
CSV にカラムのタイトルが存在する場合は、 header = next(reader)
を実行することでタイトルを取り出すことできます。
with open(FILE_NAME, "r") as f:
reader = csv.reader(f)
header = next(reader)
print("Measurement")
for row in reader:
measurement["c8y_TemperatureMeasurement"]["T"]["value"] = int(row[0])
# set time_value to time in CSV
measurement["time"] = row[1]
# # set time_value to current time
# measurement["time"] = datetime.utcnow().isoformat()
Measurement 格納
Measurement を1つずつ格納
requests.post(URL, auth=(USER, PASSWORD), headers=headers_1, data=json.dumps(measurement))
を実行することで、Measurement を1つずつ格納できます。
ここで用いる Header は、headers_1
であることにご注意ください。
with open(FILE_NAME, "r") as f:
# omission
for row in reader:
# omission
##################################################
# POST Measurement (Sequential transmission)
##################################################
r = requests.post(URL, auth=(USER, PASSWORD), headers=headers_1, data=json.dumps(measurement))
print("status : " + str(r.status_code))
measurements["measurements"].append(measurement)
Measurement Collection としてまとめて格納
requests.post(URL, auth=(USER, PASSWORD), headers=headers_2, data=json.dumps(measurement))
を実行することで、Measurement Collection としてまとめて格納できます。
ここで用いる Header は、headers_2
であることにご注意ください。
##################################################
# POST Measurement Collection (Bulk transmission)
##################################################
r = requests.post(URL, auth=(USER, PASSWORD), headers=headers_2, data=json.dumps(measurements))
print("Measurement Collection")
print("status : " + str(r.status_code))
4. 実行結果
下図のような実行結果になっていれば、Measurement 格納成功です。
レスポンスの HTTP ステータスコードが 201
になっていることをご確認ください。
実行結果 |
---|
以上が、CSV ファイルのデータを Measurement に変換し、Things Cloud に格納する方法です。
また、本レポートでは利用しませんでしたが、Things Cloud には SmartREST という機能もあります。
SmartRESTエンドポイントとの通信には CSV 形式が利用できるため、発展としてこちらの利用もご検討ください。