Bluetooth is another way of getting a reader. Right now the API only support ACS (3901) Bluetooth reader (Feitian readers (br301bl br500) maybe identified while scanned, but cannot be connected to)

Bluetooth reader require that you are paired and connected to with them before using it. Fortunately this API provides the mean to search, pair, connect, disconnect and forget a Bluetooth device.

First, you will need to explicitly start a scan via the SCMEnvironment.startBluetoothScan() function. This will start a scan for all Bluetooth peripheral around you.

After that, you must retrieve the list of detected Bluetooth devices in order to pick one. You can call the function SCMEnvironment.getDetectedBluetoothPeripherals(). This function will return the list of all currently detected peripheral (including the one that are not supported). You can check the getType() method to know if the device is supported or not.

Now, you may want to pair and connect to a Bluetooth Device. In order to do this, you should call the function SCMEnvironement.registerBluetooth(uuid: String) the expected parameter is the UUID of the device you want to be paired with. You can get the UUID of the device by calling getUuid() function, on a BluetoothPeripheral object.

Now that you are paired and connected to a Bluetooth device, the callback function ReaderEvent.onReaderAdded(reader: Reader) should be called from the class implementing the ReaderEvent protocol. Do not forget to register your class with SCMEnvironment.addReaderListener(listerner:) prior to connecting to a bluetooth device, otherwise you will not receive any callback when the reader is added, or a token is inserted/removed.

If at some point you want to disconnect yourself from the Bluetooth device, you can call SCMEnvironment.releaseBluetooth(). If you want to forget the current Bluetooth device, you can call SCMEnvironment.unregisterBluetooth(). Disconnecting yourself imply that the next time you will call SCMEnvironment.startBluetoothScan() you will be automatically connected to the prior Bluetooth device if it is detected by the scan. On the other hand, SCMEnvironment.unregisterBluetooth() require starting again from the beginning.

Here is a sample code that automatically connect you to the first supported Bluetooth device it found:

import Foundation
import ScmApi

class Bluetooth_Tester: ObservableObject
{
    @Published var bluetooth_device:Array<BluetoothPeripheral>
    private var environment: SCMEnvironment;
    init()
    {
        bluetooth_device = [];

        // initialize the environment by waiting for the asynchronous function to answer 
        var temp_env: SCMEnvironment?;
        let group = DispatchGroup();
        group.enter()
        DispatchQueue.global().async {
            SCMEnvironment.createEnvironment { env, error in
                if let env = env
                {
                    temp_env = env;
                }
                else if let error = error
                {
                    print("could not create environment : " + error.localizedDescription);
                }
                group.leave()
            }
        }
        group.wait()
        if let temp_env = temp_env {
            self.environment = temp_env;
        }
        else
        {
            fatalError("could not create environment");
        }
    }

    // Function used to start the scan for bluetooth peripheral
    func StartScan()
    {

        do
        {
            let res = try self.environment.startBluetoothScan()
            print(res ? "successfully started scan " : "scan could not be started");

        }
        catch SCMError.CXR_BT_INITIALIZATION_FAILED
        {
            print("CXR_BT_INITIALIZATION_FAILED");
        }
        catch SCMError.CXR_BT_ALREADY_PAIRED
        {
            print("CXR_BT_ALREADY_PAIRED");
        }
        catch let err
        {
            print("Unknown error being thrown from start scan : " + err.localizedDescription);
        }
    }

    // Stop scanning for bluetooth peripheral
    func StopScan()
    {
        do
        {
            let res = try self.environment.stopBluetoothScan()
            print(res ? "successfully stopped scan " : "scan could not stop");

        }
        catch SCMError.CXR_BT_INITIALIZATION_FAILED
        {
            print("CXR_BT_INITIALIZATION_FAILED");
        }
        catch let err
        {
            print("Unknown error being thrown from start scan : " + err.localizedDescription);
        }
    }

    // get the registered buetooth device
    func get_registered()
    {
        let registered = self.environment.getRegisteredBluetooth()
        if let registered = registered
        {
            print("found peripheral" + registered.getName()! + " :: " + registered.getUuid());
        }
        else
        {
            print("Nothing registered");
        }
    }

    // Check if we are scanning or not
    func is_Scannning()
    {

        let res = self.environment.isScanningBluetooth()
        print(res ? "We are scanning" : "We are not scanning");
    }

    // release the current connected Bluetooth peripheral
    func release()
    {
        do
        {
            let res = try self.environment.releaseBluetooth()
            print(res ? "Sucesfully released peripheral " : "could not release bluetooth peripheral");

        }
        catch SCMError.CXR_BT_INITIALIZATION_FAILED
        {
            print("CXR_BT_INITIALIZATION_FAILED");
        }
        catch let err
        {
            print("Unknown error being thrown from release : " + err.localizedDescription);
        }
    }

    // Unregister the currently paired luetooth device
    func unregister()
    {
        self.environment.unregisterBluetooth()
        print("successfully unregistered peripheral ");
    }

    // Update the UI with the detected peripheral
    // Obviously a scan need to be started in order for this function to work correctly
    func get_peripherals()
    {
        do
        {
            let res = try self.environment.getDetectedBluetoothPeripherals()
            self.bluetooth_device = res
        }
        catch SCMError.CXR_BT_INITIALIZATION_FAILED
        {
            print("CXR_BT_INITIALIZATION_FAILED");
        }
        catch SCMError.CXR_BT_NOT_SCANNING
        {
            print("CXR_BT_NOT_SCANNING");
        }
        catch SCMError.CXR_BT_ALREADY_PAIRED
        {
            print("CXR_BT_ALREADY_PAIRED");
        }
        catch let err
        {
            print("Unknown error returned from GetPeripherals : " + err.localizedDescription);
        }
    }

    // register a bluetooth peripheral.
    // used when you tap a bluetooth device on the UI
    func register_peripheral(UUID: String)
    {
        do
        {
            try self.environment.registerBluetooth(uuid: UUID)
            print("successfully registered bluetooth peripheral");
        }
        catch SCMError.CXR_BT_INITIALIZATION_FAILED
        {
            print("CXR_BT_INITIALIZATION_FAILED");
        }
        catch SCMError.CXR_BT_ALREADY_PAIRED
        {
            print("CXR_BT_ALREADY_PAIRED");
        }
        catch SCMError.CXR_BT_DEVICE_NOT_SUPPORTED
        {
            print("CXR_BT_DEVICE_NOT_SUPPORTED");
        }
        catch SCMError.CXR_BT_DEVICE_NOT_DETECTED
        {
            print("CXR_BT_DEVICE_NOT_DETECTED");
        }
        catch let err
        {
            print("Unknown error being thrown from register : " + err.localizedDescription);
        }
    }
}

Here is a minimalistic UI to go with the Above Code

import SwiftUI

struct ContentView: View {
    // the bluetooth tester is an observable object since we want to Update the UI for Detected Bluetooth peripher.
    @ObservedObject var m_bluetooth_tester = Bluetooth_Tester();
    var body: some View {
        ZStack
        {
            HStack{
                VStack(alignment: .leading,spacing: 20){
                    Button(action: {m_bluetooth_tester.StartScan()}){
                        Text("Start Scan")
                    }
                    Button(action: {m_bluetooth_tester.StopScan()}){
                        Text("Stop Scan")
                    }
                    Button(action: {m_bluetooth_tester.get_peripherals()}){
                        Text("get peripherals")
                    }
                    Button(action: {m_bluetooth_tester.get_registered()}){
                        Text("get registered")
                    }
                    Button(action: {m_bluetooth_tester.is_Scannning()}){
                        Text("is Scanning")
                    }
                    Button(action: {m_bluetooth_tester.release()}){
                        Text("release")
                    }
                    Button(action: {m_bluetooth_tester.unregister()}){
                        Text("unregister")
                    }
                }

                // This part is used to  show the detected peripherals as astack of buttons.
                // when you click a peripherals it means you want to pair and connect yourself to the peripheral.
                VStack(alignment: .leading)
                {
                    Text("Detected peripherals")
                    ForEach(m_bluetooth_tester.bluetooth_device, id: \.self) { my_periph in
                        Button(action: {m_bluetooth_tester.register_peripheral(UUID: my_periph.getUuid())}){
                            Text(my_periph.getName() ?? "NO_Name")
                        }
                    }
                }
            }
        }
    }
}