Trackit Sri Lanka
Tuesday, December 18, 2012
Sunday, September 16, 2012
Working with Bluetooth and GPS: Follow-up
After reading both Part 1 and Part 2
of the “Working with Bluetooth and GPS” series of articles, you were
given a clear explanation of the example code that shows you how to do
the following:
https://blogs.oracle.com/mobility_techtips/entry/working_with_bluetooth_and_gps1
Question 1: Hi Bruce, I have a problem when I start the Mpowerplayer tool with any MIDlet that uses Bluetooth and the JSR-82 API. When the application tries to execute my MIDet, it immediately displays a
Answer 1: The MPowerplayer made a change on how it handles JSR-82 libraries between releases #1127 and #1185. Unfortunately, it not explicitly stated in the documentation, but you need to make two simple changes in order to run MIDlets that require the JSR-82 API:
Question 2: Hi Bruce, this is a nice article. I would like to know how to get GPS data from a mobile phone that already has a GPS receiver built-in.
Answer 2: If your mobile phone is MSA-compliant and already has a GPS radio built-in, then you don’t need to use the JSR-82 API to connect to a remote GPS receiver. All you need to do is use the JSR-179 Location APIs in order to retrieve your location data from an embedded GPS receiver. If you’d like to get started with the JSR-179 API, then Qusay Mahmoud has written a great article, Java ME and Location-Based Services, on that topic.
Question 3: I have a Bluetooth-enabled GPS receiver: the Holux Slim 236. I also have a Bluetooth-enabled computer. Can I run this example with what I have?
Question 5: Hi, I am having problem with this example with WTK 2.5.2 and NetBeans IDE 6.1 which are both installed in my PC. When I run this application on my PC, I’m not able to get any data from the remote Bluetooth devices.
Answer 5: Actually, the whole point of Part 1 in the two-part series was to show developers how to debug and test their JSR-82 applications on their PCs using the Mpowerplayer. Neither the WTK, the NetBeans IDE, nor the Java ME SDK have the ability to leverage the Bluetooth hardware of your PC in order to discover or search for services on remote Bluetooth devices.
Question 6: I have a Bluetooth-enabled phone with a built-in GPS receiver. I want to send NMEA data from the phone to a Bluetooth-enabled PC. I have a desktop application (Streets & Trips) that can consume GPS data. Since my phone support GPS and Bluetooth, is there a Java ME application that will enable my mobile phone to do this?
Answer 6: I don’t know of any Java ME applications that do this, however this sounds like the basis for another article!
Final Thoughts
Thanks to all the readers who took the time to provide feedback to this article series! Your input, thoughts, questions, and ideas are always welcome and appreciated.
Link: https://blogs.oracle.com/mobility_techtips/entry/working_with_bluetooth_and_gps1
1. Use the JSR-82 Bluetooth API to access the data from a Bluetooth-enabled GPS receiver
2. Parse the data streams in NMEA format and obtain the coordinates of your current location
3. Formulate an HTTP request to access an external mapping service
4. Use the JSR-172 XML Parsing and Web Services API to parse an XML result
5. Make a request in order to display a map image
https://blogs.oracle.com/mobility_techtips/entry/working_with_bluetooth_and_gps1
Question 1: Hi Bruce, I have a problem when I start the Mpowerplayer tool with any MIDlet that uses Bluetooth and the JSR-82 API. When the application tries to execute my MIDet, it immediately displays a
java.lang.NoClassDefFoundError: javax/bluetooth/DiscoveryListener
. What could be the problem?Answer 1: The MPowerplayer made a change on how it handles JSR-82 libraries between releases #1127 and #1185. Unfortunately, it not explicitly stated in the documentation, but you need to make two simple changes in order to run MIDlets that require the JSR-82 API:
- 1. Place any JSR-82 implementation in the
/mpp-sdk
folder. I’ve tested with the following JSR-82 implementations: Avetana
(requires a license) and BlueCove (free open-source alternative).2. Rename that file to be called
bt.jar
.Question 2: Hi Bruce, this is a nice article. I would like to know how to get GPS data from a mobile phone that already has a GPS receiver built-in.
Answer 2: If your mobile phone is MSA-compliant and already has a GPS radio built-in, then you don’t need to use the JSR-82 API to connect to a remote GPS receiver. All you need to do is use the JSR-179 Location APIs in order to retrieve your location data from an embedded GPS receiver. If you’d like to get started with the JSR-179 API, then Qusay Mahmoud has written a great article, Java ME and Location-Based Services, on that topic.
Question 3: I have a Bluetooth-enabled GPS receiver: the Holux Slim 236. I also have a Bluetooth-enabled computer. Can I run this example with what I have?
Answer 3: Yes, you should have no
problem running the example code using the tools that you have. If you
plan to use the current version of Mpowerplayer, then be sure to follow
the instructions in the answer to Q1 first.
Question 4: Hi Bruce, thanks for creating this meaningful guide for developers. Your original article shows developers how to use the Avetana Bluetooth JSR-82 implementation with the Mpowerplayer SDK. The problem, however is that Aventana implementation only provides a free 14-day trial, and afterwards requires a license fee. Is there any way to configure the Mpowerplayer with the BlueCove JSR-82 implementation which is open source?
Answer 4: Yes, please refer to
the answer provided to Q1 listed above in order to find out how to use
the BlueCove library with the MPowerplayer SDK.Question 4: Hi Bruce, thanks for creating this meaningful guide for developers. Your original article shows developers how to use the Avetana Bluetooth JSR-82 implementation with the Mpowerplayer SDK. The problem, however is that Aventana implementation only provides a free 14-day trial, and afterwards requires a license fee. Is there any way to configure the Mpowerplayer with the BlueCove JSR-82 implementation which is open source?
Question 5: Hi, I am having problem with this example with WTK 2.5.2 and NetBeans IDE 6.1 which are both installed in my PC. When I run this application on my PC, I’m not able to get any data from the remote Bluetooth devices.
Answer 5: Actually, the whole point of Part 1 in the two-part series was to show developers how to debug and test their JSR-82 applications on their PCs using the Mpowerplayer. Neither the WTK, the NetBeans IDE, nor the Java ME SDK have the ability to leverage the Bluetooth hardware of your PC in order to discover or search for services on remote Bluetooth devices.
Question 6: I have a Bluetooth-enabled phone with a built-in GPS receiver. I want to send NMEA data from the phone to a Bluetooth-enabled PC. I have a desktop application (Streets & Trips) that can consume GPS data. Since my phone support GPS and Bluetooth, is there a Java ME application that will enable my mobile phone to do this?
Answer 6: I don’t know of any Java ME applications that do this, however this sounds like the basis for another article!
Final Thoughts
Thanks to all the readers who took the time to provide feedback to this article series! Your input, thoughts, questions, and ideas are always welcome and appreciated.
Link: https://blogs.oracle.com/mobility_techtips/entry/working_with_bluetooth_and_gps1
Wednesday, September 12, 2012
Working with Bluetooth and GPS: Part 2 - Parsing GPS Data and Rendering a Map
This article is the second of a two-part series on how to use Java ME
technology and Bluetooth to access location data from wireless GPS
devices.
As you may recall from Part 1 of this series, it is very easy to access the raw GPS data from a Bluetooth-enabled GPS device. The listing below shows what the serial output from a typical GPS device would look like:
As you also may recall from Part 1, a GPS device encodes its data according to the NMEA specification. The purpose of this article is to learn how to accomplish the following tasks:
The serial data that is produced by GPS devices is formatted
according to the NMEA specification, and each line of data is called an
NMEA sentence. There are at least 5 NMEA sentences that provide the
coordinates of your current position. The good news is that I only need
to create a parser for one of them. I'll choose the $GPGGA header for
the purposes of this article. If you want to know more about all the
various standard and non-standard NMEA sentences, refer to the NMEA FAQ website. Following is an example of what an ordinary $GPGGA sentence would look like:
After further inspection, you can now see that the individual parts of an NMEA sentence are separated by commas. The following facts can be obtained from the preceding NMEA sentence:
Now that we've properly parsed the NMEA sentence, let's explore how to get a map using an external mapping service.
In this day and age, you have several options to choose from when you
want to make a simple HTTP request to get an image that represents a
map of your current location (or any location for that matter). Several
companies -- Mapquest, Google, and ERSi -- provide these services, but I
decided to use the Yahoo! Maps service for the following reasons:
Pretty simple, huh? The result of this request is not the image itself, but an XML document that has a link to the image. The listing below shows the XML result of my HTTP request for a map image:
Ok, we're almost at the finish line. All we need to do now is to
parse the result that we got from the map service and extract the URL to
the map image. Fortunately, this is also a trivial task thanks to the
JSR-172 XML Parsing API.
You should also be glad to know that the JSR-172 API has been out for several years and is available on a wide variety of mobile handsets. Of course, the JSR-172 API is a part of the Java ME MSA standard, so if your handset supports MSA then you're obviously good to go.
In the following listing, you can see that my XML parsing class only needed to extend the
Now the code in Listing 4, specifically the
Link : http://dsc.sun.com/mobility/apis/articles/bluetooth_gps/part2/
Contents
- | Parsing the NMEA Sentences |
- | Requesting a Map Image from an External Map Service |
- | Parsing the XML Result from the Map Service |
- | Conclusion |
As you may recall from Part 1 of this series, it is very easy to access the raw GPS data from a Bluetooth-enabled GPS device. The listing below shows what the serial output from a typical GPS device would look like:
Listing 1. NMEA Formatted GPS Data
$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 |
As you also may recall from Part 1, a GPS device encodes its data according to the NMEA specification. The purpose of this article is to learn how to accomplish the following tasks:
- Parse the NMEA sentence data from a GPS device to retrieve the latitude and longitude values
- Request a map image of our current location from a external map service
- Parse the XML result data from the map service and render the map image on the mobile device
Parsing the NMEA Sentences
$GPGGA,123519,4807.038,N,01131.324,E,1,08,0.9,545.4,M,46.9,M, ,; |
After further inspection, you can now see that the individual parts of an NMEA sentence are separated by commas. The following facts can be obtained from the preceding NMEA sentence:
- the GPS fix was taken at 12:35:19 UTC time
- the latitude coordinate is 48 degrees and 07.038 minutes North
- the longitude coordinate is 11 degrees and 31.234 minutes East
- the GPS fix quality is 1
- 8 GPS satellites were being tracked
- the horizontal dilution of position was 0.9
- the altitude of the GPS fix was 545.4 meters
- the height of the geoid was 46.9 meters
StringTokenizer
class, right? Unfortunately, it's not that easy since the StringTokenizer
class only exists in Java SE implementations. However, in the example
code I've included a simple NMEA parser and String tokenization classes.
The following is a code snippet from Parser.java
that properly converts coordinate DMS format (degrees, minutes, seconds) to decimal degree values.
Listing 2. Code Snippet from
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; } |
Now that we've properly parsed the NMEA sentence, let's explore how to get a map using an external mapping service.
Requesting a Map Image from an External Map Service
- All the options can be specified in URL parameters in a single HTTP request.
- No external libraries are needed to consume the API.
- The response comes back as simple XML document that can be easily parsed.
- The resulting map image is in PNG format, which all MIDP devices support.
- latitude: 46.987484
- longitude: -84.58184
- image width: 400 pixels
- image height: 400 pixels
- zoom level: 7
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 |
Pretty simple, huh? The result of this request is not the image itself, but an XML document that has a link to the image. The listing below shows the XML result of my HTTP request for a map image:
Listing 3. XML Result from the Yahoo! Maps Service
<?xml version="1.0"?> <Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> http://gws.maps.yahoo.com/mapimage?MAPDATA=Voo4MOd6wXXT6pG.WpNC6XPETWAN8WDUsxa 8qRQ2kzC_f8vO7.FvQhW3hSbWbF_jO3H4.J2Gb7Qhc2vqoCTL0DWbaCfT751_Zt9Ysqtg0dKo2mv95 EIc4bbgdYrmebNqFcwfKb8YhOFe38Ia3Q--&mvt=m?cltype=onnetwork&.intl=us </Result> |
Parsing the XML Result from the Map Service
You should also be glad to know that the JSR-172 API has been out for several years and is available on a wide variety of mobile handsets. Of course, the JSR-172 API is a part of the Java ME MSA standard, so if your handset supports MSA then you're obviously good to go.
In the following listing, you can see that my XML parsing class only needed to extend the
DefaultHandler
class in the JSR-172 API. Since we're only interested in the contents of a single tag, namely the <Result>
tag, then the code necessary to retrieve the URL for the map image is fairly simple.
Listing 4. A Simple XML Parsing Class Using the JSR-172 API
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; } } |
Now the code in Listing 4, specifically the
getImageURL()
method, will return the URL that points to the PNG image of the map of
our current location. The only remaining step is to make another HTTP
request to retrieve the image and display it on the mobile device.
Figure 1 depicts a mobile device showing our current location.Link : http://dsc.sun.com/mobility/apis/articles/bluetooth_gps/part2/
Sunday, September 9, 2012
Working with Bluetooth and GPS: Part 1 - Reading Wireless Serial Port Data
For some developers, working with wireless technologies can be
daunting -- and sometimes downright intimidating. All communication is
wireless, so you can't just "look up" and see, for instance, 1 MB of
data going by. In addition, it is really difficult to debug
wireless applications once they are deployed to a mobile device, since
you don't have access to system traces or log files to pinpoint the
errors while the application is running.
This technical article addresses the following tasks:
I love using the Sun Wireless Toolkit for CLDC.
It is a great tool, and it's very handy when I need to create Java ME
applications that adhere to the latest and greatest Java ME JSR
specifications. However, the Java ME emulator in the Sun Wireless
Toolkit has no means to access or communicate with actual Bluetooth
hardware, which means that I don't have the ability to fully test my
application with the Sun Wireless Toolkit after I start to make API
calls that rely on functioning Bluetooth hardware. Because of this
problem, developers are left in a difficult situation when they need to
develop, test, and debug JSR-82 applications.
Additionally, testing your Java ME Bluetooth applications directly on your JSR-82 device is impractical since you don't have access to the
The good news is that you're going to learn how to construct a low-cost solution that allows you to install, debug, and test your JSR-82 applications on your computer. I'm going to introduce to you the Mpowerplayer, a CLDC emulator for the computer that can be configured to behave like a JSR-82 Bluetooth-enabled phone. With this configuration, the Mpowerplayer will behave just like a JSR-82 Bluetooth-enabled mobile phone, but you'll have access to the
The following list shows the materials that you need to run the example code provided later in this article:
Did you know that once you discover the connection URL for your desired Bluetooth service, then you no longer need to employ the device- and service-discovery processes? If you're unfamiliar with what a Bluetooth connection URL looks like, I have provided an example below:
Let us briefly revisit the purposes of the device-discovery and service-discovery processes that apply to all Bluetooth-enabled systems, whether or not if you use the JSR-82 API. The device-discovery process is used to determine what Bluetooth devices are in the vicinity. In the connection URL listed previously, the device represented has the Bluetooth address of
The inner class itself implements the
Figure 1 shows the Mpowerplayer running my application during the device-discovery process, and Figure 2 shows the state of mobile application after the device-discovery process is finished.
Now that we've taken care of the device-discovery process, and we see that the device that we want to connect to is in the list of available devices, let's take another look at the fully qualified connection URL.
As you can see, the device-discovery process lets us know the Bluetooth address (in this case,
The service-search process is dependent on knowing the type of service that you want. I want to consume serial data from a Bluetooth-enabled GPS device, and the unique identifier for wireless serial services is
Now, service searching is a blocking I/O operation, so I put the intensive work in the
To reiterate a previous point: now that you have determined the connection URL for your desired device, you no longer need to go through the device- and service-discovery processes for subsequent usage of the remote Bluetooth device. All you need to do is open a connection on the URL. After that, you have everything that you need to communicate with the remote Bluetooth device.
Figure 4 shows the operation of another thread-enabled inner class that opens the connection on the URL and then reads the data from the wireless serial port.
Wait a minute. If we're reading serial data from a GPS device, then where are the latitudes, longitudes, and other global-positioning stuff? Is the data corrupted?
Actually, the serial data that you see in Figure 4 is actually encoded in NMEA (National Marine Electronics Association) format, which is the common format for all GPS devices. Part 2 of this technical article shows you how to decode the NMEA data and plot your location on your phone.
Link: http://dsc.sun.com/mobility/apis/articles/bluetooth_gps/part1/
This technical article addresses the following tasks:
- Helps demystify some wireless concepts using Bluetooth and the JSR-82 API
- Shows how to run and debug Java ME Bluetooth applications on your desktop computer
- Explains how to read data from a Bluetooth-enabled GPS device
Contents
- | The Big Problem: Where Emulators Fail |
- | Setting Up the Environment |
- | Unraveling Some Mysteries of Bluetooth and JSR-82 |
- | Summary |
Additionally, testing your Java ME Bluetooth applications directly on your JSR-82 device is impractical since you don't have access to the
System.out
for simple debugging of your application. Additionally, the iteration
cycles for developing, compiling, provisioning, and installing the
application on a mobile phone is very time consuming.The good news is that you're going to learn how to construct a low-cost solution that allows you to install, debug, and test your JSR-82 applications on your computer. I'm going to introduce to you the Mpowerplayer, a CLDC emulator for the computer that can be configured to behave like a JSR-82 Bluetooth-enabled phone. With this configuration, the Mpowerplayer will behave just like a JSR-82 Bluetooth-enabled mobile phone, but you'll have access to the
System.out
and have the ability to view stacktraces, both of which are essential in debugging your wireless application.- Required
- The Sun Wireless Toolkit for CLDC. This tool is the defacto standard for developing Java ME applications.
- A Bluetooth-enabled computer. The Bluetooth module for your PC could
either be built-in to the computer or can be attached externally via
the USB port.
- The Mpowerplayer.
This free desktop application is a very good mobile emulator. It is
able to access your Bluetooth hardware on your desktop PC, to execute
the JSR-82 method calls that require access to actual Bluetooth
hardware.
- REQUIRED - A JSR-82 library that supports the Mpowerplayer. I use the Avetana SDK, which works beautifully with the Mpowerplayer.
- A Bluetooth-enabled GPS device. I use the DeLorme Earthmate BT-20.
- The Sun Wireless Toolkit for CLDC. This tool is the defacto standard for developing Java ME applications.
- Optional
- A Java ME phone that supports the JSR-82 API. If you don't know whether your phone supports the JSR-82 API, be sure take a look at this list. It is the best source of information to determine what Java ME APIs the major phone manufacturers support. However, I did notice that the list didn't include any RIM Blackberry devices, which also support the JSR-82 specification.
avetanaBluetoth.jar
file to the
"mpp-sdk\bluetooth" folder - it's just that simple! Later on, you're
going to see screenshots of Mpowerplayer in action.Did you know that once you discover the connection URL for your desired Bluetooth service, then you no longer need to employ the device- and service-discovery processes? If you're unfamiliar with what a Bluetooth connection URL looks like, I have provided an example below:
btspp://001AA3000C19:1;authenticate=false;encrypt=false;master=false
Let us briefly revisit the purposes of the device-discovery and service-discovery processes that apply to all Bluetooth-enabled systems, whether or not if you use the JSR-82 API. The device-discovery process is used to determine what Bluetooth devices are in the vicinity. In the connection URL listed previously, the device represented has the Bluetooth address of
001AA3000C19
. In the example code that will be presented later in this article, I used an inner class named BTUtility
that implements all the necessary JSR-82 Bluetooth API code for device
and service discovery. The code snippet below shows the necessary steps
for device discovery:public BTUtility() { try { LocalDevice localDevice = LocalDevice.getLocalDevice(); discoveryAgent = localDevice.getDiscoveryAgent(); discoveryForm.append(" Searching for Bluetooth devices in the vicinity...\n"); discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this); } catch(Exception e) { e.printStackTrace(); } } public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass cod) { try{ discoveryForm.append("found: " + remoteDevice.getFriendlyName(true)); } catch(Exception e){ discoveryForm.append("found: " + remoteDevice.getBluetoothAddress()); } finally{ remoteDevices.addElement(remoteDevice); } } public void inquiryCompleted(int discType) { if (remoteDevices.size() > 0) { // the discovery process was a success // so let's out them in a List and display it to the user for (int i=0; i<remoteDevices.size(); i++){ try{ devicesList.append(((RemoteDevice)remoteDevices.elementAt(i)).getFriendlyName(true), bt_logo); } catch (Exception e){ devicesList.append(((RemoteDevice)remoteDevices.elementAt(i)).getBluetoothAddress(), bt_logo); } } display.setCurrent(devicesList); } else { // handle this } |
The inner class itself implements the
DiscoveryListener
interface, so its deviceDiscovered()
method will be called every time a remote Bluetooth device has been
found. When the device-discovery process has finally ended, the JVM will
call the inquiryCompleted()
method. Fortunately, I don't
have to deploy this application to my JSR-82 enabled phone to properly
test it. I can test the entire application on my desktop computer using
the Mpowerplayer, as described earlier.Figure 1 shows the Mpowerplayer running my application during the device-discovery process, and Figure 2 shows the state of mobile application after the device-discovery process is finished.
Now that we've taken care of the device-discovery process, and we see that the device that we want to connect to is in the list of available devices, let's take another look at the fully qualified connection URL.
btspp://001AA3000C19:1;authenticate=false;encrypt=false;master=false
As you can see, the device-discovery process lets us know the Bluetooth address (in this case,
001AA3000C19
)
and the friendly name of the remote Bluetooth device (in this case,
Earthmate BT-20 GPS). But we still don't know what the other parameters
are that comprise the connection URL. After all, a single Bluetooth
device can offer multiple services -- for instance, a Bluetooth Access
point can offer both Dialup Networking and Personal Area Networking
services. Therefore, we need to search for the appropriate service that
we want on the selected Bluetooth device.The service-search process is dependent on knowing the type of service that you want. I want to consume serial data from a Bluetooth-enabled GPS device, and the unique identifier for wireless serial services is
0x1101
. The previously mentioned inner class, BTUtility
, has also implemented all the code for service searching. The following snippet shows what is involved.public void run(){ try { RemoteDevice remoteDevice = (RemoteDevice)remoteDevices.elementAt(devicesList.getSelectedIndex()); discoveryAgent.searchServices(attrSet, uuidSet, remoteDevice , this); } catch(Exception e) { e.printStackTrace(); } } public void servicesDiscovered(int transID, ServiceRecord[] servRecord){ for(int i = 0; i < servRecord.length; i++) { DataElement serviceNameElement = servRecord[i].getAttributeValue(0x0100); String _serviceName = (String)serviceNameElement.getValue(); String serviceName = _serviceName.trim(); btConnectionURL = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); } display.setCurrent(readyToConnectForm); readyToConnectForm.append("\n\nNote: the connection URL is: " + btConnectionURL); System.out.println("Note: the connection URL is: " + btConnectionURL); } public void serviceSearchCompleted(int transID, int respCode) { if (respCode == DiscoveryListener.SERVICE_SEARCH_COMPLETED) { // the service search process was successful } else { // the service search process has failed } } |
Now, service searching is a blocking I/O operation, so I put the intensive work in the
run()
method of a thread to allow the application to behave nicely. Whenever a
matching service has been found on the remote device, the JVM will call
my servicesDiscovered()
method to let me know so that I
can do something about it. As shown in the following figure, I've found
the service that I want, and I have everything that I need to get the
connection URL.To reiterate a previous point: now that you have determined the connection URL for your desired device, you no longer need to go through the device- and service-discovery processes for subsequent usage of the remote Bluetooth device. All you need to do is open a connection on the URL. After that, you have everything that you need to communicate with the remote Bluetooth device.
Figure 4 shows the operation of another thread-enabled inner class that opens the connection on the URL and then reads the data from the wireless serial port.
Wait a minute. If we're reading serial data from a GPS device, then where are the latitudes, longitudes, and other global-positioning stuff? Is the data corrupted?
Actually, the serial data that you see in Figure 4 is actually encoded in NMEA (National Marine Electronics Association) format, which is the common format for all GPS devices. Part 2 of this technical article shows you how to decode the NMEA data and plot your location on your phone.
Link: http://dsc.sun.com/mobility/apis/articles/bluetooth_gps/part1/
Thursday, September 6, 2012
Package de.avetana.bluetooth
Package de.avetana.bluetooth Description
This package provides an implementation of the JSR 82 specification from Sun Microsystems (c). The aim of this specification is to easily develop Bluetooth-based applications in java. It does not exist (as I am writing these comments) any universal implementation of the Sun Specification.The Avetana Bluetooth package is available under three operating systems: Linux (GPL version), Windows and Mac OS X (commercial versions) and is NOT a 100 % pure Java implementation. The use of JNI technologies allows to communicate with the hardware and system-specific bluetooth stack.
Under Linux you must have a kernel version > 2.4.20 or at least you must have the BlueZ kernel modules installed AND loaded.
Package Specification
For JSR82-Specification, please seeRelated Documentation
For overviews, examples, guides, and tool documentation, please see the API documentation and the documents stored in the directory named "doku".The class de.avetana.bluetooth.JSRTest2 gives an overview of the possibilities offered by this implementation.
Please refer to the following tutorial, too.
Quick Tutorial
Management of the local Device
The JSR82 Specification allows to work only with one Local Device, which is accessible with the help of the static method:LocalDevice m_local=LocalDevice.getLocalDevice();
You can now retrieve some properties of your local device:
//retrieves the BT address of the local device
LocalDevice.getBluetoothAdress()
//retrieves the name of the local device
LocalDevice.getFriendlyName()
// retrieves the discoverable mode. Beware, this method often requires root privileges
LocalDevice.getDiscoverableMode()
The method getRecord(ConnectionNotifier)
and updateRecord(ServiceRecord)
cannot be
directly used here. They suppose that you have already created a service waiting for incoming connections.
Device/Service Search
With yourLocalDevice
you can retrieve the DiscoveryAgent which will help you to perform an HCI inquiry
(Device search) or a service Search.
//retrieves the DiscoveryAgent
DiscoveryAgent m_agent=LocalDevice.getDiscoveryAgent()
Whatever the search you want to perforn you need beside your DiscoveryAgent a DiscoveryListener.
The DiscoveryListener will set the way your application react each time a new device or a new service is found, but also when the searches terminate normally or abnormally.
Example of a device search
DiscoveryListener myListener=new DiscoveryListener() {
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
//does nothing
}
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
try {
System.out.println("New Device "+btDevice.getBluetoothAddress()+" found!");
System.out.println("Remote Name of the device is "+btDevice.getFriendlyName(true));
}catch(Exception ex) {}
}
public void inquiryCompleted(int discType) {
System.out.println("Device Search completed!");
}
public void serviceSearchCompleted(int transID, int respCode) {
// does nothing
}
};
try {
m_agent.startInquiry(DiscoveryAgent.GIAC, myListener);
}
catch(Exception ex) {ex.printStackTrace();}
This example does not implement the part of the DiscoveryListener class used to
manage the result of a service search. In this case this does not have any influence, since
this little code-fragment is only performing a device search. A more complete example performing a service search as soon as the device search is completed can be found in the de.avetana.bluetooth.util.ServiceFinderPane class.
I strongly recommand to refer to this class for a pratical example.
Client connection and data exchange
After a service search and the choice of the service you want to connect to, you know the connection URL used to perform a client connection (this URL is given by the method javax.bluetooth.ServiceRecord#getConnectionURL(...)).Let's suppose that the choosen service waits for RFCOMM protocol based-connections. The form of the URL is:
String connectionURL="btspp://123456123456:1;encrypt=false;authenticate=false;master=true"
To connect to this service, assuming that running is a class variable set to false, when the user presses an UI button labelled Close:
Connection con=Connector.open(connectionURL);
Runnable r=new Runnable() {
public void run() {
byte b[] = new byte[200];
try {
while (running) {
dataReceived.setText("Received
" + received);
int a = is.read(b);
received += a;
}
} catch (Exception e) {e.printStackTrace();running=false; }
}
//Starts the thread used to read data
new Thread(r).run();
//Write some data
((StreamConnection)streamCon).openDataOutputStream().writeChars("Try to write");
License
In each file related to this project, you will find the following header:COPYRIGHT:
(c) Copyright 2004 Avetana GmbH ALL RIGHTS RESERVED.
This file is part of the Avetana bluetooth API for Linux.
The Avetana bluetooth API for Linux is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
The Avetana bluetooth API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
The development of the Avetana bluetooth API is based on the work of Christian Lorenz (see the Javabluetooth Stack at http://www.javabluetooth.org) for some classes, on the work of the jbluez team (see http://jbluez.sourceforge.net/) and on the work of the bluez team (see the BlueZ linux Stack at http://www.bluez.org) for the C code. Classes, part of classes, C functions or part of C functions programmed by these teams and/or persons are explicitly mentioned.
Please RESPECT the terms of this license and commit any changes!!!.
Conclusion
The JSR82 specification is really an easy-to-use development tool for Bluetooth. Moreover the use of the Avetana Bluetooth implementation is transparent for the end-programmer.This quick tutorial has made a short presentation of the possibilities offered by the Avetana Bluetooth implementation but a look at the JSRTest class could complete this HOWTO.
Several turorials are available on the internet and I strongly suggest to consult them if you are not familiar with Bluetooth, Java or the use of JSR82.
But please keep two things in mind:
- Only RFCOMM and L2CAP protocols are currently supported.
- The linux implementation is free under the terms of the GPL. So if you want to modify some files, please do it and commit any modifications with our CVS Server.
Monday, September 3, 2012
Use PHP, MySql and Google Map API v3 for displaying data on map
http://tips4php.net/2010/10/use-php-mysql-and-google-map-api-v3-for-displaying-data-on-map/Displaying data on maps can be useful in many situations.
By integrating tools like PHP, MySQL and Google Maps, you can relatively easy build customized maps for your website or blog.
In this post we’ll take a closer look on the possibilities, and build a interactive map based on PHP, MySql and Google Map API v3.
Before proceeding, you need some geocoded data (data that contains lat/long information) to display on the map. If you don’t have geocoded data, you can find a post here, where you can learn how to geocode addresses for usage on eg. Google Maps.
You can use the following test data for this example:
When you have a MySQL database with Geocoded content you’re ready to proceed.
As you can see, the output of the script is has the following format: “addMarker(lat, long, marker data);“, this is the marker format that you can use for adding multiple markers fir Google Maps API V3.
For this example, we have used the code from August LI as inspiration.
The script has the following features:
The final script with the PHP and javascript code merged looks like this:
The final result looks like this:
By integrating tools like PHP, MySQL and Google Maps, you can relatively easy build customized maps for your website or blog.
In this post we’ll take a closer look on the possibilities, and build a interactive map based on PHP, MySql and Google Map API v3.
Geocoded data
The script in this post uses MySQL for storing the data that’s going to be displayed on the map. This method works fine if you’re adding multiple points to your map (10+), and want a dynamic way to retrieve data data. If you’re going to display less than 10 Points the solution in this post is a little overkill.Before proceeding, you need some geocoded data (data that contains lat/long information) to display on the map. If you don’t have geocoded data, you can find a post here, where you can learn how to geocode addresses for usage on eg. Google Maps.
You can use the following test data for this example:
01 | CREATE TABLE IF NOT EXISTS `poi_example` ( |
02 | `id` int (11) NOT NULL AUTO_INCREMENT, |
03 | ` name ` text NOT NULL , |
04 | ` desc ` text NOT NULL , |
05 | `lat` text NOT NULL , |
06 | `lon` text NOT NULL , |
07 | PRIMARY KEY (`id`) |
08 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; |
09 |
10 | -- |
11 | -- Data dump for the table `poi_example` |
12 | -- |
13 |
14 | INSERT INTO `poi_example` (`id`, ` name `, ` desc `, `lat`, `lon`) VALUES |
15 | (1, '100 Club' , 'Oxford Street, London W1<br/>3 Nov 2010 : Buster Shuffle<br/>' , '51.514980' , '-0.144328' ), |
16 | (2, '93 Feet East' , '150 Brick Lane, London E1 6RU<br/>7 Dec 2010 : Jenny & Johnny<br/>' , '51.521710' , '-0.071737' ), |
17 | (3, 'Adelphi Theatre' , 'The Strand, London WC2E 7NA<br/>11 Oct 2010 : Love Never Dies' , '51.511010' , '-0.120140' ), |
18 | (4, 'Albany, The' , '240 Gt. Portland Street, London W1W 5QU' , '51.521620' , '-0.143394' ), |
19 | (5, 'Aldwych Theatre' , 'Aldwych, London WC2B 4DF<br/>11 Oct 2010 : Dirty Dancing' , '51.513170' , '-0.117503' ), |
20 | (6, 'Alexandra Palace' , 'Wood Green, London N22<br/>30 Oct 2010 : Lynx All-Nighter' , '51.596490' , '-0.109514' ); |
Extracting from MySQL
Next thing is to create a small piece of PHP that can connect and extract data from MySQL01 | // connection to mysql |
02 |
03 | <? |
04 | $dbname = '<database name>' ; //Name of the database |
05 | $dbuser = '<database username>' ; //Username for the db |
06 | $dbpass = '<database password>' ; //Password for the db |
07 | $dbserver = '<database server>' ; //Name of the mysql server |
08 |
09 | $dbcnx = mysql_connect ( "$dbserver" , "$dbuser" , "$dbpass" ); |
10 | mysql_select_db( "$dbname" ) or die (mysql_error()); |
11 | ?> |
12 |
13 | // extracting and looping through data |
14 |
15 | <? |
16 | $query = mysql_query( "SELECT * FROM poi_example" ); |
17 | while ( $row = mysql_fetch_array( $query )){ |
18 | $name = $row [ 'name' ]; |
19 | $lat = $row [ 'lat' ]; |
20 | $lon = $row [ 'lon' ]; |
21 | $desc = $row [ 'desc' ]; |
22 | echo ( "addMarker($lat, $lon,'<b>$name</b><br/>$desc');\n" ); |
23 | } |
24 | ?> |
Google Maps API V3
Next thing is to embed the PHP code into the javascript required for displaying multiple infowindows in Google Map API V3.For this example, we have used the code from August LI as inspiration.
The script has the following features:
- “var icon”: specifies a customizable icon. In this example a icon from Google is used, but you can add your own icons as well
- “var popup”: specifies the maximum width of the info window. In this case 300 pixels
- “addMarker”: contains latitude and longitude of the points, and a possibility to display whatever HTML content you like in the info window that corresponds to each point. In this example we’re just displaying a headline and description
- The map automatically zooms and centers to the most detailed view where all the map markers can be displayed in the same map. This is automatically calculated based on the size of the map, and the locations of the map markers.
The final script with the PHP and javascript code merged looks like this:
01 | <? |
02 | $dbname ='insert mysql database name'; //Name of the database |
03 | $dbuser ='insert mysql user name'; //Username for the db |
04 | $dbpass ='insert mysql password'; //Password for the db |
05 | $dbserver ='insert mysql database server address'; //Name of the mysql server |
06 |
07 | $dbcnx = mysql_connect ("$dbserver", "$dbuser", "$dbpass"); |
08 | mysql_select_db("$dbname") or die(mysql_error()); |
09 | ?> |
10 | < html > |
11 | < head > |
12 | < meta http-equiv = "content-type" content = "text/html; charset=utf-8" /> |
13 | < title >Google Map API V3 with markers</ title > |
14 | < style type = "text/css" > |
15 | body { font: normal 10pt Helvetica, Arial; } |
16 | #map { width: 350px; height: 300px; border: 0px; padding: 0px; } |
17 | </ style > |
18 | < script src = "http://maps.google.com/maps/api/js?v=3&sensor=false" type = "text/javascript" ></ script > |
19 | < script type = "text/javascript" > |
20 | //Sample code written by August Li |
21 | var icon = new google.maps.MarkerImage("http://maps.google.com/mapfiles/ms/micons/blue.png", |
22 | new google.maps.Size(32, 32), new google.maps.Point(0, 0), |
23 | new google.maps.Point(16, 32)); |
24 | var center = null; |
25 | var map = null; |
26 | var currentPopup; |
27 | var bounds = new google.maps.LatLngBounds(); |
28 | function addMarker(lat, lng, info) { |
29 | var pt = new google.maps.LatLng(lat, lng); |
30 | bounds.extend(pt); |
31 | var marker = new google.maps.Marker({ |
32 | position: pt, |
33 | icon: icon, |
34 | map: map |
35 | }); |
36 | var popup = new google.maps.InfoWindow({ |
37 | content: info, |
38 | maxWidth: 300 |
39 | }); |
40 | google.maps.event.addListener(marker, "click", function() { |
41 | if (currentPopup != null) { |
42 | currentPopup.close(); |
43 | currentPopup = null; |
44 | } |
45 | popup.open(map, marker); |
46 | currentPopup = popup; |
47 | }); |
48 | google.maps.event.addListener(popup, "closeclick", function() { |
49 | map.panTo(center); |
50 | currentPopup = null; |
51 | }); |
52 | } |
53 | function initMap() { |
54 | map = new google.maps.Map(document.getElementById("map"), { |
55 | center: new google.maps.LatLng(0, 0), |
56 | zoom: 14, |
57 | mapTypeId: google.maps.MapTypeId.ROADMAP, |
58 | mapTypeControl: false, |
59 | mapTypeControlOptions: { |
60 | style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR |
61 | }, |
62 | navigationControl: true, |
63 | navigationControlOptions: { |
64 | style: google.maps.NavigationControlStyle.SMALL |
65 | } |
66 | }); |
67 | <? |
68 | $query = mysql_query("SELECT * FROM poi_example"); |
69 | while ($row = mysql_fetch_array($query)){ |
70 | $name=$row['name']; |
71 | $lat=$row['lat']; |
72 | $lon=$row['lon']; |
73 | $desc=$row['desc']; |
74 | echo ("addMarker($lat, $lon,'< b >$name</ b >< br />$desc');\n"); |
75 | } |
76 | ?> |
77 | center = bounds.getCenter(); |
78 | map.fitBounds(bounds); |
79 |
80 | } |
81 | </ script > |
82 | </ head > |
83 | < body onload = "initMap()" style = "margin:0px; border:0px; padding:0px;" > |
84 | < div id = "map" ></ div > |
85 | </ html > |
Subscribe to:
Posts (Atom)