// // SocketServiceHandler.m // OneCable // // Created by KaRam Kim on 2017. 2. 17.. // Copyright © 2017년 ntels. All rights reserved. // #import "SocketServiceHandler.h" #import "Definitions.h" #import "JDJSONModel.h" #import "JDObject.h" #define MAX_RETRY_CONNECT_COUNT 1 #define MAX_REQUEST_ID 255 #define NONE_DELEGATE_REQUEST_ID -99 @interface SocketServiceHandler() { SRWebSocket *_socket; NSMutableArray *_messages; // NSMutableArray *_delegates; int _retryCount; BOOL _isShowLoading; int _loadingRequestId; } @property NSMutableDictionary* controllers; @property NSMutableDictionary* responses; @property int controllerId; @end @implementation SocketServiceHandler + (id)sharedManager { static SocketServiceHandler *sharedSocketServiceHandler = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedSocketServiceHandler = [[self alloc] init]; }); return sharedSocketServiceHandler; } - (id) init { self = [super init]; if (self) { _isConnected = NO; _messages = [[NSMutableArray alloc] init]; // _delegates = [[NSMutableArray alloc] init]; _controllers = [[NSMutableDictionary alloc] init]; _responses = [[NSMutableDictionary alloc] init]; self.controllerId = 0; // [self socketOpen]; } return self; } //- (void) initDelegate:(id) delegate //{ // [self setDelegate:delegate]; //} - (SRReadyState) getSocketStatus { return _socket.readyState; } - (void) socketOpen { NSLog(@"socketOpen"); _strSocketURL = [NSString stringWithFormat:@"%@%@", kSocketServer, API_ROOT_PATH]; NSLog(@"socketURL : %@", _strSocketURL); if( _socket != nil ) { [_socket open]; } else { NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:_strSocketURL]]; if([[JDFacade facade].loginUser authorization]!=nil) { [request setValue:[[JDFacade facade].loginUser authorization] forHTTPHeaderField:API_AUTHORIZATION_KEY]; } NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0]; #ifdef DEBUG_MODE language = @"ko"; #endif [request setValue:language forHTTPHeaderField:API_LANGUAGE_KEY]; NSLog(@"All Header Info : %@", request.allHTTPHeaderFields); _socket = [[SRWebSocket alloc] initWithURLRequest:request]; _socket.delegate = self; [_socket open]; } } - (void) open { if( !_isConnected ) { if( _socket.readyState == SR_OPEN ) { _isConnected = YES; } else if ( _socket.readyState == SR_CLOSED || _socket.readyState == SR_CLOSING ) { [self close]; _socket = nil; [self socketOpen]; } } } - (void) close { if( _isConnected ) { [_socket close]; _socket = nil; } else { if (_socket != nil) { _socket = nil; } } _isConnected = NO; } -(void)sendRequest { _isShowLoading = YES; [[JDFacade facade] loadIndicator:YES allowUserInteraction:NO]; } -(void)fisnishRequest { _isShowLoading = NO; [[JDFacade facade] loadIndicator:NO allowUserInteraction:YES]; } - (void) sendData:(SocketRequestModel *)data { if(_socket.readyState == SR_OPEN) { NSLog(@"Socket Ready Send Data"); NSLog(@"Send Data : %@", data); //NSLog(@"Send Param : %@", data.getSendMessage); [_socket send:data.getSendMessage]; } else if ( _socket.readyState == SR_CLOSED || _socket.readyState == SR_CLOSING ) { NSLog(@"Socket State is NOT Ready, Retry Process"); [_messages addObject:data]; [self reConnect]; } else { NSLog(@"Socket NOT Ready, Retry Process"); [_messages addObject:data]; if(!_isConnected) { [self socketOpen]; } } } - (void) sendDataWihOutDelegate:(SocketRequestModel *)data { [self sendDataWithDelegate:data modelClass:nil delegate:nil]; } - (void) sendDataWithDelegate:(SocketRequestModel *)data delegate:(id)delegate { [self sendDataWithDelegate:data modelClass:nil delegate:delegate]; } - (void) sendDataWithDelegate:(SocketRequestModel *)data modelClass:(Class)modelClass delegate:(id)delegate { [self sendDataWithDelegate:data modelClass:modelClass delegate:delegate isShowLoading:NO]; } - (void) sendDataWithDelegate:(SocketRequestModel *)data modelClass:(Class)modelClass delegate:(id)delegate isShowLoading:(BOOL)isShowLoading { short controllerId = NONE_DELEGATE_REQUEST_ID; if (delegate) { controllerId = self.controllerId++; if (self.controllerId >= INT16_MAX) { self.controllerId = 0; } } //NSLog(@"Request Info : %@", data); data.requestId = [NSString stringWithFormat:@"%d", controllerId]; //NSLog(@"Request ID : %@", data.requestId); if (delegate) { [_controllers setObject:delegate forKey:[NSNumber numberWithInt:controllerId]]; } if (modelClass) { [_responses setObject:modelClass forKey:[NSNumber numberWithInt:controllerId]]; } if (controllerId!=NONE_DELEGATE_REQUEST_ID && isShowLoading) { _loadingRequestId = controllerId; [self sendRequest]; } [self sendData:data]; } - (void)setDelegateController:(id)delegate { short controllerId = NONE_DELEGATE_REQUEST_ID; if (delegate) { controllerId = self.controllerId++; if (self.controllerId >= INT16_MAX) { self.controllerId = 0; } } if (delegate) { [_controllers setObject:delegate forKey:[NSNumber numberWithInt:controllerId]]; } } - (void)removeDelegate:(id)delegate { // [_delegates removeObject:delegate]; } -(void) reConnect { if(_retryCount < MAX_RETRY_CONNECT_COUNT) { _retryCount++; [self close]; _socket = nil; [self socketOpen]; } else { [self close]; } } #pragma mark - SRWebSocketDelegate - (void)webSocketDidOpen:(SRWebSocket *)webSocket { NSLog(@"SOCKET didOpen"); _retryCount = 0; // Open이 되지 않은 상태에서 전송시도한 메세지들을 발송한다. for (SocketRequestModel *data in _messages) { [self sendData:data]; [_messages removeObject:data]; } // for (id controller in _delegates) { // if (controller && [controller respondsToSelector:@selector(socketConnectComplete)]) { // [controller socketConnectComplete]; // } // } } - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message { NSLog(@"SOCKET didReceiveMessage : %@", message); NSString *errString = @""; if( message == nil || [message isEqualToString:@""] ) errString = @"message empty"; else { id JSONModel = nil; NSError *error = nil; NSString *JSONString = [NSString stringWithUTF8Data:[message dataUsingEncoding:NSUTF8StringEncoding]]; // NSDictionary *jsonObj = [NSJSONSerialization JSONObjectWithData:[message dataUsingEncoding:NSUTF8StringEncoding] // options:NSJSONReadingAllowFragments // error:&error]; // //NSLog(@"Json String : %@", JSONString); if (error != nil) { NSLog(@"NSJSONSerialization JSONObject error: %@", [error localizedDescription]); return; } SocketModel *response = [[SocketModel alloc] initWithString:JSONString error:&error]; id controller = nil; Class modelClass = nil; if (response.requestId != nil && ![response.requestId isEmptyString]) { NSNumber* controllerId = [NSNumber numberWithInteger:[response.requestId integerValue]]; if ([controllerId integerValue] == _loadingRequestId) { _loadingRequestId = -999; [self fisnishRequest]; } controller = [self.controllers objectForKey:controllerId]; modelClass = [self.responses objectForKey:controllerId]; } id rawJSON = [NSJSONSerialization JSONObjectWithData:[message dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error]; if (modelClass) { if ([rawJSON isKindOfClass:[NSArray class]]) { NSDictionary *JSONDic = @{@"list": rawJSON}; JSONModel = [[modelClass alloc] initWithDictionary:JSONDic error:&error]; } else { JSONModel = [[modelClass alloc] initWithString:JSONString error:&error]; } } else { JSONModel = rawJSON; } NSLog(@"JSONModel : %@", JSONModel); //0622 공통 메세징 처리, 기존 메세징 처리 주석 LoginViewController,ThingsDetailViewController if (!response.isSuccess) [self handlingSocketErrors:response]; if (!controller) { if (self.controllers.count > 0) { NSArray* array = self.controllers.allKeys; for (NSNumber *key in array) { id controller = [self.controllers objectForKey:key]; if ([controller respondsToSelector:@selector(socketDidReceiveMessage:result:)]) { [controller socketDidReceiveMessage:JSONModel result:response]; } } } [[NSNotificationCenter defaultCenter] postNotificationName:kSocketBoradCast object:JSONModel]; } else { if ([controller respondsToSelector:@selector(socketDidReceiveMessage:result:)]) { [controller socketDidReceiveMessage:JSONModel result:response]; } [self.controllers removeObjectForKey:[NSNumber numberWithInteger:[response.requestId integerValue]]]; // if (self.controllers.count > 1) { // NSArray* array = self.controllers.allKeys; // NSArray* sortedArray = [array sortedArrayUsingSelector:@selector(compare:)]; // // [self.controllers removeObjectForKey:[sortedArray objectAtIndex:0]]; // } } NSLog(@"[socket service didReceiveMessage]"); // TODO : 전달받은 데이터로 자동으로 처리할 내용이 있으면 이곳에서 처리할것 // 디바이스 정보인 경우 로컬 정보를 업데이트 if (response != nil && EQUALS(response.messageType, MSG_TYPE_DEVICE_CONTENT)) { [self updateDeviceContentWithJSONModel:JSONModel]; } else if(response != nil && EQUALS(response.messageType, MSG_TYPE_DEVICE_CONN)) { [self updateDeviceConnectionJSONModel:JSONModel]; } } } - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { NSLog(@"WebSocket error: %@", error); _isConnected = NO; [self reConnect]; } - (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload { NSLog(@"WebSocket Receive Pong: %@", pongPayload); } - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { NSLog(@"WebSocket closed with code: %ld reason:%@ wasClean:%d", (long)code, reason, wasClean); _isConnected = NO; [self reConnect]; } #pragma mark - socket 통신 후 공통처리 //device.content 정보 loginUser 에 반영 - (void)updateDeviceContentWithJSONModel:(id)jsonModel { ContentDeviceModel *result = [[ContentDeviceModel alloc] initWithDictionary:jsonModel error:nil]; // NSLog(@"updateDeviceContentWithJSONModel\nresult : %@", result); NSMutableArray *deviceList = [[JDFacade facade].loginUser.deviceList mutableCopy]; for (NSInteger i=0 ; i