// // ThingsDetailViewController.m // kneet // // Created by Jason Lee on 3/16/15. // Copyright (c) 2015 ntels. All rights reserved. // #import "RequestHandler.h" #import "DeviceModel.h" #import "CustomImageView.h" #import "CustomLabel.h" #import "CustomTextField.h" #import "CustomButton.h" #import "UIImageView+WebCache.h" #import "CustomTableView.h" #import "ChangeDeviceNamePopupView.h" #import "ValidateUtil.h" #import "CommandClassControlDetailView.h" #import "ThingsViewController.h" #import "ThingsDetailViewController.h" #import "ModifyDeviceNamePopupView.h" #import "JYPullToRefreshController.h" #import "ThingsForcedDelViewController.h" #import "ThingsGeneralDelViewController.h" /** Hub 명 Text Color : kUITextColor03 Update 알람 Text Color : kUITextColor04 Device 상태 표시 Text Color - 꺼짐 : kUITextColor01 - 켜짐 : kUITextColor02 - 잠김 : kUITextColor02 - 열림 : kUITextColor01 도어센서 마지막 동작 Text Color : kUITextColor01 도어센서 상태표시 Text Color - 열림 : kUITextColor02 - 닫힘 : kUITextColor01 Offline Text Color : kUITextColor01 노드명 표시 Text Color : kUITextColor03 value 표시 Text Color : kUITextColor04 (이미지 명) 플러그 on : img_things_detail_06_01_plug_state_on 플러그 off : img_things_detail_06_01_plug_state_off 밸브 on : img_things_detail_05_02_valve_state_locked 밸브 off : img_things_detail_05_02_valve_state_unlocked 도어센서 on : img_things_detail_01_02_sensor_door_open 도어센서 off : img_things_detail_01_02_sensor_door_close 장치 열림,켜짐 : img_things_detail_06_99_btn_off ,~off_press 장치 닫힘,꺼짐 : img_things_detail_06_99_btn_on ,~on_press 기기 배터리 부족시 사용할 폰트 칼라 color_text_07 (#ed1c24) **/ @implementation ThingsDetailTitleTableViewCell @end @implementation ThingsDetailControlTableViewCell - (void)awakeFromNib { [super awakeFromNib]; _controlContainer.pagingEnabled = YES; _controlContainer.scrollEnabled = NO; _pageControl.hidden = YES; } @end @implementation ThingsDetailOptionTableViewCell @end @implementation ThingsDetailDeviceIdTableViewCell @end @interface ThingsDetailViewController () { DeviceDetailModel *_deviceDetail; // ModifyDeviceNamePopupView *_mpopup; NSArray *_mandatoryNodes, *_optionalNodes; UIPageControl *_pageControl; NSTimer *_deviceBackgroundTimer; } @property (strong, nonatomic) JYPullToRefreshController *refreshController; @end #pragma mark - Class Definition @implementation ThingsDetailViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self initUI]; [self prepareViewDidLoad]; } - (void)initUI { //initialize tableView [self initTableViewAsDefaultStyle:_tableView]; _tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, 30.0f)]; // [self setThingsDetailPopoverOptions]; [self initRefreshController]; [self setMoreBtnArray]; } - (void)initRefreshController { //set refresh controls __weak typeof(self) weakSelf = self; self.refreshController = [[JYPullToRefreshController alloc] initWithScrollView:self.tableView]; self.refreshController.pullToRefreshHandleAction = ^{ [weakSelf requestDeviceDetail:@YES]; }; } //- (void)setThingsDetailPopoverOptions { // //set Popover Contents // __weak typeof(self) weakSelf = self; // _popooverOptionArray = [[NSMutableArray alloc] init]; // // [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"새로 고침",nil), // @"iconName": @"img_bg_morepopup_icon_refresh", // @"target": weakSelf, // @"selector": [NSValue valueWithPointer:@selector(requestDeviceDetail:)]}]; // // if ([JDFacade facade].loginUser.level > 10) { // [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"이름 변경", @"이름 변경"), // @"iconName": @"img_bg_morepopup_icon_edit", // @"target": weakSelf, // @"selector": [NSValue valueWithPointer:@selector(modifyDeviceName)]}]; // // } //} - (void)prepareViewDidLoad { [self requestDeviceDetail:@YES]; } //- (void)modifyDeviceName { // // _mpopup = [[ModifyDeviceNamePopupView alloc] initFromNib]; // _mpopup.txtDeviceName.text = _deviceDetail.deviceName; // // [_mpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) { // if (buttonIndex == 0) {//OK // [self requestDeviceUpdate]; // } // }]; //} - (void)changeDeviceName:(NSString *)deviceName { [self requestDeviceDetail:@YES]; _lblTitle.text = [deviceName isEqualToString:@""] ? _deviceDetail.prdName : deviceName; } - (void)updateTitle { [self setMoreBtnArray]; if ([_deviceDetail.prdName isEqualToString:_deviceDetail.prdUserName] || [_deviceDetail.prdUserName isEqualToString:@""]) { _lblTitle.text = _deviceDetail.prdName; } else { _lblTitle.text = _deviceDetail.prdUserName; } _btnUpdate.hidden = !_deviceDetail.isProfileUpdate; if (![JDFacade facade].loginUser.isHomehubOnline) { _lblTitle.text = @"홈허브 오프라인"; [_lblTitle setColor:kUITextColor01 text:_lblTitle.text]; return; } if (_deviceDetail && !_deviceDetail.isOnline) { _lblTitle.text = @"장치 상태를 확인하세요"; [_lblTitle setColor:kUITextColor02 text:_lblTitle.text]; return; } } -(NSString *)getDeviceDetailUrl { NSMutableArray *arr = [NSMutableArray array]; arr[0] = _refDevice.deviceId; arr[1] = _refDevice.nodeId; return [[JDFacade facade] getUrlWithCustAndGroupID:API_GET_NODE_DETAIL arguments:arr]; } #pragma mark - Main Logic - (void)requestDeviceDetail:(id)arg { BOOL showLoadingView = NO; if (arg) { showLoadingView = [arg isKindOfClass:[NSTimer class]] ? [((NSTimer *)arg).userInfo boolValue] : [arg boolValue]; } NSString *path = [NSString stringWithFormat:[self getDeviceDetailUrl], _refDevice.deviceId]; [[RequestHandler handler] sendAsyncRequestAPIPath:path method:ksHTTPRequestGET parameters:nil modelClass:[DeviceDetailModel class] showLoadingView:showLoadingView completion:^(id responseObject) { if (!responseObject) {//응답결과가 잘못되었거나 없을 경우, return; } _deviceDetail = (DeviceDetailModel *)responseObject; if (_deviceDetail) {//API 성공 , [self setDeviceContents]; [self requestPollingDeviceStatusInBackground]; } //refresh controller if (self.refreshController && self.refreshController.refreshState == JYRefreshStateLoading) { [self.refreshController stopRefreshWithAnimated:YES completion:nil]; } } failure:^(id errorObject) { [self releaseDeviceTimer]; JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } //디바이스 상태를 3초마다 갱신함. - (void)requestPollingDeviceStatusInBackground { //schedul timer. // if (!_deviceBackgroundTimer) { // _deviceBackgroundTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(requestDeviceDetail:) userInfo:@NO repeats:YES]; // } } - (void)setDeviceContents { [self updateTitle]; _mandatoryNodes = (NSArray *)[_deviceDetail.cmdclsList filteredArrayUsingPredicateFormat:@"cmdclsMandatoryYn == %@", @"Y"]; _optionalNodes = (NSArray *)[_deviceDetail.cmdclsList filteredArrayUsingPredicateFormat:@"cmdclsMandatoryYn == %@", @"N"]; [_tableView reloadData]; } //- (void)requestDeviceUpdate { // //parameters // NSDictionary *parameter = @{@"device_name": _mpopup.txtDeviceName.text}; // // NSString *path = [NSString stringWithFormat:API_GET_DEVICE_UPDATE, _deviceDetail.deviceId]; // // [[RequestHandler handler] sendAsyncPostRequestAPIPath:path parameters:parameter modelClass:[JDJSONModel class] completion:^(id responseObject) { // // _refDevice.deviceName = _deviceDetail.deviceName = _mpopup.txtDeviceName.text; // [_tableView reloadData]; // // //리스트를 다시 로드함. // ThingsViewController *vc = [[JDFacade facade] viewControllerOnNaviationController:[ThingsViewController class]]; // [vc.collectionView reloadData]; // // } failure:^(id errorObject) { // JDErrorModel *error = (JDErrorModel *)errorObject; // [[JDFacade facade] alert:error.errorMessage]; // }]; //} - (void)requestDeleteDevice { //parameters NSString *path = [NSString stringWithFormat:API_DELETE_DEVICE, _deviceDetail.deviceId]; [[RequestHandler handler] sendAsyncRequestAPIPath:path method:ksHTTPRequestDELETE parameters:nil modelClass:[JDJSONModel class] showLoadingView:YES completion:^(id responseObject) { [[JDFacade facade] toast:NSLocalizedString(@"장치가 삭제되었습니다", @"장치가 삭제되었습니다")]; // if ([JDFacade facade].loginHomeGroup.deviceId && ![[JDFacade facade].loginHomeGroup.deviceId isEmptyString]) { // if ([[JDFacade facade].loginHomeGroup.deviceId isEqualToString:_deviceDetail.deviceId]) {//현재 홈의 스마튼폰일 경우, // [JDFacade facade].loginHomeGroup.deviceId = nil; // [JDFacade facade].loginHomeGroup.deviceAuthorization = nil; // [JDFacade facade].loginHomeGroup.deviceKey = nil; // } // } //리스트를 다시 로드함. ThingsViewController *vc = [[JDFacade facade] viewControllerOnNaviationController:[ThingsViewController class]]; [vc prepareViewDidLoadRefreshPopup]; [self.navigationController popToRootViewControllerAnimated:YES]; } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } #pragma mark - UITableView DataSource & Delegate - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 4; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger count = 1; if (section == 1) { count = _deviceDetail && _deviceDetail.cmdclsList && _deviceDetail.cmdclsList.count > 0; } else if (section == 2) {//optional nodes count = _optionalNodes.count; //두번째 이후부터 옵셔널 노드임. } return count; } - (CGFloat)heightForMandatoryNode { CGFloat height = 0; NodeModel *node = _deviceDetail.cmdclsList.firstObject; if (node.cmdclsType == CmdClsTypeSwitchBinary || node.cmdclsType == CmdClsTypeValve) { height = 347.0f; //275 || 347 } else { height = 275.0f; } height += _mandatoryNodes.count > 1 ? 75 : 0; return height; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat height = 86; NSInteger section = indexPath.section; if (section == 0) { height = 68; } else if (section == 1) { // height = [self heightForMandatoryNode] + 35.0f; height = 322; } else if (section == 2) { height = 63; // if (indexPath.row == _deviceDetail.nodes.count - 2) { // height += 35; // } } else if (section == 3) { height = 89; } return height; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; NSInteger section = indexPath.section; if (section == 0) {//title ThingsDetailTitleTableViewCell *tcell = (ThingsDetailTitleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"TitleCellIdentifier"]; // [tcell.imgvDevice sd_setImageWithURL:[NSURL URLWithString:_deviceDetail.imageFileName] placeholderImage:nil options:SDWebImageRefreshCached]; tcell.lblDeviceUpdate.hidden = !_deviceDetail.isProfileUpdate; //배터리 30이하일때 메세지 우선순위 NSString *battery = [self getBatteryFromNode]; if (battery != nil && [battery integerValue] <= 30) { tcell.lblDeviceUpdate.hidden = NO; tcell.lblDeviceUpdate.text = @"배터리를 즉시 교체하세요."; } cell = tcell; } else if (section == 1) {//device control ThingsDetailControlTableViewCell *tcell = (ThingsDetailControlTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"ControlCellIdentifier"]; //뷰를 초기화함. [[tcell.controlContainer subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { UIView *subview = (UIView *)obj; [subview removeFromSuperview]; }]; if (_deviceDetail) { tcell.controlContainer.scrollEnabled = _mandatoryNodes.count > 1; tcell.controlContainer.contentSize = CGSizeMake(IPHONE_WIDTH * _mandatoryNodes.count, [self heightForMandatoryNode]); tcell.controlContainer.showsHorizontalScrollIndicator = NO; if (tcell.controlContainer.scrollEnabled) { tcell.controlContainer.delegate = self; } tcell.pageControl.hidden = !tcell.controlContainer.scrollEnabled; if (!tcell.pageControl.hidden && !_pageControl) { _pageControl = tcell.pageControl; _pageControl.numberOfPages = _mandatoryNodes.count; } __block CGFloat width = 0; for (NodeModel *node in _mandatoryNodes) { node.refDevice = _refDevice; NSLog(@"node.cmdclsType : %ld", (long)node.cmdclsType); CommandClassControlView *controlView = [CommandClassControlDetailView viewForCommandClass:node.cmdclsType]; node.deviceId = _deviceDetail.deviceId; node.nodeId = _deviceDetail.nodeId; controlView.node = node; controlView.isMandatoryNode = [node.cmdclsMandatoryYn boolValue] && _mandatoryNodes.count > 1; controlView.selectHub = _selectHub; tcell.controlContainer.hidden = !controlView; if (!tcell.controlContainer.hidden) { controlView.x = width; UIView *superview = tcell.controlContainer; [superview addSubview:controlView]; [controlView mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(controlView.frame.size); make.leading.equalTo(superview).offset(width); // make.trailing.equalTo(superview).offset(width+IPHONE_WIDTH); width += IPHONE_WIDTH; }]; } } } cell = tcell; } else if (section == 2) {//option control ThingsDetailOptionTableViewCell *tcell = (ThingsDetailOptionTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"OptionCellIdentifier"]; NodeModel *node = _deviceDetail.cmdclsList[indexPath.row + _mandatoryNodes.count]; //NSLog(@"NodeModel : %@", node); tcell.lblNodeName.text = node.cmdclsName; tcell.lblNodeValue.text = node.contentValueMsg; cell = tcell; } else if (section == 3){ // Device Id ThingsDetailDeviceIdTableViewCell *tcell = (ThingsDetailDeviceIdTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"DeviceIdCellIdentifier"]; tcell.lblDeviceName.text = _deviceDetail.deviceModelId; tcell.lblDeviceId.text = _deviceDetail.deviceId; cell = tcell; } return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [super tableView:tableView didSelectRowAtIndexPath:indexPath]; } - (void)setMoreBtnArray { _moreBtnArray = [NSMutableArray array]; if (![[JDFacade facade].loginUser hasHomeHub]) { [_btnOption setHidden:YES]; } if([[JDFacade facade].loginUser.gradeCode isEqualToString:KNEET_MEMBER_MASTER]) { for (int i = 0; i < 3; i++) { MoreBtnModel *btnModel; switch (i) { case 0: btnModel = [[MoreBtnModel alloc] initWithTyep:NameChange isEnable:YES]; break; case 1: btnModel = [[MoreBtnModel alloc] initWithTyep:Del isEnable:YES]; break; case 2: btnModel = [[MoreBtnModel alloc] initWithTyep:Refresh isEnable:YES]; break; default: break; } [_moreBtnArray addObject:btnModel]; } } else { MoreBtnModel *btnModel = [[MoreBtnModel alloc] initWithTyep:Refresh isEnable:YES]; [_moreBtnArray addObject:btnModel]; } } - (BOOL)checkOnlineHubAlert { if (![[JDFacade facade].loginUser onlineHomeHubFromSelectedHub:_selectHub]) { [[JDFacade facade] alert:@"허브가 오프라인 상태입니다. 허브 상태 확인 후 다시 시도해주세요." completionHander:nil]; return NO; } return YES; } - (NSString*)getBatteryFromNode { for (NodeModel *model in _deviceDetail.cmdclsList) { NSLog(@"model : %@", model); if (EQUALS(model.cmdclsId, @"battery")) { return model.contentValue; } } return nil; } -(void)deviceDelete { if (![self checkOnlineHubAlert]) return ; if (![_deviceDetail isOnline]) { ThingsForcedDelViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"ThingsForcedDelViewController" storyboardName:@"Things"]; vc.delDevice = _deviceDetail; [self showTransparencyModalView:vc removeSelf:NO]; } else { ThingsGeneralDelViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"ThingsGeneralDelViewController" storyboardName:@"Things"]; vc.delDevice = _deviceDetail; [self showTransparencyModalView:vc removeSelf:NO]; } } -(void)nodeProfileUpdate { SocketRequestModel *request = [[SocketRequestModel alloc] initWithMsgType:MSG_TYPE_NODE_PROFILE_UPDATE]; NSDictionary *param = @{@"device_id":_refDevice.deviceId, @"node_id":_refDevice.nodeId, @"cust_id": [[JDFacade facade].loginUser custId], @"ctrt_grp_id": [[JDFacade facade].loginUser ctrtGrpId]}; [request setRequestMsg:param]; [self sendDataToSocket:request modelClass:[CommandModel class] isLoading:YES]; } #pragma mark - MoreButtonDelegate -(void)moreBtnAction:(id)sender { NSInteger tag = [(UIButton *)sender tag]; NSLog(@"MoreBtn Action : %li", (long)tag); switch (tag) { case NameChange: { if (![self checkOnlineHubAlert]) return ; ChangeDeviceNamePopupView *popup = [[ChangeDeviceNamePopupView alloc]initFromNib:_deviceDetail]; popup.deviceDetailModel = _deviceDetail; popup.delegate = self; [popup show]; } break; case Del: { [self deviceDelete]; } break; case Refresh: { [self requestDeviceDetail:@YES]; } break; default: break; } } #pragma mark - UI Events - (IBAction)btnOptionTouched:(id)sender { // [self toggleOptions:sender]; [self toggleOptionsWithArray:sender btnArray:_moreBtnArray]; } //업데이트 - (IBAction)btnUpdateTouched:(id)sender { if (![self checkOnlineHubAlert]) return ; [[JDFacade facade] confirmTitle:@"장치 업데이트" message:@"지금 장치를 최신 버전으로\n업데이트 하시겠습니까?" btnOKLabel:@"예" btnCancelLabel:@"아니오" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) { if (buttonIndex == 0) { [self nodeProfileUpdate]; } }]; } - (IBAction)btnCloseTouched:(id)sender { [[JDFacade facade] dismissModalStack:YES completion:nil]; } #pragma mark - ScrollView Delegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat pageWidth = scrollView.frame.size.width; // you need to have a **iVar** with getter for scrollView CGFloat fractionalPage = scrollView.contentOffset.x / pageWidth; NSInteger page = lround(fractionalPage); _pageControl.currentPage = page; // you need to have a **iVar** with getter for pageControl } -(void) receiveSocketData:(NSNotification *)notification { SocketModel *result = [[SocketModel alloc] initWithDictionary:notification.object error:nil]; //NSLog(@"Result : %@", result); if ([result.messageType isEqualToIgnoreCase:MSG_TYPE_NODE_CONTENT]) { ContentModel *response = [[ContentModel alloc] initWithDictionary:notification.object error:nil]; //NSLog(@"Response : %@", response); if ([_refDevice.deviceId isEqualToString:response.deviceId] && [_refDevice.nodeId isEqualToString:response.nodeId]) { [self requestDeviceDetail:@NO]; } } if ([result.messageType isEqualToString:MSG_TYPE_NODE_PROFILE_UPDATE_RES]) { if (result.isSuccess) { [[JDFacade facade] alertTitle:@"장치 업데이트 완료" message:@"장치를 최신 버전으로 업데이트 하였습니다."]; } else { [[JDFacade facade] confirmTitle:@"장치 업데이트 실패" message:@"오류가 발생하여 업데이트가 완료되지 않았습니다." btnOKLabel:@"재시도" btnCancelLabel:@"취소" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) { if (buttonIndex == 0) { [self btnUpdateTouched:nil]; } }]; } } } -(void)finishDeviveDelete { NSLog(@"tdvc finishDeviveDelete"); [self btnCloseTouched:nil]; } #pragma mark - MemoryWarning - (void)releaseDeviceTimer { if (_deviceBackgroundTimer) { [_deviceBackgroundTimer invalidate]; _deviceBackgroundTimer = nil; } } - (void)viewWillDisappear:(BOOL)animated { [self releaseDeviceTimer]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end