目次
- Wio LTEを受信用デバイスとして使いたい
- SORACOM Air plan-KM1 はパケ死する
- Lambdaの作成
- API Gatewayの作成
- SORACOM Beamの設定
- Wio LTEのコード
- 実際の通信料は
Wio LTEを受信用デバイスとして使いたい
以前、SORACOM LTE-M ButtonからLINEにメッセージを送る - Qiita という記事を書きまして、その後も日々このボタンをポケットに入れ、機会あるたびに人にデモしていたのですが、ボタンを押したらLINEメッセージが届くだけでは、「すごい」と言われても、「それで?」「だから?」という気持ちが透けて見えてきました。
そのため、LTE-Mボタンを押したら、パトランプが光るようなデモができたらと考えました。そして、どうせなら、受信側も、LTE-M回線を経由して、Wio LTEを使えたら良いのではと考えました。
LTE-Mボタンを押したら、その情報を何らかのサーバを経由してWio-LTEにおくり、パトランプを点灯させるという簡単な仕組みです。
いろいろ調べて、今回は、個人が簡単に安価でできる範囲で実現するため、Wio-LTEから数秒おきにサーバに状態を問い合わせる方式とすることにしました。
SORACOM Air plan-KM1 はパケ死する
元々IoT用の Lte-M1 という通信方式は、大量に撒いたデバイスから、1日1回とか、1週間に1回、それも数十バイトといった頻度・データ量の通信を想定しているため、月額利用料は安いものの、通信料は一昔前のパケット代レベル( 1MBあたり 500円超! )になっています。
日本向け Air SIM のご利用料金
そのため、例えば、数秒おきに、HTTPSで外部サーバに接続に行くなんてことをすると、 たった1時間で数千円の請求 になりかねません。
参考:HTTP(S)とMQTT(S)の消費電流とデータサイズを計測する - Qiita
なので、今回は、便利なSORACOM Beamの、UDPを使ってデータを受信することとします。
SORACOM Beam : Beamを使用したデータの送信 | 開発者ガイド | SORACOM Developers によれば、APIのレスポンスのBody部分が、そのままデバイスに返信されます。
SORACOM Beamを設定するには、まず通信先のAPIが必要になるため、AWSのLambdaとAPI Gatewayを利用して、APIを作成します。
Lambdaの作成
将来的には直近のボタンの状態を取得して返しますが、現時点では、単純に1を返すことにします。
- ボタンが1回押された:1
- ボタンがダブルクリックされた:2
- ボタンが長押しされた(リセット):0
exports.handler = async(event) => {
return ("1\n");
};
あとで気づいたのですが、最後に改行\n
を付け加えないと、Beam側でデータを受け取ってくれない様です。特にドキュメントには書いてなかったのですが・・・。
API Gatewayの作成
LambdaをSORACOM Beamから呼べるように、API Gatewayを作成します。
普通にPOSTメソッドを先ほどのLambdaに設定すればいいのですが、1点だけ、「Lambda プロキシ統合の使用」のチェックは入れません。
SORACOM Beamの設定
SIM グループ - SORACOM ユーザーコンソール で、SIMグループの作成し、SORACOM Beamの設定で、「UDPToHTTP」を設定します。
その際、「ステータスコードを省略」をONにしておくと、さらにバイト数を節約できます。
Wio LTEのコード(都度接続版)
公式のサンプルコードにある、「soracom/soracom-harvest」を編集して、SORACOM Beamに空データを送るコードを書きました。5秒おきに接続する様になっています。
Wiki/home-ja.md at master · SeeedJP/Wiki · GitHub
#include <WioCellLibforArduino.h>
#define INTERVAL (5000)
#define RECEIVE_TIMEOUT (10000)
WioCellular Wio;
void setup() {
delay(200);
SerialUSB.begin(115200);
SerialUSB.println("");
SerialUSB.println("--- START ---------------------------------------------------");
SerialUSB.println("### I/O Initialize.");
Wio.Init();
SerialUSB.println("### Power supply ON.");
Wio.PowerSupplyCellular(true);
delay(500);
SerialUSB.println("### Turn on or reset.");
#ifdef ARDUINO_WIO_LTE_M1NB1_BG96
Wio.SetAccessTechnology(WioCellular::ACCESS_TECHNOLOGY_LTE_M1);
Wio.SetSelectNetwork(WioCellular::SELECT_NETWORK_MODE_MANUAL_IMSI);
#endif
if (!Wio.TurnOnOrReset()) {
SerialUSB.println("### ERROR! ###");
return;
}
SerialUSB.println("### Connecting to \"soracom.io\".");
if (!Wio.Activate("soracom.io", "sora", "sora")) {
SerialUSB.println("### ERROR! ###");
return;
}
SerialUSB.println("### Setup completed.");
}
void loop() {
char data[100];
sprintf(data, "{}");
SerialUSB.println("### Open.");
int connectId;
//beam.soracom.io:23080
connectId = Wio.SocketOpen("beam.soracom.io", 23080, WIO_UDP);
if (connectId < 0) {
SerialUSB.println("### ERROR! ###");
goto err;
}
SerialUSB.println("### Send.");
SerialUSB.print("Send:");
SerialUSB.print(data);
SerialUSB.println("");
if (!Wio.SocketSend(connectId, data)) {
SerialUSB.println("### ERROR! ###");
goto err_close;
}
SerialUSB.println("### Receive.");
int length;
length = Wio.SocketReceive(connectId, data, sizeof (data), RECEIVE_TIMEOUT);
if (length < 0) {
SerialUSB.println("### ERROR! ###");
goto err_close;
}
if (length == 0) {
SerialUSB.println("### RECEIVE TIMEOUT! ###");
goto err_close;
}
SerialUSB.print("Receive:");
SerialUSB.print(data);
SerialUSB.println("");
err_close:
SerialUSB.println("### Close.");
if (!Wio.SocketClose(connectId)) {
SerialUSB.println("### ERROR! ###");
goto err;
}
err:
delay(INTERVAL);
}
プログラムを書き込んで実行すると、下記のようなログがシリアルモニタに出力されました。
--- START ---------------------------------------------------
### I/O Initialize.
### Power supply ON.
### Turn on or reset.
### Connecting to "soracom.io".
### Setup completed.
### Open.
### Send.
Send:{}
### Receive.
Receive:1
### Close.
### Open.
### Send.
Send:{}
### Receive.
Receive:1
実際の通信料は
実際に起動して数分放置させ、180回弱ほど通信した後、SIM 管理 - SORACOM ユーザーコンソール から通信料履歴タブを見ると、21.9KBほどの通信が発生していました。
1回の通信で、約120byteほどのデータを消費しているようです。
これでも、5秒おきに通信するとなると、 120byte * 12回/分 * 60分 * 24時間 * 30日 = 40MB = 3万円/月 ぐらいの通信料になるので、素直に plan-K か plan-D を使うことをおすすめします。
Wio LTEのコード(接続しっぱなし版)
先ほどのコードでは、Socket通信を毎回オープン・クローズしていたので、もしかしたらオーバーヘッドがあるかもしれないと思い、接続しっぱなしのバージョンも試してみました。
コードはこちら。
#include <WioCellLibforArduino.h>
#define INTERVAL (10000)
#define RECEIVE_TIMEOUT (10000)
#define RED_PIN (WIO_D20)
#define YELLOW_PIN (WIO_D19)
WioCellular Wio;
bool socketStatus;
void setup() {
delay(200);
SerialUSB.begin(115200);
SerialUSB.println("");
SerialUSB.println("--- START ---------------------------------------------------");
SerialUSB.println("### I/O Initialize.");
Wio.Init();
SerialUSB.println("### Power supply ON.");
Wio.PowerSupplyCellular(true);
delay(500);
SerialUSB.println("### Turn on or reset.");
#ifdef ARDUINO_WIO_LTE_M1NB1_BG96
Wio.SetAccessTechnology(WioCellular::ACCESS_TECHNOLOGY_LTE_M1);
Wio.SetSelectNetwork(WioCellular::SELECT_NETWORK_MODE_MANUAL_IMSI);
#endif
if (!Wio.TurnOnOrReset()) {
SerialUSB.println("### ERROR! ###");
return;
}
SerialUSB.println("### Connecting to \"soracom.io\".");
if (!Wio.Activate("soracom.io", "sora", "sora")) {
SerialUSB.println("### ERROR! ###");
return;
}
socketStatus = false;
SerialUSB.println("### Setup completed.");
}
void loop() {
char data[100];
int v;
int connectId;
sprintf(data, "0");
if(!socketStatus){
SerialUSB.println("### Open.");
//beam.soracom.io:23080
connectId = Wio.SocketOpen("beam.soracom.io", 23080, WIO_UDP);
if (connectId < 0) {
SerialUSB.println("### ERROR! ###");
goto err;
}
socketStatus = true;
}
SerialUSB.println("### Send.");
SerialUSB.print("Send:");
SerialUSB.print(data);
SerialUSB.println("");
if (!Wio.SocketSend(connectId, data)) {
SerialUSB.println("### ERROR! ###");
goto err_close;
}
SerialUSB.println("### Receive.");
int length;
length = Wio.SocketReceive(connectId, data, sizeof (data), RECEIVE_TIMEOUT);
if (length < 0) {
SerialUSB.println("### ERROR! ###");
goto err_close;
}
if (length == 0) {
SerialUSB.println("### RECEIVE TIMEOUT! ###");
goto err_close;
}
SerialUSB.print("Receive:");
SerialUSB.print(data);
SerialUSB.println("");
goto err;
err_close:
SerialUSB.println("### Close.");
if (!Wio.SocketClose(connectId)) {
SerialUSB.println("### ERROR! ###");
goto err;
}
socketStatus = false;
err:
delay(INTERVAL);
}
65回ほど通信させて、8.1KB。1回の通信で約120バイト。
残念ながら、消費するバイト数は同じくらいでした。もしかしたらもう少し放置したら違いが出るかも?
続き
完成したものは、こちら。
「ボタンを押したらパトランプ点灯してブザーを鳴らす」を、すべてLTE-M回線で実現してみた。 - Qiita
#あのボタン を押したことを Wio LTE M1/NB1で受信して、パトランプとブザーを鳴らしてみた。音量注意。#SORACOM #AWS pic.twitter.com/4UMEiCktyH
— Kosuke Koiwai (@kocko) April 28, 2019