เมื่อสองสามวันที่แล้วมีโอกาสไปโม้เรื่อง GPS Navigation และการทำ GPS tracking ให้นักศึกษาที่มหิดลฟัง โดยน้องเค้าอยากทำโปรเจคที่เกี่ยวกับระบบ GPS Tracking โดยรายละเอียดไม่ขออธิบายนะครับ เดี่ยวจะเป็นการเสียมารยาท แต่โปรเจคน้องเค้าน่าสนใจดี ผมชอบคุยกับคนที่อยากทำอะไรมากมายแบบนี้จัง คุยและแลกเปลี่ยนแล้วมันมีไฟ นึกถึงตอนที่ตัวเองเพิ่งเริ่มทำงานใหม่ๆอะไรก็อยากทำ อะไรก็อยากเรียนรู้ แต่เดี่ยวนี้รู้สึกเริ่ม bias ทำงานมากแล้วคิดมากคิดโน้นคิดนี้ คิดไปถึงคุ้มไม่คุ้ม สำเร็จไม่สำเร็จ แต่น้องๆเหล่านี้มีไฟดีครับคิดเต็มที่ ไอเดียกระฉูด ผมเองได้แต่นั่งฟังไม่อยากขัด ในใจก็เป็นห่วงว่ามันจะทำเสร็จไหม แต่ไม่อยากขัดเดี่ยวไฟจะมอดพากันฝ่อไปเปล่าๆ ไปครั้งนี้ก็เตรียมเอา opensource โปรเจคประมาณนี้หลายตัวไปแนะนำ เพื่อจะได้ลดภาระการเขียนโปรแกรมลง งานสนทนากลุ่มเล็กแบบนี้ผมชอบจริงๆครับได้เจอคำถามใหม่ๆเยอะดี น้องๆคนไหนที่อยากทำโปรเจคประมาณนี้ลอง mail มาคุยกันได้จะรวมกลุ่มแล้วมาคุยกันก็ได้ ถ้าเป็นโปรเจคนักศึกษาหรือ thesis ให้คำปรึกษาฟรีครับไม่มีค่าใช้จ่ายอะไร เอาความตั้งใจมาก็พอ

           เข้าเรื่องสักหน่อยสืบเนื่องจากคำถามที่ได้รับ หลังจากลองค้นก็ไปเจอ code ของ    Bluetooth GPS simulator ภาษา Java  อธิบายง่าก็คือ มันจะจำลองตัวเองเป็น Bluetooth GPS receiver บนเครื่องมือถือ J2ME phone โค้ดนี้รองรับ protocol แบบ NMEA sentence ใช่สำหรับมือใหม่ที่อยากพัฒนา application แต่ยังไม่มี GPS ที่สำคัญไม่ต้องมานั่งรอสัณญาณ GPS เวลาทดสอบโปรแกรม code นี้มาจาก www.digitalmobilemap.com

