Skip to content

(Mobile) A repository to manage SmartScanner-iOS-Spec - iOS resources

Notifications You must be signed in to change notification settings

securingsam/SmartScanner-iOS-Spec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SAM Seamless Network

SmartScanner SDK - Developer Documentation

SDK Version 1.0.0


Installation

Minimum system requirements

The SmartScannerSDK library requires iOS 14.0 or later and Swift 5.0 or later.

Note Apple platforms other than iOS are not currently supported.

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler.

Once you have your Swift package set up, adding the SmartScannerSDK as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
    .package(
        url: "https://github.com/securingsam/SmartScanner-iOS-Spec",
        .upToNextMajor(from: "1.0.0")
    )
]

Manually

If you prefer not to use dependency managers, you can integrate the SmartScannerSDSK into your project manually.

Download the XCFramework file and copy it to your Xcode project.


API reference

For a more detailed list of all of the available SDK API methods and types, please refer to the API reference.


Usage

Example

A full example ViewModel class file can be found here.

Setup

Importing the library

Importing the library in your Swift code is pretty straightforward

import SmartScannerSDK

It is important to know that this variation will work for compiling and running on physical devices only. In case an iPhone Simulator support is required, please use the following import code snippet:

#if targetEnvironment(simulator)
import SmartScannerSDKSimulator
#else
import SmartScannerSDK
#endif

This will ensure to import the simulator variation of the library when the Xcode target device is an iOS simulator.

Note The simulator variation will compile and run, but the scanner will not work on the iPhone simulator in any way.

Setup and authentication

The SmartScannerSDK library requires a SAM vendor authentication token in order to verify your identity.

Setting up occurs anywhere, as long as it happens before using any of the SmartScannerSDK's features. Interacting with any other API methods beforehand will result in 401 errors.

SmartScanner.getInstance().setup(token: "yoursamvendortoken")

The Scanner API

The Scan instance

The Scan instance is used in order to communicate with the SmartScannerSDK.

let scanner: Scan = SmartScanner.getInstance().getScanInstance()

Quick scan

In order to start scanning, call the .scan(params:) method from the Scan instance. This method returns a Combined AnyPublisher and provides a ScanResult object which contains the data that was collected by the scanner.

let config = ScanConfig()

scanner.scan(params: config)
    .receive(on: RunLoop.main)
    .sink { completion in
        switch completion {
        case .finished:
            print("Completed!")
        case .failure(let error):
            // Scan process failed. Print the error
            print(error.description)
        }
    } receiveValue: { result in
        // On success, print the list of the detected devices.
        guard
            let result,
            let devices = result.devices
        else {
            print("No devices found")
            return
        }

        print("Devices: \(devices)")
    }
    .store(in: &cancellables)

Observing the scanner's progress

The Scan instances exposes an observer instance called .observeProgress() that allows you to observe the progress of the scan (progress values ranging from 0 - 100). The .observeProgress() method returns a new Combine AnyPublisher with a value of type Int that progress values can be read from.

scanner
    .observeProgress()
    .receive(on: RunLoop.main)
    .sink { value in
        print("Progress: \(value)")
    }
    .store(in: &cancellables)

Observing detected devices

As it is better to get devices when they are detected, The Scan instance also exposes an .observeDevices() method that returns an array of Device items.

This allows you to retrieve a list of detected devices as they are detected.

scanner
    .observeDevices()
    .receive(on: RunLoop.main)
    .sink(receiveCompletion: { error in
        print("The scanner encountered an error: \(error)")
    }, receiveValue: { devices in
        print("Detected devices: \(devices)")
    })
    .store(in: &cancellables)

Stopping the scan process

In order to stop the currently active scan, you can use the .killScan() method built into the Scan instance.

scanner.killScan()

Custom scanner configurations

The scan method accepts a ScanConfig object.

The ScanConfig object allows the SDK client to control the scanner's configurations. For example, the following code snippet starts a scan that is using only PING to detect devices in the network and sets the scan to last only 2 minutes.

All scanner types can be found within the SamScannerType enum.

Note The default configurations are considered to be optimized for the best scan results.

let config = ScanConfig(
    allowedScannerTypes: [.PING],
    scanTimeInSeconds: 2000
)

scanner.scan(params: config)
    .receive(on: RunLoop.main)
    .sink { ... }
    .store(in: &cancellables)

Handling 401 Unauthorized errors

In case the authentication token provided in the initialization and authentication phase is expired during the scan process, the scan process will automatically stop and return a SamSDKError instance with code of .UNAUTHORIZED (401).

In that scenario a new/refreshed token must be provided to the SDK by executing the .setup(token:) function again.

func startScan() {
    let config = ScanConfig()

    scanner.scan(params: config)
        .receive(on: RunLoop.main)
        .sink { [weak self] completion in
            switch completion {
            case .finished:
                print("Finished!")
            case .failure(let error):
                /// Treat an `.UNAUTHORIZED` type error
                if error == .UNAUTHORIZED {
                    self?.handle401UnauthorizedErrorAndRescan()
                    return
                }
                print(error.description)
            }
        } receiveValue: { result in
            // On success, print the list of deteceted devices
            guard
                let result,
                let devices = result.devices
            else {
                print("No devices found")
                return
            }

            print("Devices: \(devices)")
        }
        .store(in: &cancellables)
}

private func handle401UnauthorizedErrorAndRescan() {
    setupScanner(token: refreshToken())
    startScan()
}

private func refreshToken() -> String {
    // Refresh the token and return a new valid one
}