【新機能】SORACOM Beamを使ってLoRaゲートウェイからのデータをKibanaで可視化する #scd2016 #soracom
こんにちは、せーのです。今日はSORACOM Conference "Discovery"というSORACOMさんのイベント会場に来ております。こちらからご紹介するのはSORACOM BeamがLoRaに対応した、というお話です。
LoRaって何
"LoRa"とはLPWA(Low Power Wide Area Networkと呼ばれる 無線通信規格の1つです。Bluetoothとか赤外線通信とかの仲間ですね。特徴としてはなんといっても「長距離(最大15km)」というところです。LoRaはモジュールとゲートウェイからなるのですが、ゲートウェイが5〜6個あれば町ひとつをまるまるカバーする、ということも可能なレベルです。
その他LoRaの説明、SORACOMとLoRaの関連はこちらを参考にして下さい。
SORACOMのSIMとLoRaデバイスが一つのコンソールで同じように管理出来る、というのは非常に便利ですね。
今回はプレビュー版をいち早く触る機会がありましたので早速使ってみました。
やってみた
さて今回はLoRaモジュールにPIRセンサーのデータを送り、そこからSORACOM Beamを使ってAPI Gatewayに渡し、Lambdaを使ってAmazon ES Serviceに投入してKIBANAで表示、というソリューションを作ってみました。
右側にある長四角いモジュールがLoRaモジュールです。Arduinoに刺さっています。Arduinoを使ってLoRaモジュールにデータを送るスケッチに関してはこちらを参考にして下さい。
さて、次はBeamの設定です。これは本来のBeamの設定とそう変わりません。LoRaの場合はβ版の現時点ではLoRaモジュール => HTTP/HTTPSのみサポートしています。ではグループを開きます。新規グループを作成し、API GatewayのURLとパスを設定します。
現在はカスタムヘッダが使えないのでAPI Gatewayはオープンにしておきます(近々つくそうです)。これでBeam部分ができました。
後は対象となるLoRaデバイスにこのグループをつければLoRaゲートウェイからのデータがBeamを通してAPI Gatewayに送られます。
どうでしょう。SIMの時とほぼ変わりませんね。
AWS側構築
ついでにAWS側の設定もご紹介します。AWS側はAPI GatewayでBeamからのデータを受け、Lambdaに渡してES Serviceに登録、Kibanaで表示、という形になります。まずはLambdaから。新規にLambda Funcitonを作ります。RoleはES Serviceが操作でき、Cloudwatch Logsに登録できる権限があればOKです。
コードは特にローカルでダウンロードしなければいけない外部ライブラリをつかわなかったので、エディタ上で書きました。
console.log('Loading function'); /** * Provide an event that contains the following keys: * * - operation: one of the operations in the switch statement below * - tableName: required for operations that interact with DynamoDB * - payload: a parameter to pass to the operation being performed */ var AWS = require('aws-sdk'); var path = require('path'); var creds = new AWS.EnvironmentCredentials('AWS'); var esDomain = { endpoint: 'search-soracomdiscovery2016-XXXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.es.amazonaws.com', region: 'ap-northeast-1', index: 'lora', doctype: 'data' }; var endpoint = new AWS.Endpoint(esDomain.endpoint); exports.handler = (event, context, callback) => { console.log('Received event:', JSON.stringify(event, null, 2)); var countdata = Number(event.message.moduleData.data.slice(-2)); console.log('count: ', countdata); var dt = event.message.moduleData.date; var result = { count:countdata, dt:dt }; postDocumentToES(JSON.stringify(result), function(ret){ if (ret == "success"){ context.succeed("success"); } else { context.fail("failed."); } }); }; function postDocumentToES(doc, callback) { var req = new AWS.HttpRequest(endpoint); req.method = 'POST'; req.path = path.join('/', esDomain.index, esDomain.doctype); req.region = esDomain.region; req.body = doc; req.headers['presigned-expires'] = false; req.headers['Host'] = endpoint.host; // Sign the request (Sigv4) var signer = new AWS.Signers.V4(req, 'es'); signer.addAuthorization(creds, new Date()); var send = new AWS.NodeHttpClient(); send.handleRequest(req, null, function(httpResp) { var body = ''; httpResp.on('data', function (chunk) { body += chunk; }); httpResp.on('end', function (chunk) { //console.log("es ok chunk:"+body); callback("success"); }); }, function(err) { console.log("es error"+err); callback("fail"); }); }
LoRaデータのJSONの内PIRセンサーのカウントデータが入っている部分を切り出して数値化、日時データと一緒に新たなJSONとしてHTTPリクエストを投げる、という感じですね。次にAPI Gateway。
パスを適当に設定してPOSTメソッドを作成します。Lambdaにはそのまんま渡すだけなのでLambdaに渡す権限をRoleにつけてあげればあとはデフォルトのままでOKです。一応content typeとしてapplication/jsonを付与するようにしました。最後にES Service。
クラスタ自体はテストなので1つのみ、オープンで立てました。UTCで日時データが飛んで来るのでLambdaのログが入っているCloudwatch LogsにES Serviceに送るデータを吐いてコピペし、1件だけ登録すれば自動的にdate型(日時)とint型(カウントデータ)でマッピングされます。
curl -XPOST search-soracomdiscovery2016-XXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.es.amazonaws.com/lora/data -d '{"count":0,"dt":"2016-07-12T06:26:00.000Z"}'
最後はKibanaです。これは好きな様にグラフ化したら良いかと思います。私の場合は棒グラフでカウントデータを日時順に表示し、全体の合計カウントをMetricsとして数値で表示しました。
こんな感じで構築完了です。AWS側も慣れれば数時間でできると思います。
まとめ
いかがでしたでしょうか。LoRa部分はArduinoのスケッチが書ければ後の流れは通常のIoTとそう変わらないことがわかるかと思います。データが通った時には結構な快感がありますので、是非LoRa+SORACOM、お試し下さい!