Last Updated on : 2023-10-11 07:20:49download
Matter device pairing applies to both the Tuya-enabled and third-party Matter devices. The API calls for both types of devices remain consistent, but their pairing behavior differs. Matter device pairing supports auto-discovery, QR code scan, and manual setup code.
When the device pairing service is initialized, register the pairing type, which is ThingSmartActivatorTypeMatterModel
.
API description
/// Initialize network configuration types
/// @param typeList Network configuration types
- (void)registerWithActivatorList:(NSArray<ThingSmartActivatorTypeModel *>*)typeList;
Parameter description
Parameters | Description |
---|---|
typeList | The list of pairing types. |
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;
Parameter description
Parameters | 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. |
Read the QR code or manual setup code. If the code is wrong, the device model is not returned.
/// Check the matter code is legal or not. Returns nil if it is invalid.
/// @param qrString The matter QRCode string or Manual Code string.
- (ThingSmartActivatorDeviceModel *)parseSetupCode:(NSString *)qrString;
Parameter description
Parameters | Description |
---|---|
qrString | The information read from the QR code or manual setup code. |
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. |
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. |
After the 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 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. |
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. |
The SDK automatically selects the optimal pairing option based on the advertising data. It then sends the selection to the business layer through the callback for displaying on the respective app page. There are three pairing options: Tuya-specific pairing, sharing and pairing, and MatterSupport.
To enable MatterSupport, see Prepare for Integration with Matter Device. MatterSupport is available only after you configure it for your project.
/// Discoveryed Matter Device.
/// @param typeModel device type model
- (void)matterDeviceDiscoveryed:(ThingMatterDeviceDiscoveriedType *)typeModel;
Parameter description
Parameters | Description |
---|---|
typeModel | The pairing option. |
After the Matter device is connected, the completion of Password Authenticated Session Establishment (PASE) will invoke the PASE session success callback.
/// Matter commission establish complete, model's type will be known.
/// @param deviceModel Device model.
- (void)matterCommissioningSessionEstablishmentComplete:(ThingSmartActivatorDeviceModel *)deviceModel;
Parameter description
Parameters | Description |
---|---|
deviceModel | The Matter device model in the PASE session. |
With the PASE session, some key information such as device type is obtained. If the device needs to connect to the cloud and the parameters required for Certificate Authenticated Session Establishment (CASE) are ready, you can call this method to establish a CASE session.
/// @param deviceModel the matter devicemodel.
/// @param typeModel Network configuration type.
- (void)continueCommissionDevice:(ThingSmartActivatorDeviceModel *)deviceModel typeModel:(ThingSmartActivatorTypeMatterModel *)typeModel;
Parameter description
Parameters | Description |
---|---|
deviceModel | The Matter device model returned by the PASE completion callback matterCommissioningSessionEstablishmentComplete . |
typeModel | The parameter model for a CASE session. For a combo device, ssid and password are required, and for a Thread device, gwDevId is required. |
The callback to invoke when an attempt is made to pair a device that is not Matter-certified. After this callback is invoked, the pairing process will be suspended until the user chooses to continue or cancel.
// Matter device attestation fails, use `-continueCommissioningDevice:ignoreAttestationFailure:error:` to continue OR interrupt.
///
/// **Notice**
/// Usually app will display an alert view to the user, allowing the user to judge whether to ignore the attestation failure.
///
/// @param device the failure device.
/// @param error the failure error info.
- (void)matterDeviceAttestation:(void *)device error:(NSError * _Nonnull)error;
Parameter description
Parameters | Description |
---|---|
device | The pointer to the device object address in the pairing process. |
error | The error message for an uncertified device. |
If the user chooses to add an uncertified Matter device, call this method to continue the pairing process.
/// Continue the pairing or NOT.
///
/// **Notice:** Can only be used after the `-matterDeviceAttestation:error:` delegate callback.
///
/// @param device It MUST BE the device object through the `-matterDeviceAttestation:error:` delegate callback.
/// @param ignoreAttestationFailure Ignore the attestation fail or NOT. `YES` - continue pairing, `NO` - interrupt pairing.
/// @param error the error info.
- (void)continueCommissioningDevice:(void *)device
ignoreAttestationFailure:(BOOL)ignoreAttestationFailure
error:(NSError * __autoreleasing *)error;
Parameter description
Parameters | Description |
---|---|
device | The pointer to the device object address in the device attestation callback method. Be sure to pass in the raw parameter data. |
ignoreAttestationFailure | Specifies whether to ignore the attestation failure. |
error | The error message that might be returned in this call. |
// 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. |
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. |
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.
Swift:
class BEMatterTableViewController: UITableViewController {
private var typeModel: ThingSmartActivatorTypeMatterModel = {
let type = ThingSmartActivatorTypeMatterModel()
type.type = ThingSmartActivatorType.matter
type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorType.matter)
type.timeout = 180
return type
}()
lazy var discovery: ThingSmartActivatorDiscovery = {
let discovery = ThingSmartActivatorDiscovery()
discovery.register(withActivatorList: [self.typeModel])
discovery.setupDelegate(self)
discovery.loadConfig()
return discovery
}()
func bindMatter(qrcode codeStr: String?) -> Void {
let homeId = (Home.current?.homeId)!
let payload = self.discovery.parseSetupCode(codeStr ?? "")
let activator = ThingSmartActivator()
activator.getTokenWithHomeId(homeId, success: { [weak self] (token) in
guard let self = self else { return }
self.typeModel.token = token ?? ""
self.typeModel.spaceId = homeId
self.discovery.startActive(self.typeModel, deviceList:[payload])
SVProgressHUD.show(withStatus: NSLocalizedString("Configuring", comment: ""))
}, failure: { (error) in
let errorMessage = error?.localizedDescription ?? ""
SVProgressHUD.showError(withStatus: errorMessage)
})
}
private func stopConfigWifi() {
SVProgressHUD.dismiss()
discovery.stopActive([typeModel], clearCache: true)
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
discovery.startSearch([self.typeModel])
}
}
extension BEMatterTableViewController: ThingSmartActivatorSearchDelegate {
func activatorService(_ service: ThingSmartActivatorSearchProtocol, activatorType type: ThingSmartActivatorTypeModel, didFindDevice device: ThingSmartActivatorDeviceModel?, error errorModel: ThingSmartActivatorErrorModel?) {
if let device = device {
if device.deviceModelType == ThingSearchDeviceModelTypeMatterWifi {
self.typeModel.ssid = ssid.text ?? ""
self.typeModel.password = password.text ?? ""
print("Please use Dual Mode to pair: %@", device.uniqueID)
}
if device.deviceModelType == ThingSearchDeviceModelTypeMatterThread {
self.typeModel.gwDevId = "gateway deivce id"
}
let homeId = (Home.current?.homeId)!
let payload = self.discovery.parseSetupCode(codeStr ?? "")
let activator = ThingSmartActivator()
activator.getTokenWithHomeId(homeId, success: { [weak self] (token) in
guard let self = self else { return }
self.typeModel.token = token ?? ""
self.typeModel.spaceId = homeId
self.discovery.startActive(self.typeModel, deviceList:[payload])
SVProgressHUD.show(withStatus: NSLocalizedString("Configuring", comment: ""))
}, failure: { (error) in
let errorMessage = error?.localizedDescription ?? ""
SVProgressHUD.showError(withStatus: errorMessage)
})
}
if let errorModel = errorModel {
// Error
SVProgressHUD.showError(withStatus: errorModel.error.localizedDescription)
}
}
}
extension BEMatterTableViewController: 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
isSuccess = true
SVProgressHUD.show(withStatus: "Bind Success. \n devId: \(device?.uniqueID ?? "") \n name: \(device?.name ?? "")")
}
}
extension BEMatterTableViewController: ThingSmartActivatorDeviceExpandDelegate {
func matterDeviceDiscoveryed(_ typeModel: ThingMatterDeviceDiscoveriedType) {
deviceTypeModel = typeModel
}
func matterCommissioningSessionEstablishmentComplete(_ deviceModel: ThingSmartActivatorDeviceModel) {
if deviceTypeModel?.deviceType == .wifi {
self.typeModel.ssid = ssid.text ?? ""
self.typeModel.password = password.text ?? ""
self.discovery.continueCommissionDevice(deviceModel, typeModel: self.typeModel)
}
///
if deviceTypeModel?.deviceType == .thread {
self.typeModel.gwDevId = "your gateway id"
self.discovery.continueCommissionDevice(deviceModel, typeModel: self.typeModel)
}
}
func matterDeviceAttestation(_ device: UnsafeMutableRawPointer, error: Error) {
let alertControl = UIAlertController(title: "Attestation", message: "Should Continue?", preferredStyle: .alert)
let alertAction = UIAlertAction(title: "Continue", style: .default) { _ in
self.discovery.continueCommissioningDevice(device, ignoreAttestationFailure: true, error: nil)
}
let canAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in
self.discovery.continueCommissioningDevice(device, ignoreAttestationFailure: false, error: nil)
}
alertControl.addAction(alertAction)
alertControl.addAction(canAction)
self.present(alertControl, animated: true)
}
}
Objective-C:
- (void)getToken {
ThingSmartActivator *wiredActivator = [[ThingSmartActivator alloc] init];
[wiredActivator getTokenWithHomeId:homeId success:^(NSString *token) {
NSLog(@"getToken success: %@", token);
[self startConfigWiFi:token];
} failure:^(NSError *error) {
NSLog(@"getToken failure: %@", error.localizedDescription);
}];
}
- (void)startConfigWiFi:(NSString *)token {
ThingSmartActivatorTypeMatterModel *matterType = [[ThingSmartActivatorTypeMatterModel alloc] init];
matterType.type = ThingSmartActivatorTypeMatter;
matterType.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorTypeMatter);
matterType.timeout = 120;
matterType.spaceId = homeId;
matterType.token = token;
[self.discovery registerWithActivatorList:@[matterType]];
[self.discovery setupDelegate:self];
[self.discovery startSearch:@[matterType]];
}
- (void)activatorService:(id<ThingSmartActivatorSearchProtocol>)service activatorType:(ThingSmartActivatorTypeModel *)type didFindDevice:(ThingSmartActivatorDeviceModel *)device error:(ThingSmartActivatorErrorModel *)errorModel {
if (errorModel) {
[self _connectWifiError:errorModel];
return;
}
if (device) {
[self _handleDevice:device];
}
}
- (void)_handleDevice:(ThingSmartActivatorDeviceModel *)deviceModel {
ThingSmartActivatorTypeMatterModel *matterType = (ThingSmartActivatorTypeMatterModel *)[self.discovery activatorTypeModelWith:ThingSmartActivatorTypeMatter];
[self.discovery startActive:matterType deviceList:@[deviceModel]];
}
- (void)matterRoutingComplete:(ThingSmartMatterRoutingType)routingType {
self.routingType = routingType;
if (routingType == ThingSmartMatterRoutingTypeSupport) {
}
}
-(void)matterCommissioningSessionEstablishmentComplete:(ThingSmartActivatorDeviceModel *)deviceModel {
if (self.routingType == ThingSmartMatterRoutingTypeThing && deviceModel.deviceModelType == ThingSearchDeviceModelTypeMatterThread) {
self.matterType..gwDevId = gatewayID;
[self.discovery continueCommissionDevice:deviceModel typeModel:self.matterType];
}
if (self.routingType == ThingSmartMatterRoutingTypeThing && deviceModel.deviceModelType == ThingSearchDeviceModelTypeMatterWifi) {
self.matterType.ssid = factoryConfig.ssid;
self.matterType.password = factoryConfig.password;
[self.discovery continueCommissionDevice:deviceModel typeModel:self.matterType];
}
}
- (void)activatorService:(id<ThingSmartActivatorActiveProtocol>)service
activatorType:(ThingSmartActivatorTypeModel *)type
didReceiveDevices:(nullable NSArray<ThingSmartActivatorDeviceModel *> *)devices
error:(nullable ThingSmartActivatorErrorModel *)errorModel {
if (devices && devices.count > 0) {
}
}
- (ThingSmartActivatorDiscovery *)discovery {
if (!_discovery) {
_discovery = [[ThingSmartActivatorDiscovery alloc] init];
}
return _discovery;
}
Swift:
class BEMatterTableViewController: UITableViewController {
/// UI
private var typeModel: ThingSmartActivatorTypeMatterModel = {
let type = ThingSmartActivatorTypeMatterModel()
type.type = ThingSmartActivatorType.matter
type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorType.matter)
type.timeout = 180
return type
}()
lazy var discovery: ThingSmartActivatorDiscovery = {
let discovery = ThingSmartActivatorDiscovery()
discovery.register(withActivatorList: [self.typeModel])
discovery.setupDelegate(self)
discovery.loadConfig()
return discovery
}()
func bindMatter(qrcode codeStr: String?) -> Void {
let homeId = (Home.current?.homeId)!
let payload = self.discovery.parseSetupCode(codeStr ?? "")
let activator = ThingSmartActivator()
activator.getTokenWithHomeId(homeId, success: { [weak self] (token) in
guard let self = self else { return }
self.typeModel.token = token ?? ""
self.typeModel.spaceId = homeId
self.discovery.startActive(self.typeModel, deviceList:[payload])
SVProgressHUD.show(withStatus: NSLocalizedString("Configuring", comment: ""))
}, failure: { (error) in
let errorMessage = error?.localizedDescription ?? ""
SVProgressHUD.showError(withStatus: errorMessage)
})
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = QRCodeScanerViewController()
vc.scanCallback = { [weak self] codeStr in
self?.bindMatter(qrcode: codeStr)
}
navigationController?.pushViewController(vc, animated: true)
}
}
extension BEMatterTableViewController: 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
isSuccess = true
SVProgressHUD.show(withStatus: "Bind Success. \n devId: \(device?.uniqueID ?? "") \n name: \(device?.name ?? "")")
}
}
extension BEMatterTableViewController: ThingSmartActivatorDeviceExpandDelegate {
func matterDeviceDiscoveryed(_ typeModel: ThingMatterDeviceDiscoveriedType) {
deviceTypeModel = typeModel
}
func matterCommissioningSessionEstablishmentComplete(_ deviceModel: ThingSmartActivatorDeviceModel) {
if deviceTypeModel?.deviceType == .wifi {
self.typeModel.ssid = ssid.text ?? ""
self.typeModel.password = password.text ?? ""
self.discovery.continueCommissionDevice(deviceModel, typeModel: self.typeModel)
}
///
if deviceTypeModel?.deviceType == .thread {
self.typeModel.gwDevId = "your gateway id"
self.discovery.continueCommissionDevice(deviceModel, typeModel: self.typeModel)
}
}
func matterDeviceAttestation(_ device: UnsafeMutableRawPointer, error: Error) {
let alertControl = UIAlertController(title: "Attestation", message: "Should Continue?", preferredStyle: .alert)
let alertAction = UIAlertAction(title: "Continue", style: .default) { _ in
self.discovery.continueCommissioningDevice(device, ignoreAttestationFailure: true, error: nil)
}
let canAction = UIAlertAction(title: "Cancel", style: .cancel) { _ in
self.discovery.continueCommissioningDevice(device, ignoreAttestationFailure: false, error: nil)
}
alertControl.addAction(alertAction)
alertControl.addAction(canAction)
self.present(alertControl, animated: true)
}
}
Objective-C:
- (void)getToken {
ThingSmartActivator *wiredActivator = [[ThingSmartActivator alloc] init];
[wiredActivator getTokenWithHomeId:homeId success:^(NSString *token) {
NSLog(@"getToken success: %@", token);
[self startConfigWiFi:token];
} failure:^(NSError *error) {
NSLog(@"getToken failure: %@", error.localizedDescription);
}];
}
- (void)startConfigWiFi:(NSString *)token {
ThingSmartActivatorTypeMatterModel *matterType = [[ThingSmartActivatorTypeMatterModel alloc] init];
matterType.type = ThingSmartActivatorTypeMatter;
matterType.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorTypeMatter);
matterType.timeout = 120;
matterType.spaceId = homeId;
matterType.token = token;
[self.discovery registerWithActivatorList:@[matterType]];
[self.discovery setupDelegate:self];
ThingSmartActivatorDeviceModel *deviceModel = [self.discovery parseSetupCode:code];
if (deviceModel) {
[self.discovery startActive:matterType deviceList:@[deviceModel]];
} else {
}
}
//Follow-up processing logic is consistent with search activate
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback