Wio LTEで遊んでみる(その8:外部システムへ連携)
Grove IoT スターターキット for SORACOMで遊んでみるの続き。
- 初回:環境構築+Lチカ
- 二回目:温湿度センサー
- 三回目:ボタン+ブザー
- 四回目:磁気スイッチと超音波距離センサー
- 五回目:3軸デジタル加速度センサーとGPS
- 六回目:簡易地震計を作ってみる
- 七回目:簡易地震計を改善する
今回の目的
今まではHarvestへ連携していたデータをBeam,AWS Lambdaを使用して別システムへ連携させることを目的とする。
GPSで位置情報が取得できるのでArcGISへ連携してみる。
※可能であればSlackにも通知したい。
※2018/08/03時点では未完成
必要なものを順番に準備
連携先(ArcGIS)を作成
https://developers.arcgis.com/
まずアカウントを作る。
※既にあるのであれば不要。
[Details]
名前とタグを適当に設定
[Geometry]
今回は点のデータなのでpointを指定。
測地系(Spatial Reference)はたぶん世界測地系なので4326のままでOK
[Fields]
今回使用する項目を定義する
とりあえずは以下を想定
imei:SIMのIMEI:データ的には数字列なのだが、Longだと桁数的にはいらないので文字列にしておく
time:取得日時用?
lat:緯度
lon:経度
mode:送信モード:モードの設定に対してコード値ドメインも設定
temp:温度
humi:湿度
g_ave:揺れ関係のデータ
other_string:後で追加したくなったとき用(文字列)
other_double:後で追加したくなったとき用(数字)
other_date:後で追加したくなったとき用(日時)
[Settings]
ShareLayer
セキュリティ的なものも考えるとPrivateがいいんだが、外から呼び出す際にトークンを生成したりするのがめんどくさいのでとりあえずPublicにしてしまう。
Permissions Settings
Publicにしている代わりというわけではないが、Addのみにしておく。
で、CreateLayer
作成したレイヤーがちゃんとできているかを確認する。
レイヤーからWebMapを作成。
[編集]を押下して、New Featureで追加できることを確認。
これでArcGIS側の準備はOK
作成したフィーチャレイヤーのServie URLを控えておく。
https://[xxxxxxxx].arcgis.com/[XXXXXXXXXXXX]/arcgis/rest/services/fromsoracom_01/FeatureServer
これの後ろに[/0/applyEdits]をつけ、以下のDataをPOSTしてあげると登録できる。
※この段階で一度試してみておくとよい。
URL:
https://[xxxxxxxx].arcgis.com/[XXXXXXXXXXXX]/arcgis/rest/services/fromsoracom_01/FeatureServer/0/applyEditsContent-Type:application/x-www-form-urlencoded
Data : "adds=" + json_q + "&f=pjson"
json_qの中身はこんな感じ。
{
"geometry":{
"x":140,
"y":35,
"spatialReference":{"latestWkid":4326,"wkid":4326}
},
"attributes":{
"imei":1234,
"mode":0,
"temp":30,
"humi":60,
"g_ave":2,
"lon":140,
"lat":35
}
}
SORACOM Beam→AWS API Gateway →AWS Lambda
上記で単純なPythonからの登録処理はできそうなのでSORACOM→AWS Lambdaの部分を作る
以下を参考にする。
https://dev.soracom.io/jp/docs/aws_guide/
API Gateway → Lambdaの部分までは問題なく完了。
外部からAPIをCallしてArcGISへ登録できることも確認。
ただ、SORACOM Beam → API Gatewayの部分の連携がよくわからない。
どういう形式で飛んでいくことを想定しているのか。。。
POST/PUTのJsonのBodyがそのまま[$input.json('$')]の部分に当てはまるということなのだろうが
UDP経由でBeamに上げHTTPSで転送した場合どうなるのだろう?
具体的にいうと
int connectId;
connectId = Wio.SocketOpen("beam.soracom.io", 23080, WIOLTE_UDP);
if (!Wio.SocketSend(connectId, data))
{
SerialUSB.println("### SocketSend ERROR! ###");
goto err_close;
}
int length;
length = Wio.SocketReceive(connectId, data, sizeof (data), RECEIVE_TIMEOUT);
if (length < 0)
{
SerialUSB.println("### SocketReceive ERROR! ###");
goto err_close;
}
という流れの中で
### SocketReceive ERROR! ###
となる。
以下を読むとBase64で変換されてしまっているのからなのか?
https://dev.soracom.io/jp/beam/send-data-using-beam/#udp2http
変換したものを送って、それを直接読み込もうとしているからエラーになっているということなのか?
ただ、軽く調査した感じだとAWSのLambdaまでデータが行ってなさそう。
※Lambdaの関数が呼び出されてなさそうな感じがする。
で、Open/SendはできているということはSORACOMまでは行っているような気がする。
※でもコンソール画面のエラーログには出ていないので行っていない可能性もある?
わからん。
ハマりかけている気がするのでいったんここで終了。
追記
Lambdaでの処理が間違っていた
Harvestからぶっこ抜いてきたエンコードされているデータをこれを使って検証にしてみることにする。
[データ]
{"payload":"eyJsYXQiOjAuMDAwMDAwLCJsb24iOjAuMDAwMDAwLCJ0ZW1wIjoyNS43LCJodW1pIjo1OS4wLCJnX2F2ZSI6MC43MTUsIm1vZGUiOjJ9"}
[一次処理済みデータ]
{"value":"{\"lat\":0.000000,\"lon\":0.000000,\"temp\":25.7,\"humi\":59.0,\"g_ave\":0.715,\"mode\":2}"}
※payloadを変換したあとにvalueが入ってる?
結論
base64.b64decodeで変換した結果の使い方が間違っていたっぽい。
辞書で渡してたから変換後もそのままで扱ってたけど、よく考えたらこれの結果は文字列だった。
なのでjson.loadsしてあげればOK
encoded = event["item"]["payload"]
receive_data = base64.b64decode(encoded).decode()
receive_json_data = json.loads(receive_data)
こんな感じ。
payloadの状態でLambdaでテストしてなかったのが間違いだった。テスト大事。
※payloadを変換した結果にvalueというKeyも入っているのかと思ったらそんなことはなかった。
ダメだった。
が、これでOKかと思ったらそんなことはなかった。
デバイスからだとやっぱり上手くいかず。
やはりAWSまで飛んでいないのか?
一回Harvestへの送信に戻してみる。
特に問題なくできてそう。
で、もう一回Beam。
飛んでこない。
CloudWatch でも確認してみるがやっぱり飛んできてなさそう。
確認のため、BeamからSlackへ飛ばしてみることにする
飛ばせてる。
当たり前だけど、SORACOMまでは来ていることが分かる。
※この辺を簡単にグループ設定/変更できるのはSORACOMのいいところだと思う。
突然の解決
ふと思い立って「事前共有鍵」の設定を追加。
※これがなんだかよくわからなかったので未設定だった。
これでAWSへも送信されるようになった。
AWSへ送信したい場合はこれの設定が不可欠だったのか?
ということでやりたかったことは完成。
ついでに「揺れ」を検知した場合はSlackへの送信するようにしてみた。
※GPSから位置情報が取れなかったとき、適当な位置にポイント作成するようにしてます。
Lambda
import json
import base64
AGOL_applyEdits = r"https://[xxxxxxxx].arcgis.com/[XXXXXXXXXXXX]/arcgis/rest/services/fromsoracom_01/FeatureServer/0/applyEdits"
Slack_Token = "xoxp-xxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxxxxxxxx"
def lambda_handler(event, context):
# Base64で変換された結果がpayloadに格納されているのでデコードする
encoded = event["item"]["payload"]
receive_data = base64.b64decode(encoded).decode()
receive_json_data = json.loads(receive_data)
send_data = CreateAddData(receive_json_data)
AddFeature(AGOL_applyEdits, send_data)
if(receive_json_data["mode"] == 2):
to_slack(receive_json_data)
def CreateAddData(attributes_dic):
# 測地系設定:固定(WGS1984で設定)
geometry_dic = {}
geometry_dic["x"] = attributes_dic["lon"]
if(0==geometry_dic["x"]):
geometry_dic["x"] = 140.1
geometry_dic["y"] = attributes_dic["lat"]
if(0==geometry_dic["y"]):
geometry_dic["y"] = 35.1
spatialReference_dic = {}
spatialReference_dic["latestWkid"] = 4326
spatialReference_dic["wkid"] = 4326
geometry_dic["spatialReference"] = spatialReference_dic
# パラメータ作成
devData_dic = {}
devData_dic["geometry"] = geometry_dic
# 時間:SORACOMから渡されるUNIX TIMEを使用してもいい。
from datetime import datetime
attributes_dic["time"] = datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S')
devData_dic["attributes"] = attributes_dic
return devData_dic
def AddFeature(url, devData_dic):
# 送信する
# 属性データの辞書をJSONに変換
json_str = json.dumps(devData_dic)
# 属性JSONをURLエンコード
import urllib.parse
json_q = urllib.parse.quote(json_str)
# 送信パラメータを構築
sendData = "adds=" + json_q + "&f=pjson"
# 送信(POST)
headers = {"Content-Type" : "application/x-www-form-urlencoded"}
req = urllib.request.Request(url, headers=headers, data=sendData.encode('utf-8'))
with urllib.request.urlopen(req) as response:
response_body = response.read().decode("utf-8")
json_dict = json.loads(response_body)
return json_dict
def to_slack(receive_json_data):
import urllib.request, urllib.parse
params = {
"token": Slack_Token,
"channel": "random",
"text": "ゆれた気がする\n緯度:{}\n経度:{}".format(receive_json_data["lat"],receive_json_data["lon"])
}
p = urllib.parse.urlencode(params)
url = "https://slack.com/api/chat.postMessage?" + p
with urllib.request.urlopen(url) as res:
res.read().decode("utf-8")
以下で参照することもできます。
https://rio-naka.maps.arcgis.com/apps/webappviewer/index.html?id=3466ae5585364e98ae7e7abdfa4bfb89
まとめ
とりあえずこれでひとしきりで遊んでみたい連携機能の確認はできたような気がする。
セキュリティ的にはザルなので気を付ける必要はありますが。。
SORACOMのBeam上で複数の送信先に転送ができるといいなぁとも思う。
あと、エラーログ?しかコンソール上では確認できないみたいなので、もうちょっといろいろと参照できると嬉しいかも。Harvestとかだとあまり気にならないが、BeamだとIN/OUTが見たかった。
逆にやりたいことに合わせてグループを作成しておけば、簡単に変更できるというのはGood。
Author And Source
この問題について(Wio LTEで遊んでみる(その8:外部システムへ連携)), 我々は、より多くの情報をここで見つけました https://qiita.com/ryo_naka/items/cede1f4ce3dce0aed350著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .