/* * This file is part of GPSLogger for Android. * * GPSLogger for Android 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. * * GPSLogger for Android 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. * * You should have received a copy of the GNU General Public License * along with GPSLogger for Android. If not, see <http://www.gnu.org/licenses/>. */ package com.mendhak.gpslogger.common; import android.content.Context; import android.location.Location; import com.loopj.android.http.AsyncHttpClient; import com.loopj.android.http.AsyncHttpResponseHandler; import com.loopj.android.http.RequestParams; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; /** * OpenGTS Client * * @author Francisco Reynoso <franole @ gmail.com> */ public class OpenGTSClient { private Context applicationContext; private IActionListener callback; private String server; private Integer port; private String path; private AsyncHttpClient httpClient; private int locationsCount = 0; private int sentLocationsCount = 0; public OpenGTSClient(String server, Integer port, String path, IActionListener callback, Context applicationContext) { this.server = server; this.port = port; this.path = path; this.callback = callback; this.applicationContext = applicationContext; } public void sendHTTP(String id, Location location) { sendHTTP(id, new Location[]{location}); } /** * Send locations sing HTTP GET request to the server * <p/> * See <a href="http://opengts.sourceforge.net/OpenGTS_Config.pdf">OpenGTS_Config.pdf</a> * section 9.1.2 Default "gprmc" Configuration * * @param id id of the device * @param locations locations */ public void sendHTTP(String id, Location[] locations) { try { locationsCount = locations.length; StringBuilder url = new StringBuilder(); url.append("http://"); url.append(getURL()); httpClient = new AsyncHttpClient(); for (Location loc : locations) { RequestParams params = new RequestParams(); params.put("id", id); params.put("code", "0xF020"); params.put("gprmc", OpenGTSClient.GPRMCEncode(loc)); Utilities.LogDebug("Sending URL " + url + " with params " + params.toString()); httpClient.get(applicationContext, url.toString(), params, new MyAsyncHttpResponseHandler(this)); } } catch (Exception e) { Utilities.LogError("OpenGTSClient.sendHTTP", e); OnFailure(); } } public void sendRAW(String id, Location location) { // TODO } private void sendRAW(String id, Location[] locations) { // TODO } private String getURL() { StringBuilder url = new StringBuilder(); url.append(server); if (port != null) { url.append(":"); url.append(port); } if (path != null) { url.append(path); } return url.toString(); } private class MyAsyncHttpResponseHandler extends AsyncHttpResponseHandler { private OpenGTSClient callback; public MyAsyncHttpResponseHandler(OpenGTSClient callback) { super(); this.callback = callback; } @Override public void onSuccess(String response) { Utilities.LogInfo("Response Success :" + response); callback.OnCompleteLocation(); } @Override public void onFailure(Throwable e, String response) { Utilities.LogError("OnCompleteLocation.MyAsyncHttpResponseHandler Failure with response :" + response, new Exception(e)); callback.OnFailure(); } } public void OnCompleteLocation() { sentLocationsCount += 1; Utilities.LogDebug("Sent locations count: " + sentLocationsCount + "/" + locationsCount); if (locationsCount == sentLocationsCount) { OnComplete(); } } public void OnComplete() { callback.OnComplete(); } public void OnFailure() { httpClient.cancelRequests(applicationContext, true); callback.OnFailure(); } /** * Encode a location as GPRMC string data. * <p/> * For details check org.opengts.util.Nmea0183#_parse_GPRMC(String) * (OpenGTS source) * * @param loc location * @return GPRMC data */ public static String GPRMCEncode(Location loc) { DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); DecimalFormat f = new DecimalFormat("0.000000", dfs); String gprmc = String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,,", "$GPRMC", NMEAGPRMCTime(new Date(loc.getTime())), "A", NMEAGPRMCCoord(Math.abs(loc.getLatitude())), (loc.getLatitude() >= 0) ? "N" : "S", NMEAGPRMCCoord(Math.abs(loc.getLongitude())), (loc.getLongitude() >= 0) ? "E" : "W", f.format(MetersPerSecondToKnots(loc.getSpeed())), f.format(loc.getBearing()), NMEAGPRMCDate(new Date(loc.getTime())) ); gprmc += "*" + NMEACheckSum(gprmc); return gprmc; } public static String NMEAGPRMCTime(Date dateToFormat) { SimpleDateFormat sdf = new SimpleDateFormat("HHmmss.SSS"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); return sdf.format(dateToFormat); } public static String NMEAGPRMCDate(Date dateToFormat) { SimpleDateFormat sdf = new SimpleDateFormat("ddMMyy"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); return sdf.format(dateToFormat); } public static String NMEAGPRMCCoord(double coord) { // “DDDMM.MMMMM” int degrees = (int) coord; double minutes = (coord - degrees) * 60; DecimalFormat df = new DecimalFormat("00.00000", new DecimalFormatSymbols(Locale.US)); StringBuilder rCoord = new StringBuilder(); rCoord.append(degrees); rCoord.append(df.format(minutes)); return rCoord.toString(); } public static String NMEACheckSum(String msg) { int chk = 0; for (int i = 1; i < msg.length(); i++) { chk ^= msg.charAt(i); } String chk_s = Integer.toHexString(chk).toUpperCase(); while (chk_s.length() < 2) { chk_s = "0" + chk_s; } return chk_s; } /** * Converts given meters/second to nautical mile/hour. * * @param mps meters per second * @return knots */ public static double MetersPerSecondToKnots(double mps) { // Google "meters per second to knots" return mps * 1.94384449; } }