Wednesday, July 29, 2015

Where am I? Collecting GPS data with Apache Camel

This is the re-post of my article Where Am I? Collecting GPS Data With Apache Camel originally posted at the DZone.

One of the most popular requirement for the field devices used in the IoT systems is to provide the current GPS location of that device and send this information to the data center. In hereby article I will tell you how Apache Camel can turn full-stack Linux microcomputer (like Raspberry Pi) into the device collecting the GPS coordinates.

Which GPS unit should I choose?

There is a myriad of the GPS receivers available in the market. BU353 is one of the most popular and the cheapest GPS units. It can be connected to the computer device via the USB port. If you are looking for good and cheap GPS receiver for your IoT solution, you should definitely consider purchasing this unit.

The picture below presents the BU353 connected to the Raspberry Pi device via the USB port.
You can optionally equip your Pi into the external mobile battery, like GOODRAM Power Bank P661. Equipped with the external power supply you can take your mobile GPS system to the car or into the outdoors. Battery significantly simplifies testing "in the field" part of your solution.


How can Camel help me?

Camel GPS BU353 component can be used to read the current GPS information from that device. With Camel GPS BU353 you can just connect the receiver to your computer's USB port and read the GPS data - the component will make sure that GPS daemon is up, running and switched to the NMEA mode. The component also takes care of parsing the NMEA data read from the serial port, so you can enjoy the GPS data wrapped into the com.github.camellabs.iot.component.gps.bu353.ClientGpsCoordinates POJO objects (which in turn are forwarded to your Camel routes).

Show me the code

In order to take advantage of the Camel GPS BU353 you have to add the following dependency to your Maven project:
    <dependency>
      <groupId>com.github.camel-labs</groupId>
      <artifactId>camel-gps-bu353</artifactId>
      <version>0.1.1</version>
    </dependency>
BU353 component supports only consumer endpoints - it makes sense as GPS component is used to read, not write, GPS data. The BU353 consumer is the polling one, i.e. it periodically asks the GPS device for the current coordinates. The Camel endpoint URI format for the BU353 consumer is as follows:
    gps-bu353:label
Where label can be replaced with any text label:
    from("gps-bu353:current-position").
      to("file:///var/gps-coordinates");
The Camel route presented above reads the current GPS coordinates every 5 seconds and saves these into the /var/gps-coordinates directory. Each GPS coordinates pair is saved into the dedicated file. The complete runnable example of the route above is presented in the code snippet below. I use Camel Spring Boot support to start the Camel context and load the route definition:
@SpringBootApplication
public class GpsReader extends FatJarRouter {

  public void configure() throws Exception {
    from("gps-bu353:current-position").
      to("file:///var/gps-coordinates");
  }

}
BU353 consumer receives the com.github.camellabs.iot.component.gps.bu353.ClientGpsCoordinates instances. ClientGpsCoordinates class is a convenient POJO wrapper around the GPS data:
  ConsumerTemplate consumerTemplate = camelContext.createConsumerTemplate();
  ClientGpsCoordinates currentPosition = 
    consumerTemplate.receiveBody("gps-bu353:current-position", ClientGpsCoordinates.class);

  String deviceId = currentPosition.clientId();
  Date taken = currentPosition.timestamp();
  double latitude = currentPosition.lat();
  double longitude = currentPosition.lng();
ClientGpsCoordinates class name is prefixed with the Client keyword to indicate that these coordinates have been created on the device, not on the server side of the IoT solution.

Process manager

Process manager is used by the BU353 component to execute Linux commands responsible for starting GPSD daemon and configuring the GPS receiver to provide GPS coordinates in the NMEA mode. If for some reason you would like to change the default implementation of the process manager used by Camel (i.e. com.github.camellabs.iot.utils.process.DefaultProcessManager), you can set it on the component level:
    GpsBu353Component bu353 = new GpsBu353Component();
    bu353.setProcessManager(new CustomProcessManager());
    camelContext.addComponent("gps-bu353", bu353);
If the custom process manager is not set on the component, Camel will try to find the manager instance in the registry. So for example for the Spring application, you can just configure the manager as the bean:
    @Bean
    ProcessManager myProcessManager() {
        new CustomProcessManager();
    }
The custom process manager may be useful if for some reasons your Linux distribution requires executing some unusual commands in order to make the GPSD up and running.

What's next?

Do geographical capabilities of the Camel seem compelling to you? Then you should also Camel Geocoder component which can be used to easily convert GPS coordinates collected via Camel into the human readable street address. Also stay tuned for the geofencing features coming soon to the Camel IoT Labs project.

5 comments:

  1. Hello,

    many thanks for this article and the work on Rhiot! Unfortunately, I'm unable to use the GpsBu353Component. I connected my Bu353S4 receiver to my Raspberry Pi (Raspbian) which is working fine. That means gpsd is running and cgps prints out valid coordinates. But when I run your camel example on the raspberry, I always get the following exception:

    Consumer Consumer[gps-bu353://current-position] failed polling endpoint: Endpoint[gps-bu353://current-position]. Will try again at next poll. Caused by: [java.lang.RuntimeException - java.io.FileNotFoundException: /dev/ttyUSB0 (Device or resource busy)].

    The "fuser" command tells me, that the java process running camel is actually the only process that accesses ttyUSB0. Can you help me?

    Best regards
    Thomas

    ReplyDelete
    Replies
    1. Hi Thomas,

      I'm glad you like the Rhiot! I created the bug report [1] for your issue. Can we try to sort it out together there?

      Cheers!

      [1] https://github.com/rhiot/rhiot/issues/210

      Delete
  2. GPS Tracker App uses the latest Global Positioning System (GPS) technology to get the precise location of people within your network. Satellites send triangulated positions to the GPS Tracker App providing the most accurate location. This process continually updates to provide very accurate, real-time GPS tracking.
    Custom gps solution | Fuel monitoring online

    ReplyDelete
  3. The remote uses its area for two particular purposes: to start with, to point the reception apparatus at the satellite, and second, to register the separation to the satellite. The separation to the satellite is pivotal when choosing when to transmit a TDMA burst. https://biobigdata.ucsd.edu/members/1939/blog/2016/09/garmin-camper-660lmt-the-latest-navigator-you-need-to-have

    ReplyDelete
  4. You can collect all the data you need just by using your phone. Here is the article about it.

    ReplyDelete