Skip to content
Pooja Gulabchand Mishra edited this page Feb 14, 2023 · 61 revisions

Welcome to the Mist vBLE iOS SDK wiki!

Table Contents:
Overview
System requirements
App Permissions
Installation using Cocoa-pods
Installation - Manually using framework
Integration steps

Sample app Reference
Documentation for MistSDK callbacks
Release Notes

Overview

Mist SDK will provide you the indoor blue dot experience using Mist’s 16 vBLE antenna array Access point. Using this SDK you will know where the user is and can provide the proximity-related notification using Mist patented vBeacon technology.

MistSDK uses a dead reckoning approach to calculate the user’s current position by using a previous position and advancing that position based on known and estimated speeds over elapsed time. Meaning DR is designed to take all location information available that a user had when connected and work the same as though the client is connected, even when experiencing a disconnect or blimp in the connection.

Mist SDK(iOS) is compatible with Objective C and Swift 4.2 or later.

Mist ios vBLE SDK :
1. Zone notifications.
2. Virtual beacon notifications.

System requirements

Software:

  1. Xcode: 12 or later.
  2. iOS deployment Target: 13.0 or later.
  3. Access to Mist Account
  4. Mobile SDK secret.

Hardware:

  1. Mist Access Point with BLE support.
  2. iPhone/iPad device. Mist SDK cannot be tested on the Xcode simulator.

App Permissions

MistSDK will require your ios App to access the device's location, Bluetooth, accelerometer, and internet permissions. You need to add the following keys to Info.plist file in your project:

  1. Location: NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription key is required to access location(only for background mode).
  2. Bluetooth:NSBluetoothAlwaysUsageDescription is required to allow the ability to connect to Bluetooth peripherals. =

 <key>NSLocationWhenInUseUsageDescription</key>
 <string>(Insert description)</string>
 <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
 <string>(Insert description)</string>
 <key>NSBluetoothPeripheralUsageDescription</key>
 <string>(Insert description)</string>
 <key>NSBluetoothAlwaysUsageDescription</key>
 <string>(Insert description)</string>

Installation using Cocoa-pods

Follow the steps to integrate Cocoa-Pod in the Xcode project or [Refer CocoaPods Getting Started guide]:

  1. Open the terminal and change directory to your project folder, and create and initialize Podfile using the commands below.
$ cd ./project_folder_path
$ sudo gem install cocoapods
$pod init
  1. Open the Podfile with a text editor and add the component to the pod file.

For Mist SDK using DR, use the following:

target 'MyApp' do
   #Pods for MyApp
    pod 'MistSDKDR'
end
  1. Go back to the terminal and Run <$pod install> in your project directory
$pod install
  1. Open MyApp.xcworkspace and build.
  2. Add import MistSDK in swift OR #import <MistSDK/MistSDK.h> in Objective c to get started.

Note: Mist SDK DR version is not compliant with bitcode. You need to set BitCode -> Enable = No in the build setting of your XCode Project.

Installation - Manually using the framework

  • For the latest SDK version, download the MistSDK.framework.
  • Drag and drop the MistSDK.framework in the project file.
  • In your Xcode project file add MistSDK.framework to Targets > General > Framework, Libraries and Embedded contents > select Embed and Sign.
  • Add import MistSDK in swift OR #import <MistSDK/MistSDK.h> in Objective c .

Integration Steps:

Enroll device using Mobile SDK secret:

  1. Get Mobile SDK secret from Mist Web Portal:
    Get the Mobile SDK Secret from the following path: Mist Login -> Organization -> Mobile SDK -> secret. [Refer FAQs - where can I find my secret key?]

  2. Enroll your device with Mobile SDK secret:
    a. Use the MobileSDK secret to enroll your device in the Organization using MSTOrgCredentialsManager. (Refer to Objective C/Swift Code below).
    b. Once enrolled, you will receive org_id and secret token from the response required to initialize MSTCentralManager.
    c. Please enroll the device only once and save the received secret token in memory.
    d. To limit the effects of compromised secret tokens, Mist SDK auto refreshes the received secret token after every 30 days. Please read more in the error handling section below.

//Objective c
[MSTOrgCredentialsManager enrollDeviceWithToken:@"(Mist Portal SDK secret)" onComplete:^(NSDictionary *response, NSError *error) {
        NSLog(@"name %@", [response objectForKey:@"name"]);
        NSLog(@"org_id %@", [response objectForKey:@"org_id"]);
        NSLog(@"secret %@", [response objectForKey:@"secret"]);
	}];
//Swift
MSTOrgCredentialsManager.enrollDevice(withToken: "(Mist Portal SDK secret)", onComplete: { response, error in  
        	guard error == nil, response != nil, let env = secret.first else {
            	print("Error: Cannot enroll devices to organization. \n\(String(describing: error))")
            	return
        	}      
                guard let response = response,
            		let name = response["name"] as? String,
            		let org_id = response["org_id"] as? String,
            		let secret = response["secret"] as? String else {
                	print("Error: Cannot retrieve org or secret from org enrollment")
            	return
        	}
})

