SORACOM Air의 바이너리 파서를 사용해 보았습니다.

개요



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 설정을 엽니다.

그러면 하단에

바이너리 파서 설정이 나오므로 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입니다.

이 바이너리의 한 문자는 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의 바이너리 파서로 데이터를 잘 변환 할 수 없습니다.

참고문헌

좋은 웹페이지 즐겨찾기