この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、せーのです。今日は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、お試し下さい!