Thursday, April 26, 2012

J2ME Bluetooth GPS Guide

J2ME Bluetooth GPS Guide

 

Bluetooth API JSR-82

The Java APIs for Bluetooth define the following package that depends on the CLDC javax.microedition.io package:
  • javax.bluetooth: core Bluetooth API
The above package is a separate optional package, which means that a CLDC implementation can include either package or both. MIDP-enabled devices are expected to be the kind of devices to incorporate this specification.

Application Programming

The anatomy of a Bluetooth application has five parts: stack initialization, device management, device discovery, service discovery, and communication.

Stack Initialization

The Bluetooth stack is responsible for controlling the Bluetooth device. The initialization process comprises a number of steps whose purpose is to get the device ready for wireless communication.

Device Management

The Java Bluetooth APIs contain the classes LocalDevice and RemoteDevice, which provide the device-management capabilities defined in the Generic Access Profile. LocalDevice depends on the javax.bluetooth.DeviceClass class to retrieve the device's type and the kinds of services it offers. The RemoteDevice class represents a remote device (a device within a range of reach) and provides methods to retrieve information about the device, including its Bluetooth address and name. The following code snippet retrieves that information for the local device:
...
// retrieve the local Bluetooth device object
LocalDevice local = LocalDevice.getLocalDevice();
// retrieve the Bluetooth address of the local device
String address = local.getBluetoothAddress();
// retrieve the name of the local Bluetooth device
String name = local.getFriendlyName();
...
You can get the same information about a remote device:
...
// retrieve the device that is at the other end of
// the Bluetooth Serial Port Profile connection,
// L2CAP connection, or OBEX over RFCOMM connection
RemoteDevice remote =
    RemoteDevice.getRemoteDevice(
        javax.microedition.io.Connection c);
// retrieve the Bluetooth address of the remote device
String remoteAddress = remote.getBluetoothAddress();
// retrieve the name of the remote Bluetooth device
String remoteName = local.getFriendlyName(true);
...
The RemoteDevice class also provides methods to authenticate, authorize, or encrypt data transferred between local and remote devices.

Device Discovery

Because wireless devices are mobile they need a mechanism that allows them to find other devices and gain access to their capabilities. The core Bluetooth API's DiscoveryAgent class and DiscoveryListener interface provide the necessary discovery services.
A Bluetooth device can use a DiscoveryAgent object to obtain a list of accessible devices, in any of three ways:
The DiscoveryAgent.startInquiry method places the device into an inquiry mode. To take advantage of this mode, the application must specify an event listener that will respond to inquiry-related events. DiscoveryListener.deviceDiscovered is called each time an inquiry finds a device. When the inquiry is completed or canceled, DiscoveryListener.inquiryCompleted is invoked.
If the device doesn't wish to wait for devices to be discovered, it can use the DiscoveryAgent.retrieveDevices method to retrieve an existing list. Depending on the parameter passed, this method will return either a list of devices that were found in a previous inquiry, or a list of pre-known devices that the local device has told the Bluetooth Control Center it will contact often.
These three code snippets demonstrate the various approaches:
...
// retrieve the discovery agent
DiscoveryAgent agent = local.getDiscoveryAgent();
// place the device in inquiry mode
boolean complete = agent.startInquiry();
...
...
// retrieve the discovery agent
DiscoveryAgent agent = local.getDiscoveryAgent();
// return an array of pre-known devices
RemoteDevice[] devices =
   agent.retrieveDevices(DiscoveryAgent.PREKNOWN);
...
...
// retrieve the discovery agent
DiscoveryAgent agent = local.getDiscoveryAgent();
// return an array of devices found in a previous inquiry
RemoteDevice[] devices =
    agent.retrieveDevices(DiscoveryAgent.CACHED);
...

Service Discovery

Once the local device has discovered at least one remote device, it can begin to search for available services - Bluetooth applications it can use to accomplish useful tasks. Because service discovery is much like device discovery, DiscoveryAgent also provides methods to discover services on a Bluetooth server device, and to initiate service-discovery transactions. Note that the API provides mechanisms to search for services on remote devices, but not for services on the local device.

Communication

