// // webRtcManager.m // 双子星云手机 // // Created by xd h on 2024/9/5. // #import "webRtcManager.h" #import "webRtcManager+StatisticsReport.h" #import "RcGameWQKeyChain.h" #import "errorAlertTool.h" #import "webRtcManager+downloadNasFile.h" #import "nasMixUploadManager.h" #import "nasUploadFileManager.h" #import "nasDownloadFileManager.h" @interface webRtcManager () { NSMutableArray *commandSendCheckArr;//需要检测任务是否发出的的指令 NSTimer *linkCheckSecondTimer; // 检测链接状态 NSInteger tryRelinkNum;//重连次数 } //第一次链接设备 要发送指令信息 实现单点登录 @property (nonatomic, assign)BOOL didSendfristMsg; @end @implementation webRtcManager + (instancetype)shareManager { static webRtcManager *_instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } - (instancetype)init { if (self = [super init]) { //[self registeNotification]; tryRelinkNum = 0; //2.客户端开始写日志 [ksharedAppDelegate.WebRtcLogger start]; HLog(@"webrtc :%@",ksharedAppDelegate.WebRtcLogger) _webRtcChannelSessionId = [iTools getNowTimeStampString]; _mediaStream = [[RTC_OBJC_TYPE(AMediaStream) alloc] initWithFrame:CGRectZero]; [_mediaStream setEventDelegate:self]; linkCheckSecondTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(timerChange) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:linkCheckSecondTimer forMode:NSRunLoopCommonModes]; } return self; } #pragma mark 十秒一次的timer检测 - (void)timerChange{ [self checkChannelLinkStateFun]; [self checkAllTaskFun]; } #pragma mark 检测链接是否OK - (void)checkChannelLinkStateFun { if(_channelState != RTCDataChannelStateOpen ||(_ConnectionState != RTCIceConnectionStateConnected && _ConnectionState != RTCIceConnectionStateCompleted) ){ if(!_didReportWebRtcFailType){//还没上报过通道链接情况 tryRelinkNum ++; if(tryRelinkNum == 2){ _didReportWebRtcFailType = YES; // KWeakSelf // globalBlock(^{ // [[addLogObject shareInstance] gotoAddLogFunBySuccess:^(NSString * _Nonnull key) { // [weakSelf reportWebRtcRePoportTypeIsChannel:YES withStats:nil withSessionId:self->_webRtcChannelSessionId withLogKey:key]; // }]; // }); //检测盒子心跳 [self checkBoxHeartbeatFun]; } } [self relinkWebRtcFun]; } } #pragma mark 关闭链接 - (void)closeLinkWebRtcFun { if((_ConnectionState == RTCIceConnectionStateConnected && _ConnectionState == RTCIceConnectionStateCompleted) || _channelState == RTCDataChannelStateOpen) { KWeakSelf mainBlock(^{ [weakSelf.mediaStream disconnect]; }); } } #pragma mark 开始链接 - (void)beginToLinkWebRtcFun { KWeakSelf mainBlock(^{ [weakSelf secondBeginToLinkWebRtcFun]; }); } - (void)secondBeginToLinkWebRtcFun { if(ksharedAppDelegate.isWebSockLinkOKAginType || !ksharedAppDelegate.DeviceWebRtcMsgMod){ return; } webRtcMsgModel * _webRtcMsgMod = ksharedAppDelegate.DeviceWebRtcMsgMod; webrtcServerModel * webrtcServerMod = ksharedAppDelegate.bestWebrtcServerModel; //链接用 NSString *signallingUrl = [[NSString alloc] initWithFormat:@"%@:%@",webrtcServerMod.signallingIp,webrtcServerMod.signallingPort]; NSURL *url = [NSURL URLWithString:signallingUrl]; //ice用 NSString *iceUrl = [[NSString alloc] initWithFormat:@"%@:%@",webrtcServerMod.turnIp,webrtcServerMod.turnPort]; NSMutableDictionary *ice = [NSMutableDictionary new]; if(iceUrl){ [ice setValue:iceUrl forKey:@"CHINANET"]; [ice setValue:iceUrl forKey:@"CMNET"]; [ice setValue:iceUrl forKey:@"UNICOM"]; } NSString *roomName = _webRtcMsgMod.data.uniqueIdentifier; [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webrtc channel startUploadChannel--%@",signallingUrl]]; //1.盒子开始写20秒日志 [_mediaStream setCardLogToFile:@"/sdcard/webrtc_box.log" captureTime:@"20"]; //2.客户端开始写日志 [ksharedAppDelegate.WebRtcLogger start]; HLog(@"webrtc :%@ --- channl start:%@",ksharedAppDelegate.WebRtcLogger,url) //vclusters 信令不鉴权 写不写都OK NSInteger result = [_mediaStream startUploadChannel:url ice:ice sn:roomName token:@"vclusters"]; HLog(@"webrtc 发起连接 result:%ld",result) [_mediaStream setShouldGetStats:YES]; } - (void)relinkWebRtcFun{ ksharedAppDelegate.isWebSockLinkOKAginType = NO; if(!_isChangeBoxType){ //客户端停止写日志 [ksharedAppDelegate.WebRtcLogger stop]; [cachesFileManager writeLogsWithMsg:@"webrtc channel relinkWebRtcFun"]; [self beginToLinkWebRtcFun]; } } #pragma mark webrtc P2P通道发送消息 - (void)send_data:(NSString *)dataStr { [_mediaStream sendData:dataStr]; HLog(@"客户端发出命令:%@",dataStr); } #pragma mark 盒子链接成功后需要处理的各种各样事情 - (void)handlAllMsgAfterDidLinkFun { _isRebootIngType = NO; _isResetingType = NO; _isChangeBoxType = NO; tryRelinkNum = 0; ksharedAppDelegate.isWebSockLinkOKAginType = YES; //获取云机尺寸 兼容 720*1080 &1080*1920 不同分辨率的展示和触控 NSString *getPhoneSizeStr = [RCCommandHelp getPhoneSizecommand]; [self send_data:getPhoneSizeStr]; //判断是否为需要改机 BOOL isNeedRandomChangeParams = [HWDataManager getBoolWithKey:Const_need_random_Change_Params]; if(isNeedRandomChangeParams) { NSString *commondStr = @"{\"type\":\"randomChangeParams\"}"; [self send_data:commondStr]; [HWDataManager setBoolWithKey:Const_need_random_Change_Params value:NO]; } [self fristConnectNeedGiveAMsgFun]; [self updateCopydata]; // 报链接失败 后面又连接上了 [[errorAlertTool shareInstance] dismissErrorAlertFun]; //处理相册备份 [[nasBackupsManager shareInstance] AutohandlePhotosBackupsFun]; //获取磁盘外挂 [self getExtraFilesListFun]; [self getBaseInfoFun]; [self getTvStatusFun]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self closeBoxHeartbeatReStartViewFun]; }); if(ksharedAppDelegate.needToShowReStratSucType){ ksharedAppDelegate.needToShowReStratSucType = NO; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self showReStartSucFun]; }); } } #pragma mark 盒子第一次连接成功 给ws发送信息 单点登录 把其他账号挤下去 - (void)fristConnectNeedGiveAMsgFun{ if(!_didSendfristMsg ) { [self getSysInfoFun]; // NSString *curOaidStr = [RcGameWQKeyChain getOaidStringFun]; // if(!curOaidStr){ // curOaidStr = @""; // } // //未调通挤下线 // NSString *commondStr = [[NSString alloc] initWithFormat:@"{\"type\":\"login\",\"value\":\"%@\"}",curOaidStr]; // [self send_data:commondStr]; // [self addCommandSendTaskFunWithType:@"offline_notification" WithCommandStr:commondStr]; _didSendfristMsg = YES; [self getPreferredLanguage]; NSString *commondStr2 = @"{\"type\":\"TvStatus\"}"; [self send_data:commondStr2]; } } #pragma mark 语言和市区 同步云机 -(void)getPreferredLanguage {//{"data":{"language":"zh-CN","timeZone":"Etc/GMT+8"},"type":"setLanguages"} // iOS 获取设备当前语言的代码 NSString *preferredLanguage = [[[NSBundle mainBundle] preferredLocalizations] firstObject]; HLog(@"当前语言:%@", preferredLanguage); //en-US 英文 ja-JP 日文 NSArray *arLanguages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"]; NSLog(@"arLanguages:%@",arLanguages); ///获取设备当前地区的代码和APP语言环境 NSString *languageCode = [NSLocale preferredLanguages][0]; //目前支持 中文(简体 繁体) 英文 日语 if([languageCode rangeOfString:@"zh-Hans"].location != NSNotFound) { preferredLanguage = @"zh-CN"; } else if([languageCode rangeOfString:@"zh-Hant"].location != NSNotFound) { preferredLanguage = @"zh-HK"; } else if([languageCode rangeOfString:@"ja-"].location != NSNotFound) { preferredLanguage = @"ja-JP"; } else{ preferredLanguage = @"en-US"; } // if([languageCode rangeOfString:preferredLanguage].location != NSNotFound){ // preferredLanguage = languageCode; // } // else{ // preferredLanguage = @"en-US"; // } NSString*gmtStr = [self UTCOffset]; HLog(@"%@",gmtStr); // //获取名字,如“GMT+08:00 NSString *commondStr = [NSString stringWithFormat:@"{\"type\":\"setLanguages\",\"data\":{\"language\":\"%@\",\"timeZone\":\"%@\"}}",preferredLanguage,gmtStr]; [self send_data:commondStr]; } #pragma mark 获取云机系统镜像等信息 - (void)getSysInfoFun { NSString *commondStr = @"{\"type\":\"getSysInfo\"}"; [self send_data:commondStr]; } -(NSString *)UTCOffset { NSTimeZone *localTZ = [NSTimeZone localTimeZone]; float offset = localTZ.secondsFromGMT/3600.0; if(offset > 0){ return [NSString stringWithFormat:@"Etc/GMT+%g",offset]; } return [NSString stringWithFormat:@"Etc/GMT%g",offset]; } #pragma mark 收到系统信息消息回调处理 - (void)getCouldPhoneSysInfoResponseFun:(NSDictionary *)dataDict{ couldphoneSysInfoModel *model = [[couldphoneSysInfoModel alloc] initWithDictionary:dataDict error:nil]; //[[NSNotificationCenter defaultCenter] postNotificationName:getCouldPhoneSysInfoNotification object:model]; // NSString *hostImgVer = model.data.data.hostImgVer; // NSString *MyNewVersion = model.data.data.MyNewVersion; NSString *hostImgVer = model.data.hostImgVer; NSString *MyNewVersion = model.data.MyNewVersion; //test code // hostImgVer = @"1.2.3"; // MyNewVersion = @"1.2.0"; //判断当前版本号 待更新版本 if (!hostImgVer || hostImgVer.length < 3 ||!MyNewVersion || MyNewVersion.length < 3) { return; } NSArray *versionArr = [hostImgVer componentsSeparatedByString:@"."]; NSArray *MyNewVersionArr = [MyNewVersion componentsSeparatedByString:@"."]; NSInteger versionArrCount = versionArr.count; NSInteger MyNewVersionArrCount = MyNewVersionArr.count; NSInteger maxCount = versionArrCount < MyNewVersionArrCount ? versionArrCount:MyNewVersionArrCount; BOOL isNeedShowType = NO; //判断是否要更新镜像框 if(maxCount > 0){ for (int i=0; i numberStr1.intValue){ isNeedShowType =YES; break; } } } if(isNeedShowType){ ksharedAppDelegate.isNeedShowImageNewType = YES; } //是否禁用文件传输 (1.3以及以上的镜像可以使用文件传输) if(versionArr.count >= 3) { NSString * oneStr = versionArr[0]; NSString * twoStr = versionArr[1]; NSString * threeStr = versionArr[2]; if(oneStr.integerValue <=1 && twoStr.integerValue <=3 && threeStr.integerValue <=0){//禁用 ksharedAppDelegate.DisabledFileTransferType = YES; if(MyNewVersionArr.count >= 3) { NSString * newOneStr = MyNewVersionArr[0]; NSString * newTwoStr = MyNewVersionArr[1]; NSString * newThreeStr = MyNewVersionArr[2]; if(newOneStr.integerValue >=1 && newTwoStr.integerValue >=3 && newThreeStr.integerValue >= 1){ ksharedAppDelegate.isImageNewFor130 = YES; } else{ ksharedAppDelegate.isImageNewFor130 = NO; } } } else{ ksharedAppDelegate.DisabledFileTransferType = NO; } //判断镜像是否为1.4.4以后 if(oneStr.integerValue >=2){ ksharedAppDelegate.isImageFor144Orlater = YES; [HWDataManager setBoolWithKey:stringKeyAddSn(Const_image_version_for_new_token) value:YES]; } else if(twoStr.integerValue > 4){ ksharedAppDelegate.isImageFor144Orlater = YES; [HWDataManager setBoolWithKey:stringKeyAddSn(Const_image_version_for_new_token) value:YES]; } else if(threeStr.integerValue >= 4){ ksharedAppDelegate.isImageFor144Orlater = YES; [HWDataManager setBoolWithKey:stringKeyAddSn(Const_image_version_for_new_token) value:YES]; } else{ ksharedAppDelegate.isImageFor144Orlater = NO; } } [[NSNotificationCenter defaultCenter] postNotificationName:getCouldPhoneSysInfoNotification object:model]; } #pragma mark 添加消息重复机制 -(void)addCommandSendTaskFunWithType:(NSString*)type WithCommandStr:(NSString*)commandStr { if(!commandSendCheckArr){ commandSendCheckArr = [NSMutableArray new]; } BOOL didAddType = NO; for (commandSendCheckModel *model in commandSendCheckArr) { if([model.type isEqualToString:type]){ didAddType = YES; model.reSendNum = 0; model.sendTimerStamp = [iTools getNowTimeStamp]; break; } } if(!didAddType){ commandSendCheckModel *model = [commandSendCheckModel new]; model.commandStr = commandStr; model.type = type; model.reSendNum = 0; model.sendTimerStamp = [iTools getNowTimeStamp]; [commandSendCheckArr addObject:model]; } } #pragma mark 删除代理确认收到的消息 -(void)deleteCommandSendTaskFunWith:(NSString*)type { if(commandSendCheckArr && commandSendCheckArr.count >0){ NSArray *taskArr = [NSArray arrayWithArray:commandSendCheckArr]; for (commandSendCheckModel *model in taskArr) { if([type isEqualToString:model.type]){ [commandSendCheckArr removeObject:model]; } } } } #pragma mark 复制手机消息到云机 - (void)updateCopydata{ UIPasteboard* pasteboard = [UIPasteboard generalPasteboard]; NSString *str = [pasteboard string]; HLog(@"__________%s______%@____",__func__,str); if ([str rangeOfString:@"CVLUSTERS_NOUSE_"].location != NSNotFound) { str = nil; } if (str && str.length >0) { //HLog(@"hxd111 cutting %@",str); /*发送数据*/ NSString *dataStr = [RCCommandHelp commandCuttingWithContent:str]; [self send_data:dataStr]; //pasteboard.string = @""; } } #pragma mark 获取云机以及外挂磁盘 - (void)getExtraFilesListFun { // NSString *ExtraCommondStr = [RCCommandHelp getExtraFilesList]; // [self send_data:ExtraCommondStr]; //改走http方案 [[NSNotificationCenter defaultCenter] postNotificationName:getExtraFilesDoneNotification object:nil];/*发送通知*/ } #pragma mark 获取到云机以及外挂磁盘信息 - (void)getExtraFilesResponseFun:(NSDictionary *)dataDict { cloudPhoneExtraFileListModel *model = [[cloudPhoneExtraFileListModel alloc] initWithDictionary:dataDict error:nil]; ksharedAppDelegate.cloudPhoneExtraFileListMod = model; [[NSNotificationCenter defaultCenter] postNotificationName:getExtraFilesDoneNotification object:dataDict];/*发送通知*/ } #pragma mark 获取云机基本信息 - (void)getBaseInfoFun { NSString *commondStr = @"{\"type\":\"getBaseInfo\"}"; [self send_data:commondStr]; } #pragma mark 获取到云机基本信息 - (void)getCouldPhoneBaseInfoResponseFun:(NSDictionary *)dataDict { couldPhoneBaseInfoModel *model = [[couldPhoneBaseInfoModel alloc] initWithDictionary:dataDict error:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:getCouldPhoneBaseInfoNotification object:model]; } #pragma mark 获取到TV投屏状态 - (void)getCouldPhoneTvStatusResponseFun:(NSDictionary *)dataDict { TvStatusModel *model = [[TvStatusModel alloc] initWithDictionary:dataDict error:nil]; ksharedAppDelegate.TvStatusMod = model; [[NSNotificationCenter defaultCenter] postNotificationName:getCouldPhoneTvStatusNotification object:model]; // if(![model.msg containsString:@"PushStreamBActivity"]) // { // return; // } // // UIViewController*topVc = self.navigationController.viewControllers.lastObject; // if([topVc isKindOfClass:[PlayerViewController class]]){ // [[iToast makeText:NSLocalizedString(@"tv_p2p_ing",nil)] show]; // } } #pragma mark 重启云机 - (void)needToRebootFun { NSString *commondStr = @"{\"type\":\"reboot\"}"; [self send_data:commondStr]; //添加到任务监听 [self addCommandSendTaskFunWithType:@"reboot" WithCommandStr:commondStr]; //数据埋点 [[netWorkManager shareInstance] DataEmbeddingPointBy:3 withEventValue:@"Cloud_restart"]; _isRebootIngType = YES; //1、重启、恢复出厂设备、首次设置密码 3个情况下8分钟之内不弹 long seconds = [iTools getNowTimeStamp]; NSNumber *secondsNum = [NSNumber numberWithLong:seconds]; if(secondsNum){ [HWDataManager setNumberWithKey:stringKeyAddSn(@"disenable_type2_BoxHeartbeat") value:secondsNum]; } } #pragma mark 恢复出厂设置 - (void)needToResetFun { NSString *commondStr = @"{\"type\":\"reset\"}"; [self send_data:commondStr]; //添加到任务监听 [self addCommandSendTaskFunWithType:@"reset" WithCommandStr:commondStr]; //数据埋点 [[netWorkManager shareInstance] DataEmbeddingPointBy:3 withEventValue:@"Cloud_restore_factory"]; _isResetingType = YES; //1、重启、恢复出厂设备、首次设置密码 3个情况下8分钟之内不弹 long seconds = [iTools getNowTimeStamp]; NSNumber *secondsNum = [NSNumber numberWithLong:seconds]; if(secondsNum){ [HWDataManager setNumberWithKey:stringKeyAddSn(@"disenable_type2_BoxHeartbeat") value:secondsNum]; } } #pragma mark 云机截图保存到云机图库 - (void)screenshotInCloudPhoneFun{ NSString*taskUid = [iTools getTaskUidStr]; NSString *commondStr = [RCCommandHelp commandCloudPhoneScreenshotWithTaskUid:taskUid]; [self send_data:commondStr]; } #pragma mark 获取TV投屏状态 - (void)getTvStatusFun { NSString *commondStr = @"{\"type\":\"TvStatus\"}"; [self send_data:commondStr]; } #pragma mark 关闭TV投屏状态 - (void)offTvFun { NSString *commondStr = @"{\"type\":\"TvOff\"}"; [self send_data:commondStr]; } #pragma mark 开启TV投屏状态 - (void)onTvFun { NSString *commondStr = @"{\"type\":\"wakeupTV\"}"; [self send_data:commondStr]; } #pragma mark 创建备份文件夹 - (void)createBackupsFolderBy:(NSString*)backupsDefaultPath { NSString *folderName = backupsDefaultPath; if(folderName && folderName.length >0){ NSString * commandStr = [RCCommandHelp applyForCreateFolderwithFolderName:folderName]; [self send_data:commandStr]; } } #pragma mark 获取备份文件夹列表 - (void)getBackupFolderListFun { NSString * commandStr = [RCCommandHelp getCreateFolderList]; [self send_data:commandStr]; } #pragma mark 创建文件夹回调 - (void)createFolderResponseFun:(NSDictionary *)dataDict { couldPhoneCommonModel *model = [[couldPhoneCommonModel alloc] initWithDictionary:dataDict error:nil]; if(model){ NSNumber *curNum = [NSNumber numberWithInteger:model.status]; [[NSNotificationCenter defaultCenter] postNotificationName:createFolderDoneNotification object:curNum];/*发送通知*/ } } - (void)getFolderListResponseFun:(NSDictionary *)dataDict { [[NSNotificationCenter defaultCenter] postNotificationName:getFolderListDoneNotification object:dataDict];/*发送通知*/ } - (void)searchFileListResponseFun:(NSDictionary *)dataDict { [[NSNotificationCenter defaultCenter] postNotificationName:searchFileListDoneNotification object:dataDict];/*发送通知*/ } #pragma mark U盘插入相关 - (void)getExtraMediaEventResponseFun:(NSDictionary *)dataDict { mainBlock((^{ extraMediaEventModel *model = [[extraMediaEventModel alloc] initWithDictionary:dataDict error:nil]; NSString *tip = nil; if(model.data.event == 0){ tip = NSLocalizedString(@"disk_insertion_tip",nil); [self showInsertPopViewFun:model.data.name]; } else if(model.data.event == 1){ tip = NSLocalizedString(@"disk_extract_tip",nil); } else if(model.data.event == 2){ tip = NSLocalizedString(@"disk_save_extract_tip",nil); } NSString *totalTips = [[NSString alloc] initWithFormat:@"%@%@",model.data.name,tip]; [[iToast makeText:totalTips] show]; })); } #pragma mark 显示插入UI弹框 - (void)showInsertPopViewFun:(NSString*)name { if(self->curUSBInsertPopV){ [self->curUSBInsertPopV removeFromSuperview]; self->curUSBInsertPopV = nil; } self->curUSBInsertPopV = [[USBInsertPopView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_W, SCREEN_H) withName:name]; [[iTools getKeyWindow] addSubview:self->curUSBInsertPopV]; } #pragma mark 检测nas任务情况 - (void)checkAllTaskFun { HLog(@"checkAllTaskFun"); //处理相册备份 [[nasBackupsManager shareInstance] checkReBackupsFileFun]; //处理上传失败的重新上传 //[[nasUploadFileManager shareInstance] reUploadFileFunByNetWork]; //[[nasDownloadFileManager shareInstance] reDownloadloadFileFunByNetWork]; //if([AudioSessionObject shareManager].isBackgroundType) { [self checkFileTransfeTaskFun]; } if([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusUnknown){ [ksharedAppDelegate MonitorNetworkChangesFun]; } } #pragma mark 检测是否正在进行的文件传输任务 设置后台状态 - (void)checkFileTransfeTaskFun { BOOL isBackupsingType = [[nasBackupsManager shareInstance] checkBackupsingFun]; BOOL isUploadingType = [[nasMixUploadManager shareManager] checkUploadTaskDoingFun]; BOOL isDownloadingType = [[nasDownloadManager shareManager] isDownLoadIngType]; BOOL isNasDownloadingType = [customDownloadManager shareManager].isDownLoadIngType; BOOL isBackground = [HWDataManager getBoolWithKey:stringKeyAddSn(Const_file_Transfe_working_background)]; if ((isBackupsingType || isUploadingType || isDownloadingType ||isNasDownloadingType) && isBackground) { HLog(@"后台保活中"); //[cachesFileManager writeLogsWithMsg:@"Background working"]; } else{ HLog(@"停止后台保活"); //[cachesFileManager writeLogsWithMsg:@"stop Background working"]; //[[AudioSessionObject shareManager] stopBackgroundActiveFun]; } } #pragma mark 收到的webrtc消息处理 - (void)handleWebRtcMsgResponseBy:(NSData*)message { if([message isKindOfClass:[NSMutableString class]] || [message isKindOfClass:[NSString class]]) { message = [(NSString *)message dataUsingEncoding:(NSUTF8StringEncoding)]; } NSError *error = nil; NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:message options:NSJSONReadingMutableContainers error:&error]; HLog(@"webRtc P2P 通道接收消息:------------------%@",dataDict); // if([message isKindOfClass:[NSData class]] && [message length] == 0){ // if(type == RCSocketCloudPhoneReceiveTypeForPong) // { // [weakSelf keepWebSocketOKFun]; // } // return; // } // // HLog(@"webSocket指令通道接收消息:------------------\n%@",message); // // if([message isKindOfClass:[NSMutableString class]] || [message isKindOfClass:[NSString class]]) // { // message = [(NSString *)message dataUsingEncoding:(NSUTF8StringEncoding)]; // } // // NSError *error = nil; // NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:message options:NSJSONReadingMutableContainers error:&error]; if(!dataDict){ //[weakSelf handleDownloadResponseFunBy:message]; return; } if(![dataDict isKindOfClass:[NSDictionary class]]){ //[__NSCFString allKeys] unrecognized selector sent to ins return; } if(![[dataDict allKeys] containsObject:@"type"]){ return; } NSString *messageType = dataDict[@"type"]; if ([messageType isEqualToString:@"cutting"]) { //[[iToast makeText:@"复制成功"] show]; } // else if ([messageType isEqualToString:@"forwardMsgRep"]){/*转发的回复*/ // // cloudPhoneCommonModel *model = [[cloudPhoneCommonModel alloc] initWithDictionary:dataDict error:nil]; // if(!model){ // return; // } // // if([model.data.msg isEqualToString:@"only one socket"]|| // [model.data.msg isEqualToString:@"only one socket2"]){ // [weakSelf deleteCommandSendTaskFunWith:@"offline_notification"]; // } // } // else if ([messageType isEqualToString:@"forwardMsg"]){/*转发*/ // /*获取指令类型*/ // NSString *code = nil; // if ([[dataDict allKeys] containsObject:@"data"]) { // NSDictionary *data = dataDict[@"data"]; // // if([data isKindOfClass:[NSString class]]){ // NSString * dataStr = (NSString*)data; // if([dataStr isEqualToString:@"offline_notification"]){ // HLog(@"被别人挤下线了"); // [weakSelf LogoutByOtherFun]; // } // // return; // } // else if ([data isKindOfClass:[NSDictionary class]] && [[data allKeys] containsObject:@"code"]) { // code = [data objectForKey:@"code"]; // // if (![code isKindOfClass:[NSString class]]) { // code = [NSString stringWithFormat:@"%ld",[code integerValue]]; // } // } // } // // /*获取用户名*/ // NSString *useName = nil; // if ([[dataDict allKeys] containsObject:@"data"]) { // NSDictionary *data = dataDict[@"data"]; // if ([[data allKeys] containsObject:@"userName"]) { // //useName = [data objectForKey:@"userName"]; // } // } // // // if ([code isEqualToString:@"phoneSizeChange"]){/*分辨率改变*/ // if ([[dataDict allKeys] containsObject:@"data"]) { // NSDictionary *data = dataDict[@"data"]; // if ([[data allKeys] containsObject:@"width"]) { // ksharedAppDelegate.couldPhone_W_PHONE = [[data objectForKey:@"width"] integerValue]; // } // if ([[data allKeys] containsObject:@"height"]) { // ksharedAppDelegate.couldPhone_H_PHONE = [[data objectForKey:@"height"] integerValue]; // } // // if (ksharedAppDelegate.couldPhone_W_PHONE > ksharedAppDelegate.couldPhone_H_PHONE) { // CGFloat temp = ksharedAppDelegate.couldPhone_W_PHONE; // ksharedAppDelegate.couldPhone_W_PHONE = ksharedAppDelegate.couldPhone_H_PHONE; // ksharedAppDelegate.couldPhone_H_PHONE = temp; // } // } // } // } else if ([messageType isEqualToString:@"getPhoneSize"] || [messageType isEqualToString:@"setPhoneSize"]){ //NSString *sn = nil; if([messageType isEqualToString:@"setPhoneSize"]){ self.isDiDChangePhoneSizeType = YES; } if ([[dataDict allKeys] containsObject:@"data"]) { NSDictionary *data = dataDict[@"data"]; if ([[data allKeys] containsObject:@"status"]) { NSInteger status = [[data objectForKey:@"status"] integerValue]; if (status == 0) {/*不是当前设备直接返回*/ if ([[data allKeys] containsObject:@"width"]) { ksharedAppDelegate.couldPhone_W_PHONE = [[data objectForKey:@"width"] integerValue]; } if ([[data allKeys] containsObject:@"height"]) { ksharedAppDelegate.couldPhone_H_PHONE = [[data objectForKey:@"height"] integerValue]; } if (ksharedAppDelegate.couldPhone_W_PHONE > ksharedAppDelegate.couldPhone_H_PHONE) { CGFloat temp = ksharedAppDelegate.couldPhone_W_PHONE; ksharedAppDelegate.couldPhone_W_PHONE = ksharedAppDelegate.couldPhone_H_PHONE; ksharedAppDelegate.couldPhone_H_PHONE = temp; } } } } } // else if ([messageType isEqualToString:@"sync_wifi"]){ // [weakSelf sync_wifiBackHandleFun]; // } // else if ([messageType isEqualToString:@"reProduceText"]){ // if ([[dataDict allKeys] containsObject:@"data"]) { // NSDictionary *data = dataDict[@"data"]; // // if ([[data allKeys] containsObject:@"text"]) { // NSString *pasteboardStr = [data objectForKey:@"text"]; // UIPasteboard* pasteboard = [UIPasteboard generalPasteboard]; // pasteboard.string = pasteboardStr; // } // } // } // else if ([messageType isEqualToString:@"downAdnInstallRep"]){ // if ([[dataDict allKeys] containsObject:@"data"]) { // NSDictionary *data = dataDict[@"data"]; // // if ([[data allKeys] containsObject:@"status"]) { // NSString *status = [data objectForKey:@"status"]; // if ([status isEqualToString:@"1"]) { // mainBlock(^{ // // [[iToast makeText:@"App下载完成"] show]; // }); // }else if ([status isEqualToString:@"0"]){ // mainBlock(^{ // //[[iToast makeText:@"App下载中"] show]; // }); // } // } // } // } // else if ([messageType isEqualToString:@"shakeit"]){ // HLog(@"\n-----摇一摇成功------"); // }else if ([messageType isEqualToString:@"keyboardFeedbackBean"]){/*调起键盘*/ // HLog(@"\n-----待处理 调起键盘------"); // // [weakSelf keyboardFeedbackBeanFun]; // }else if ([messageType isEqualToString:@"FileRandomReady"] // ||[messageType isEqualToString:@"FilePartReady"] // ){/*申请文件上传得到答复*/ // [weakSelf applyUploadFileServiceResponseFun:dataDict]; // } // else if ([messageType isEqualToString:@"uploadFileRandomRet"] // ||[messageType isEqualToString:@"uploadFilePartRet"] // ){/*文件上传得到答复*/ // [weakSelf upLoadFileFunServiceResponseFun:dataDict]; // } // else if ([messageType isEqualToString:@"backUpFileRandomReady"] // ||[messageType isEqualToString:@"backUpPartReady"] // ){/*文件备份得到答复*/ // [weakSelf applyBackupsFileServiceResponseFun:dataDict]; // } // else if ([messageType isEqualToString:@"backUpFileRandomRet"] // ||[messageType isEqualToString:@"backUpFilePartRet"]){/*文件备份得到答复*/ // [weakSelf backupsFileFunServiceResponseFun:dataDict]; // } else if ([messageType isEqualToString:@"getBaseInfo"]){/*获取云机的基本信息*/ [self getCouldPhoneBaseInfoResponseFun:dataDict]; } else if ([messageType isEqualToString:@"getSysInfo"]){/*获取云机的系统信息*/ [self getCouldPhoneSysInfoResponseFun:dataDict]; } else if ([messageType isEqualToString:@"TvStatus"]){/*获取TV投屏信息*/ [self getCouldPhoneTvStatusResponseFun:dataDict]; } else if ([messageType isEqualToString:@"TvOff"]){/*关闭TV投屏*/ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self getTvStatusFun]; }); } else if ([messageType isEqualToString:@"wakeupTV"]){/*开启TV投屏*/ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self getTvStatusFun]; }); } else if ([messageType isEqualToString:@"reboot"]){/*重启*/ //[weakSelf stopForceStartTimerFun]; } else if ([messageType isEqualToString:@"mkdir"]){/*创建文件夹*/ [self createFolderResponseFun:dataDict]; } else if ([messageType isEqualToString:@"getBackupPath"]){/*创建文件夹*/ [self getFolderListResponseFun:dataDict]; } else if ([messageType isEqualToString:@"search"]){/*创建文件夹*/ [self searchFileListResponseFun:dataDict]; } else if ([messageType isEqualToString:@"getExtraFiles"]){/*获取云机产品信息*/ [self getExtraFilesResponseFun:dataDict]; } else if ([messageType isEqualToString:@"extraMediaEvent"]){/*磁盘插拔*/ [self getExtraMediaEventResponseFun:dataDict]; [self getExtraFilesListFun]; } else if ([messageType isEqualToString:@"reset"]){/**/ [self deleteCommandSendTaskFunWith:@"reset"]; } else if ([messageType isEqualToString:@"shortcatRep"]){/*截图*/ [[iToast makeText:NSLocalizedString(@"shortcatRep_tip",nil)] show]; } } #pragma mark WebRTC 回调 MediaStreamClientEventsDelegate #pragma mark 不能再这里函数判断 这个是推拉流的 -(void)onChangeConnectionStateFromPeerName:(NSString*)peerName didChangeIceConnectionState:(RTCIceConnectionState)state { HLog(@"channel P2P onChangeConnectionStateFromPeerName: state:%ld",state) self.ConnectionState = state; [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webrtc channel onChangeConnectionStateFromPeerName:%ld",state]]; switch (state) { case RTCIceConnectionStateConnected:{ //链接成功 } break; case RTCIceConnectionStateCompleted: //链接完成 break; case RTCIceConnectionStateFailed: case RTCIceConnectionStateDisconnected: case RTCIceConnectionStateClosed:{ if(!_didReportWebRtcFailType && state == RTCIceConnectionStateFailed){//还没上报过通道链接情况 _didReportWebRtcFailType = YES; // KWeakSelf // globalBlock(^{ // [[addLogObject shareInstance] gotoAddLogFunBySuccess:^(NSString * _Nonnull key) { // [weakSelf reportWebRtcRePoportTypeIsChannel:YES withStats:nil withSessionId:self->_webRtcChannelSessionId withLogKey:key]; // }]; // }); } //链接关闭 [self relinkWebRtcFun]; } break; default: break; } } #pragma mark 通道连接状态变化监听 - (void)dataChannelDidChangeFromPeerName:(NSString*)peerName State:(RTCDataChannelState)state { HLog(@"webRtc P2P dataChannelDidChangeFromPeerName: state:%ld",state) [cachesFileManager writeLogsWithMsg:[[NSString alloc] initWithFormat:@"webrtc channel dataChannelDidChangeFromPeerName:%ld",state]]; self.channelState = state; switch (state) { case RTCDataChannelStateConnecting: { } break; case RTCDataChannelStateOpen: { //链接成功 [self handlAllMsgAfterDidLinkFun]; //客户端停止写日志 [ksharedAppDelegate.WebRtcLogger stop]; } break; case RTCDataChannelStateClosing: { } break; case RTCDataChannelStateClosed: { //链接断开 [self relinkWebRtcFun]; } break; default: break; } } -(void)onChannelDataFromPeerName:(NSString*)peerName buffer:(RTC_OBJC_TYPE(RTCDataBuffer) *)buffer { //HLog(@"onIceConnectedFromPeerName:%@",buffer.data); if(buffer && buffer.data){ KWeakSelf mainBlock(^{ [weakSelf handleWebRtcMsgResponseBy:buffer.data]; }); } } -(void)didGetStats:(NSString*)peerName stats:(RTC_OBJC_TYPE(RTCStatisticsReport) *)stats { //HLog(@"didGetStats:%@",stats) if(!_didReportWebRtcOKType && (self.ConnectionState == RTCIceConnectionStateConnected ||self.ConnectionState == RTCIceConnectionStateCompleted)){ [self reportWebRtcRePoportTypeIsChannel:YES withStats:stats withSessionId:_webRtcChannelSessionId withLogKey:@""]; _didReportWebRtcOKType = YES; _didReportWebRtcFailType = NO;//链接成功后 失败要重新上报 [_mediaStream setShouldGetStats:NO]; } } -(void)onAuthResultFromPeerName:(NSString*)peerName code:(int)code descriptions:(NSString*)descriptions { //HLog(@"webRtc P2P onAuthResultFromPeerName") } - (void)connectionChange:(NSString*)peerName didChangeLocalCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)local remoteCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)remote lastReceivedMs:(int)lastDataReceivedMs changeReason:(NSString *)reason { //HLog(@"webRtc P2P didChangeLocalCandidate") [self reportWebRtcRePoportTypeIsChannel:YES withLocal:local remoteCandidate:remote withSessionId:self.webRtcChannelSessionId withLogKey:@""]; } #pragma mark 检测盒子的心跳情况 - (void)checkBoxHeartbeatFun { //2、点击系统升级弹框确定按钮后30分钟内不弹; NSNumber *preSecondNum = [HWDataManager getNumberWithKey:stringKeyAddSn(@"disenable_type1_BoxHeartbeat")]; if(preSecondNum){ long seconds = [iTools getNowTimeStamp]; if(seconds - preSecondNum.longValue <= 60*30){ return; } } //3、重启、恢复出厂设备、首次设置密码 3个情况下8分钟之内不弹 NSNumber *preSecondNum2 = [HWDataManager getNumberWithKey:stringKeyAddSn(@"disenable_type2_BoxHeartbeat")]; if(preSecondNum2){ long seconds = [iTools getNowTimeStamp]; if(seconds - preSecondNum2.longValue <= 60*8){ return; } } if(ksharedAppDelegate.didShowBoxHeartbeatAlertType ||[webRtcManager shareManager].isResetingType ||[webRtcManager shareManager].isRebootIngType || [ksharedAppDelegate didShowImageRenewViewFun]){ return; } //1.隐私模式密码界面 3秒检测一次是否输入完成密码了 if(ksharedAppDelegate.isDidShowPwdType){ KWeakSelf dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf checkBoxHeartbeatFun]; }); return; } // [[BoxHeartbeatAlertTool shareInstance] showBoxHeartbeatAlertFun:1 didClickBut:^(NSInteger tag) { // // }]; if(ksharedAppDelegate.isWebSockLinkOKAginType && ksharedAppDelegate.cloudPhoneExtraFileListMod){ return; } NSMutableDictionary *paraDict = [NSMutableDictionary new]; KWeakSelf [[netWorkManager shareInstance] CommonGetWithCallBackCode:queryHeartbeat Parameters:paraDict success:^(id _Nonnull responseObject){ queryHeartbeatModel *heartbeatMod = [[queryHeartbeatModel alloc] initWithDictionary:responseObject error:nil]; if(heartbeatMod && heartbeatMod.data){ [weakSelf checkBoxHeartbeatToShowPopViewFunBy:heartbeatMod]; } } failure:^(NSError * _Nonnull error) { }]; } #pragma mark 根据盒子的心跳情况 显示异常谈了 - (void)checkBoxHeartbeatToShowPopViewFunBy:(queryHeartbeatModel*)heartbeatMod { if(!heartbeatMod || !heartbeatMod.data){ return; } if (//!heartbeatMod.data.frpStatus&& !heartbeatMod.data.hostAgentStatus &&!heartbeatMod.data.containerAgentStatus) {//全部异常 [[BoxHeartbeatAlertTool shareInstance] showBoxHeartbeatAlertFun:1 didClickBut:^(NSInteger tag) { }]; } else if (heartbeatMod.data.hostAgentStatus //&& !heartbeatMod.data.frpStatus && !heartbeatMod.data.containerAgentStatus) {//frp异常 [[BoxHeartbeatAlertTool shareInstance] showBoxHeartbeatAlertFun:2 didClickBut:^(NSInteger tag) { }]; } } #pragma mark 显示重启成功 - (void)showReStartSucFun { //1.隐私模式密码界面 3秒检测一次是否输入完成密码了 if(ksharedAppDelegate.isDidShowPwdType){ KWeakSelf dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf showReStartSucFun]; }); return; } [self closeBoxHeartbeatReStartViewFun]; BoxHeartbeatReStartSucView *view = [[BoxHeartbeatReStartSucView alloc] init]; [ksharedAppDelegate.window addSubview:view]; [view mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(0.f); make.bottom.mas_equalTo(0.f); make.right.mas_equalTo(0.f); make.top.mas_equalTo(0.f); }]; } #pragma mark 关闭心跳弹框 - (void)closeBoxHeartbeatReStartViewFun { NSArray * subViews = ksharedAppDelegate.window.subviews; for (BoxHeartbeatReStartView*view in subViews) { if([view isKindOfClass:[BoxHeartbeatReStartView class]]){ [view colseFun]; break; } } } @end