/*————————————————–
* BlueGPS.java
*
*————————————————-*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;
import javax.bluetooth.*;
import javax.microedition.io.*;
import java.io.*;
public class BlueGPS extends MIDlet implements Runnable
{
private Display display; // The display
private TestCanvas canvas; // Canvas

LocalDevice localDevice;
ServiceRecord serviceRecord;

StreamConnectionNotifier notifier = null;
StreamConnection conn = null;
private static final UUID L2CAP_UUID = new UUID(256L); // simulate L2CAP service provided by real bluetooth GPS receiver.
private static String serverUrl = “btspp://localhost:” + L2CAP_UUID + “;authorize=false;encrypt=false”; // simulate no authorize and no encrypt required by real bluetooth GPS receiver.
OutputStream output;
InputStream input;

String[] sentence;
// Time in ms to wait until send next NMEA Sentence.
private static final long BREAK = 400;

public BlueGPS()
{
display = Display.getDisplay(this);
canvas = new TestCanvas(this);
display.setCurrent(canvas);
}

protected void startApp()
{
new Thread(this).start();
}

public void run()
{
DataInputStream in;
int i = 0, numSentence = 0;
String str;
long time;

canvas.message = “Starting BlueGPS…”;
canvas.paintScreen();

try
{
conn = null;
localDevice = LocalDevice.getLocalDevice();
localDevice.setDiscoverable(DiscoveryAgent.GIAC);
notifier = (StreamConnectionNotifier)Connector.open(serverUrl);
}
catch (BluetoothStateException e)
{
canvas.message = e.getMessage();
canvas.paintScreen();
return;
}
catch (IOException e)
{
canvas.message = e.getMessage();
canvas.paintScreen();
return;
}

numSentence = 18; // number of sentences
sentence = new String[numSentence];

// real bluetooth GPS recevier send a lot of different sentence types
// I only simulate 3 important sentence types:
// $GPGSA – GPS DOP and active satellites. This sentence provides details on the nature of the fix
// $GPGGA – Essential fix data which provide 3D location and accuracy data
// $GPRMC – Recommended Minimum Sentence C which provide essential gps pvt (position, velocity, time) data.
// you can modify these NMEA sentences as you wish
// you read more detail about NMEA sentence types hereNMEA sentences

sentence[0] = “$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39”;
sentence[1] = “$GPGGA,123519,0117.349,N,10350.488,E,1,08,0.9,545.4,M,46.9,M,,*47”;
sentence[2] = “$GPGGA,123519,0117.358,N,10350.495,E,1,08,0.9,545.4,M,46.9,M,,*47”;
sentence[3] = “$GPRMC,130843,A,0117.3740,N,10350.5070,E,005.0,315.0,011206,000.0,E*6F”;
sentence[4] = “$GPRMC,130844,A,0117.3890,N,10350.5190,E,005.0,315.0,011206,000.0,E*68”;
sentence[5] = “$GPRMC,130845,A,0117.3960,N,10350.5290,E,005.0,315.0,011206,000.0,E*69”;
sentence[6] = “$GPRMC,130846,A,0117.3980,N,10350.5420,E,005.0,315.0,011206,000.0,E*6A”;
sentence[7] = “$GPRMC,130847,A,0117.3970,N,10350.5460,E,005.0,315.0,011206,000.0,E*6B”;
sentence[8] = “$GPRMC,130848,A,0117.3940,N,10350.5640,E,005.0,315.0,011206,000.0,E*64”;
sentence[9] = “$GPRMC,130849,A,0117.3710,N,10350.6080,E,005.0,315.0,011206,000.0,E*65”;
sentence[10] = “$GPRMC,130850,A,0117.3420,N,10350.6470,E,005.0,315.0,011206,000.0,E*6D”;
sentence[11] = “$GPRMC,130851,A,0117.3200,N,10350.6740,E,005.0,315.0,011206,000.0,E*62”;
sentence[12] = “$GPRMC,130852,A,0117.2900,N,10350.7060,E,005.0,315.0,011206,000.0,E*6C”;
sentence[13] = “$GPRMC,130853,A,0117.2670,N,10350.7310,E,005.0,315.0,011206,000.0,E*6D”;
sentence[14] = “$GPRMC,130854,A,0117.2510,N,10350.7620,E,005.0,315.0,011206,000.0,E*6F”;
sentence[15] = “$GPRMC,130855,A,0117.2690,N,10350.7800,E,005.0,315.0,011206,000.0,E*68”;
sentence[16] = “$GPRMC,130856,A,0117.2930,N,10350.8010,E,005.0,315.0,011206,000.0,E*69”;
sentence[17] = “$GPRMC,130857,A,0117.3170,N,10350.8210,E,005.0,315.0,011206,000.0,E*6A”;

try
{
canvas.message = “Waiting to send…”;
canvas.sentence = sentence[0];
canvas.paintScreen();
conn = notifier.acceptAndOpen();
output = conn.openOutputStream();
}
catch (IOException e)
{
canvas.message = e.getMessage();
canvas.paintScreen();
}

i = 0;
while (true)
{
try
{
canvas.message = “Waiting to send…”;
canvas.sentence = sentence[i];
canvas.paintScreen();

output.write(sentence[i].getBytes());
// simulate carry return character
output.write(13);
output.write(10);
output.flush();
}
catch (IOException e)
{
canvas.message = e.getMessage();
canvas.paintScreen();
}

try
{
Thread.sleep(BREAK); // wait for a while before send next sentence
}
catch (Exception e) {}

if (i < numSentence – 1)
i++;
else
i = 0;
} // while (true)
}

protected void pauseApp() { }

protected void destroyApp( boolean unconditional ) { }

public void exitMIDlet()
{
destroyApp(true);
notifyDestroyed();
}
}

/*————————————————–
* Class TestCanvas
*
*————————————————-*/
class TestCanvas extends Canvas implements CommandListener
{
private BlueGPS midlet;
public String message;
private int width, height;
String sentence;

/*————————————————–
* Constructor
*————————————————-*/
public TestCanvas(BlueGPS pmidlet)
{
midlet = pmidlet;
setFullScreenMode(true);
width = getWidth();
height = getHeight();
message = new String();
sentence = new String();
setCommandListener(this);
}

public void paintScreen()
{
repaint();
serviceRepaints();
}

/*————————————————–
* Paint canvas
*————————————————-*/
protected void paint(Graphics g)
{
g.setColor(0xCCFFCC);
g.fillRect(0, 0, width, height);

g.setColor(0x0000FF);
g.drawString(message,0,g.getFont().getHeight()*1,g.BASELINE|g.LEFT);
g.drawString(sentence,0,g.getFont().getHeight()*2,g.BASELINE|g.LEFT);
g.drawString(“Press any key to exit”,0,g.getFont().getHeight()*3,g.BASELINE|g.LEFT);
}

protected void keyPressed(int key)
{
midlet.exitMIDlet();
}

public void commandAction(Command c, Displayable d) {}

}

 

การใช้งานก็ง่ายครับ

1. สร้าง project BlueGPS ทำการ settings :

JSR082: true
JSR172: false
JSR177: false
JSR179: false
JSR184: false
JSR211: false
JSR75: false
MMAPI: false
WMA0: true
WMA1.1: false
WMA2.0: false
configuration: CLDC1.0
platform: CUSTOM
profile: MIDP2.0

 

2.  Copy source code ข้างบน และทำการ save ชื่อ BlueGPS.java

3. Open BlueGPS.java และแก้ NMEA sentences สำหรับค่า latitude , longitude ที่เราต้องการ

5. Compile code สร้าง .jar file

6. Installและ run BlueGPS.jar บน มือถือ.

อ่านรายละเอียดเพิ่มเติมที่

http://www.digitalmobilemap.com/index.php?slug=bluetooth-gps-simulator-for-j2me-phone