Pair with QR Code

Last Updated on : 2024-08-22 06:14:43download

The app scans the device’s QR code to pair with it. This is a quick way to pair a single device. It applies to directly connected devices and Bluetooth devices.

The ThingSmartBusinessExtensionKit component offers more features than the ThingSmartActivator. If you are still using ThingSmartActivator, please refer to this document.

## Pairing process

Directly connected device

A directly connected device can connect to the internet without an intermediary, such as GPRS and LTE Cat.1.

AppBizBundle SDKDeviceCloudDevice enters pairing mode.Scan device's QR code1Parse the QR code.Call the QR code parsingmethod.2Call the QR code parsing method.3Return the parsing result.4Return the parsing result.5alt[Scan for devices.]Start activating the device.6Start activating the device.7Return the list of activated devices.8Return the list of activateddevices.9alt[Activation and pairing]AppBizBundle SDKDeviceCloudPair a Directly-Connected Device with QR Code

Bluetooth device

The process of pairing a Bluetooth device by QR code.

AppBizBundle SDKDeviceCloudDevice enters pairing mode.Scan device's QR code1Parse the QR code.Call the QR code parsingmethod.2Call the QR code parsing method.3Return the parsing result.4Return the parsing result.5Compare and getdevice information.alt[Scan for devices.]Start activating the device.6Start activating the device.7Return the list of activated devices.8Return the list of activateddevices.9alt[Activation and pairing]AppBizBundle SDKDeviceCloudPair a Bluetooth Device with QR Code

Parse QR code

Extract the URL from the QR code and get the device information through the common API. Based on the return value, determine whether the device is a directly connected device or a Bluetooth device.

@protocol ThingSmartActivatorRequestProtocol <NSObject>

/// Provide QR code parsing capability
/// @param param Request Parameters
/// @param success Network success callback
/// @param failure Network Failure Callbacks
- (void)requestParseQRCodeWithParam:(ThingActivatorParseQRCodeRequestData *)param success:(void(^)(ThingSmartAScanCodeModel *result))success failure:(ThingActivatorCallbackError)failure;
@end

Parameter description

Parameters Description
param The request parameter.
success The success callback.
failure The failure callback.

Description of the return value:

@interface ThingSmartAScanCodeModel : NSObject
@property (nonatomic, strong) NSString * _Nullable actionName;
@property (nonatomic, assign) id _Nullable actionData;
@end

The types of QR code are the following. See the example for usage.

  • The actionName for a directly connected device is "device_net_conn_multi_ver".
  • The actionName for a Bluetooth device is "device_net_conn_bind_blue".

Register the pairing type

When the device pairing service is initialized, register the pairing type. ThingSmartActivatorTypeMQTTDirectlyModel is for a directly connected device, and ThingSmartActivatorTypeBleModel is for a Bluetooth device.

/// Initialize network configuration types
/// @param typeList Network configuration types
- (void)registerWithActivatorList:(NSArray<ThingSmartActivatorTypeModel *>*)typeList;

Parameter description

Parameters Description
typeList The list of pairing types.

Start searching

Pass in the registered typeList to start searching.

API description

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

Parameter description

Parameters Description
typeList The list of pairing types.

Stop searching

API description

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

Parameter description

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

Device search callback

After the device is paired, 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 Network configuration 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;

Parameter description

Parameters 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 This model is returned if pairing fails or times out. nil is returned on success.

Activate a device

API description

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

Parameter description

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

Stop activation

API description

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

Parameter description

Parameters Description
typeList The pairing type.
clearCache Specifies whether to clear the cache search result.

Activation callback

API description

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

Parameter description

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

Error codes

ThingSmartActivatorErrorModel is returned if pairing fails or times out.

@interface ThingSmartActivatorErrorModel : NSObject
@property (nonatomic, strong) ThingSmartActivatorDeviceModel *deviceModel;
@property (nonatomic) NSError *error;
@end

ThingSmartActivatorDiscoveryError includes the definition of error codes.

Example

Directly connected device

Swift:

class mqttDirectlyModeConfigurationVC: UITableViewController {

    private var token: String = ""
    private var typeModel:ThingSmartActivatorTypeMQTTDirectlyModel = {
        let type = ThingSmartActivatorTypeMQTTDirectlyModel()
        type.type = ThingSmartActivatorType.mqttDirectly
        type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorType.mqttDirectly)
        type.timeout = 120
        return type
    }()


    lazy var discovery: ThingSmartActivatorDiscovery = {
        let discovery = ThingSmartActivatorDiscovery()
        discovery.register(withActivatorList: [self.typeModel])
        discovery.setupDelegate(self)
        discovery.loadConfig()
        return discovery
    }()

    var request: ThingSmartActivatorDiscoveryRequest = {
        let request = ThingSmartActivatorDiscoveryRequest()
        return request
    }()

    private func startConfiguration(qrcode codeStr: String?) -> Void{
        SVProgressHUD.show()
        guard let homeID = Home.current?.homeId else { return }
        self.typeModel.spaceId = homeID

        let requestDate = ThingActivatorParseQRCodeRequestData()
        requestDate.code = codeStr ?? ""
        request.requestParseQRCode(withParam: requestDate) { codeModel in
            if codeModel.actionName == "device_net_conn_multi_ver" {
                self.typeModel.uuid = codeModel.actionData?.object(forKey: "uuid") as! String
                self.discovery.startActive(self.typeModel, deviceList: [])
            }
        } failure: { error in

        }
    }
}

