// // Copyright © 2018å¹´ dahua. All rights reserved. // #import "DHNetSDKSearchManager.h" #import "DHNetSDKInterface.h" #import "DHDeviceNetInfo.h" #import <LCBaseModule/UIDevice+LeChange.h> #import <LCBaseModule/DHNetWorkHelper.h> #import <LCBaseModule/DHModuleConfig.h> #import <LCBaseModule/DHFileManager.h> #import <LCBaseModule/DHMobileInfo.h> #import <LCAddDeviceModule/LCAddDeviceModule-Swift.h> @interface DHNetSDKSearchManager() @property (nonatomic, strong) NSMutableDictionary<NSString *, DHDeviceNetInfo*> *netInfoDic; @property (nonatomic, assign) long searchHandle; @property (nonatomic, copy) dispatch_queue_t queue; @property (nonatomic, copy) dispatch_queue_t searchQueue; @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, assign) NSInteger tickCount; @property (nonatomic, assign) NSTimeInterval lastFindTime; /**< 记录上次NETSDK回调结果的时间 */ @property (nonatomic, assign) NSInteger searchSequence; /**< æœç´¢çš„åºå· */ @property (nonatomic, copy) NSString *lastSSID;//上次连接的wifiçš„ssid,用于网络环境å˜åŒ–釿–°æœç´¢è®¾å¤‡ @end @implementation DHNetSDKSearchManager #pragma mark - circle life - (instancetype)init { if(self = [super init]) { [self initNetSdk]; _netInfoDic = @{}.mutableCopy; _queue = dispatch_queue_create("syncOperation", DISPATCH_QUEUE_CONCURRENT); _searchQueue = dispatch_queue_create("searchQueue", DISPATCH_QUEUE_SERIAL); _tickCount = 0; #if DEBUG _showDebugLog = NO; #else _showDebugLog = YES; #endif } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Notification - (void)addObservers { //防æ¢é‡å¤æ·»åŠ [self removeObservers]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; //ç›‘å¬æ˜¯å¦è§¦å‘home键挂起程åºï¼Œï¼ˆæŠŠç¨‹åºæ”¾åœ¨åŽå°æ‰§è¡Œå…¶ä»–æ“作) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; //ç›‘å¬æ˜¯å¦é‡æ–°è¿›å…¥ç¨‹åºç¨‹åº.(回到程åº) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkDidChanged:) name:@"LCNotificationWifiNetWorkDidSwitch" object:nil];//从一个wifi网络切æ¢åˆ°å¦å¤–一个wifi网络也è¦é‡æ–°èŽ·å–设备列表 } - (void)removeObservers { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)applicationWillResignActive:(NSNotification *)notification { if(self.timer != nil) { [self.timer fire]; [self.timer invalidate]; self.timer = nil; } DH_LOG_FUN dispatch_async(self.searchQueue, ^{ if(self.searchHandle) { NSLog(@"DHNetSDKSearchManager::Stop search in resign active:%ld, sequence:%ld", self.searchHandle, (long)self.searchSequence); [[DHNetSDKInterface sharedInstance] stopSearchDevices:self.searchHandle]; self.searchHandle = 0; } }); } - (void)applicationDidBecomeActive:(NSNotification *)notification { if(self.isSearching) { [self startSearch]; } } - (void)networkDidChanged:(NSNotificationCenter *)notification { // DTS000583328 å¶çŽ°å´©æºƒ [DHMobileInfo sharedInstance].WIFISSID if (!self.isSearching) { return; } //针对软apæ·»åŠ çš„bug NSString *wifiSSID = [[DHMobileInfo sharedInstance].WIFISSID uppercaseString]; if (![wifiSSID isEqualToString:self.lastSSID] && wifiSSID.length) { self.lastSSID = wifiSSID; [self.netInfoDic removeAllObjects]; if(self.isSearching) { [self startSearch]; } } } #pragma mark - interface - (void)startSearch { if(self.timer != nil) { [self.timer fire]; [self.timer invalidate]; self.timer = nil; } DH_LOG_FUN NSInteger tick = 2; self.timer = [NSTimer scheduledTimerWithTimeInterval:tick target:self selector:@selector(timeTick) userInfo:nil repeats:YES]; self.isSearching = YES; [self timeTick]; //æ·»åŠ é€šçŸ¥ [self addObservers]; } - (void)timeTick { //wifi连接连接过程ä¸ï¼Œå¯èƒ½ä¼šå‡ºçŽ°æ— æ³•è¯†åˆ«çš„æƒ…å†µï¼Œä¸èƒ½åŠ æ¤åˆ¤æ– //åªå¤„ç†ios13ä»¥ä¸‹ç³»ç»Ÿï¼Œä¸æ˜¯WiFiçŠ¶æ€æ—¶ï¼Œä¸è¿›è¡Œæ£€æµ‹ if (DH_IOS_VERSION < 13 && [DHNetWorkHelper sharedInstance].emNetworkStatus != AFNetworkReachabilityStatusReachableViaWiFi) { return; } //ã€*】打å°å½“å‰çš„WIFIä¿¡æ¯ã€å®šä½è½¯AP相关问题 if (self.tickCount % 10 == 0) { NSLog(@"DHNetSDKSearchManager::当å‰WIFIä¿¡æ¯ %@, Mask:%@, Router:%@, IP:%@", DHMobileInfo.sharedInstance.WIFISSID, UIDevice.lc_getMaskAddress, [UIDevice lc_getRouterAddress], UIDevice.lc_getIPAddress); } //计时ä¸ä¸æ– self.tickCount++; NSInteger intervalCheck = 10; if(self.tickCount % intervalCheck == 0) { [self clearnUnReceiveDevice]; } if (self.tickCount % 5 == 0) { if (_showDebugLog) { dispatch_barrier_async(self.queue, ^{ NSLog(@"当剿œç´¢åˆ°çš„设备:\n%@",self.netInfoDic.allKeys); }); } } // è·ç¦»ä¸Šæ¬¡å›žè°ƒæ—¶é—´å¤§äºŽ3s,æ‰é‡æ–°å¼€å§‹é‡æ–°æœç´¢ NSTimeInterval currentTime = NSDate.date.timeIntervalSince1970; if (fabs(currentTime - self.lastFindTime) < 3) { NSLog(@"DHNetSDKSearchManager:: Ignore tick process..."); return; } // å·²ç»åœæ¢äº†ï¼Œä¸éœ€è¦å†é‡æ–°æœç´¢ if (self.isSearching == false) { NSLog(@"DHNetSDKSearchManager:: Search is stopped, return..."); return; } dispatch_async(self.searchQueue, ^{ if(self.searchHandle) { NSLog(@"DHNetSDKSearchManager::Stop search in timetick:%ld, sequence:%ld", self.searchHandle, (long)self.searchSequence); [[DHNetSDKInterface sharedInstance] stopSearchDevices:self.searchHandle]; self.searchHandle = 0; } //ã€*ã€‘è®°å½•ä¸‹å½“å‰æœç´¢çš„åºå· //ã€*ã€‘ä¼˜åŒ–ï¼šé‡‡ç”¨ä¼ IP+ä¸ä¼ IP交替æœç´¢ NSString *localIp = (self.searchSequence % 2) == 0 ? UIDevice.lc_getIPAddress : nil; self.searchSequence++; NSInteger sequence = self.searchSequence; self.searchHandle = [[DHNetSDKInterface sharedInstance] startSearchDevices:^(DHDeviceNetInfo *netInfo) { dispatch_barrier_async(self.queue, ^{ netInfo.searchSequence = sequence; if (self.showDebugLog) { NSLog(@"DHNetSDKSearchManager::-find device: %@ - %@,æœç´¢åºå·ï¼š%ld, Init type:%lu, status: %lu", netInfo.deviceType, netInfo.serialNo, (long)netInfo.searchSequence, (unsigned long)netInfo.deviceInitType, (unsigned long)netInfo.deviceInitStatus); } //é¿å…找到deviceId为空的情况 if (netInfo.serialNo.length > 0) { DHNetSDKSearchManager.sharedInstance.netInfoDic[netInfo.serialNo] = netInfo; } self.lastFindTime = NSDate.date.timeIntervalSince1970; }); } byLocalIp: localIp]; NSLog(@"DHNetSDKSearchManager:: Start search with handle:%ld, search sequence:%ld", self.searchHandle, (long)self.searchSequence); if(self.searchHandle == 0) { unsigned int errorCode = [DHNetSDKInterface getLastError]; NSLog(@"NetSDKInteface:: Load wifilist failed with errorCode:...0x%x", errorCode); NSLog(@"DHNetSDKSearchManager::CLIENT_StartSearchDevices-fail"); DHAddDeviceLogModel *model = [[DHAddDeviceLogModel alloc] init]; model.method = @"startSearchDevices"; model.res = model.resFail; model.errCode = errorCode; [[DHAddDeviceLogManager shareInstance] addDeviceNetSDKLogWithModel:model]; } }); } - (void)stopSearch { //åœæ¢é€šçŸ¥ [self removeObservers]; dispatch_barrier_async(self.queue, ^{ [self.netInfoDic removeAllObjects]; }); if(self.timer != nil) { [self.timer fire]; [self.timer invalidate]; self.timer = nil; } dispatch_async(self.searchQueue, ^{ if(self.searchHandle) { NSLog(@"DHNetSDKSearchManager::Stop search in stop:%ld, sequence:%ld", self.searchHandle, (long)self.searchSequence); [[DHNetSDKInterface sharedInstance] stopSearchDevices:self.searchHandle]; self.searchHandle = 0; } }); self.searchSequence = 0; self.lastFindTime = 0; self.isSearching = NO; } - (id<ISearchDeviceNetInfo>)getNetInfoByID:(NSString *)deviceID; { __block id<ISearchDeviceNetInfo> device; dispatch_barrier_sync(self.queue, ^{ device = self.netInfoDic[deviceID]; }); return device; } #pragma mark - Custom - (void)clearnUnReceiveDevice { dispatch_barrier_async(self.queue, ^{ //æŠŠæ‰€æœ‰æœªæ ‡è®°çš„ä»Ždicä¸ä¸€å‡º å·²æ ‡è®°çš„å˜æˆæœªæ ‡è®° ç‰å¾…下一次的æœç´¢ NSArray<NSString *> *allKeys = [self.netInfoDic allKeys].copy; for (NSString *key in allKeys) { DHDeviceNetInfo *device = self.netInfoDic[key]; if(!device.isVaild) { NSLog(@"%@ 在这次æœç´¢ä¸è¢«ç§»é™¤", key); [self.netInfoDic removeObjectForKey:key]; } else if (device.searchSequence != self.searchSequence) { //ã€*】21589ï¼šåªæœ‰å½“å‰çš„æœç´¢ç»“æŸäº†ï¼Œæ‰å°†ç¼“å˜ä¸æœªæœç´¢åˆ°çš„设备有效状æ€é‡ç½® NSLog(@"DHNetSDKSearchManager:: é‡ç½®è®¾å¤‡æœ‰æ•ˆçжæ€,设备 %@, æœç´¢åºå·ï¼š %ld, 当å‰åºå·ï¼š%ld", device.deviceSN, (long)device.searchSequence, (long)self.searchSequence); self.netInfoDic[key].isVaild = NO; } } }); } #pragma mark - private method -(void)initNetSdk { [DHNetSDKInterface initSDK]; #if DEBUG NSString *path = [[DHFileManager supportFolder] stringByAppendingPathComponent:@"cache"]; [DHNetSDKInterface logOpen: path]; #endif } #pragma mark - singleton static DHNetSDKSearchManager *_instance = nil; + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } + (id)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } - (id)copyWithZone:(NSZone *)zone{ return _instance; } @end