Open barbeau opened 7 years ago
That open311-mobile
project looks promising, but it's licensed under GPL 3, which is unfortunately incompatible with Apache 2.0: https://www.apache.org/licenses/GPL-compatibility.html
I'll go do some hunting and see what I find. Thanks for the detailed writeup!
Yeah, GPL is one reason we built our own Apache-licensed version for Java.
Unfortunately I couldn't find any Objective-C or Swift Open-311 libraries, besides this very unfinished attempt and the open311-mobile GPL project. @aaronbrethorst have you played around with Google's Java-to-objC transcoder? Maybe this could be used in combination with CUTR's open311 client. I've never used it & I can't imagine that it would work perfectly (for one thing, how would it handle the Jackson dependency?) but perhaps it would be better than writing a new library from scratch.
@sdjacobs I'm certainly willing to take a look, but I'd be surprised if it saved us a lot of time. Most of the effort on this will be around building the UI, and the transcoder can't do that. I think what probably would be most helpful for iOS would be a document outlining how the Android interfaces with the server and how it renders its UI.
I'm going to put together a quick design doc outlining the iOS work.
The entire OBA Android implementation for the new issue reporting flow is implemented in this package: https://github.com/OneBusAway/onebusaway-android/tree/master/onebusaway-android/src/main/java/org/onebusaway/android/report
The majority of Open311-specific UI logic is in this Fragment: https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/java/org/onebusaway/android/report/ui/Open311ProblemFragment.java
Here are a few items on Android that took us a while to figure out, but shouldn't be difficult to implement if you follow the approach we settled on:
If all issue categories are transit-related, then they should fall under a single "transit" category:
There is a concept of a group
and keywords
field for Open311 services - the "right" way to do this is for the group
field to be set to transit
for transit issues, and all other issue group
fields be set to null (or something else). We've implemented this in Android. However, SeeClickFix hasn't implemented support for assigned groups to issue categories yet, so we're stuck with hacky heuristic-based matching for the current implementation - we've implemented this as well if all group
fields are null
. We look at the titles of the issue categories, and if there is >= 4 categories that have "transit-related" words in them, we assume all categories are transit related. Heuristics matching code is called at https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/java/org/onebusaway/android/report/ui/InfrastructureIssueActivity.java#L787, and is implemented in a utility method at https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/java/org/onebusaway/android/report/ui/util/ServiceUtils.java#L30.
Heuristics keywords we're using to identify "stop" related categories are at: https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/res/values/arrays.xml#L190:
transit
\u0020bus\u0020
stop
route/trip is missing
Note the space unicode characters around "bus" - \u0020bus\u0020
(otherwise this matches to "business").
EDIT Jan 2 2018 - We're now using passenger
as a stop heuristic keyword too (see https://github.com/OneBusAway/onebusaway-android/issues/826).
Heuristics keywords we're using to identify "trip (i.e., arrival time)" related categories are at: https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/res/values/arrays.xml#L197:
arrival
schedule
Unit tests that make sure the heuristic-based matching works with the current HART/PSTA deployments by querying the actual SeeClickFix API there is at https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/androidTest/java/org/onebusaway/android/io/test/ReportProblemOpen311Test.java#L40.
We automatically populate stop_code
field in the UI - this should again be simple with use of keywords
field, but SeeClickFix doesn't support it. So, more heuristics matching based on issue category name. Heuristics matching code for this is at https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/java/org/onebusaway/android/report/ui/util/ServiceUtils.java#L200, and uses the keywords listed at https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/res/values/arrays.xml#L202:
stop
id
bus
We have a OBA info that "anonymous" issues are reported under - For Open311 servers we allow the user to choose to remain anonymous and not enter first name, last name, email, and phone number. However, these fields must be populated for the server to accept a report. In that case, we submit the issue under an OBA name and email. Strings we use for this anonymous submission are at https://github.com/OneBusAway/onebusaway-android/blob/master/onebusaway-android/src/main/res/values/donottranslate.xml#L170:
OneBusAway
User
issue-report@onebusaway.org
We add metadata in bottom of issue description before issue is submitted to server - We allow the user to type in their summary of the issue, and then we append metadata to the bottom of the description so it's easier for the agency to see more info.
Here's what we append for arrival time problems:
---------------------
service_date=01-03-2017;
agency_name=Hillsborough Area Regional Transit;
gtfs_stop_id=Hillsborough Area Regional Transit_1688;
stop_name=30th St @ Annie St;
route_id=Hillsborough Area Regional Transit_18;
route_display_name=18;
trip_id=Hillsborough Area Regional Transit_235407;
trip_headsign=South to UATC/Downtown/MTC;
predicted=true;
vehicle_id=Hillsborough Area Regional Transit_1020;
vehicle_location=28.080591201782227 -82.43084716796875;
schedule_deviation=8.000 min late;
stop_arrival_time=05:16 PM;
stop_departure_time=05:16 PM;
Here's what we append for stop problem reports (basically, anything that's not an "arrival time" report):
---------------------
gtfs_stop_id=Hillsborough Area Regional Transit_7582;
stop_name=56th St @ Mission Hills Av;
Please keep the exact same field names - we'd like this to be machine-readable so we can do bulk analysis of data
You can see example issues that have been submitted via OBA Android by looking any any recent issue in Hillsborough County: https://seeclickfix.com/hillsborough-county-fl
...as well as any issue in Pinellas County that has been assigned to "PSTA", such as: http://seeclickfix.com/issues/3131124-psta-bus-stops
That's what I can think of off the top of my head. Let me know if you have any questions when you start digging in, and I'll post again if I think of anything else.
One edit for 3) above - we autopopulate the stop_code
(not stop_id
) in the UI based on the stop the user tapped on. stop_id
is in the metadata that gets tacked onto the bottom of the report, but stop_code
is the user-facing "Stop ID" that gets autopopulated in the UI. This is especially important for PSTA, as their stop_ids
and stop_codes
are different. For HART and many other agencies, stop_id
and stop_code
are the same.
Current thoughts:
Users can reach the new Open311 UI options by opening a stop, which is where they are used to reporting problems with their stops and vehicles today already. They can also access the full "Send Feedback" experience from the Info tab which will display a modal view controller with four options, as seen in the accompanying screenshots.
If the current region has an Open311 server defined, use the new Open311 client library; otherwise use the existing "Report a Problem" UI.
A modal is presented. This page goes out to the server and hits the "Discover Services" endpoint, retrieving a list of available services, and populates a table based on the list.
The user's entry point is through a single item on the Info tab entitled "Send Feedback". When the user taps Send Feedback, they will see the UI modeled in the mockup below:
Unlike Android, a piece of static text at the bottom of the view will tell them what region they have selected and provide them with a button to change their region if need be. The Update Region button will open the region picker UI.
A table of all agencies in the current region with tappable options for sending email and making phone calls, modeled after Android.
A map with stops is displayed. The user selects a stop (or another point as they see fit). A new page is pushed onto the stack. This page goes out to the server and hits the "Discover Services" endpoint, retrieving a list of available services, and populates a table based on the list.
The table in both examples includes options like:
This table's contents are grouped into two sections (Transit and Other) based upon the same heuristics that Android uses.
Selecting one of these options pushes a new page onto the stack. This new page contains a dynamically constructed form representing the selected service. For instance, for "Wifi on bus isn't working", the following form elements are dynamically created from the service data:
Static Text: "Hillsborough Area Regional Transit (HART) monitors SeeClickFix from 8am to 5pm on regular business days for non-emergency conditions. Please call 911 for emergencies." Number entry: "What is the 4- digit bus number? (This can be found above the interior windshield.)"
Forms that include "Stop ID" will have that field automatically populated by the stop ID that was selected from the map, if a stop was selected.
Plus, a series of standard fields that are included with every form:
Displays the email feedback UI.
OBAClassicDepartureView
s to the form view controller and populate stop_info based on its selectionUpdated version of the above task breakdown: https://docs.google.com/document/d/13hZwNKAWit0Uouv1_5qF1RPsfAs2tXi6K5bMH4e7bD4/edit?usp=sharing
We recently improved the feedback process in OBA Android to better channel feedback to different locations based on the type of feedback. HART has expressed interest in implementing something similar on iOS, so I wanted to capture some of the current Android implementation details here as a jumping off point.
Details on the OBA Android UI are here: http://www.slideshare.net/sjbarbeau/onebusaway-new-issue-reporting-flow-in-onebusaway-android
After tapping on "Send feedback" in main menu, the first time the user does this they are asked to confirm their region (to prevent against feedback going to the wrong region, and to intercept "wrong region" feedback). On Android we ask "Are you in X"? If yes proceed to feedback, if no direct to region selection setting. We save this acknowledgment and reset it if the region is changed.
After the user confirms the region at least once, when they tap on "Send feedback" the following categories are shown (see slide 2 in above presentation for screenshots):
open311Servers
array in Regions API, then direct feedback to Open311 endpoint. Otherwise, direct to legacy stop/trip problem reporting APIs for the region. Slides 4-8.open311Servers
array in Regions API, then direct feedback to Open311 endpoint. Otherwise, direct to legacy stop/trip problem reporting APIs for the region. Slides 4-8.android-app@onebusaway.org
Implementing most of the above is fairly trivial - however, the Open311 submission would require a decent amount of UI work. This is because the problem reporting UI is dynamically driven by data in the Open311 server response. In other words, an agency defines the issue category types (including whether the answer is text, multiple choice, checkbox, etc.), and this is dynamically discovered from the Open311 server REST API (a lat/long for the reporting location is sent to the Open311 server, and it responds with valid categories for the location). There are also some UI design decisions that are driven because for this - you need the user to pick a stop or location before they can choose the type of issue they want to report.
We wrote our own Open311 Java client, but I'm hoping there are existing iOS-compatible libraries (Objective C or Swift) that could be leveraged. Here's what I could find from some quick Googling (feel free to add more):
Here's a general list of OSS related to Open311: