Get Wi-Fi Networks

Last Updated on : 2025-05-22 01:57:01download

Combo devices running TuyaOS v3.10.0 or later support Wi-Fi network list retrieval during pairing. This feature addresses the limitation of being unable to get nearby Wi-Fi networks due to mobile device permission restrictions. The Wi-Fi networks retrieved by the device are all connectable. This resolves the issue of pairing failures caused by users entering unavailable Wi-Fi credentials, helping to improve the pairing success rate.

The following describes how to use the extension SDK to get the list of Wi-Fi networks during the pairing process, as an optimization strategy for combo device pairing.

  1. Search for combo devices, query device capabilities, and determine whether ThingActivatorDeviceAbilityWifiList is supported.
  2. Call the APIs to query the list of Wi-Fi networks. Available Wi-Fi networks are returned on success, and a failure message is returned on failure.
  3. Select a Wi-Fi network and enter the password to pair the device.

Integrate Device Pairing Extension SDK

Add dependencies to the Podfile, including the core dependency ThingSmartBusinessExtensionKit and the Bluetooth implementation dependency ThingSmartBusinessExtensionKitBLEExtra.

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. For combo devices, the pairing type is ThingSmartActivatorTypeBle and the model is ThingSmartActivatorTypeBleModel.

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

Register method

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

This method is declared in the ThingSmartActivatorDiscoveryManager.h header file.

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

/**
 * Get token with home id
 * @param homeId  home id
 * @param success success block
 * @param failure failure block
 */
- (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 to be 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 a Bluetooth device is discovered, the callback returns the device information. If the operation fails, the callback returns an 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.

Get Wi-Fi networks

The supportAbilityWifiList method of the ThingSmartActivatorDeviceModel class can be used to determine whether the discovered device supports the Wi-Fi network list retrieval feature. This method is declared in the ThingSmartActivatorDeviceModel.h header file.

/**
 *  Determine whether the device supports the capability to obtain a Wi-Fi list
 */
- (BOOL)supportAbilityWifiList;

If the device supports this feature, in the ThingSmartActivatorDiscovery class, you can use the -scanWifiList:activatorTypeModel:deviceModel: method provided by the ThingSmartActivatorBleProtocol protocol to get the list of Wi-Fi networks. This method is declared in the ThingSmartActivatorBleProtocol.h header file.

/**
 *  Get wifi list
 *  @param ssid          ssid
 *  @param typeModel     typeModel
 *  @param deviceModel   deviceModel
 */
- (void)scanWifiList:(NSString *)ssid
   activatorTypeModel:(ThingSmartActivatorTypeModel *)typeModel
          deviceModel:(ThingSmartActivatorDeviceModel *)deviceModel;

The Wi-Fi list callback is delivered via the universal device information callback method declared in ThingSmartActivatorActiveProtocol.h.

/**
 * Response information from the device (required for AP/BLE/Broadband service).
 * @param service Pairing instance.
 * @param type Pairing type.
 * @param response Response information from the device.
 * @param errorModel Error returned by the device.
 */
- (void)activatorService:(id<ThingSmartActivatorActiveProtocol>)service
           activatorType:(ThingSmartActivatorTypeModel *)type
      didReceiveResponse:(id __nullable)response
                   error:(nullable ThingSmartActivatorErrorModel *)errorModel;

When requesting the Wi-Fi network list, the response return value is of type ThingActivatorDeviceResponseData. The response.responseType is ThingActivatorResponseTypeWifiList, and the response.responseData is of type NSArray. The following is an example of the returned Wi-Fi list data:

  • rssi: The received signal strength indicator.
  • sec: The security configuration.
  • ssid: The service set identifier that uniquely names a Wi-Fi network.
{
  {
      rssi = "-45";
      sec = 5;
      ssid = "OS_BASE_2G";
  },
  {
      rssi = "-50";
      sec = 5;
      ssid = "11S-11-11";
  },
  {
      rssi = "-52";
      sec = 5;
      ssid = We;
  },
  {
      rssi = "-53";
      sec = 5;
      ssid = "Tuya-Test";
  },
  {
      rssi = "-55";
      sec = 5;
      ssid = "TP-LINK_001";
  }
}

Activate devices

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 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 pairing types
 * @param clearCache Whether to clear the cache
 */
- (void)stopActive:(NSArray <ThingSmartActivatorTypeModel *>*)typeList clearCache:(BOOL)clearCache;

Parameters

Parameter Description
typeList The pairing type.
clearCache Specifies whether to clear the cache device information.

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 The pairing type.
devices The activated device.
errorModel This model is returned if pairing fails or times out. nil is returned on success.

Example

class BEDualModeWifiListTableViewController: UIViewController, UITextFieldDelegate {

    // MARK: - Discovery service
    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
    }()

    // MARK - Activator type
    private lazy var typeModel: ThingSmartActivatorTypeBleModel = {
        let type = ThingSmartActivatorTypeBleModel()
        type.type = ThingSmartActivatorType.ble
        type.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorType.ble)
        type.timeout = 120
        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
    }()

    @objc private func searchTapped() {
        // Start finding un-paired BLE devices
        discovery.startSearch([self.typeModel])
    }

    private func stopConfiguring() {
        discovery.stopSearch([self.typeModel], clearCache: true)
        discovery.stopActive([self.typeModel], clearCache: true)
        discovery.removeDelegate(self)
    }

    private func getWiFiList() {
        guard let device = selectedDevice, device.supportAbilityWifiList() else {
            SVProgressHUD.showError(withStatus: "Device does not support WiFi list")
            return
        }

        SVProgressHUD.show(withStatus: "Getting WiFi List")
        let param = ThingSmartActivatorScanWifiParam.default()
        param.uuid = device.uniqueID;
        discovery.scanWifiList(
            param,
            activatorTypeModel: typeModel,
            deviceModel: device
        )
    }

    @IBAction func connectButtonTapped(_ sender: UIButton) {
        /// Start pairing device
        guard let device = selectedDevice,
              let wifi = selectedWiFi,
              let ssid = wifi["ssid"] as? String else {
            return
        }

        typeModel.ssid = ssid
        typeModel.password = passwordTextField.text ?? ""
        device.selectAbility = .wifiList
        ThingSmartActivator.sharedInstance()?.getTokenWithHomeId(typeModel.spaceId, success: { [weak self] (token) in
            guard let self = self else { return }
            typeModel.token = token ?? ""
            discovery.startActive(typeModel, deviceList: [device])
            SVProgressHUD.show(withStatus: NSLocalizedString("Activating", comment: "Active BLE."))
        }, failure: { (error) in

        })
    }
}