Initialize Location Manager (MSTCentralManager)

MSTCentralManager object is used to configure, start, and stop the Location updates. Initialize this object with OrgID and secret token received on device enrollment.

MSTCentralManager adopts MSTCentralManagerDelegate protocol and provides you the indoor location events. Implement this protocol in your class.

//Objective c
self.mstCentralManager = [[MSTCentralManager alloc] initWithOrgID:orgID AndOrgSecret:orgSecret];
self.mstCentralManager.delegate = self;
[self.mstCentralManager setAppState:[[UIApplication sharedApplication] applicationState]];
//Swift
self.mstCentralManager = MSTCentralManager(orgID: org_id, andOrgSecret: secret)
self.mstCentralManager?.delegate = self
self.mstCentralManager?.setAppState(UIApplication.shared.applicationState)

Set Cloud Environment

The cloud environment is identified based on the first char of the Mobile SDK secret obtained from the Mist web Portal.

self.mstCentralManager?.setEnviroment(env.uppercased())

Start and Stop Location Manager (MSTCentralManager)

  • startLocationUpdates: To start receiving location update use the code below.
//Objective c 
[self.mstCentralManager startLocationUpdates];
//Swift
self.mstCentralManager?.startLocationUpdates()
  • stopLocationUpdates: To stop receiving location update use the code below. This method is called whenever you no longer need to receive location events.
//Objective c 
[self.mstCentralManager stopLocationUpdates];   
//Swift
self.mstCentralManager?stopLocationUpdates()

Get Map information

You can get the map detail of your current map from the object MSTMap. MSTMap provides you the mapId, mapName and mapURL to render the map on the device. ‘didUpdateDRMap’ callback is used to get the map detail whenever a new map is available while switching floor and site.

MSTMap object contains the following variable:

  • mapName
  • mapId
  • ppm: Pixel per meter is the map scale in Mist Universe.
  • mapType: MapTypeIMAGE (.IMAGE)
  • mapURL
  • mapWidth, mapHeight
  • siteId: Site id for that map
  • orientation
//objective-c
-(void)mistManager:(MSTCentralManager *)manager didUpdateDRMap:(MSTMap *)map at:(NSDate *)dateUpdated{
    if(map != nil)
    {
        self.ppm = map.ppm;
        if (self.currentMap.mapId != map.mapId) {
            self.currentMap = map;
            [self addFloorMap:self.currentMap.mapURL];
        }
        else{
            [self addFloorMap:self.currentMap.mapURL];
        }
    }
}
//Swift
func mistManager(_ manager: MSTCentralManager!, didUpdateDRMap map: MSTMap!, at dateUpdated: Date!){
DispatchQueue.main.async {
            guard let newMap = map, let mapURL = map.mapURL, newMap.mapType == .IMAGE else {
                return
            }
            self.ppm = newMap.ppm
            if let previousMap = self.currentMap {
                if previousMap.mapId != newMap.mapId {
                    self.currentMap = newMap
                    self.addIndoorMapView(url: mapURL)
                }
            } else {
                self.addIndoorMapView(url: mapURL)
            }
        }
}

Get Location Updates

The following callback returns location updates of the user device in (X, Y) measured in meters from the map origin. Mist Snapped.X and Snapped.Y, Latitude, and Longitude coordinates are available from the drInfo dictionary.

Note: Please use Snapped X and Y to get better location accuracy.

//Objective C
 -(void)mistManager:(MSTCentralManager *)manager didUpdateDRRelativeLocation:(NSDictionary *)drInfo inMaps:(NSArray *)maps at:(NSDate *)dateUpdated {
        //location update in X,Y using DR Snapped
        double sX = [[[drInfo objectForKey:@"Snapped"] objectForKey:@"X"] doubleValue];
        double sY = [[[drInfo objectForKey:@"Snapped"] objectForKey:@"Y"] doubleValue];
        double sLat = [[[drInfo objectForKey:@"Snapped"] objectForKey:@"Lat"] doubleValue];
        double sLon = [[[drInfo objectForKey:@"Snapped"] objectForKey:@"Lon"] doubleValue];
        double speed = [[[drInfo objectForKey:@"Snapped"] objectForKey:@"Speed"] doubleValue];
        // using the MSTPoint
        MSTPoint *sPoint = [[MSTPoint alloc] initWithX:sX andY:sY];
  } 
   //Swift
   func mistManager(_ manager: MSTCentralManager!, didUpdateDRRelativeLocation drInfo: [AnyHashable : Any]!, inMaps maps: [Any]!, at dateUpdated: Date!) {
        print(drInfo!)
        guard let drInfo = drInfo,
            let snapped = drInfo["Snapped"] as? [String : Any],
            let sX = snapped["X"] as? Double,
            let sY = snapped["Y"] as? Double,
            let sLon = snapped["Lon"] as? NSNumber,
            let sLat = snapped["Lat"] as? NSNumber,
            let speed = snapped["Speed"] as? NSNumber else {
                print("Error: drInfo empty")
                return
        }
        
        DispatchQueue.main.async {
            let sPoint = MSTPoint.init(x: sX, andY: sY) // location update in X,Y using DR Snapped
            sPoint?.sLon = sLon
            sPoint?.sLat = sLat
            sPoint?.sSpeed = speed
            if sPoint != nil{
                self.updatePoint(point:sPoint!)
            }
        }
    }

drInfo Json Response :

{
  "Snapped": {
    "Lat": 37.2950, 
    "Lon": -122.0325,
    "MapId": "2e8b48e5-2b94-422f-84c3-1722bf9baad4",
    "Speed": 0.7509392410618689,
    "X": 16.49580083355138,
    "Y": 22.88201353189894
  }
}

Set Latitude and Longitude:

To get the accurate lat/long values, get 3 points of interest on the Mist map(typically, corners of the map) and get the associated lat/long values from Google/Apple maps. Perform a PUT in the maps API.

By default, SDK will return invalid Lat/Lon values if the GeoRefParams is not configured in the maps API.

Sample payload in the maps API.

/api/v1/sites/:site_id/maps
 
"GeoRefParamsv2": {
        "active": true,
        "p1": {
            "mist_xy": {
                "x": 36.9239,
                "y": -9.9473
            },
            "lat_lon": {
                "x": 37.37522,
                "y": -122.02166
            }
        },
        "p2": {
            "mist_xy": {
                "x": 27.7134,
                "y": -11.5848
            },
            "lat_lon": {
                "x": 37.37523,
                "y": -122.0217
            }
        },
        "p3": {
            "mist_xy": {
                "x": 14.076,
                "y": -22
            },
            "lat_lon": {
                "x": 37.37523,
                "y": -122.02175
            }
        }
    }

Get direction(Snapped Heading)

Following callback provide the device direction in degrees(0-360).

//Objective C
-(void) mistManager: (MSTCentralManager *) manager didUpdateDRHeading: (NSNumber *) heading
//Swift
func mistManager(_ manager: MSTCentralManager!, didUpdateDRHeading heading: NSNumber!)  

Error handling

Now if there is Auth failure in SDK, it will stop the SDK and inform the App via the following callback.

 func manager(_ manager: MSTCentralManager!, didErrorOccurWith errorType: ErrorType, andDetails errorDetails: String!)

ErrorType

· ErrorTypeAuthFailure: will return when MSTCentralManager uses an incorrect or expired secret for initialization. This secrets will be refreshed after every 30 days. The App Developer must implement the ErrorHandling callback to re-enroll the device once the existing token has expired.

· ErrorTypeServerOverloaded: will return when backoff is triggered due to server overload. SDK will pause for a given amount of time before retrying to connect.
· ErrorTypeNoBeaconsDetected : will return when device is not in BLE Proximity.

No action is required from the Mobile App in case of “ErrorTypeServerOverloaded”

//Objective 
- (void)manager:(MSTCentralManager *)manager didErrorOccurWithType:(ErrorType)errorType andDetails:(NSString *)errorDetails{
    NSLog(@"%@", errorDetails);
    if(errorType == ErrorTypeAuthFailure){
            [MSTOrgCredentialsManager enrollDeviceWithToken:sdkSecret onComplete:^ (NSDictionary *response, NSError *error){
                if (error == nil) {
                //Reinitialize MSTCentralManager using the new secret received here and start location update.
                }
            }];
    }
}
//Swift
   func manager(_ manager: MSTCentralManager!, didErrorOccurWith errorType: ErrorType, andDetails errorDetails: String!) {
            if errorType == ErrorType.authFailure {
                if let secret = clientSecret{
                     MSTOrgCredentialsManager.enrollDevice(withToken: secret, onComplete: { (response, error) in
                         if error == nil, response != nil {
                             //Reinitialize MSTCentralManager using the new secret received here and start location update.
                         }})
                    }
                }
    }

Save SDKClient Name

You can update the app client name from the app using mstcentralManagerObj.saveClientInformation(). Make sure you update the name after Mist cloud connection returns true. By default client name is Anonymous.
Key: ‘name’

Value: ‘App-client-name’

//swift
self.manager?.saveClientInformation(["name":"Mist-Appclient-iOS"])
image

Sample app Reference

For more detail, you can see the implementation in the Demo app.
Download the demo app here.

Documentation for MistSDK callbacks

For more callback information refer to Mist SDK callbacks page.

Released Notes

Check what's new in the release notes

Release Notes

Release Notes

Getting Started

Integration Guide

Legacy [Deprecated]

Legacy Integration Document

Clone this wiki locally