이 기사는 자바 ME 기술과 블루투스를 사용하여 무선 GPS 장치에서 위치 데이터에 액세스하는 방법을 다룬 2부작 시리즈의 제2부입니다.

이번 시리즈의 1부에서 살펴본 것처럼, 블루투스 기반 GPS 장치에서 기본 GPS 데이터에 매우 쉽게 액세스할 수 있습니다. 아래의 목록 출력은 일반적인 GPS 장치에서 직렬 출력의 형식을 보여 줍니다.

목록 출력 1. NMEA 형식의 GPS 데이터

$GPGSV,3,3,10,31,76,012,31,32,60,307,38,,,,,,,,*72
$GPGSA,A,3,32,31,16,11,23,,,,,,,,4.5,3.1,3.3*34

$GPRMC,122314.000,A,3659.249,N,09434.910,W,0.0,0.0,220908,0.0,E*78
$GPGGA,122314.000,3659.24902,N,09434.91042,W,1,05,3.1,261.51,M,-29.1,M,,*58

$GPGSV,3,1,10,01,62,343,00,11,14,260,34,14,35,079,27,16,29,167,28*73
$GPGSV,3,2,10,20,44,309,00,22,13,145,00,23,08,290,31,30,23,049,33*7C
$GPGSV,3,3,10,31,76,012,31,32,60,307,38,,,,,,,,*72
$PSTMECH,32,7,31,7,00,0,00,0,14,4,30,4,16,7,00,0,11,7,23,7,00,0,00,0*50

$GPRMC,122315.000,A,3659.249,N,09434.910,W,0.0,0.0,220908,0.0,E*79
$GPGGA,122315.000,3659.24902,N,09434.91048,W,1,05,3.1,261.61,M,-29.1,M,,*50


NMEA 문장 구문 분석

GPS 장치가 생성하는 직렬 데이터는 NMEA 사양에서 정한 형식을 따르며, 각 데이터 행을 NMEA 문장이라고 부릅니다. 5개 이상의 NMEA 문장이 현재 위치의 좌표를 알려 줍니다. 다행히 여기서는 그 중 하나의 구문 분석기만 만들면 됩니다. 이 글에서는 $GPGGA 헤더를 선택하겠습니다. 다양한 표준 및 비표준 NMEA 문장에 대해 자세히 알고 싶다면 NMEA FAQ 웹 사이트를 참조하십시오. 다음은 일반적인 $GPGGA 문장이 어떤 모양인지 보여 주는 예입니다.

$GPGGA,123519,4807.038,N,01131.324,E,1,08,0.9,545.4,M,46.9,M, ,;


더 살펴보면 NMEA 문의 각 부분이 쉼표로 구분되어 있음을 알 수 있습니다. 앞의 NMEA 문장에서 다음과 같은 사실을 확인할 수 있습니다.

  • GPS fix를 12:35:19(UTC 기준)에 얻었습니다.
  • 위도 좌표는 북위 48도 07.038분입니다.
  • 경도 좌표는 동위 11도 31.234분입니다.
  • GPS fix quality는 1입니다.
  • 8개의 GPS 위성을 추적하던 중이었습니다.
  • 위치 수평 저하는 0.9였습니다.
  • GPS fix의 고도는 545.4미터였습니다.
  • 지오이드의 높이는 46.9미터였습니다.

StringTokenizer 클래스를 사용하면 자바 ME 장치에서 NMEA 문장을 정말 쉽게 구문 분석할 수 있으리라는 생각이 드십니까? 안타깝게도 그렇게 쉽지 않습니다. StringTokenizer 클래스는 자바 SE 구현에만 있기 때문입니다. 그러나 저는 예시 코드에 간단한 NMEA 구문 분석기와 String tokenization 클래스를 포함시켰습니다. 다음은 좌표 DMS 형식(도, 분, 초)을 십진수 도 값으로 알맞게 변환하는 Parser.java의 코드 단편입니다.

목록 출력 2. Parser.java의 코드 단편

if (token.endsWith("$GPGGA")) {
    type = TYPE_GPGGA;
    // Time of fix
    tokenizer.next();
    // Latitude
    String raw_lat = tokenizer.next();
    String lat_deg = raw_lat.substring(0, 2);
    String lat_min1 = raw_lat.substring(2, 4);
    String lat_min2 = raw_lat.substring(5);
    String lat_min3 = "0." + lat_min1 + lat_min2;
    float lat_dec = Float.parseFloat(lat_min3)/.6f;
    float lat_val = Float.parseFloat(lat_deg) + lat_dec;
    // Latitude direction
    String lat_direction = tokenizer.next();
    if(lat_direction.equals("N")){
        // do nothing
    } else {
        lat_val = lat_val * -1;
    }
    record.latitude = lat_val + "";
    // Longitude
    String raw_lon = tokenizer.next();
    String lon_deg = raw_lon.substring(0, 3);
    String lon_min1 = raw_lon.substring(3, 5);
    String lon_min2 = raw_lon.substring(6);           
    String lon_min3 = "0." + lon_min1 + lon_min2;
    float lon_dec = Float.parseFloat(lon_min3)/.6f;
    float lon_val = Float.parseFloat(lon_deg) + lon_dec;
   
   
    // Longitude direction
    String lon_direction = tokenizer.next();
    if(lon_direction.equals("E")){
        // do nothing
    } else {
        lon_val = lon_val * -1;
    }
    record.longitude = lon_val + "";
    record.quality = tokenizer.next();
    record.satelliteCount = tokenizer.next();
    record.dataFound = true;
    // Ignore rest
    return 200;
}

NMEA 문장을 제대로 구문 분석했으므로, 이제는 외부 매핑 서비스를 사용하여 맵을 얻는 방법을 알아보겠습니다.

외부 맵 서비스에 맵 이미지 요청

요즘에는 현재 위치(또는 기타 관심 위치)의 맵 이미지를 얻기 위해 간단한 HTTP 요청을 보낼 때 몇 가지 옵션 중에서 선택할 수 있습니다. Mapquest, Google 및 ERSi와 같은 일부 회사들은 그러한 서비스를 제공하지만, 저는 다음과 같은 이유로 Yahoo! Maps 서비스로 결정했습니다.

  1. 모든 옵션을 하나의 HTTP 요청에서 URL 매개 변수에 지정할 수 있습니다.
  2. API를 사용하는 데 외부 라이브러리가 필요하지 않습니다.
  3. 구문 분석하기 용이한 간단한 XML 문서의 형태로 응답합니다.
  4. 결과 맵 이미지가 PNG 형식이므로, 모든 MIDP 장치가 지원합니다.

Yahoo! Maps API를 사용하려면 등록하여 무료 개발자 계정 ID 키를 얻으면 됩니다. 자, 제가 다음 매개 변수의 맵을 필요로 할 경우

  • 위도: 46.987484
  • 경도: -84.58184
  • 이미지 너비: 400픽셀
  • 이미지 높이: 400픽셀
  • 줌 레벨: 7

HTTP 요청의 URL은 다음과 같습니다.

http://local.yahooapis.com/MapsService/V1/mapImage?appid=
YOUR_YAHOO_ID_KEY&latitude=46.987484&longitude=-
84.58184&image_width=400&image_height=400&zoom=7


매우 간단하지 않습니까? 이 요청의 결과는 이미지 자체가 아니라 그 이미지의 링크를 포함하는 XML 문서입니다. 아래의 목록 출력은 제가 보낸 맵 이미지에 대한 HTTP 요청의 XML 결과입니다.

목록 출력 3. Yahoo! Maps 서비스의 XML 결과
<?xml version="1.0"?>
<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
http://gws.maps.yahoo.com/mapimage?mapd ··· n8wdusxa
8qRQ2kzC_f8vO7.FvQhW3hSbWbF_jO3H4.J2Gb7Qhc2vqoCTL0DWbaCfT751_Zt9Ysqtg0dKo2mv95
EIc4bbgdYrmebNqFcwfKb8YhOFe38Ia3Q--&mvt=m?cltype=onnetwork&.intl=us
</Result>


맵 서비스에서 XML 결과 구문 분석

자, 결승선이 얼마 남지 않았습니다. 이제 필요한 작업은 맵 서비스에서 얻은 결과를 구문 분석하고 맵 이미지의 URL을 추출하는 것입니다. 다행히 JSR-172 XML Parsing API 덕분에 큰 수고 없이 해결됩니다.

또한 JSR-172 API는 등장한 지 몇 년 되었기 때문에 다양한 모바일 핸드셋에서 사용 가능하다는 것도 희소식입니다. 물론 JSR-172 API는 자바 ME MSA 표준의 일부이므로 핸드셋에서 MSA를 지원한다면 아무 문제가 없습니다.

다음 목록 출력에서는 제 XML 구문 분석 클래스가 JSR-172 API의 DefaultHandler 클래스만 확장하면 된다는 것을 보여 줍니다. 오로지 단일 태그, 즉 <Result> 태그의 내용이 우리의 관심사이므로, 맵 이미지의 URL을 얻는 데 필요한 코드는 매우 간단합니다.

목록 출력 4. JSR-172 API를 사용하는 간단한 XML 구문 분석 클래스

public class SimpleHandler extends DefaultHandler {
   
    public String image_url = null;
   
    public SimpleHandler() {}
    public void startDocument() throws SAXException {}
 
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equals("Result")) {
  // do nothing
        } else {
            throw new SAXException("<Result> tag not found");
        }
    }
  
    public void characters(char[] ch, int start, int length) throws SAXException {
        image_url = new String(ch, start, length).trim();
    }
 
  public void endElement(String uri, String localName, String qName, Attributes attributes) throws SAXException{}
 
  public void endDocument() throws SAXException{}   
 
  public String getImageURL(){
      return image_url;
  }       
}

목록 출력 4의 코드, 즉 getImageURL() 메소드가 현재 위치의 맵 PNG 이미지를 가리키는 URL을 반환합니다. 이제 할 일은 이미지를 가져와 모바일 장치에 표시하도록 또 다른 HTTP 요청을 보내는 것뿐입니다. 그림 1은 현재 위치를 보여 주는 모바일 장치입니다.


그림 1. 드디어 현재 위치을 알려주는 맵 이미지 출현!

결론

이 기사에서 소개한 예시 코드는 JSR-82(블루투스) API를 사용하면 블루투스 기반 GPS 수신기의 데이터에 액세스하고 데이터 스트림을 구문 분석하며 현재 위치의 좌표를 얻는 작업이 얼마나 쉽게 해결되는지 보여 줍니다. 또한 외부 매핑 서비스에 액세스하고 JSR-172(XML 구문 분석 및 웹 서비스) API를 활용해 결과를 구문 분석하며 맵 이미지를 얻기 위한 최종 요청을 보내기 위해 HTTP 요청을 작성하는 방법도 확인했습니다. JSR-82와 JSR-172 모두 자바 ME MSA 표준에 포함되어 있습니다.

여기서 소개한 예시 코드를 바탕으로 멋진 위치 기반 애플리케이션을 개발하실 수 있기를 기대합니다!


이 글의 영문 원본은
Working with Bluetooth and GPS: Part 2 - Parsing GPS Data and Rendering a Map
에서 보실 수 있습니다.

"Java ME" 카테고리의 다른 글

2008/12/11 16:14 2008/12/11 16:14

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/692

댓글을 달아 주세요

[로그인][오픈아이디란?]

◀ Prev 1  ... 167 168 169 170 171 172 173 174 175  ... 806  Next ▶