// MARK: - ThingSmartActivatorSearchDelegate
extension BEDualModeWifiListTableViewController: ThingSmartActivatorSearchDelegate {
    func activatorService(
        _ service: ThingSmartActivatorSearchProtocol,
        activatorType type: ThingSmartActivatorTypeModel,
        didFindDevice device: ThingSmartActivatorDeviceModel?,
        error errorModel: ThingSmartActivatorErrorModel?
    ) {
        if let errorModel = errorModel {
            SVProgressHUD.showError(withStatus: errorModel.error.localizedDescription)
            return
        }

        if let device = device {
            if device.deviceModelType == ThingSearchDeviceModelTypeBle {
                print("Please use Dual Mode to pair: \(device.uniqueID)")
                return
            }

            if device.deviceModelType == ThingSearchDeviceModelTypeBleWifi {
                if !deviceList.contains(where: { $0.uniqueID == device.uniqueID }) {
                    deviceList.append(device)
                    tableView.reloadData()
                }
            }

            SVProgressHUD.dismiss()
        }
    }

}

// MARK: - ThingSmartActivatorActiveDelegate
extension BEDualModeWifiListTableViewController: ThingSmartActivatorActiveDelegate {
    func activatorService(
        _ service: ThingSmartActivatorActiveProtocol,
        activatorType type: ThingSmartActivatorTypeModel,
        didReceiveDevices devices: [ThingSmartActivatorDeviceModel]?,
        error errorModel: ThingSmartActivatorErrorModel?
    ) {
        if let errorModel = errorModel {
            SVProgressHUD.showError(withStatus: errorModel.error.localizedDescription)
            return
        }

        if let devices = devices, let device = devices.first {
            if let index = deviceList.firstIndex(where: { $0.uniqueID == device.uniqueID }) {
                deviceList[index].deviceStatus = ThingSearchDeviceStatusNetwork
                tableView.reloadData()
                SVProgressHUD.showSuccess(withStatus: "Device activated successfully")
                isSuccess = true
            }
        }
    }
}

// MARK: - ThingSmartActivatorDeviceExpandDelegate
extension BEDualModeWifiListTableViewController: ThingSmartActivatorDeviceExpandDelegate {

    func activatorService(
        _ service: ThingSmartActivatorActiveProtocol,
        activatorType type: ThingSmartActivatorTypeModel,
        didReceiveResponse response: Any?,
        error errorModel: ThingSmartActivatorErrorModel?
    ) {

        if let response = response as? ThingActivatorDeviceResponseData,
           response.responseType == .wifiList,
           let wifiArray = response.responseData as? [[String: Any]] {
            wifiList = wifiArray
            tableView.reloadData()
            SVProgressHUD.dismiss()
        }

        if let errorModel = errorModel {
            SVProgressHUD.showError(withStatus: errorModel.error.localizedDescription)
            return
        }
    }
}