Arrive iOS SDK

Introduction

The Arrive iOS SDK enables developers to find and book parking using the Arrive platform. Contained within the SDK are network requests and responses that can be used to access the Arrive API via native implementations as well as fully fleshed out model objects. Each SDK function provides access to the API without the overhead of building an integration from the ground up.

You will need an API key to use with the SDK. If you do not already have one, send an email to partner-support@arrive.com to request credentials. There will be different API keys that correspond to production and sandbox environments respectively. In order to use each environment, the proper key will need to match.

Setup

We provide two options for consumers (dSYMs are included for all libraries).

  1. Manually download the SDK and use it as a fat library - https://s3.us-west-2.amazonaws.com/cdn.ios.parkwhiz.com/ios-sdk/{build_number}/Arrive.zip
    • Import files to project.
    • Include library/all libraries at Target → General → Frameworks, Libraries, and Embedded Content.
    • In some cases, the library should be Embed & Sign.
  2. By CocoaPods - Our latest build's podspec is stored at - https://s3.us-west-2.amazonaws.com/cdn.ios.parkwhiz.com/ios-sdk/ArriveSDK.podspec However, if for any reason a specific build is needed, it could be found at - https://s3.us-west-2.amazonaws.com/cdn.ios.parkwhiz.com/ios-sdk/{build_number}/ArriveSDK.podspec
@podspec_path = 'https://s3.us-west-2.amazonaws.com/cdn.ios.parkwhiz.com/ios-sdk/ArriveSDK.podspec'

For All Libraries (Core+BLE) -

pod 'ArriveSDK', :podspec => @podspec_path

For Arrive Core API -

pod 'ArriveSDK/Core', :podspec => @podspec_path

Initialize an Arrive instance

import Arrive

let apiKey = "<#yourApiKey#>"
let configuration = ApiConfiguration(clientId: apiKey, environment: .sandbox)
self.arriveApi = ArriveApi(with: configuration)

Token Management

before making any api calls, you need to get a public token.

Public Token

arriveApi.authenticationService.getPublicToken {
    response in
    print(response)
}

Authenticated Token

Most api calls require a user authentication. To get a user authentication, use the SDK's AuthenticationService to authenticate a user

arriveApi.authenticationService.authenticateUser(email: "<#username#>", password: "<#password#>") {
    response in
    switch response {
    case .success(let authorization):
        print(authorization)
    case .failure(let error):
        print(error)
    }
}

The authentication token is automatically stored and refreshed after a successful login api call is made. You can check the users logged in state:

arriveApi.authenticationService.isUserAuthenticated

Sample Calls

Get Locations

API reference

let coordinates = Coordinates(lat: 41.879072, lng: -87.6448557)
arriveApi.locationService.getLocations(near: coordinates, within: 0.5) {
    locations in
    ...
    //work with the returned array of locations
    ...
}

Add a Vehicle

API reference

arriveApi.vehicleService.addVehicle(plateNumber: "1B5 2R9",
                                    state: "CA",
                                    nickname: "The pickup truck",
                                    isDefault: true
) {
    vehicle in
    ...
    //work with the returned vehicle
    ...
}

Get Quotes

API reference

To search for parking around a geographic location, create a search (ParkingSearch) and use an instance of the ParkingSearchService from the SDK to execute the search.

Note: Parking searches only require a public token

let search = ParkingSearch.center(Coordinates(lat: 41.879072, lng: -87.6448557))
arriveApi.parkingSearchService.getQuotes(search: search) { (quotes) in
    ...
    //work with the returned array of quotes
    ...
}

Get Ticket associated with a Booking

API reference

Note: You must pass in the booking's original authorization code. The authorization code can be found on the Booking model.

arriveApi.bookingService.getTicket(bookingId: 123, authorizationCode: "abc123") { result in
    switch result {
        case .success(let ticket):
            //work with the returned ticket
        case .failure(let error):
            //error
    }
}

ArriveBLE Docs

