Jake Wright

Puft Mobile Application

An Android and iOS application designed to give the user full wireless control of the Puft air suspension management system via Bluetooth Low Energy, BLE, for stable and secure communication.

Platforms
Tools

The first step in the process was to define a set of high-level requirements for the application. Without going into too much detail, these boiled down to:

  • Quickly and easily connect to only genuine Puft devices via BLE.
  • Monitor air pressures throughout the system.
  • Trigger automatic adjustment of the vehicle to preset suspension pressures.
  • Allow independent manual adjustment of all four corners of the vehicle’s suspension.
  • Ability to configure the system to user specifications.

 

Once the first step in the process to complete, mock-ups could be drawn up to ensure the UI would be able to neatly and intuitively display that specified by the requirements. Despite the popularity of wireframing tools like Figma, as these mock-ups depicted only the main screen of the application, Adobe Photoshop was chosen for familiarities-sake, and in-turn the speed of the turnaround. Only the main screen and its relevant states, ‘adjusting’ and ‘editing’ presets, were intended to be mocked-up as this required the only custom UI elements throughout the design and therefore the most forethought before moving into implementation. The remaining screens depicting features such as configuration settings and device connections are only composed of Material UI elements and so can be built in the framework without graphical reference material.

The main screen is designed to implement requirements two, three, and four. From top-to-bottom: the ‘pressures bar’ allows the user to monitor all pressures in the system at a glance and animates to reveal preset pressures when requested, the ‘preset adjustment bar’ allows a user to request the pressures configured for a preset and either request an automatic adjustment of the system or edit the saved values, while the final ‘manual adjustment section’ allows the user to select individual corners of the vehicle they wish to inflate/deflate via a combination of the radio buttons and the directional pad.
The main screen is designed to be intuitive for those new to air suspension management, allowing the user to monitor all pressures in the system at a glance and modify the pressure/height across all corners of a vehicle’s suspension via either manual control, or by triggering one of five user programmable presets. 

Single tapping any of the five preset buttons triggers the pressures configured for that preset to be displayed on the screen, and the button morphs to signify both that the preset that is currently selected, and the remaining time available before that preset is automatically deselected via an animated countdown that takes the place of the buttons previous outline.

Tapping again while the countdown is in-progress requests the system to adjust to that preset. If the system is currently able to fulfil the request, the main screen will change to the ‘adjusting’ state, and will remain in this state until the adjustment has finished or the user chooses to cancel it.

Holding the preset animates the main screen into a new ‘editing’ state. In which the manual adjustment arrows become modifiers for the preset pressures shown on screen. The edit can be cancelled or confirmed at any time and the UI will return to its previous state.

Once the UI mockups were finalised it was time to decide on a development framework for the application. Not wanting to isolate potential users, it was essential to be able to deploy to both Android and iOS devices. There are multiple frameworks available that aim to provide the ability to ‘write-once, deploy anywhere’: Flutter, React Native, and Xamarin to name the main three that appeared consistently across searches. After writing some basic example applications in each, the decision to move forward using the Flutter framework seemed like a no-brainer. The similarity of its ‘Widget’ based UI when compared to that of the ‘Composable’ in Jetpack Compose provided a familiarity given my Android background that allowed rapid development timescales. Not only that, its vast library of available Dart packages for essential functionality such as Bluetooth and SQLite databases that supported both Android and iOS platforms without code changes made it entirely platform agnostic.

Implementing the fundamental functionality of the application first, a Bluetooth handler was created in order to connect to in-range Puft devices, decode their transmissions via a state-machine,, authenticate via the proprietary handshake process, and provide a method of encoding and sending messages from the mobile application. By employing the use of RxDart streams, once this handler was completed any part of the UI could be built by collecting from event driven streams constructed from decoded messages received from the connected management.

The first integration of this handler to the UI resulted in the ‘scan screen’ where the application scans for and displays only to devices advertising themselves as a genuine Puft product through the use of BLE GATT characteristics. Once selected by the user, the desired device undergoes a handshake process serving a dual purpose as both a 2 factor authentication process, and gathering of initial state. If determined to be legitimate, the user can then choose for the device’s unique details to be stored in a local SQLite database in order to automatically connect the next time the application is launched.

Through the combined use of StatelessWidget’s and StatefulWidget’s, the main screen was constructed to the specification laid out by the UI design mockups. Custom buttons are implemented using a GestureDetector.
Where state is to be shared between buttons, for example in the ‘manual adjustment’ section’s radio buttons, StatefulWidget wrapper classes and callbacks are used to pass user interactions to overarching business logic.
Where UI elements are to be updated continuously based on incoming events via the BLE connection to the management, for example in the ‘pressure bar’, StreamBuilders are used to automatically update values displayed to the user as they are received and parsed by the Bluetooth handler.

The application scans for and connects only to devices advertising themselves as a genuine Puft product through the use of BLE GATT characteristics. Once connected, the device’s unique details can be stored in a local SQLite database in order to automatically connect the next time the application is launched. 

The main screen is designed to be intuitive for those new to air suspension management, allowing the user to monitor all pressures in the system at a glance and modify the pressure/height across all corners of a vehicle’s suspension via either manual control, or by triggering one of five user programmable presets. For those more familiar with air suspension, advanced control options not offered by other brands are available through the configuration settings.

On the whole, the lifecycle of the development was a smooth process. Defining requirements prior to undertaking any further work ensured focus was kept on building a minimum viable product, cutting down development time. Bugs were encountered during the implementation, but Flutter’s ‘hot reload’ feature kept build time to a minimum allowing them to be fixed rapidly.