Mobile SDKs

The following section describes how to integrate the mobile SDKs and the main methods that are required to operate with Harbor Lockers.

Integrate iOS SDK

The iOS SDK is available through Cocoapods. Add the following line to your Podfile:

pod "HarborLockersSDK"

You can also specify the version of the SDK, for example:

pod "HarborLockersSDK", '1.0.10'

Then run pod install to install the pods. To start using the HarborSDK, you must import it into your files

@import HarborLockersSDK

The iOS SDK requires Bluetooth access, in your info.plist add the following entries:

  • NSBluetoothAlwaysUsageDescription -> A description of why your app needs access to Bluetooth.

  • NSBluetoothPeripheralUsageDescription -> Same description as before. This is needed only if your app targets iOS 12 or earlier.

Integrate Android SDK

The Android SDK is distributed through Jitpack. It can be integrated through gradle, maven, sbt, and leiningen as following:

In your root build.gradle, at the end of repositories, add the following

allprojects {
  repositories {
    maven { url '' }

Then add the dependency

dependencies {
  implementation 'com.github.Harbor-Lockers:harbor-android-sdk:<version>'

Add the following entries to your AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

The android:required value in the last line depends on wether you want your app to be listed to users that doesn’t have BLE support on their devices. This might be the case if all your app does is control lockers with Harbor SDK and can’t do anything useful without BLE support.

Using the SDK

Once you have the SDK integrated there are a series of steps you need to follow to connect to a tower and open a locker.

Most of the data required by the SDK are provided by your server. Your Backend is responsible for the following:

  1. Define the location ID, tower ID, and locker ID you’ll interact with.

  2. Provide you with an SDK authentication token.

  3. Provide you with the session token information so you can connect to the tower.

  4. Provide you with the payload and payload auth to control your assigned locker.

In addition to that, your backend will be responsible for managing the lockers assigned to your account.


You might need to integrate other API calls to release lockers, change assigned locker, or mark a locker as used. Check the API integration sections for details.

Initialize the SDK

The SDK is a singleton class, so you can access it as follows:

[HarborSDK shared]

Before connecting to a tower, you’ll need to initialize the SDK, set the Environment you want to use, set the Harbor Access Token, and start looking for nearby towers.

The first thing you need to do is to set the HarborSDKDelegate and, if needed, configure a HarborSDKConsole to get the logs (you might want to do this only in debug mode)

The HarborSDKDelegate will notify you about nearby towers found through BLE, while the HarborSDKConsole delegate might be helpful for debugging.

public protocol HarborSDKConsole {
  func printToConsole(_ string: String)

public protocol HarborSDKDelegate {
  func harborDidDiscoverTowers(_ towers: [Tower])

Now set the environment you want to use with the setEnvironment function. This will allow you to use either DEVELOPMENT or PRODUCTION envs (defined in an enum) or a custom URL if you get a dedicated environment set for you.

The last step to initialize the SDK is to set the SDK Access Token. For this, you’ll need the SDK Access Token provided by your server. A boilerplate initialization code looks like this:

[[HarborSDK shared] setDelegate:self];
[[HarborSDK shared] setOutputConsole:self];
[[HarborSDK shared] setEnvironment:EnvironmentDevelopment];
[[HarborSDK shared] setAccessToken:token];

Connect to a Tower and Establish a Session

Now that the SDK is configured, you can search for nearby towers and try to connect to them.

When you get notified about discovered towers, you might either show a list of the towers to connect to or if you already know which tower to connect, you can automatically connect to it.

To search for nearby towers, call the startTowersDiscovery function. Note that you’ll need to set up the HarborSDKDelegate before getting notified about the discovered towers.

To connect to a tower, use the connectToTower function. This function receives a Tower object, which you receive in the HarborSDKDelegate methods

The connectToTower function has a completion callback that notifies you if you got connected to the tower correctly.

Here’s an example that automatically connects to a tower assuming you are looking for tower with ID 0000000000000010. This example is written in Objective-C, but it should be easy to translate to other languages.

- (void)harborDidDiscoverTowers:(NSArray<Tower *> *)towers {
  for(Tower * tower in towers) {
    if ([tower.towerId.hexString isEqualToString:@"0000000000000010"]) {
      [[HarborSDK shared] connectToTower:tower completion:^(NSString * _Nullable name, NSError * _Nullable error) {
        if([name length] > 0) {
          // Tower connected successfully
        } else if(error != nil) {
          // An error occurred

Once you’re connected to a tower, you need to establish a session to start interacting with it. To establish a session, use the establishSession function to create a pickup or drop off session in the tower.

The establishSession function receives the following parameters:

  • towerId: 8 bytes containing the towerID.

  • duration: How long you expect the session to last (in seconds). Note that if you don’t interact with the tower in more than a minute, your session will be closed by the tower.

  • sessionPermissions: Indicates the permission level for your session. Most of the third party developers will only be able to establish pickup and drop off sessions.

  • completionHandler: Callback to handle the results.

Interacting with the Tower

Once you’re connected to a tower and have a session established. You can start interacting with it to open the lockers.

After you establish a session, the SDK handles the synchronization between Harbor servers and the tower itself. This will trigger several BLE commands that you might see in the logs. You don’t need to wait until this process is completed to interact with the tower, but if you want to see clearer logs while developing your application, you might want to wait until the sync is done.

Open a locker

Your server must be integrated with the Harbor API to do this. Your server will request a payload and a payload auth to Harbor that will contain the encrypted data required to open your locker. The details on how to do this are covered in Make a delivery, so we assume you already have the payload and payload auth to be sent to the tower.

Use the sendOpenLockerWithToken function to open a locker. This function receives the following parameters:

  • payload: encrypted payload containing the data about the locker to be opened.

  • payloadAuth: authentication packet to validate the authenticity of the payload.

  • completionHandler: callback indicating if a locker was opened (providing locker ID), or if some error happened (for example the locker wasn’t found).

After a locker was opened, the tower remembers the last opened locker, which is the one considered for other commands such as reopenLocker, checkLockerDoor, or revertLockerState.

Check Locker Door

After a locker was opened, you can check the state of the door using the sendCheckLockerDoor function.

The completion handler will notify you if the door you just tried to open is open or close. If no door was opened during your session, the completion handler will return an error.

You can use this method for 2 things:

  1. To confirm the door was opened (as it might fail to pop open).

  2. To get notified when your user closed the locker door, and move the app to the next screen/state.

Reopen Locker Door

Another thing you might want to do is to reopen the lastly opened locker. This might be useful if your user forgot to add something inside, or if the door was accidentally closed before the user completed the drop off.

Call the sendReopenLocker function to reopen the same locker that was lastly opened in your session. If no door was opened during your session, the completion handler will return an error.

Terminate a session

After you’re done interacting with the tower, you must terminate your session. This will trigger some processes both in the SDK and the tower, that are important to keep consistency in the system.

Since the tower doesn’t have an internet connection, your application (through the SDK) is a key piece to keep it updated and synchronized with the Harbor backend.

Call the sendTerminateSession function to terminate a session. This function allows you to specify an error code and message, in case the session is being terminated prematurely for some reason. This code and message will be helpful for us in case we need to debug your issue.

The sendTerminateSession function receives the following parameters:

  • errorCode: A code to log to the terminate session event on the device side. Maybe 0 if no error occurred.

  • errorMessage: An optional message to store in the error event log, in case there was an error.

  • completionHandler: A callback containing a boolean indicating if the session was terminated successfully, and an optional error in case something unexpected happened.

Terminating the session triggers a sync process on the SDK, which is important to notify Harbor that the locker was used and to update the state of the tower.

This covers the basic use of a Harbor Tower through the SDK.