ArriveBLE gives the ability to interact with Flash gates through the device's CoreBluetooth. It is a standalone framework, but parts of its logic have dependencies in Arrive/Core SDK.

Every file that needs to use ArriveBLE logic, must import it.

import ArriveBLE

Enable Monthly

Initialize a BLEGateManager instance

Create a BLEGateManager and conform to its delegate - BLEGateDelegate. A BLEGateManager requires a BLEGateConfigurations object to configure the manager. Use passType: .monthly.

import ArriveBLE

class SomeClass: BLEGateDelegate  {
    // ...
    lazy var bleConfig = BLEGateConfigurations(passType: .monthly)
    lazy var manager = BLEGateManager(with: bleConfig, delegate: self)
    // ...
}

Start by registering the device associated with the user's Flash monthly account. The user can only register the phone number of whatever is tied to the SIM card in the phone. Follow the code below to bootstrap the onboarding process.

Start the registration process by calling register:

// ...
manager.register(self)
// ...

Note that register takes a UIViewController. This is required to present the MFMessageComposeViewController to the user in order to send a text message to associate the phone number with the current device.

  • If the customer is registered in the system, and has at least one monthly parking location, gateSuccess will be invoked with BLEGateMessage equaling .authentication.
  • If no monthly locations are associated with the phone number, or the account does not exist, gateFailure will be invoked with an .authentication error. Use this to determine if the user has monthly parking enabled or not.
  • If the user cancels the registration process by dismissing the MFMessageComposeViewController, gateFailure will also be invoked with an .authentication error.

Open Gate

First, the device and customer must be registered - see Enable Monthly.

To open a gate within BLE range, ensure that the gate is ready, then call openGate():

if isReady {
    manager.openGate()
}
  • If the gate successfully opens, the gateSuccess function of BLEGateDelegate will be invoked.
  • If the gate fails to open, or another error occurs, the gateFailure function of BLEGateDelegate will be invoked.

Start/Stop Scan

Initializing a BLEGateManager will automatically start scanning for gates, but it is possible to start scanning manually:

manager.startScan()

To stop scanning for gates, call:

manager.stopScan()

Get QR Code

Kiosks allow for scanning of a QR code to vend monthly customers. To generate the QR code string, ensure your passType for BLEGateManager is .monthly. After the device is registered (see Enable Monthly), the QR code is stored permanently, and accessible as a property on the manager from there on out:

gateManager.qrCode
  • If the current passType is not .monthly, qrCode will be nil.
  • If the device has not been registered, qrCode will be nil.

Get Monthly Parking Status

Altough it is not possible for a customer register for monthly parking without having at least one monthly location, it may be useful to check the monthly parking status before/after registration:

gateManager.isMonthlyRegistered

Monthly Pass Sample Code:

import UIKit
import ArriveBLE

class ViewController: UIViewController, BLEGateDelegate {
    lazy var bleConfig = BLEGateConfigurations(passType: .monthly)
    var manager: BLEGateManager!
    private var isReady = false

    // MARK: - Proposed Methods

    override func viewDidLoad() {
        super.viewDidLoad()
        manager = BLEGateManager(with: bleConfig, delegate: self)
    }

    @IBAction func register(_ sender: UIButton) {
        if !manager.isMonthlyRegistered {
            manager.register(self)
        }
    }

    @IBAction func openGate(_ sender: UIButton) {
        if isReady {
            manager.openGate()
        }
    }

    // MARK: - BLEGateDelegate

    func gateIsReady() {
        // Gate is discovered and ready.
        isReady = true
    }

    func gateSuccess(_ status: BLEGateMessage) {
        // Authenticated successfully, or gate opened.
        switch status {
            case .authentication:
                print("Authenticated successfully!")
            case .opened:
                print("Opened gate successfully!")
            default:
                break
        }
    }

    func gateFailure(_ error: BLEGateError) {
        // Issue with gate or authentication.
        switch error {
            case .authentication:
                print("User has no monthly locations!")
            default:
                print("Other error occurred.")
        }
    }
}
Last updated March 10, 2022