智能摄像头扫码配网

更新时间:2023-09-27 03:32:48下载pdf

扫码配网指的是设备扫描 App 生成的二维码,二维码包含 Wi-Fi 信息和 token,设备扫描成功后,主动连接到路由器去云端进行激活的配网方式。主要针对具有摄像头扫描功能和 Wi-Fi 模组的设备,所以通常是智能摄像头或是带有摄像头的设备(如可视门铃)支持二维码配网。

配网流程

App业务拓展 SDK云端设备路由器设备进入配网模式请求配网 Token1请求配网 Token2返回配网 Token3返回配网 Token4用户输入路由器名称和-密码从而生成一个二维-扫描设备二维码5开始配对6开始配对7连接路由器8连接成功9指示灯常亮激活设备10成功激活设备11返回设备列表12返回设备列表13App业务拓展 SDK云端设备路由器扫码配网流程

注册配网类型

基座初始化时,需要注册一下配网的类型,扫码配网模式对应为 ThingSmartActivatorTypeQRCodeModel

接口说明

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

参数说明

参数 说明
typeList 配网类型列表

查询 Token

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

接口说明

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

参数说明

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

二维码字符串

获取到配网 Token 后,还需要有期望设备连接的 Wi-Fi 的 ssid 和密码,通过下面的方式拼接成字符串,然后根据该字符串生成一个二维码图片。

Objective-C

NSDictionary *dictionary = @{
@"s": self.ssid,
@"p": self.pwd,
@"t": self.token
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
self.wifiJsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

Swift

let dictionary = [
    "s": self.ssid,
    "p": self.pwd,
    "t": self.token
]
let jsonData = JSONSerialization.data(withJSONObject: dictionary, options: JSONSerialization.WritingOptions.Element)
self.wifiJsonStr = String(data: jsonData, encoding: String.Encoding.utf8)

开始搜索

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

接口说明

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

参数说明

参数 说明
typeList 配网类型列表

停止搜索

接口说明

/// Stop searching
/// @param typeList Network configuration 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 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;

参数说明

参数 说明
service 配网服务
type 配网类型,此处返回 ThingSmartActivatorTypeQRCodeModel
device 发现设备,返回此次配网的设备模型,失败时返回 nil
errorModel 如果配网失败或者超时,返回此模型,成功时返回 nil

设备信息更新回调

接口说明

/// Device information update or device rediscovered on a different channel
/// @param service Search instance
/// @param type Network configuration type
/// @param device Device model
- (void)activatorService:(id<ThingSmartActivatorSearchProtocol>)service
            activatorType:(ThingSmartActivatorTypeModel *)type
           didUpdateDevice:(ThingSmartActivatorDeviceModel *)device;

参数说明

参数 说明
service 配网服务
type 配网类型,此处返回 ThingSmartActivatorTypeQRCodeModel
device 返回变化的设备信息

错误码说明

配网失败或者配网超时的情况下,会返回 ThingSmartActivatorErrorModel

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

其中 error 对应的错误码,定义在 ThingSmartActivatorDiscoveryError 中。下表展示了常见错误与说明。

错误码 配网错误
ThingSmartActivatorDiscoveryErrorTimeout 配网超时。
ThingSmartActivatorDiscoveryErrorDeviceAlreadyBound 设备强绑定错误。该设备已经被用户绑定,无法被第二个用户绑定,需要第一个用户解绑才能完成配网操作。
ThingSmartActivatorDiscoveryErrorAPPUnsupportProduct 配网账号的 App 和产品没有绑定关系。
ThingSmartActivatorDiscoveryErrorTokenExpired Token 失效。
ThingSmartActivatorDiscoveryErrorGuestNotSupportStrongBind 游客模式无法对强绑定设备进行配网。
ThingSmartActivatorDiscoveryErrorRemoteApiParamIllegal 接口参数不合法。

示例代码

Swift

class qrmodeConfigurationVC: UITableViewController {

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


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

    private func startConfiguration() {
        guard let homeID = Home.current?.homeId else { return }
        SVProgressHUD.show(withStatus: NSLocalizedString("Requesting for Token", comment: ""))

        ThingSmartActivator.sharedInstance()?.getTokenWithHomeId(homeID, success: { [weak self] (token) in
            guard let self = self else { return }
            self.token = token ?? ""
            self.startConfiguration(with: self.token)
        }, failure: { (error) in
            let errorMessage = error?.localizedDescription ?? ""
            SVProgressHUD.showError(withStatus: errorMessage)
        })
    }

    private func startConfiguration(with token: String) {
        SVProgressHUD.show(withStatus: NSLocalizedString("Configuring", comment: ""))
        guard let homeID = Home.current?.homeId else { return }
        typeModel.token = self.token;
        typeModel.spaceId = homeID
        discovery.startSearch([typeModel])
    }
}

extension qrmodeConfigurationVC: 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 (device != nil) {
            if device?.step == ThingActivatorStep.found {
                // device find
            }
        }
    }

    func activatorService(_ service: ThingSmartActivatorSearchProtocol, activatorType type: ThingSmartActivatorTypeModel, didUpdateDevice device: ThingSmartActivatorDeviceModel) {
        if device.step == ThingActivatorStep.intialized {
            // Success
            let name = device.name
            SVProgressHUD.showSuccess(withStatus: NSLocalizedString("Successfully Added \(name)", comment: "Successfully added one device."))
            navigationController?.popViewController(animated: true)
        }
    }
}

Objective-C

/// Get token
- (void)getToken {
    ThingSmartActivator *qrActivator = [[ThingSmartActivator alloc] init];
    [qrActivator getTokenWithHomeId:homeId success:^(NSString *token) {
        NSLog(@"getToken success: %@", token);
        [self startConfigWiFi:token];
    } failure:^(NSError *error) {
        NSLog(@"getToken failure: %@", error.localizedDescription);
    }];
}

/// Start activate
- (void)startConfigQRCode:(NSString *)token {
  ThingSmartActivatorTypeQRCodeModel *qrCodeModel  = [[ThingSmartActivatorTypeQRCodeModel alloc] init];
  qrCodeModel.type = ThingSmartActivatorTypeQRCode;
  qrCodeModel.typeName = NSStringFromThingSmartActivatorType(ThingSmartActivatorTypeQRCode);
  qrCodeModel.timeout = 120;
  qrCodeModel.spaceId = homeId;

  [self.discovery registerWithActivatorList:@[qrCodeModel]];
  [self.discovery setupDelegate:self];

  [self.discovery startSearch:@[qrCodeModel]];
}

- (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)activatorService:(id<ThingSmartActivatorSearchProtocol>)service activatorType:(ThingSmartActivatorTypeModel *)type didUpdateDevice:(ThingSmartActivatorDeviceModel *)device {
    if (device) {
        [self _handleDevice:device];
    }
}

- (void)_handleDevice:(ThingSmartActivatorDeviceModel *)device {
    ThingActivatorStep step = device.step;

    if (step == ThingActivatorStepFound) {
      // discovery device
    } else if (step == ThingActivatorStepRegisted) {
      // device registe
    } else if (step == ThingActivatorStepIntialized) {
        /// activated successfully
    }
}

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