For a local device to use a service on a remote device, the two devices must share a common communications protocol. So that applications can access a wide variety of Bluetooth services, the Java APIs for Bluetooth provide mechanisms that allow connections to any service that uses RFCOMM, L2CAP, or OBEX as its protocol. If a service uses another protocol (such as TCP/IP) layered above one of these protocols, the application can access the service, but only if it implements the additional protocol in the application, using the CLDC Generic Connection Framework.

Serial Port Profile

The RFCOMM protocol, which is layered over the L2CAP protocol, emulates an RS-232 serial connection. The Serial Port Profile (SPP) eases communication between Bluetooth devices by providing a stream-based interface to the RFCOMM protocol. Some capabilities and limitations to note:
  • Two devices can share only one RFCOMM session at a time.
  • Up to 60 logical serial connections can be multiplexed over this session.
  • A single Bluetooth device can have at most 30 active RFCOMM services.
  • A device can support only one client connection to any given service at a time.
For a server and client to communicate using the Serial Port Profile, each must perform a few simple steps.
As the following code snippet demonstrates, the server must:
  1. Construct a URL that indicates how to connect to the service, and store it in the service record
  2. Make the service record available to the client
  3. Accept a connection from the client
  4. Send and receive data to and from the client
The URL placed in the service record may look something like:
btspp://102030405060740A1B1C1D1E100:5
This says that a client should use the Bluetooth Serial Port Profile to establish a connection to this service, which is identified with server channel 5 on a device whose address is 102030405060740A1B1C1D1E100.
...
// assuming the service UID has been retrieved
String serviceURL =
    "btspp://localhost:"+serviceUID.toString());
// more explicitly:
String ServiceURL =
    "btspp://localhost:10203040607040A1B1C1DE100;name=SPP
        Server1";
try {
    // create a server connection
    StreamConnectionNotifier notifier =
      (StreamConnectionNotifier) Connector.open(serviceURL);
    // accept client connections
    StreamConnection connection = notifier.acceptAndOpen();
    // prepare to send/receive data
    byte buffer[] = new byte[100];
    String msg = "hello there, client";
    InputStream is = connection.openInputStream();
    OutputStream os = connection.openOutputStream();
    // send data to the client
    os.write(msg.getBytes());
    // read data from client
    is.read(buffer);
    connection.close();
} catch(IOException e) {
  e.printStackTrace();
}
...
At the other end, as the next code snippet shows, to set up an RFCOMM connection to a server the client must:
  1. Initiate a service discovery to retrieve the service record
  2. Construct a connection URL using the service record
  3. Open a connection to the server
  4. Send and receive data to and from the server
...
// (assuming we have the service record)
// use record to retrieve a connection URL
String url =
    record.getConnectionURL(
        record.NOAUTHENTICATE_NOENCRYPT, false);
// open a connection to the server
StreamConnection connection =
    (StreamConnection) Connector.open(url);
// Send/receive data
try {
    byte buffer[] = new byte[100];
    String msg = "hello there, server";
    InputStream is = connection.openInputStream();
    OutputStream os = connection.openOutputStream();
    // send data to the server
    os.write(msg.getBytes);
    // read data from the server
    is.read(buffer);
    connection.close();
} catch(IOException e) {
  e.printStackTrace();
}
...
How to read GPS data from Bluetooth stream

Code snippet
readBluetoothBuffer()
{
data = readAllAvailableBytes()
if (data.length == 0)
Bluetooth connection not there
else
Bluetooth seems OK
bytesRead = readBytes();
if (no bytesRead)
read error
else
START Loop
find newLine()
{
                    //figure out whether it's RMC or GGA
                    String candidate = readBuffer
                
                    //figure out whether RMC or GGA
                    if (candidate is $GPRMC....)
                   {
                        Store candidate as RMC
                    }
                    else if (candidate is $GPGGA)
                    {
Store candidate as GGA
                    }
            }
            END Loop
}
Common NMEA Sentence types
The following information describes the NMEA-0183 sentences transmitted by TeleType GPS receivers.
Sentence Description
$GPGGA Global positioning system fixed data
$GPGLL Geographic position - latitude / longitude
$GPGSA GNSS DOP and active satellites
$GPGSV GNSS satellites in view
$GPRMC Recommended minimum specific GNSS data
$GPVTG Course over ground and ground speed

Link : http://developer.att.com/developer/forward.jsp?passedItemId=3400032

 

No comments:

Post a Comment