JLChen
2021-05-18 a869383e163a18cdedcf587383c1eca043129754
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
//
//  Copyright © 2018年 dahua. All rights reserved.
//
 
#import "DHNetSDKInitialManager.h"
#import "DHDeviceNetInfo.h"
#import "DHNetSDKInterface.h"
#import <LCAddDeviceModule/LCAddDeviceModule-Swift.h>
 
@interface DHNetSDKInitialManager()
 
@property (nonatomic,copy) NSString *pwdString;
 
@end
 
@implementation DHNetSDKInitialManager
 
#pragma mark - circle life
 
- (instancetype)init {
    if(self = [super init]) {
 
    }
    return self;
}
 
#pragma mark - singleton
 
static DHNetSDKInitialManager *_instance = nil;
+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}
 
#pragma mark - interface
 
- (void)initialDeviceWithPassWord:(NSString *)pwdString
                         isSoftAp:(BOOL)isSoftAp
                  withInitialType:(DHDeviceInitType)initialType
                 withSuccessBlock:(InitialSuccessHandle)success
                 withFailureBlock:(InitialFailHandle)fail {
    if (isSoftAp) {
        [self initialApDeviceWithPassword:pwdString withInitialType:initialType withSuccessBlock:success withFailureBlock:fail];
    } else {
        [self initialCommonDeviceWithPassWord:pwdString withInitialType:initialType withSuccessBlock:success withFailureBlock:fail];
    }
}
 
-(void)initialCommonDeviceWithPassWord:(NSString *)pwdString
                       withInitialType:(DHDeviceInitType)initialType
                      withSuccessBlock:(InitialSuccessHandle)success
                      withFailureBlock:(InitialFailHandle)fail {
    /*
     **初始化逻辑**
     新设备程序在配网成功的情况下,可以根据搜索得到的设备信息中的specialAbility的bit2-3位判断IP是否有效(老设备程序无此能力,但可以根据此字段确定是否新老程序),所以初始化逻辑重要有以下三种:
     1、老设备程序:specialAbility的bit2-3位为0,此时走老的组播单播初始化逻辑
     2、IP有效:直接走单播初始化逻辑,节省了组播初始化时间
     3、IP无效:则需要等待DHCP分配IP成功才可以进行初始化。SearchManager在后台持续搜索,当DHCP分配成功,设备会重新发广播上报,SearchManager能够更新搜索到的设备信息,因此在IP无效的情况下,InitialManager(本类)只需要每隔0.5秒从SearchManager更新一次搜索结果,等待DHCP分配成功,根据获取到的有效IP进行单播初始化,20次以后DHCP未分配成功则初始化失败。
     */
    
    NSLog(@"DHNetSDKInitialManager::Initial common device with type:%lu", (unsigned long)initialType);
    self.pwdString = pwdString;
    
    switch (initialType) {
            //老设备程序
        case DHDeviceInitTypeOldDevice:
            [self multicastWithPassWord:pwdString withInitialType:initialType withSuccessBlock:success withFailureBlock:fail];
            break;
            
            //IP有效初始化
        case DHDeviceInitTypeIPEnable:
            [self unicastWithPassWord:pwdString withInitialType:initialType withSuccessBlock:success withFailureBlock:fail];
            break;
            
            //IP无效
        case DHDeviceInitTypeIPUnable:
        {
            //计数器
            __block int count = 0;
            //计数最大值
            int maxCount = 20;
            //定时器对象
            __block dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
            //从现在开始,每0.5秒执行一次
            dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC), 0);
            //定时器回调
            dispatch_source_set_event_handler(timer, ^{
                
                NSLog(@"CGD定时器-----%@",[NSThread currentThread]);
                count++;
                if (count == maxCount) { // 执行20次(10秒后),释放定时器
                    dispatch_async(dispatch_get_main_queue(), ^{
                        //fail();
                        
                        //超时失败后,走老的初始化
                        [self initialCommonDeviceWithPassWord:pwdString withInitialType:DHDeviceInitTypeOldDevice withSuccessBlock:success withFailureBlock:fail];
                    });
 
                    dispatch_cancel(timer);
                    timer = nil;
                }else{
                    //更新设备信息,获取IP
                    DHDeviceNetInfo *deviceNetInfo = [self updateDeviceSearchInfo];
                    if (deviceNetInfo.deviceInitType == DHDeviceInitTypeIPEnable){
                        //最新IP有效
                        if ([self unicastIpWithDeviceInfo:deviceNetInfo isMulticast:NO]) {
                            //单播初始化成功
                            dispatch_async(dispatch_get_main_queue(), ^{
                                success();
                            });
                        }else{
                            //单播初始化失败
                            dispatch_async(dispatch_get_main_queue(), ^{
                                fail();
                            });
                        }
                        dispatch_cancel(timer);
                        timer = nil;
                    }
                    
                }
            });
            //启动定时器
            dispatch_resume(timer);
        }
            break;
            
        default:
            break;
    }
}
 
