A Tropo SMS/IM app that provides transit route and stop locations.
<?php | |
/* | |
* Copyright 2010 Mark J. Headd | |
* | |
* This application 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 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This application 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. | |
* | |
*/ | |
require_once 'path/to/tropo.class.php'; | |
// Constants used to geocode an address. | |
define("MAPS_LOOKUP_BASE_URL", "http://maps.google.com/maps/geo"); | |
define("MAPS_LOOKUP_FORMAT", "xml"); | |
define("MAPS_API_KEY", "your-api-key-goes-here"); | |
// Configurable items. | |
define("DEFAULT_ERROR_MESSAGE", "An error occured. Try again later. :-("); | |
define("DEFAULT_NO_INFORMATION_MESSAGE", "No information was available to respond to your request. Try again..."); | |
define("DEFAULT_NUMBER_DEPARTURES", 3); | |
define("DEFAULT_ROUNDING_PRECISION", 2); | |
define("DEFAULT_STOP_DISTANCE", 5); | |
define("DEFAULT_NUMBER_STOPS", 3); | |
// Exception classes. | |
class DatabaseException extends Exception {} | |
class GeoCodeException extends Exception {} | |
/********************************************************************* | |
* Display methods. | |
*********************************************************************/ | |
// Get the latest departure times for a specific stop, identified by stopID. | |
function getDepartureTimes(&$tropo, $stopID) { | |
$sql = "CALL GetDepartureTimesAndRoutesByStopID($stopID, ".DEFAULT_NUMBER_DEPARTURES.", DAYOFWEEK(CURDATE()))"; | |
$result = runQuery($sql); | |
while ($row = $result->fetch_assoc()) { | |
$tropo->say("Route ". $row["route_id"]."/".$row["route_long_name"].", Departs in: ".$row["min_leaving"]); | |
} | |
} | |
// Get the closest transit stop given a specific address. | |
function getClosestStop(&$tropo, $address) { | |
$geoXML = new SimpleXmlElement(geoCodeAddress($address)); | |
$coordinates = $geoXML->Response->Placemark->Point->coordinates; | |
$coordinatesArray = explode(",", $coordinates); | |
$sql = "CALL GetClosestStopsByLocation($coordinatesArray[1], $coordinatesArray[0], ".DEFAULT_ROUNDING_PRECISION.", ".DEFAULT_STOP_DISTANCE.", ".DEFAULT_NUMBER_STOPS.")"; | |
$result = runQuery($sql); | |
while ($row = $result->fetch_assoc()) { | |
$tropo->say($row["stop_id"]."/". $row["stop_name"].", Distance: ".$row["DISTANCE"]." miles"); | |
} | |
} | |
/********************************************************************* | |
* Helper methods. | |
*********************************************************************/ | |
// Geocode an address. | |
function geoCodeAddress($address) { | |
// Format address and URL. | |
$address = str_replace(" ", "+", $address); | |
$url = MAPS_LOOKUP_BASE_URL."?q=".$address."&output=".MAPS_LOOKUP_FORMAT."&sensor=".false."&key=".MAPS_API_KEY; | |
// Set up cURL call. | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
// Execute. | |
$output = curl_exec($ch); | |
$info = curl_getinfo($ch); | |
// Return results. | |
if($info['http_code'] != '200') { | |
throw new GeoCodeException(DEFAULT_ERROR_MESSAGE); | |
} | |
else { | |
return $output; | |
} | |
} | |
// Run an SQL query. | |
function runQuery($query) { | |
try { | |
$mysqli = new mysqli($_SERVER["TRANSIT_DB_HOST"], $_SERVER["TRANSIT_DB_USER"], $_SERVER["TRANSIT_DB_USER"], $_SERVER["TRANSIT_DB_USER"], $_SERVER["TRANSIT_DB_USER"]); | |
if (mysqli_connect_errno()) { | |
throw new Exception(DEFAULT_ERROR_MESSAGE); | |
} | |
$result = $mysqli->query($query); | |
if($result->num_rows > 0) { | |
return $result; | |
} | |
else { | |
throw new Exception(DEFAULT_NO_INFORMATION_MESSAGE); | |
} | |
} | |
catch (Exception $ex) { | |
throw new DatabaseException($ex->getMessage()); | |
} | |
} | |
// Instantiate a new Tropo object. | |
$tropo = new Tropo(); | |
// Get the incoming session information from Tropo | |
$session = new Session(); | |
// Access the initial text sent with the session. | |
$message = $session->getInitialText(); | |
try { | |
// If the user sent a stop number. | |
if(is_numeric($message)) { | |
getDepartureTimes($tropo, $message); | |
} | |
// If the user sent an address. | |
else { | |
getClosestStop($tropo, $message); | |
} | |
$tropo->renderJSON(); | |
} | |
// Handler for various database exceptions. | |
catch (DatabaseException $ex) { | |
$tropo->say($ex->getMessage()); | |
$tropo->renderJSON(); | |
} | |
// Handler for geocoding exceptions. | |
catch (GeoCodeException $ex) { | |
$tropo->say($ex->getMessage()); | |
$tropo->renderJSON(); | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment