/* * This file is part of Transitime.org * * Transitime.org is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License (GPL) as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Transitime.org 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 Transitime.org . If not, see <http://www.gnu.org/licenses/>. */ package org.transitime.avl; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.transitime.config.StringConfigValue; import org.transitime.configData.AvlConfig; import org.transitime.db.structs.AvlReport; import org.transitime.modules.Module; /** * AVL module for Workwave AVL feed. Polls JSON feed. First gets a valid * session ID to pass to the AVL requests. * * @author Michael Smith * */ public class WorkwaveAvlModule extends PollUrlAvlModule { private final static String AVL_URL = "http://gps.workwave.com/php/points.php"; private final static String GET_SESSION_URL = "http://gps.workwave.com/map/view-only?api-key="; private final static DateFormat workwaveTimeFormat = new SimpleDateFormat("MM/dd/yy hh:mm:ss a"); private static StringConfigValue apiKey = new StringConfigValue("transitime.avl.workwaveApiKey", "The API key to use when getting session ID for Workwave " + "AVL feed."); // The authorization cookie to be provided when requesting AVL data String sessionId = null; private static final Logger logger = LoggerFactory .getLogger(TranslocAvlModule.class); /********************** Member Functions **************************/ public WorkwaveAvlModule(String agencyId) { super(agencyId); // Initialize the session ID setSessionId(); } /** * Access the page GET_SESSION_URL to get the cookie PHPSESSID and stores * the resulting cookie in sessionId member. Then when getting AVL data * can send the PHPSESSID cookie as authentication. */ private void setSessionId() { // Make sure the API key is configured if (apiKey.getValue() == null) { logger.error("API key not set for WorkwaveAvlModule. Needs to be " + "set via Java property {} .", apiKey.getID()); return; } String fullUrl = null; try { // Create the connection fullUrl = GET_SESSION_URL + apiKey.getValue(); URL url = new URL(fullUrl); URLConnection con = url.openConnection(); // Set the timeout so don't wait forever int timeoutMsec = AvlConfig.getAvlFeedTimeoutInMSecs(); con.setConnectTimeout(timeoutMsec); con.setReadTimeout(timeoutMsec); // Get the PHPSESSID cookie to use as the session ID Map<String, List<String>> headerFields = con.getHeaderFields(); List<String> cookies = headerFields.get("Set-Cookie"); for (String cookie : cookies) { if (cookie.contains("PHPSESSID")) { int equalSign = cookie.indexOf('='); int semicolon = cookie.indexOf(';'); sessionId = cookie.substring(equalSign + 1, semicolon); logger.info("Session ID for Workwave AVL feed is " + "PHPSESSID={}", sessionId); } } } catch (Exception e) { logger.error("Could not access URL {}.", fullUrl, e); } } /** * Set the PHPSESSID as a cookie as authorization */ @Override protected void setRequestHeaders(URLConnection con) { if (sessionId == null) logger.error("PHPSESSID not set when trying to fetch AVL data."); con.setRequestProperty("Cookie", "PHPSESSID=" + sessionId); } @Override protected String getUrl() { return AVL_URL; } /** * Reads in and processes JSON AVL data */ @Override protected Collection<AvlReport> processData(InputStream in) throws Exception { String jsonStr = getJsonString(in); try { JSONObject jsonObj = new JSONObject(jsonStr); // Make sure no problem getting data boolean success = jsonObj.getBoolean("success"); if (!success) { String message = jsonObj.getString("message"); logger.error("Error occurred when getting AVL data. URL={} and " + "PHPSESSID={}. {}", getUrl(), sessionId, message); // Since there was a problem try getting new session ID since // perhaps old one is invalid. setSessionId(); return new ArrayList<AvlReport>(); } // The return value for the method Collection<AvlReport> avlReportsReadIn = new ArrayList<AvlReport>(); JSONObject points = jsonObj.getJSONObject("points"); JSONArray features = points.getJSONArray("features"); for (int i=0; i<features.length(); ++i) { JSONObject feature = features.getJSONObject(i); // Get latitude/longitude JSONObject geometry = feature.getJSONObject("geometry"); JSONArray coordinates = geometry.getJSONArray("coordinates"); double latitude = Double.parseDouble(coordinates.getString(1)); double longitude = Double.parseDouble(coordinates.getString(0)); // Get vehicleId, heading, velocity, and timestamp JSONObject properties = feature.getJSONObject("properties"); String vehicleId = properties.getString("deviceId"); float heading = (float) Double.parseDouble(properties.getString("heading")); float speed = (float) Double.parseDouble(properties.getString("velocity")); String gpsTimeStr = properties.getString("timestamp"); Date gpsTime = workwaveTimeFormat.parse(gpsTimeStr); // Process AVL report AvlReport avlReport = new AvlReport(vehicleId, gpsTime.getTime(), latitude, longitude, speed, heading, "WorkWave"); avlReportsReadIn.add(avlReport); } // Return all the AVL reports read in return avlReportsReadIn; } catch (JSONException e) { logger.error("Error parsing JSON. {}. {}", e.getMessage(), jsonStr, e); return new ArrayList<AvlReport>(); } } /** * Just for debugging */ public static void main(String[] args) { Module.start("org.transitime.avl.WorkwaveAvlModule"); } }