
In this blog post, please find a lengthy list of tasks I performed over the past 8 months to complete my Senior Software Engineering Capstone Project. These tasks were reported at asynchronous weekly Standup “Discussions”.
I do not recommend reading the entire list, but a light skim may be intriguing 🤔👨‍💻👍.
- Performed “elevation” tests on physical devices (iPhone and Android), gathered data, and set time to perform another round of tests.
- Maintained a pre-alpha dependency of our project (SurveyKit Flutter package).
- Implemented “DrillEvent” model
- Implemented “DrillEvent.example()” constructor with example data
- Switched source of Pre- and Post-DrillSurveys to DrillEvent.example()
- Implemented “Confirm Drill Details” page [fig. 1]
- Implemented “During Drill” page while pair-coding with Jasmine [fig. 2]
- Implemented Navigator with basic app flow
- Made choice with Jasmine to not use “bloc” for state management
- Met with Project Partners and provided update on current status of the app
- Requested and gained permission to set up shared Google credentials for the project in order to be ready to start spinning up the cloud databases
- Helped Dean setup development environment
- Performed test of elevation on iOS and Android, making initial confirmation of consistently lower elevation output on Android and consistently correct elevation output on iOS [fig. 3, courtesy of Dean]
- Based on excellent feedback from Jasmine, tested Strava on my dev Android device to confirm the elevation offset issue we are facing can be coded away. See the screenshot of the correct elevation at my house (from Strava, ~100 m) vs incorrect elevation at the beach (from our prototype, ~ -30 m)
- Ran into a wall when setting up the cloud with the group, and emailed our project partner requesting they meet with us to enter payment details for the cloud
- When we did not receive a response for several days, explored an alternative: Using Firebase as an in route to Google Firestore (the initial service we wanted to use, but with Firebase there is a free tier that does not require payment details to be input)
- Did the extensive development setup/integration for Firebase with the group
- Got an example of passing data using the Firebase Firestore working
- Implemented the communications from the app to the cloud
- Populated the “DrillEvent” object with data from the cloud
- Completed the “Distribute” and “Instruction” aspects of the Midpoint Project Archive
- Emailed the completed Midpoint Project Archive to the project partners
- Got a more illustrative demo of the cloud working in the app
- Met with the project partners to present progress and instructed primary project partner on how to add payment details to the Firebase.
- Implemented the DrillResults model, along with methods to parse SurveyKit SurveyResults objects into JSON
- Worked with Jasmine to get her dev environment back up and running after breaking changes.
- Implemented the LocationTracker class which streams location data to the local SQLite database during the drill and then calls the previously implemented “CreateGpx” class to, well, create a gpx file.
- Implemented an Asymmetric KeyGen and Asymmetric Block Cipher based on RSA, Fortuna, and AES using the pointy_castle dart package to encrypt files before cloud upload and decrypt after cloud download.
- Integrated the location tracking functionality into the BasicDrillPresenter to run while a participant is viewing the “DuringDrill” page. (**This implementation is fragile due to lack of persistence.)
- Created Cloud Storage directory for DrillResults in Firebase (will be sorted by DrillEvent.id subdirectories, then user.id sub-subdirectories).
- Implemented upload of encrypted results from participant app to Cloud Storage in Firebase. (**This implementation is fragile due to lack of negotiation with Cloud/server for unique user id.)
- Implemented unique user id negotiation on DrillConfirm participant action.
- Found the easiest way to bulk export DrillResults, which turned out to be using Google Cloud Functions to access our Cloud Storage, then calling the cloud function via https, using a message signature to validate the identity of researchers
- Ensured RSA message signing is interoperable between current Dart codebase & new JS Cloud Function codebase
- Initialized Cloud Functions for our Firebase project
- Wrote a Cloud Function which verifies a DrillEvent Firebase Document ID is signed by an authorized researcher, and if so collects all the (encrypted) results that participant have uploaded to Cloud Firestore from the mobile app, zips these result files, and returns the zipped archive as a download.
- Hooked the above Cloud Function into a development (not production) https endpoint
- Initialized the Flutter Researcher Console, now that we are sure we can access our Firebase data via https calls to our serverless backend (Cloud Functions)
- Created an initial page for the Researcher Console which accepts a DrillEvent Firebase Document ID and a downloads location on the local machine.
- Implemented a function in the Researcher Console which signs the input ID using the relevant hardcoded private key, obtains the zipped archive of encoded result files via an https request to the Cloud Function endpoint, unzips the archive, decrypts and parses the files contained in the archive, and saves the resultant csv table and gpx files to the indicated downloads location on the local machine.
- Collected about a dozen “trajectories” using both Strava and our Evac. App (on both iOS and Android devices) to compare/contrast our new toolchain to the one previously use by our Project Partners
- Downloaded and decrypted all results
- Installed a VS Code extension which allowed me to view the “trajectories” within the IDE, superseding Dean’s task in issue #91 of generating .jpg files from all .gpx files.
- Compiled Android app to Emulator, resolving any errors which crop up
- Uploaded all .gpx “trajectory” results to Shared Google Drive
- Analyze the results of the “trajectories”, making initial screenshots and graphs
- Determined that offsetting the Android elevation likely will be worthless due to significant noise in data
- Began documentation of recommended feature additions for future teams working with this project
- Registered for Expo (In-Person & virtual)
- Worked with Jasmine on reflow of app (see her post for primary things) (previously named “DrillTaskMenu” in sprint plan)
- Code Review Dean’s work with package progress_indicator_button on invite_code_page.dart
- Analyzed the results of location data gathering to:
- Generate 3 distinct conclusions:
- Need an “Acquiring GPS Signal” Feature, like Strava’s
- Android output noisier data than iPhone, regardless of app
- Strava queries an API for elevation data, not the device sensor
- Generate slide deck based on results, visuals, and conclusions
- Generate 3 distinct conclusions:
- Presented results and conclusions to Project Partners with group
- Implemented new admin cloud endpoint which allows for the remote creation and upload of DrillEvents in Firestore, with unique (to system) 6 digit invite code generated and returned from endpoint.
- Completed “Wave swipe” animation to change screens at beginning of app flow
- Made a breakthrough on developing our Cloud Security:
- We only need to `read` from Firestore for the DrillEvent details
- We only need to `write` from Cloud Storage to upload results
- If only one or the other is active on a given service, a malicious actor cannot use it as free storage space (this was my main concern)
- Everything else is backend with admin permissions, so front facing security rules don’t apply
- Implemented the above restrictions as rules, meaning that our cloud services are no longer at risk of unauthorized use (it would serve no purpose) and can therefore remain live at all times. All data is public, not an issue if someone does read. They would need our private API keys anyways.
- Had the opportunity to learn more about Cloud Security when I realized we actually do have a `write` call to Firestore. It’s for a future feature (indicating to researchers that a given participant is ready for drill to begin)
- Implemented an exception to the Firestore rule for `participants` sub-collections to `DrillEvents` documents, allowing for specific `write`s to be performed
- Redefined overall data structure of the app to incorporate Tasks Page
- DrillResult is now DrillResults
- has a list of TaskResults (see below)
- DrillEvent is now DrillDetails
- has a list of DrillTasks
- DrillTasks model class is defined
- has enumerated DrillTaskType
- Survey
- AllowLocationPermissions
- WaitForStart
- PerformDrill
- Upload
- Travel
- has TaskDetails child
- has enumerated DrillTaskType
- TaskDetails model class extended for each DrillTaskType
- TaskResult model class extended for each DrillTaskType
- has Function builder which adds TaskResult to DrillResults
- TaskDisplay Widget created for each DrillTaskType
- Incorporated Waves transition into app
- Completed Tasks Page
- Has Oregon State brand asset icon (clipboard)
- TaskButton accomplished with ExpansionTileCard per Jasmine’s research
- has Function builders for TaskButton `onTap()`s for each DrillTaskType
- Jasmine’s refreshed InviteCodePage incorporated into app
- Created presentation for NSF SCC focused research group meeting
- Presented app to NSF SCC focused research group
- Worked to finish transcript for project demo video
- Recorded, edited, uploaded projet demo video
- Added logo to InviteCodePage
- Code Reviewed Dean’s recent Pull Requests
- Incorporated his AboutDialog into refreshed InviteCodePage, under new logo
- Incorporated his ProgressIndicatorButton into refreshed InviteCodePage
- Added Oregon State University logo (svg) to AboutDialog
- Added `onTap()` to InviteCodePage which removes focus from invite code entry box, thereby dismissing keyboard
- Changed keyboard back to numpad (on iOS doesn’t have “done” dismiss keyboard button, so had switched to full keyboard to alleviate user frustration)
- Rerecorded and uploaded video with above changes to app walkthrough
- Completed Virtual Expo Website
- Nearly completed project poster, working on final visuals for bottom right picture
- Created TelemetryTest DrillDetails which has only tasks which test “location tracking” functionality (no surveys, etc.)
- Performed new Telemetry Comparison Test at beach: Torrey Pines State Nature Reserve
- Completed Project Poster with new visuals from new Telemetry Comparison Test
- Submitted Project Poster for printing