Smart Config Plus

Last Updated on : 2025-04-11 06:10:05download

Smart Config Plus is an optimized version of combo device pairing, designed to enhance bulk pairing speed.

  • Add devices in bulk.
  • When pairing fails, the system can quickly locate issues and automatically retry.
  • Enhances device compatibility with various router models and configurations.
  • Method calls are consistent with standard combo device pairing for quick integration.

Integrate Device Pairing Extension SDK

Add dependencies to the Podfile, including the base dependency ThingSmartBusinessExtensionKit and the Bluetooth implementation dependency ThingSmartBusinessExtensionKitBLEExtra, as shown below:

source 'https://github.com/tuya/tuya-pod-specs.git'
platform :ios, '11.0'

target 'Your_Project_Name' do
    # Build and get ThingSmartCryption from the Tuya Developer Platform (https://platform.tuya.com).
    # After the official edition is purchased, rebuild the SDK on the Tuya Developer Platform and integrate it into your project.
    # The dot slash (./) notation represents that the files that are obtained after ios_core_sdk.tar.gz is extracted are put at a sibling directory as podfile.
    # To use another directory, change the path to your desired directory. 
    pod 'ThingSmartCryption', :path =>'./'
    pod 'ThingSmartHomeKit'
    pod 'ThingSmartBusinessExtensionKit'
    # Bluetooth implementation layer
    pod 'ThingSmartBusinessExtensionKitBLEExtra'

end

API description

Register the pairing type

When the device pairing service is initialized, register the pairing type.

Device type Pairing type Model
Bluetooth LE or combo device ThingSmartActivatorTypeBle ThingSmartActivatorTypeBleModel

Bluetooth pairing model

/// Ble
@interface ThingSmartActivatorTypeBleModel : ThingSmartActivatorTypeModel
/// Ble Scan Type
@property (nonatomic, assign) ThingActivatorBleScanType scanType;
/// Home ID
@property (nonatomic, assign) long long spaceId;
/// Pairing token (only used for Bluetooth fallback pairing)
@property (nonatomic, strong) NSString *token;
/// Wi-Fi name
@property (nonatomic, strong) NSString *ssid;
/// Wi-Fi password
@property (nonatomic, strong) NSString *password;
/// Gateway ID
@property (nonatomic, copy) NSString *gwDevId;
/// Active Type
@property (nonatomic, assign) ThingActivatorBleActiveType activeType;
@end

For Smart Config Plus pairing, select ThingActivatorBleActiveTypeBatch for activeType.

Registration method

/// Initialize pairing types
/// @param typeList Pairing types
- (void)registerWithActivatorList:(NSArray<ThingSmartActivatorTypeModel *>*)typeList;

Parameters

Parameter Description
typeList The list of pairing types.

Get a token

The SDK gets a pairing token from the cloud before it can start the pairing process. The token is valid for 10 minutes and expires immediately after the device is paired. A new token must be generated if the device needs to be paired again.

API description

- (void)getTokenWithHomeId:(long long)homeId
                   success:(ThingSuccessString)success
                   failure:(ThingFailureError)failure;

Parameters

Parameter Description
homeId The ID of the home with which the device is bound.
success The success callback. A pairing token is returned.
failure The failure callback. An error message is returned.

Start searching

Pass in the registered typeList to start searching.

API description

/// Start searching
/// @param typeList Pairing types
- (void)startSearch:(NSArray <ThingSmartActivatorTypeModel *>*)typeList;

Parameters

Parameter Description
typeList The list of pairing types.

Stop searching

API description

/// Stop searching
/// @param typeList Pairing types
/// @param clearCache Whether to clear the cache
- (void)stopSearch:(NSArray <ThingSmartActivatorTypeModel *>*)typeList clearCache:(BOOL)clearCache;

Parameters

Parameter Description
typeList The list of pairing types.
clearCache Specifies whether to clear the cache search result.

Device search callback

After the Bluetooth device is discovered, the callback returns the device information. If the operation fails, the callback returns the error message.

API description

/// Device search callback
/// @param service Search instance
/// @param type Pairing type
/// @param device Discovered device
/// @param errorModel Error callback
- (void)activatorService:(id<ThingSmartActivatorSearchProtocol>)service
            activatorType:(ThingSmartActivatorTypeModel *)type
             didFindDevice:(nullable ThingSmartActivatorDeviceModel *)device
                     error:(nullable ThingSmartActivatorErrorModel *)errorModel;

Parameters

Parameter Description
service The pairing service.
type The pairing type.
device The discovered device. The device model is returned on success. nil is returned on failure.
errorModel When searching for Bluetooth devices, this model will not be returned in cases where no devices are found or when the search times out.

Activate device

API description

/// Activate devices with a single pairing type
/// @param type Pairing type
/// @param deviceList Devices to be activated
- (void)startActive:(ThingSmartActivatorTypeModel *)type deviceList:(NSArray<ThingSmartActivatorDeviceModel *>*)deviceList;

Parameters

Parameter Description
type Pairing type
deviceList The list of devices to be activated. Currently, only one device is supported.

Allow bulk activation

Unlike single combo device pairing, bulk pairing requires to set the activeType property of ThingSmartActivatorTypeBleModel to batch. Also, a token shall be set to join the network.

/// Special attention: Batch pairing requires this setting, otherwise only the standard single device pairing will proceed.
    typeModel.activeType = ThingActivatorBleActiveType.batch
    typeModel.token = token

Stop activation

API description

/// Stop activating devices
/// @param typeList Array of pairing types
/// @param clearCache Whether to clear the cache
- (void)stopActive:(NSArray <ThingSmartActivatorTypeModel *>*)typeList clearCache:(BOOL)clearCache;

Parameters

Parameter Description
typeList Pairing type
clearCache Specifies whether to clear the cache search result.

Activation callback

API description

// Device pairing result callback
/// @param service Device pairing implementation object
/// @param type Pairing type
/// @param devices Devices being paired
/// @param errorModel Error encountered during pairing
- (void)activatorService:(id<ThingSmartActivatorActiveProtocol>)service
           activatorType:(ThingSmartActivatorTypeModel *)type
       didReceiveDevices:(nullable NSArray<ThingSmartActivatorDeviceModel *> *)devices
                   error:(nullable ThingSmartActivatorErrorModel *)errorModel;

Parameters

Parameter Description
service The pairing service.
type Pairing type
devices The activated device.
errorModel This model is returned if pairing fails or times out. nil is returned on success.

Sample code

Start searching

class BEDualModePlusViewController: UIViewController {
   
    // MARK: - Properties
    private var deviceList: [ThingSmartActivatorDeviceModel] = []
    private var cellModelList: [BEDeviceCellModel] = [] 
    private var isSuccess = false
    
    private lazy var discovery: ThingSmartActivatorDiscovery = {
        let discovery = ThingSmartActivatorDiscovery()
        discovery.register(withActivatorList: [self.typeModel])
        discovery.setupDelegate(self)
        discovery.loadConfig()
        if let currentHome = Home.current {
            discovery.currentSpaceId(currentHome.homeId)
        } else {
            assert((Home.current != nil), "Home cannot be nil, need to create a Home")
        }
        return discovery
    }()
    
    private lazy var typeModel: ThingSmartActivatorTypeBleModel = {
        let type = ThingSmartActivatorTypeBleModel()
        type.type = ThingSmartActivatorType.ble
        type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorType.ble)
        type.timeout = 120
        /// Special attention: Batch pairing requires this setting, otherwise only the standard single device pairing will proceed.
        type.activeType = ThingActivatorBleActiveType.batch
        if let currentHome = Home.current {
            type.spaceId = currentHome.homeId
        } else {
            assert((Home.current != nil), "Home cannot be nil, need to create a Home")
        }
        return type
    }()
    
 
    // MARK: - Actions
    @objc private func searchTapped() {
        deviceList.removeAll()
        tableView.reloadData()
        discovery.startSearch([self.typeModel])
        SVProgressHUD.show(withStatus: "Searching for devices...")
    }
    
    // MARK: - Private Methods
    private func stopConfiguring() {
        if !isSuccess {
            SVProgressHUD.dismiss()
        }
        
        discovery.stopSearch([self.typeModel], clearCache: true)
        discovery.stopActive([self.typeModel], clearCache: true)
        discovery.removeDelegate(self)
    }
    
}

