Wi-Fi 列表获取

更新时间:2025-05-21 02:08:17下载pdf

设备 TuyaOS 版本 v3.10.0 及以上的双模设备支持 Wi-Fi 列表获取功能。此功能弥补了因移动设备权限限制等原因无法获取周围 Wi-Fi 列表的不足。设备可获取的 Wi-Fi 均是设备可连接的,从而解决了因用户输入不可用 Wi-Fi 信息而导致配网失败的问题,提升配网成功率。

以下将介绍如何在配网流程中使用扩展 SDK 获取 Wi-Fi 列表,作为 双模设备配网 的一种优化策略:

  1. 搜索双模设备,查询设备能力,判断是否支持 ThingActivatorDeviceAbilityWifiList
  2. 调用接口查询 Wi-Fi 列表,成功则返回 Wi-Fi 列表,失败则返回失败信息。
  3. 选择一个 Wi-Fi,输入密码进行配网。

接入配网扩展 SDK

在 Podfile 文件中添加以下依赖,核心依赖为 ThingSmartBusinessExtensionKit,蓝牙实现依赖为 ThingSmartBusinessExtensionKitBLEExtra

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

target 'Your_Project_Name' do
    # 从涂鸦开发者平台(https://platform.tuya.com)构建和获取 ThingSmartCryption
    # 购买正式版后,需重新在涂鸦开发者平台构建 SDK 并重新集成
    # ./ 代表将 ios_core_sdk.tar.gz 解压之后所在目录与 Podfile 同级
    # 若自定义存放目录,可以修改 Path 为自定义目录层级
    pod 'ThingSmartCryption', :path =>'./'
    pod 'ThingSmartHomeKit'
    pod 'ThingSmartBusinessExtensionKit'
    #蓝牙实现层
    pod 'ThingSmartBusinessExtensionKitBLEExtra'

end

接口说明

注册配网类型

在基座初始化时,需要注册配网类型。对于双模设备,配网类型为 ThingSmartActivatorTypeBle,模型为 ThingSmartActivatorTypeBleModel

设备类型 配网类型 模型
蓝牙单点、双模 ThingSmartActivatorTypeBle ThingSmartActivatorTypeBleModel

蓝牙配网模型

/// 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

注册方法

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

该方法声明于 ThingSmartActivatorDiscoveryManager.h 头文件中。

参数说明

参数 说明
typeList 配网类型列表

查询 Token

使用涂鸦 SDK 获取配网 Token,然后进行设备配网。Token 的有效期为 10 分钟,且配置成功后就会失效。再次配网时,需要重新查询 Token。

接口说明

/**
 * 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;

参数说明

参数 说明
homeId 设备将要绑定到的家庭的 ID
success 成功回调,返回配网 Token
failure 失败回调,返回失败原因

开始搜索

开始搜索时,需要传入已注册的 typeList

接口说明

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

参数说明

参数 说明
typeList 配网类型列表

停止搜索

接口说明

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

参数说明

参数 说明
typeList 配网类型列表
clearCache 是否清空当前搜索设备缓存

设备搜索回调

成功搜索到蓝牙设备后,会通过搜索回调返回设备信息。如果失败,则会返回对应的失败信息。

接口说明

/**
 * 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;

参数说明

参数 说明
service 配网服务
type 配网类型
device 发现设备,返回此次配网的设备模型,失败时返回 nil
errorModel 搜索蓝牙设备时,未搜到设备以及搜索超时的情况下均不返回此模型

获取 Wi-Fi 列表

通过 ThingSmartActivatorDeviceModel 类的 supportAbilityWifiList 方法,可以判断搜索到的设备是否支持 Wi-Fi 列表获取功能。该方法声明于 ThingSmartActivatorDeviceModel.h 头文件中。

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

如果设备支持 Wi-Fi 列表获取功能,在 ThingSmartActivatorDiscovery 类中,使用 ThingSmartActivatorBleProtocol 协议提供的 -scanWifiList:activatorTypeModel:deviceModel: 方法来获取 Wi-Fi 列表。该方法声明于 ThingSmartActivatorBleProtocol.h 头文件中。

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

Wi-Fi 列表的回调通过通用的设备信息回调方法如下所示,该方法声明于 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;

请求 Wi-Fi 列表时,response 返回值为 ThingActivatorDeviceResponseData 类型,且 response.responseTypeThingActivatorResponseTypeWifiListresponse.responseDataNSArray 类型。返回的 Wi-Fi 列表数据示例如下所示,其中:

  • rssi:接收到的信号强度
  • sec:安全配置
  • ssid:标识网络名称
{
  {
      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 with a single pairing type
 * @param type Pairing type
 * @param deviceList Devices to be activated
 */
- (void)startActive:(ThingSmartActivatorTypeModel *)type deviceList:(NSArray<ThingSmartActivatorDeviceModel *>*)deviceList;

参数说明

参数 说明
type 配网类型
deviceList 待激活设备列表,目前仅支持单个设备

停止激活

接口说明

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

参数说明

参数 说明
typeList 配网类型
clearCache 清空缓存设备信息

设备激活回调

接口说明

/**
 * 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;

参数说明

参数 说明
service 配网服务
type 配网类型
devices 激活成功设备
errorModel 配网失败或者超时,返回此模型,成功时返回 nil

示例代码

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
        }
    }
}