The car rental market is notorious for being slow and inefficient; we set out to solve this problem by eliminating the need for human interaction and complicated UIs or forms. SwiftLift streamlines the car rental process with a simple and familiar UI (via Twilio) and minimal work on the user's end.
What it does
To use SwiftLift, the user must first fill out a short registration form (locally hosted webpage) with their name, phone number, credit card, and a SwiftLift password. Then, the process begins with a simple text to the Twilio phone number, for example, "I want to rent a car." SwiftLift then retrieves and lists all company cars within a 15 km radius, using the Smartcar API. The user can then ask for more detailed information about any car's current mileage, exact location, and cost. When the customer confirms their selection, the car is unlocked for them and they are free to use the rental car. Once the customer confirms over text that they are finished, they receive a message stating their total mileage and incurred cost. This money would be billed directly to the customer's credit card. The user can then log in to the webpage from earlier using their phone number and password to view a dashboard of all their past rides, including the time, distance traveled, start and end point, and total cost. The guiding principle of SwiftLift is to keep the UI and process as simple and clean as possible. Twilio provides a perfect paradigm for this, as texting is easy and familiar, and doesn’t even require installation of any new software.
Related to the project, we built a creative display of how interest in the current rental car market is distributed as opposed to big-name ride-sharing companies such as Lyft and Uber to visualize optimal transportation services in a given location.
How we built it
Tl;dr: it’s all Flask. Most of the project is written with Python and the Flask web framework. We used the Twilio API with Python + Flask and ngrok for our webhook to send and receive SMS communication. Once the Flask server receives the user’s request for a car, we sent a Smartcar API request (also with Python) to get vehicle.info(), vehicle.odometer(), and vehicle.location(). With the server set up, back-and-forth communication between Twilio and Smartcar is straightforward; the only overhead involved is having to bootstrap the Smartcar API’s auth_url (explained later). Once we got the texting portion working from requesting a rental car all the way to returning it, we created a simple webapp (with Flask yet again) so the user could register their phone number to their credit card and be billed accordingly. To do so, we utilized Flask’s ample support for user registration and login authorization. For data storage, we created a database using SQLAlchemy to create a database of “User” and “Trip” objects. The webapp creates a new User object whenever a new number is registered to the database, and a new Trip object associated with the User corresponding to the phone number whenever a text exchange occurs. With the database in place, the webapp just becomes a task of using Flask’s login authorization to fetch the respective User’s associated Trips and displaying them in the dashboard.
Challenges we ran into
- Initially, we tried to automate the Smartcar API’s authorization step because we knew the login credentials would be constant (the ‘company’ credentials). However, OAuth2, by design, is not meant to be programmatically authorized, as the program should not have access to the login credentials in the first place. Ultimately, we ended up bootstrapping the OAuth step by entering the credentials ourselves beforehand and leaving the server running, allowing the program to take over from there. -Because we wrote the Twilio/Smartcar end first, then separately wrote the webapp with the SQLAlchemy database, integrating the two ends involved many coding and logistical hurdles (e.g. conflicting Flask instances and virtualenvs, communication between instances). Ultimately we just decided to merge them both into the same python script so as to avoid tedious communication between directories--which was a major and time-consuming redesign, but ended up contributing to the organization of the code.
- One of the biggest problems we faced, however, did not have to do with code. It did not have to do with hardware, or software, or APIs. No, it was domain.com. We had heard the horror stories from others, but we foolishly disregarded their advice. Four website creation attempts leading to an “under review” status later (a twenty-four hour process), we’d had enough. After a thirty-minute call, an online chat session and a couple of emails later, we finally got the domain ruhungry4pi.com registered to our team. To actually access the site on the web, however, was an insurmountable problem. We learned that owning a domain name did not automatically qualify us to have the site hosted, so our site appears to be a spam site, despite the work put into the web design. After several more email and chat conversations, we’d spoken to somewhere between eight and nine representatives from domain.com. This challenge was never resolved, but we are simply choosing to use the preview function on the web development tool as a proof-of-concept.
- Lastly, and most importantly: coming up with such a killer name
Accomplishments that we're proud of
- Clean integration of the webapp and the Twilio service (though it was a struggle, see above)
- Using Flask’s login authorization to allow users to register their information and store it to a SQL database so all trips with SwiftLift are recorded and securely accessible
- Making a data visualization that looks like it could be on /r/dataisbeautiful
- Sticking to our original vision of keeping the user interface and experience as simple as possible
- Once again: the killer name
What we learned
What's next for Swift Lift
Some ideas, in order of increasing complexity:
- Geofencing the cars to a certain radius could be useful, so SwiftLift would ensure its cars all stay within a certain radius (probably would help logistically for a large-scale platform). All we’d need to do is set a “home latitude” and “home longitude” and draw boundaries the user cannot exit. We already use the user location to detect cars within a certain distance radius; implementing a geofence would just be this, but with slightly different parameters. -Currently, there is no payment API. There are many options available, notably Stripe or the PayPal API, but (ironically) due to monetary restrictions we opted not to include it in our prototype. Doing so would be very simple, as we already authorize user info and prompt them for their credit card info; it’d just be a function of working in some basic API calls
- Using Natural Language Processing in the interpretation of the user’s messages would make the program more flexible and less error-prone. Right now, the app looks for specific keywords (such as “rent” & “car”, “confirm”, and “done”) to know when the user makes a certain command. But it would be more flexible if the user could text whatever they wanted and the program figured out what they meant. However, this is definitely a non-trivial problem--NLP is no joke.