extension mqttDirectlyModeConfigurationVC: ThingSmartActivatorActiveDelegate {
    func activatorService(_ service: ThingSmartActivatorActiveProtocol, activatorType type: ThingSmartActivatorTypeModel, didReceiveDevices devices: [ThingSmartActivatorDeviceModel]?, error errorModel: ThingSmartActivatorErrorModel?) {
        if errorModel != nil {
            SVProgressHUD.showError(withStatus: "Bind Failure. (\(errorModel?.error.localizedDescription ?? ""))")
            return
        }

        let device = devices?.first
        SVProgressHUD.show(withStatus: "Bind Success. \n devId: \(device?.uniqueID ?? "") \n name: \(device?.name ?? "")")
    }
}

Objective-C:

- (void)qrParse:(NSString *)url {
   ThingActivatorParseQRCodeRequestData *param = [[ThingActivatorParseQRCodeRequestData alloc] init];
   param.code = url;
   [self.requestService requestParseQRCodeWithParam:param success:^(ThingSmartAScanCodeModel * _Nonnull model) {
       if ([model.actionName isEqualToString:@"device_net_conn_multi_ver"]){
        NSDictionary *dict = result.actionData;
        NSString *uuid = [dict objectForKey:@"uuid"];
        ThingSmartActivatorTypeMQTTDirectlyModel *type = [[ThingSmartActivatorTypeMQTTDirectlyModel alloc] init];
        type.type = ThingSmartActivatorTypeMQTTDirectly;
        type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorTypeMQTTDirectly);
        type.timeout = 120;
        type.spaceId = [ThingSmartActivatorLinkTool getSpaceId];
        type.uuid = uuid;
        [self startConfigQRCode:type];
       }
   } failure:^(NSError *error) {

   }];
}

- (void)startConfigQRCode:(ThingSmartActivatorTypeMQTTDirectlyModel *)type {

  [self.discovery registerWithActivatorList:@[type]];
  [self.discovery setupDelegate:self];
  [self.discovery startActive:self.typeModel deviceList:@[]];

}

- (void)activatorService:(id<ThingSmartActivatorActiveProtocol>)service 
           activatorType:(ThingSmartActivatorTypeModel *)type 
       didReceiveDevices:(NSArray<ThingSmartActivatorDeviceModel *> *)devices 
                   error:(ThingSmartActivatorErrorModel *)errorModel {
    if (errorModel) {
        [self _connectWifiError:errorModel];
        return;
    }

    if (device) {
        [self _handleDevice:device];
    }
}

- (void)_handleDevice:(ThingSmartActivatorDeviceModel *)deviceModel {
}

- (ThingSmartActivatorDiscovery *)discovery {
    if (!_discovery) {
        _discovery = [[ThingSmartActivatorDiscovery alloc] init];
    }
    return _discovery;
}

- (ThingSmartActivatorDiscoveryRequest *)requestService {
    if (!_requestService) {
        _requestService = [[ThingSmartActivatorDiscoveryRequest alloc] init];
    }
    return _requestService;
}

Bluetooth device

Swift:

class BleScanModeConfigurationVC: UITableViewController {

    private var uuid: String = ""
    private var mac: String = ""
    private var typeModel:ThingSmartActivatorTypeBleModel = {
        let type = ThingSmartActivatorTypeBleModel()
        type.type = ThingSmartActivatorType.ble
        type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorType.ble)
        type.timeout = 120
        type.spaceId = Home.current!.homeId
        return type
    }()


    lazy var discovery: ThingSmartActivatorDiscovery = {
        let discovery = ThingSmartActivatorDiscovery()
        discovery.register(withActivatorList: [self.typeModel])
        discovery.setupDelegate(self)
        discovery.loadConfig()
        return discovery
    }()

    var request: ThingSmartActivatorDiscoveryRequest = {
        let request = ThingSmartActivatorDiscoveryRequest()
        return request
    }()

    private func startConfiguration(qrcode codeStr: String?) -> Void{
        SVProgressHUD.show()
        let requestDate = ThingActivatorParseQRCodeRequestData()
        requestDate.code = codeStr ?? ""
        request.requestParseQRCode(withParam: requestDate) { codeModel in
            if codeModel.actionName == "device_net_conn_bind_blue" {
                self.uuid = codeModel.actionData?.object(forKey: "uuid") as! String
                self.mac = codeModel.actionData?.object(forKey: "mac") as! String
                self.discovery.startSearch([self.typeModel])
            }
        } failure: { error in

        }
    }
}

