LoginSignup
2
1

More than 3 years have passed since last update.

SORACOM Air のバイナリパーサーを使ってみた

Last updated at Posted at 2019-07-01

概要

SORACOM Air for セルラー のLTE-M回線を使って、センサから吸い上げたデータを、SORACOM Unified Endpointに送信します。

通信量を削減すると、通信料金を安くできるだけでなく、消費電力の節約にもつながります。

そこで、バイナリパーサーを使って、通信量の削減に挑戦してみます。

開発環境

Arduino IDE: 1.8.9
Wio_cell_lib_for_Arduino
こちらのライブラリをフォークして、開発しております。

SORACOMコンソールでバイナリパーサーを設定

コンソールにログイン後、左上の MENU を開き、 SORACOM Air for Cellular を選択します。

基本設定 内の SORACOM Air for Cellular 設定 を開きます。

すると、最下部に
スクリーンショット 2019-06-30 19.10.05.png
バイナリパーサー設定 が出てきますので、ONにして保存します。

画像の右側の フォーマット 部分に、設定を記述していきます。

バイナリパーサーのフォーマットを作成

SORACOMさんの解説記事を参考にしながら、フォーマットを作成していきます。

バイナリパーサーに送るデータは、「経度:139752101」、「緯度:35682501」です。
バイナリパーサーは floatにも対応していますが、使用しているライブラリの UDP通信のメソッドが charのみに対応しているので、 10^6をかけています。

フォーマットは、lat:offset:length:operations lng:offset:length:operationsという形になります。

16進数への変換

経度: (139752101)10 = (85472A5)16
緯度: (35682501)10 = (22078C5)16

変換した16進数をくっつけます。
バイナリパーサーで変換するバイナリは、0x85472A522078C5となります。

このバイナリの1文字は、16進数ですので4bitsです。

そのため、 length = 4 * 8です。

offsetの指定

経度・緯度を16進数で表したものはそれぞれ7桁ですが、送信されるデータは先頭に0が付与されて8桁です(1Byteごとに送信されるため)。

そのため、offsetは
lat: 0
lng: 4
となります。

operationsの設定

こちらは、10^6で割れば良いので、/1000000です。

作成されたフォーマット

以上より、作成されたフォーマットは、lat:0:uint:32:/1000000 lng:4:uint:32:/1000000です。

バイナリへの変換

ここで私は、つまづいてしまいました。

心優しい方が、実装してくださっていたので、それを活用しております。
SORACOM バイナリパーサーで、位置情報送ってみよう!

私の失敗に関しては後ほど触れます。

バイナリパーサーでの変換に成功したソースコードはこちらです。

grove-gps.ino
float lat = 139.752101;
float lng = 35.682501;

unsigned long int const lat_decimal = (unsigned long int)(lat * 1000000);
unsigned long int const lng_decimal = (unsigned long int)(lng * 1000000);

// Calculating the digits of lat, lng in hexadecimal.
unsigned long int lat_to_calc_digit = lat_decimal;
unsigned long int lng_to_calc_digit = lng_decimal;
unsigned int lat_digit_hex = 0;
unsigned int lng_digit_hex = 0;
while (lat_to_calc_digit!=0) {
    lat_to_calc_digit /= 16;
    lat_digit_hex++;
}
while (lng_to_calc_digit!=0) {
    lng_to_calc_digit /= 16;
    lng_digit_hex++;
}
int size_of_post_data_lat = (int)(ceil((double)lat_digit_hex/2));
int size_of_post_data_lng = (int)(ceil((double)lng_digit_hex/2));

// Convert into binary data to post to SORACOM binary parser.
// Binary parser configuration on SORACOM console: "lat:0:uint:32:/1000000 lng:4:uint:32:/1000000"
char *post_data_lat[size_of_post_data_lat];
char *post_data_lng[size_of_post_data_lng];
memcpy(&post_data_lat[0], Nectis.ConvertDecimalToHex(lat_decimal, size_of_post_data_lat), size_of_post_data_lat);
memcpy(&post_data_lng[0], Nectis.ConvertDecimalToHex(lng_decimal, size_of_post_data_lng), size_of_post_data_lng);

char post_data[] = {0x00};
memcpy(&post_data[0], post_data_lat, size_of_post_data_lat);
memcpy(&post_data[0]+size_of_post_data_lat, post_data_lng, size_of_post_data_lng);
NectisCellular.cpp
char *NectisCellular::ConvertDecimalToHex(unsigned long int const decimal, int byte_size) {
    // The last index of post_data is filled with 0x00 for print function.
    memset(&HexConvertedFromDecimal[0], 0X00, sizeof(HexConvertedFromDecimal));

    for (int i = 0; i < (int) byte_size; i++) {
        // 16進数に変換し、4ビットずつ post_data を埋めていく
        HexConvertedFromDecimal[i] = (decimal >> (8 * ((byte_size - 1) - i))) & 0xff;
    }
    return HexConvertedFromDecimal;
}

ポイントは、 memcpy() を用いて、取得した緯度経度のデータをくっつけているところです。

実際に送信したデータをArduinoIDEのシリアルモニタで確認すると、
Send:Tr⸮ x⸮
と文字化けしており、変換に成功したことが確認できます。

送信データをSORACOMコンソールで確認

{"lat":139.752101,"lng":35.682501,"binaryParserEnabled":true}

となっており、バイナリパーサーで正確に変換できていることを確認できました。

失敗したバイナリへの変換

こちらの記事にまとめております。

SORACOM Air のバイナリパーサーでうまくデータを変換できない。

参考文献

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1