Device search callback

// MARK: - ThingSmartActivatorSearchDelegate
extension BEDualModePlusViewController: ThingSmartActivatorSearchDelegate {
    func activatorService(_ service: ThingSmartActivatorSearchProtocol, activatorType type: ThingSmartActivatorTypeModel, didFindDevice device: ThingSmartActivatorDeviceModel?, error errorModel: ThingSmartActivatorErrorModel?) {
        if errorModel != nil {
            SVProgressHUD.showError(withStatus:"Faulty device")
            return
        }
        
        guard let device = device else { return }
        
        switch device.deviceModelType {
        case ThingSearchDeviceModelTypeBle:
            print("Please use Dual Mode to pair \(device.uniqueID)")
            SVProgressHUD.dismiss()
        case ThingSearchDeviceModelTypeBleWifi:
            if !deviceList.contains(where: { $0.uniqueID == device.uniqueID }) {
                deviceList.append(device)
                tableView.reloadData()
            }
            SVProgressHUD.dismiss()
        default:
            break
        }
    }
    
    func activatorService(_ service: ThingSmartActivatorSearchProtocol, activatorType type: ThingSmartActivatorTypeModel, didUpdateDevice device: ThingSmartActivatorDeviceModel) {
        let devicecellModel = cellModel(for: device)
        updateDeviceStatus(for: devicecellModel)
    }
}

Start pairing

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        ssidTextField.resignFirstResponder()
        passwordTextField.resignFirstResponder()
        let deviceCellModel = cellModelList[indexPath.row]
        
        guard let ssid = ssidTextField.text, !ssid.isEmpty else {
            SVProgressHUD.showError(withStatus: "Please enter the WiFi name")
            return
        }
        
        guard let password = passwordTextField.text, !password.isEmpty else {
            SVProgressHUD.showError(withStatus: "Please enter the WiFi password")
            return
        }
        
        if typeModel.token.isEmpty {
            ThingSmartActivator.sharedInstance()?.getTokenWithHomeId(typeModel.spaceId, success: { [weak self] (token) in
                guard let self = self else { return }
                typeModel.token = token ?? ""
                self.startConfiguringNetwork(deviceCellModel: deviceCellModel, indexPath: indexPath)
            }, failure: { (error) in

            })
        } else {
            startConfiguringNetwork(deviceCellModel: deviceCellModel, indexPath: indexPath)
        }
    }

       private func startConfiguringNetwork(deviceCellModel: BEDeviceCellModel, indexPath: IndexPath) {
        deviceCellModel.deviceStatus = "Adding"
        typeModel.ssid = ssidTextField.text ?? ""
        typeModel.password = passwordTextField.text ?? ""
        updateDeviceStatus(for: deviceCellModel)

        // Start pairing
        discovery.startActive(typeModel, deviceList: [deviceCellModel.deviceModel])
//        discovery.startActive(typeModel, deviceList: deviceList)

        tableView.deselectRow(at: indexPath, animated: true)
    }

Pairing callback

// MARK: - ThingSmartActivatorActiveDelegate
extension BEDualModePlusViewController: ThingSmartActivatorActiveDelegate {
    func activatorService(_ service: ThingSmartActivatorActiveProtocol, activatorType type: ThingSmartActivatorTypeModel, didReceiveDevices devices: [ThingSmartActivatorDeviceModel]?, error errorModel: ThingSmartActivatorErrorModel?) {
        if let errorModel = errorModel {
            let cellModel = cellModel(for: errorModel.deviceModel!)
            cellModel.deviceStatus = "Failed"
            updateDeviceStatus(for: cellModel)            
            return
        }

        guard let device = devices?.first else { return }

        let cellModel = cellModel(for: device)
        cellModel.deviceStatus = "succeed"
        updateDeviceStatus(for: cellModel)
        isSuccess = true
    }
}