extension BleScanModeConfigurationVC: ThingSmartActivatorActiveDelegate {
    func activatorService(_ service: ThingSmartActivatorActiveProtocol, activatorType type: ThingSmartActivatorTypeModel, didReceiveDevices devices: [ThingSmartActivatorDeviceModel]?, error errorModel: ThingSmartActivatorErrorModel?) {
        if errorModel != nil {
            SVProgressHUD.showError(withStatus: "Bind Failure. (\(errorModel?.error.localizedDescription ?? ""))")
            return
        }

        let device = devices?.first
        SVProgressHUD.show(withStatus: "Bind Success. \n devId: \(device?.uniqueID ?? "") \n name: \(device?.name ?? "")")
    }
}

extension BleScanModeConfigurationVC: ThingSmartActivatorSearchDelegate {

    func activatorService(_ service: ThingSmartActivatorSearchProtocol, activatorType type: ThingSmartActivatorTypeModel, didFindDevice device: ThingSmartActivatorDeviceModel?, error errorModel: ThingSmartActivatorErrorModel?) {
        if (errorModel != nil) {
            // Error
            SVProgressHUD.showError(withStatus: errorModel?.error.localizedDescription)
            return
        }

        if let device = device {
            if device.uniqueID.caseInsensitiveCompare(self.uuid) == .orderedSame ||  device.uniqueID.caseInsensitiveCompare(self.mac) == .orderedSame{
                discovery.currentSpaceId(Home.current!.homeId)
                discovery.startActive(typeModel, deviceList: [device])
            }
        }
    }

    func activatorService(_ service: ThingSmartActivatorSearchProtocol, activatorType type: ThingSmartActivatorTypeModel, didUpdateDevice device: ThingSmartActivatorDeviceModel) {

    }
}

Objective-C:

- (void)qrParse:(NSString *)url {
   ThingActivatorParseQRCodeRequestData *param = [[ThingActivatorParseQRCodeRequestData alloc] init];
   param.code = url;

   [self.requestService requestParseQRCodeWithParam:param success:^(ThingSmartAScanCodeModel * _Nonnull model) {
       if ([model.actionName isEqualToString:@"device_net_conn_bind_blue"]){
        NSDictionary *dict = result.actionData;
        self.uuid = [dict objectForKey:@"uuid"];
        self.mac = [dict objectForKey:@"mac"];
        ThingSmartActivatorTypeBleModel *type = [[ThingSmartActivatorTypeBleModel alloc] init];
        type.type = ThingSmartActivatorTypeBle;
        type.scanType = ThingBluetoothScanTypeNoraml | ThingBluetoothScanTypeQRCode;
        type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorTypeBle);
        type.timeout = self.timeout;

        [self startConfigQRCode:type];
       }
   } failure:^(NSError *error) {

   }];
}

- (void)startConfigQRCode:(ThingSmartActivatorTypeMQTTDirectlyModel *)type {

  [self.discovery registerWithActivatorList:@[type]];
  [self.discovery setupDelegate:self];
  [self.discovery startSearch:@[type]];

}

- (void)activatorService:(id<ThingSmartActivatorSearchProtocol>)service activatorType:(ThingSmartActivatorTypeModel *)type didFindDevice:(ThingSmartActivatorDeviceModel *)device error:(ThingSmartActivatorErrorModel *)errorModel {
    if (errorModel) {
        [self _connectWifiError:errorModel];
        return;
    }

    if (device) {
        if ((NSOrderedSame == [device.uniqueID caseInsensitiveCompare:self.uuid])|| (NSOrderedSame == [device.uniqueID caseInsensitiveCompare:self.mac]))
        /// Bluetooth scanned the device is the QR code device
        [self _handleDevice:device];
    }
}

- (void)_handleDevice:(ThingSmartActivatorDeviceModel *)deviceModel {
     ThingSmartActivatorTypeBleModel *type = (ThingSmartActivatorTypeBleModel *)[activatorGateway activatorTypeModelWith:ThingSmartActivatorTypeBle];
    [self.discovery startActive:type deviceList:@[deviceModel]];
}

- (void)activatorService:(id<ThingSmartActivatorActiveProtocol>)service
           activatorType:(ThingSmartActivatorTypeModel *)type
       didReceiveDevices:(nullable NSArray<ThingSmartActivatorDeviceModel *> *)devices
                   error:(nullable ThingSmartActivatorErrorModel *)errorModel {
                   if (errorModel) {
        [self _connectWifiError:errorModel];
        return;
    }

    if (device) {
        /// device activated successfully
    }
}

- (ThingSmartActivatorDiscovery *)discovery {
    if (!_discovery) {
        _discovery = [[ThingSmartActivatorDiscovery alloc] init];
    }
    return _discovery;
}

- (ThingSmartActivatorDiscoveryRequest *)requestService {
    if (!_requestService) {
        _requestService = [[ThingSmartActivatorDiscoveryRequest alloc] init];
    }
    return _requestService;
}