A GPS Tracker on the Sigfox IoT Network

  Android, GPS, IoT, Java, MKRFOX1200, mySQL, Sigfox, Tomcat

Receiving servlet

Make yourself familiar with the servlet code which we’ll deploy to a Tomcat web container. The complete Eclipse project can be found here: https://github.com/sgoemans/arduino-gps-web:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* Retrieve user (ID) and password (KEY) from the "Authorization" header (Basic Auth)
*/
  final String authorization = request.getHeader("Authorization");
  if (authorization != null && authorization.toLowerCase().startsWith("basic")) {
    // Authorization: Basic base64credentials
    String base64Credentials = authorization.substring("Basic".length()).trim();
    byte[] credDecoded = Base64.decodeBase64(base64Credentials.getBytes());
    String credentials = new String(credDecoded, StandardCharsets.UTF_8);
    // credentials = username:password
    final String[] values = credentials.split(":", 2);
    id = values[0];
    key = values[1];
  }

  /*
  * Check whether a session already exists (the user has successfully logged in before)
  */
  boolean loggedIn = false;
  HttpSession session = request.getSession(false);
  if(session == null) {
    // TODO: check user and password against database table "users"
    session = request.getSession(true);
    loggedIn = true;
  }
  // TODO: Remove next line if credentials are checked against the database
  loggedIn = true;
  
  if(loggedIn) {
    Path FILE_PATH = Paths.get(getServletContext().getRealPath("/"), "temp.txt");
    String lat = request.getParameter("lat");
    String lng = request.getParameter("lng");
    String alt = request.getParameter("alt");
  
    if(lat == null && lng == null && alt == null) {
      response.getWriter().append(curPos);
    } else {
      curPos = lat + "," + lng + "," + alt;
  
      String query = "INSERT INTO coords ("
      + " pk,"
      + " id,"
      + " lat,"
      + " lng,"
      + " alt ) VALUES (null, ?, ?, ?, ?)";

      ServletContext ctx = this.getServletContext();
      DBConnectionManager dbManager = (DBConnectionManager) ctx.getAttribute("DBManager");
      Connection connection = dbManager.getConnection();

      try {
        PreparedStatement st = connection.prepareStatement(query);
        st.setString(1, id);
        st.setString(2, lat);
        st.setString(3, lng);
        st.setString(4, alt);
        st.executeUpdate();
        st.close();
      } catch (SQLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
      }

      //Writing to the file temp.txt
      try (BufferedWriter writer = Files.newBufferedWriter(FILE_PATH, StandardCharsets.UTF_8,
      Files.exists(FILE_PATH) ? StandardOpenOption.APPEND : StandardOpenOption.CREATE)) {
        writer.write(ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME));
        writer.write(curPos + "\n");
      } catch (IOException e) {
        e.printStackTrace();
      }
      response.getWriter().append(curPos);
    }
  }
}

Let’s go quickly through the different code blocks in the above listing.

Line 5 – 15 Authorization

Its not unlikely that your backend server will be frequently targeted by hackers. First line of defense will be password protection of the Tomcat server, so that not just anybody can send data to you servlet. Most simple way of doing password protection is editing the tomcat-users.xml file. On the previous page I mentioned how to add the basic authentication HTTP header to the Sigfox backend device type definition page. This header contains the base64 encoded username and password which is transmitted to your Tomcat server. The header is transmitted as part of the http request in clear text. For this security measure to be of any use, the transmission must be encrypted by TLS/SSL, so that hackers can’t read the requests coming from Sigfox and recompile its user/password values. See my recent article about securing a Tomcat server with Basic Auth and TLS/SSL.
A more sophisticated user/password protection scheme would be using the Tomcat JDBCRealm, which makes use of a database for storing user credentials and permissions/roles. It is described in the coming chapter “Database Persistance”.

Line 17 – 30 Session control

What happens to the GPS data that Sigfox sends to your server? The server stores the data in a database, but what for? The answer is that we want to visualize the data on desktop PCs or mobile device like smartphones or tablets. If we want to let multiple devices  access the data, its a good idea to establish some kind of authorization to control access to the data.  Therefore, the code checks if the user has already logged on using his credentials. If not, his credentials are checked against a database table and, if successful, a session is created during which the user is authorized to use the web application. As long as the session is valid, the user doesn’t need to provide his credentials any more.

Line 31 – 63 Persistence

GPS data is persisted in both a text file and a database. The data itself is taken from the request’s query string. Data is only stored if either a latitude, a longitude, or an altitude value is present. If none of them can be found in the query string, nothing is stored. What’s missing in the database part is the date/time the GPS data was received. I was just too lazy to dig myself through the differences of date/time formats between Java and mySQL. Nevertheless, lines 48 – 50 require some explanation. See next page where I explain the use of a servletContext and access to the mySql database by using datasources.

LEAVE A COMMENT