Quectel 社製 LTE-MモジュールBG96 が搭載されているIoT スターターキット for Arduinoの公式サンプルスケッチを例にデータ利用量を大幅に削減する方法を紹介します。
まず公式soracom-labのリポジトリからsend_multiple_sensor_data_with_soracom.inoを使ってみます。
セットアップページに従って送信を開始するとsoracom Harvest Dataのページでこのようにデータが流れてきているのがわかります。
このスケッチではHTTP POSTメソッドでJSON形式のデータを送信しています。
(163行目)
char payload[90];
sprintf_P(payload, PSTR("{\"light\":%d,\"sound\":%d,\"temp_c\":%s,\"humi\":%d,\"air_pressure_hpa\":%s}"),
light_mapped_value, sound_mapped_value, temp_buf, humi, hPa_buf);
/* example:
* {"light":48,"sound":60,"temp_c": 25.0,"humi":34,"air_pressure_hpa":1015.5}
*/
CONSOLE.println(payload);
CONSOLE.print(F("Send..."));
drawText_P(&u8x8, PSTR("Send..."));
/* connect */
if (!ctx.connect(ENDPOINT, 80)) {
CONSOLE.println(F("failed."));
drawText_P(&u8x8, PSTR("failed."));
delay(3000);
return;
}
/* send request */
char hdr_buf[40];
ctx.println(F("POST / HTTP/1.1"));
sprintf_P(hdr_buf, PSTR("Host: %s"), ENDPOINT);
ctx.println(hdr_buf);
ctx.println(F("Content-Type: application/json"));
sprintf_P(hdr_buf, PSTR("Content-Length: %d"), strlen(payload));
ctx.println(hdr_buf);
ctx.println();
ctx.println(payload);
/* receive response */
// NOTE: response header and body are ignore due to saving for memory
ctx.stop();
CONSOLE.println(F("done."));
u8x8.clearLine(6);
この部分を以下のように変更します
1. int型(float型)の数値を%04X(%08lX)フォーマット指定子をつかって16進数に置き換え
2. ATコマンドの+QISENDEXを使って送信
https://www.quectel.com/product/bg96.htm
にある Quectel_BG96_TCP(IP)_AT_Commands_Manual_V1.1.pdf を参照
2.1.9. AT+QISENDEX Send Hex String
This command cannot be applied for "UDP SERVICE" and "TCP LISTENER" sockets.
Write Command
AT+QISENDEX=<connectID>,<hex_string>
Parameter
<connectID> Integer type. The socket service index. The range is 0-11.
<hex_string> String type. Hex string. The max length is 512 bytes.
3. 送信先をHTTP 80番ポートからTCP 23080番ポートに変更
https://dev.soracom.io/jp/unified_endpoint/how-it-works/
char cmd[64]={"0"};
sprintf_P(cmd, PSTR("+QISENDEX=0,\"%04X%04X%08lX%04X%08lX\""),
light_mapped_value, sound_mapped_value, temp, humi, hPa);
/* binary-parser format:
* light:0:int:16 sound:2:int:16 temp_c:4:float:32 humi:8:int:16 air_pressure_hpa:10:float:32
*/
CONSOLE.println(cmd);
CONSOLE.print(F("Send..."));
drawText_P(&u8x8, PSTR("Send..."));
/* connect */
if (!ctx.connect(ENDPOINT, 23080)) {
CONSOLE.println(F("failed."));
drawText_P(&u8x8, PSTR("failed."));
delay(3000);
return;
}
/*send AT command */
modem.sendAT(cmd);
/* receive response */
// NOTE: response header and body are ignore due to saving for memory
ctx.stop();
CONSOLE.println(F("done."));
u8x8.clearLine(6);
次に ユーザーコンソール > SIM グループ > SORACOM Air for Cellular 設定 > バイナリーパーサーフォーマット に以下のように入力します
light:0:int:16 sound:2:int:16 temp_c:4:float:32 humi:8:int:16 air_pressure_hpa:10:float:32
バイナリパーサーカスタムフォーマットについてはhttps://dev.soracom.io/jp/docs/binary_parser/ を参照
再びHarvest Dataで見てみると"binaryParserEnabled":true となっています。
データ使用量を比べて見ると1時間あたり420KiB から50KiB程まで削減できました。
さらに、例えばDHT11の温度は整数で(-127~127)で表せるので
16bitのint型でなくchar(int8_t)にすれば1byteに、
気圧はhPaの小数第2位(Pa)で800.00~1200.00ぐらい表せればいいので
(int)(hPa*100-100000)で送ってバイナリーパーサーoperationsで:+100000/100
として元の数値に戻せば2byteに削減できます。
またbyte単位でなくbit単位でもカスタムできます。