- (void)initialApDeviceWithPassword:(NSString *)pwdString
                    withInitialType:(DHDeviceInitType)initialType
                   withSuccessBlock:(InitialSuccessHandle)success
                   withFailureBlock:(InitialFailHandle)fail {
    NSLog(@"DHNetSDKInitialManager::Initial ap device with type:%lu", (unsigned long)initialType);
    self.pwdString = pwdString;
    
    switch (initialType) {
            //老设备程序或者IP效,均走老流程
        case DHDeviceInitTypeOldDevice:
        case DHDeviceInitTypeIPUnable:
            [self multicastWithPassWord:pwdString withInitialType:initialType withSuccessBlock:success withFailureBlock:fail];
            break;
            
            //IP有效初始化
        case DHDeviceInitTypeIPEnable:
            [self unicastWithPassWord:pwdString withInitialType:initialType withSuccessBlock:success withFailureBlock:fail];
            break;
            
        default:
            break;
    }
}
 
- (void)multicastWithPassWord:(NSString *)pwdString
              withInitialType:(DHDeviceInitType)initialType
             withSuccessBlock:(InitialSuccessHandle)success
             withFailureBlock:(InitialFailHandle)fail {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //组播 前三次发组播包 每次五秒
        DHDeviceNetInfo *deviceNetInfo = [self updateDeviceSearchInfo];
        if(deviceNetInfo==nil)
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                fail();
            });
        }else if ([self multicastWithDeviceInfo:deviceNetInfo isMulticast:YES]) {
            //组播初始化成功
            dispatch_async(dispatch_get_main_queue(), ^{
                success();
            });
        }else{
            //组播初始化失败,获取最新的设备信息进行单播初始化
            deviceNetInfo = [self updateDeviceSearchInfo];
            if(deviceNetInfo==nil)
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    fail();
                });
            }
            else if ([self unicastIpWithDeviceInfo:deviceNetInfo isMulticast:NO]) {
                //单播初始化成功
                dispatch_async(dispatch_get_main_queue(), ^{
                    success();
                });
            }
            else {
                //单播初始化失败
                dispatch_async(dispatch_get_main_queue(), ^{
                    fail();
                });
            }
        }
    });
}
 
- (void)unicastWithPassWord:(NSString *)pwdString
            withInitialType:(DHDeviceInitType)initialType
           withSuccessBlock:(InitialSuccessHandle)success
           withFailureBlock:(InitialFailHandle)fail {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        DHDeviceNetInfo *deviceNetInfo = [self updateDeviceSearchInfo];
        if ([self unicastIpWithDeviceInfo:deviceNetInfo isMulticast:NO]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                success();
            });
        }
        else {
            dispatch_async(dispatch_get_main_queue(), ^{
                fail();
            });
        }
    });
}
 
#pragma mark - private
 
- (BOOL)unicastIpWithDeviceInfo:(DHDeviceNetInfo *)deviceNetInfo isMulticast:(BOOL)isMulticast {
    DHDeviceInfoLogModel *model = [DHNetSDKInterface initDevAccount:self.pwdString device:deviceNetInfo useIp:YES];
    [self addDeviceNetSDKLog:model.isSuccess];
    [self addDeviceInitLog:deviceNetInfo info:model isMulticast:isMulticast];
    return model.isSuccess;
}
 
- (BOOL)multicastWithDeviceInfo:(DHDeviceNetInfo *)deviceNetInfo isMulticast:(BOOL)isMulticast {
    DHDeviceInfoLogModel *model = [DHNetSDKInterface initDevAccount:self.pwdString device:deviceNetInfo useIp:NO];
    [self addDeviceNetSDKLog:model.isSuccess];
    [self addDeviceInitLog:deviceNetInfo info:model isMulticast:isMulticast];
    return model.isSuccess;
}
 
//从DHNetSDKSearchManager获取最新的设备搜索信息
- (DHDeviceNetInfo*)updateDeviceSearchInfo {
    
    NSString *deviceID = [DHAddDeviceManager sharedInstance].deviceId;
    DHDeviceNetInfo *deviceNetInfo = [[DHNetSDKSearchManager sharedInstance] getNetInfoByID:deviceID];
    return deviceNetInfo;
}
 
- (void)addDeviceNetSDKLog:(BOOL)isSuccess
{
    DHAddDeviceLogModel *model = [[DHAddDeviceLogModel alloc] init];
    model.method = @"initDevAccount";
    model.res = isSuccess ? model.res : model.resFail;
    model.errCode = isSuccess ? model.errCode : [DHNetSDKInterface getLastError];
    [[DHAddDeviceLogManager shareInstance] addDeviceNetSDKLogWithModel:model];
}
 
- (void)addDeviceInitLog:(DHDeviceNetInfo *)deviceNetInfo info:(DHDeviceInfoLogModel *)info isMulticast:(BOOL)isMulticast
{
    DHAddDeviceLogModel *model = [[DHAddDeviceLogModel alloc] init];
    model.deviceInfo = info;
    model.type = isMulticast ? model.initDev : model.initDev;
    model.res = info.isSuccess ? model.res : model.resFail;
    model.errCode = info.isSuccess ? model.errCode : [DHNetSDKInterface getLastError];
    [[DHAddDeviceLogManager shareInstance] addDeviceInitLogWithModel:model];
}
 
 
@end