ThingsViewController.m 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. //
  2. // ThingsViewController.m
  3. // kneet
  4. //
  5. // Created by Jason Lee on 3/10/15.
  6. // Copyright (c) 2015 ntels. All rights reserved.
  7. //
  8. #import "JDObject.h"
  9. #import "RequestHandler.h"
  10. #import "JDJSONModel.h"
  11. #import "DeviceModel.h"
  12. #import "CustomLabel.h"
  13. #import "CustomImageView.h"
  14. #import "CustomTextField.h"
  15. #import "CustomLabelButton.h"
  16. #import "CustomButton.h"
  17. #import "JYRefreshController.h"
  18. #import "WYPopoverController.h"
  19. #import "ImageUtil.h"
  20. #import "ThingsAddCompleteViewController.h"
  21. #import "UIImageView+WebCache.h"
  22. #import "UIButton+WebCache.h"
  23. #import "CommandClassControlView.h"
  24. #import "ThingsDetailViewController.h"
  25. #import "ThingsViewController.h"
  26. #import "ThingsAddViewController.h"
  27. #import "ThingsAddStartViewController.h"
  28. #import "CustomTableView.h"
  29. #import "JYPullToRefreshController.h"
  30. #import "HomeMemberViewController.h"
  31. #define kfThingsTableViewCellHeight 100.0f
  32. #define kiCellInset 5
  33. #define kiCellItem 2
  34. #define kiCellRatio 74
  35. #define kiCellDivision 3
  36. /**
  37. Head Text Color : kUITextColor01
  38. Device 명 Text Color : kUITextColor01
  39. Device 상태표시 Text Color
  40. - 열림 : kUITextColor02
  41. - 닫힘 : kUITextColor01
  42. 장치 추가 Text Color : kUITextColor01
  43. (이미지 명)
  44. 디바이스 아이콘 bg
  45. - Default : img_thing_icon_bg_default
  46. - Active : img_thing_icon_bg_active
  47. 도어 컨텍트 센서 : 40102
  48. 가스 밸브 : 40108
  49. 다윈 플러그 : 40402
  50. **/
  51. @interface ThingsCollectionViewCell () {
  52. NSInteger _commandStatusElapsedTime;
  53. }
  54. @property (weak, nonatomic) NSIndexPath *indexPath;
  55. @end
  56. @implementation ThingsCollectionViewCell
  57. - (void)awakeFromNib {
  58. _pcontainerView.hidden = NO;
  59. }
  60. - (void)startProgressAni {
  61. //chagne button image
  62. [UIView animateWithDuration:0.5f delay:0.0f options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
  63. _imgvProgress.transform = CGAffineTransformMakeRotation(M_PI);
  64. } completion:nil];
  65. }
  66. - (void)stopProgressAni {
  67. [UIView animateWithDuration:0.0f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear animations:^{
  68. _imgvProgress.transform = CGAffineTransformMakeRotation(0);
  69. } completion:nil];
  70. }
  71. @end
  72. @implementation ThingsAddCollectionCell
  73. @end
  74. @interface ThingsViewController () <UICollectionViewDataSource, UICollectionViewDelegate> {
  75. NSMutableArray *_deviceList;
  76. NSMutableArray *_deviceReOrderList;
  77. NSString *_pagingId, *_pagingType;
  78. BOOL _isNotFirstLoading, _isReOrderMode, _isDeleteMode;
  79. NSMutableArray<DeviceModel> *_commandArray;
  80. NSTimer *_devicesBackgroundTimer;
  81. NSTimer *_deviceCommandsBackgroundTimer;
  82. NSInteger _deviceFlag;
  83. UIPanGestureRecognizer *_moveCellGesture;
  84. NSIndexPath *_dragIndexPath;
  85. ThingsCollectionViewCell *_moveCell;
  86. NodeListModel *_nodeListData;
  87. DeviceModel *_selectHub;
  88. }
  89. @property (strong, nonatomic) JYPullToRefreshController *refreshController;
  90. @property (nonatomic, strong) UIView *cellFakeView;
  91. @end
  92. #pragma mark - Class Definition
  93. @implementation ThingsViewController
  94. - (void)viewDidLoad {
  95. [super viewDidLoad];
  96. [self initProperties];
  97. [self initUI];
  98. }
  99. - (void)viewWillAppear:(BOOL)animated {
  100. [super viewWillAppear:animated];
  101. [self prepareViewDidLoad];
  102. }
  103. - (void)initProperties {
  104. _deviceFlag = IS_IPHONE_6P ? 2 : 2;
  105. }
  106. - (void)initUI {
  107. //set tableview option
  108. _collectionView.delegate = self;
  109. _collectionView.dataSource = self;
  110. _collectionView.backgroundColor = [UIColor clearColor];
  111. _collectionView.alwaysBounceVertical = YES;
  112. _lblEditMode.hidden = YES;
  113. [self viewOfflineSetHidden:YES];
  114. [_btnClose setHidden:YES];
  115. [_btnOption setHidden:NO];
  116. [_viewEditMode setHidden:YES];
  117. // [self setThingsPopoverOptions];
  118. [self setMoreBtnArray];
  119. [self initRefreshController];
  120. }
  121. - (void)viewOfflineSetHidden:(BOOL)hidden{
  122. _viewHeight.constant = hidden ? 0 : 54;
  123. }
  124. - (void)initRefreshController {
  125. //set refresh controls
  126. __weak typeof(self) weakSelf = self;
  127. self.refreshController = [[JYPullToRefreshController alloc] initWithScrollView:self.collectionView];
  128. self.refreshController.pullToRefreshHandleAction = ^{
  129. [weakSelf requestDeviceList:@YES];
  130. };
  131. }
  132. - (void)setThingsPopoverOptions {
  133. //
  134. // //set Popover Contents
  135. // __weak typeof(self) weakSelf = self;
  136. // _popooverOptionArray = [[NSMutableArray alloc] init];
  137. //
  138. // [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"새로고침", @"새로고침"),
  139. // @"iconName": @"img_bg_morepopup_icon_refresh",
  140. // @"target": weakSelf,
  141. // @"selector": [NSValue valueWithPointer:@selector(refreshDeviceList)]}];
  142. //
  143. //// if ([JDFacade facade].loginUser.level == 90) {//권한
  144. //// [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"추가", @"추가"),
  145. //// @"iconName": @"tp_01_img_bg_morepopup_icon_group_deviceadd",
  146. //// @"target": weakSelf,
  147. //// @"selector": [NSValue valueWithPointer:@selector(addNewDevice)]}];
  148. ////
  149. //// [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"삭제", @"삭제"),
  150. //// @"iconName": @"tp_01_img_bg_morepopup_icon_group_deviceadd",
  151. //// @"target": weakSelf,
  152. //// @"selector": [NSValue valueWithPointer:@selector(toggleEditMode)]}];
  153. //// }
  154. }
  155. - (void)setMoreBtnArray {
  156. _moreBtnArray = [NSMutableArray array];
  157. if (![[JDFacade facade].loginUser hasHomeHub]) {
  158. [_btnOption setHidden:YES];
  159. }
  160. if([[JDFacade facade].loginUser.gradeCode isEqualToString:KNEET_MEMBER_MASTER]) {
  161. for (int i = 0; i < 4; i++) {
  162. MoreBtnModel *btnModel;
  163. switch (i) {
  164. case 0:{
  165. btnModel = [[MoreBtnModel alloc] initWithTyep:ReOrder isEnable:YES];
  166. btnModel.enable = [_nodeListData isCanReOrder];
  167. }
  168. break;
  169. case 1:{
  170. btnModel = [[MoreBtnModel alloc] initWithTyep:Add isEnable:YES];
  171. btnModel.enable = [_nodeListData isCanAddNode];
  172. }
  173. break;
  174. case 2:{
  175. btnModel = [[MoreBtnModel alloc] initWithTyep:Del isEnable:YES];
  176. btnModel.enable = [_nodeListData isCanDelNode];
  177. }
  178. break;
  179. case 3:
  180. btnModel = [[MoreBtnModel alloc] initWithTyep:Refresh isEnable:YES];
  181. break;
  182. default:
  183. break;
  184. }
  185. [_moreBtnArray addObject:btnModel];
  186. }
  187. }
  188. else {
  189. MoreBtnModel *btnModel = [[MoreBtnModel alloc] initWithTyep:Refresh isEnable:YES];
  190. [_moreBtnArray addObject:btnModel];
  191. }
  192. }
  193. - (void)prepareViewDidLoad {
  194. //fetch devices from server
  195. [self updateTitle];
  196. [self performSelector:@selector(requestHomeHubList) withObject:nil afterDelay:0.0f];
  197. [self performSelector:@selector(requestDeviceList:) withObject:@YES afterDelay:0.0f];
  198. }
  199. - (void)updateHomeHubStatusToDevices {
  200. [self updateTitle];
  201. for (DeviceModel *device in _deviceList) {
  202. device.onlineState = [JDFacade facade].loginUser.homehubOnlineState;
  203. }
  204. [_collectionView reloadData];
  205. }
  206. //제어를 요청한 장치상태를 조회함.
  207. - (void)requestPollingCommandStatusOfDeviceInBackground:(DeviceModel *)device {
  208. if (!_commandArray) {
  209. _commandArray = (NSMutableArray<DeviceModel> *)[[NSMutableArray alloc] init];
  210. }
  211. __block BOOL isStatusChanged = NO;
  212. if (device && [device isKindOfClass:[DeviceModel class]]) {//validate, aleady have,
  213. if (![_commandArray objectByUsingPredicateFormat:@"deviceId == %@ && nodeId == %@", device.deviceId, device.nodeId]) {//일치하는 디바이스가 있을 경우, 추가하지 않음.
  214. [_commandArray addObject:device];
  215. isStatusChanged = YES;
  216. }
  217. }
  218. if (_commandArray.count) {
  219. NSMutableString *pathParams = [[NSMutableString alloc] init];
  220. for (DeviceModel *pDevice in _commandArray) {
  221. NSString *prefix = [pathParams isEmptyString] ? ksEmptyString : @",";
  222. [pathParams appendFormat:@"%@%@_%@", prefix, pDevice.deviceId, pDevice.nodeId];
  223. }
  224. //20
  225. NSString *path = [NSString stringWithFormat:API_GET_DEVICE_NODE_STATUS, pathParams];
  226. dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//RUN to background thread
  227. NodeListModel *fdevices = [[RequestHandler handler] sendSyncGetRequestAPIPath:path parameters:nil
  228. modelClass:[NodeListModel class] showLoadingView:YES];
  229. if (fdevices && fdevices.nodes && fdevices.nodes.count) {
  230. [_commandArray enumerateObjectsUsingBlock:^(DeviceModel *rdevice, NSUInteger idx, BOOL * _Nonnull stop) {
  231. DeviceModel *matchedDevice = (DeviceModel *)[fdevices.nodes objectByUsingPredicateFormat:@"deviceId == %@ && nodeId == %@", rdevice.deviceId, rdevice.nodeId];
  232. //실행 여부 및 10초 경과 확인
  233. BOOL isOverTimeLimit = [self elapsedSecondsFromNow:rdevice] > 10;
  234. //실행 여부 확인
  235. NSInteger elapsedTime = [self elapsedSecondsFrom:rdevice to:matchedDevice];
  236. BOOL hasChangedStatus = elapsedTime > 0;
  237. rdevice.isRequesting = [rdevice.contentValue isEqualToString:matchedDevice.contentValue] && !hasChangedStatus && !isOverTimeLimit;
  238. //TODO - home hub check
  239. // rdevice.requestTime = matchedDevice.requestTime;
  240. // rdevice.collectTime = matchedDevice.collectTime;
  241. rdevice.onlineState = matchedDevice.onlineState;
  242. if (!rdevice.isRequesting || !rdevice.isOnline || ![JDFacade facade].loginUser.isHomehubOnline) {//정상적으로 변경됨.
  243. rdevice.contentValue = matchedDevice.contentValue;
  244. [_commandArray removeObject:rdevice];
  245. isStatusChanged = YES;
  246. }
  247. #ifdef DEBUG_MODE
  248. NSLogInfo(@"==########== device command status = %@, elapsedTime = %zd ==########==", [JDFacade facade].loginUser.homehubOnlineState, elapsedTime);
  249. #endif
  250. }];
  251. } else {//
  252. NSLog(@"no devices");
  253. }
  254. if (_commandArray.count) {//커맨드 실행 중인 디바이스가 있을 경우,
  255. //schedul timer.
  256. if (!_deviceCommandsBackgroundTimer) {
  257. _deviceCommandsBackgroundTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(requestPollingCommandStatusOfDeviceInBackground:) userInfo:nil repeats:YES];
  258. }
  259. } else {
  260. [_deviceCommandsBackgroundTimer invalidate];
  261. _deviceCommandsBackgroundTimer = nil;
  262. }
  263. //리스트와 상세의 상태를 계속 매핑해줌.
  264. [self matchDeviceListWithOnCommandsDevices];
  265. //변화가 있을 경우, 컬렉션뷰를 리로드
  266. if (isStatusChanged) {
  267. [_collectionView reloadData];
  268. ThingsDetailViewController *vc = (ThingsDetailViewController *)[JDFacade facade].currentViewController;
  269. if ([vc isKindOfClass:[ThingsDetailViewController class]]) {
  270. [vc.tableView reloadData];
  271. }
  272. }
  273. });
  274. }
  275. }
  276. -(void)requestDeviceControl
  277. {
  278. [_collectionView reloadData];
  279. ThingsDetailViewController *vc = (ThingsDetailViewController *)[JDFacade facade].currentViewController;
  280. if ([vc isKindOfClass:[ThingsDetailViewController class]]) {
  281. [vc.tableView reloadData];
  282. }
  283. }
  284. - (NSInteger)elapsedSecondsFromNow:(DeviceModel *)runningDevice {
  285. NSInteger seconds = 0;
  286. if (runningDevice.requestTime && ![runningDevice.requestTime isEmptyString]) {
  287. NSDate *rdate = [CommonUtil dateFromDateString:[CommonUtil localDateFromUTC:runningDevice.requestTime]];
  288. NSTimeInterval elapsed = [[NSDate systemDate] timeIntervalSinceDate:rdate];
  289. seconds = elapsed;
  290. }
  291. return seconds;
  292. }
  293. - (NSInteger)elapsedSecondsFrom:(DeviceModel *)runningDevice to:(DeviceModel *)fetchedDevice {
  294. NSInteger seconds = 0;
  295. if (runningDevice.requestTime && ![runningDevice.requestTime isEmptyString] && fetchedDevice.collectTime && ![fetchedDevice.collectTime isEmptyString]) {
  296. NSDate *rdate = [CommonUtil dateFromDateString:[CommonUtil localDateFromUTC:runningDevice.requestTime]];
  297. NSDate *fdate = [CommonUtil dateFromDateString:[CommonUtil localDateFromUTC:fetchedDevice.collectTime]];
  298. seconds = [fdate secondsAfterDate:rdate];
  299. }
  300. return seconds;
  301. }
  302. - (void)addNewDevice {
  303. UIViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"ThingsAddViewController" storyboardName:@"Things"];
  304. [self presentViewController:vc animated:YES completion:nil];
  305. }
  306. - (void)refreshDeviceList {
  307. [self performSelector:@selector(requestDeviceList:) withObject:@YES afterDelay:0.0f];
  308. }
  309. #pragma mark - Main Logic
  310. - (void)requestDeviceListRecently {
  311. DeviceModel *firstDevice = [_deviceList firstObject];
  312. _pagingType = ksListPagingTypeUpward;
  313. _pagingId = firstDevice.createDatetime;
  314. [self performSelector:@selector(requestDeviceList:) withObject:@YES afterDelay:0.0f];
  315. }
  316. - (void)requestDeviceListOlder {
  317. DeviceModel *lastDevice = [_deviceList lastObject];
  318. _pagingType = ksListPagingTypeDownward;
  319. _pagingId = lastDevice.createDatetime;
  320. [self performSelector:@selector(requestDeviceList:) withObject:@YES afterDelay:0.0f];
  321. }
  322. - (void)requestHomeHubList {
  323. NSString *path = [[JDFacade facade] getUrlWithCustAndGroupID:API_GET_DEVICE_LIST aditional:@""];
  324. [[RequestHandler handler] sendAsyncRequestAPIPath:path method:ksHTTPRequestGET parameters:nil
  325. modelClass:[DeviceListModel class] showLoadingView:NO completion:^(id responseObject) {
  326. if (!responseObject) {//응답결과가 잘못되었거나 없을 경우,
  327. return;
  328. }
  329. DeviceListModel *deviceList = (DeviceListModel *)responseObject;
  330. NSMutableArray *list = [NSMutableArray array];
  331. for (DeviceModel *info in deviceList.list) {
  332. [list addObject:info];
  333. }
  334. [JDFacade facade].loginUser.deviceList = list;
  335. } failure:^(id errorObject) {
  336. // [self releaseDevicesTimer];
  337. JDErrorModel *error = (JDErrorModel *)errorObject;
  338. [[JDFacade facade] alert:error.errorMessage];
  339. }];
  340. }
  341. - (void)requestDeviceList:(id)arg {
  342. if (![JDFacade facade].loginUser.hasHomeHub) {
  343. return;
  344. }
  345. // BOOL showLoadingView = [arg isKindOfClass:[NSTimer class]] ? [((NSTimer *)arg).userInfo boolValue] : [arg boolValue];
  346. BOOL showLoadingView = YES;
  347. //parameters
  348. NSDictionary *parameter = @{@"device_id": _selectHub ? _selectHub.deviceId : ksEmptyString};
  349. // NSString *path = [NSString stringWithFormat:API_GET_DEVICE_LIST];
  350. // 멀티 홈허브 환경에서 선택된 홈허브 아이디가 있을경우 적용하기
  351. NSString *path = [[JDFacade facade] getUrlWithCustAndGroupID:API_GET_NODE_LIST aditional:@""];
  352. [[RequestHandler handler] sendAsyncRequestAPIPath:path method:ksHTTPRequestPOST parameters:parameter
  353. modelClass:[NodeListModel class] showLoadingView:showLoadingView completion:^(id responseObject) {
  354. if (!responseObject) {//응답결과가 잘못되었거나 없을 경우,
  355. return;
  356. }
  357. _nodeListData = (NodeListModel *)responseObject;
  358. [self setMoreBtnArray];
  359. if (_nodeListData && _nodeListData.nodes && _nodeListData.nodes.count) {
  360. _deviceList = _nodeListData.nodes;
  361. _deviceReOrderList = [[NSMutableArray alloc] initWithArray:_deviceList];
  362. [self updateTitle];
  363. } else {
  364. if (!_deviceList.count) {//이미 로드된 데이터가 있을 경우는 출력하지 않음.
  365. _lblConnectHub.text = @"등록된 장치가 없습니다";
  366. _imgvHubAlert.hidden = YES;
  367. _imgvConnectHub.image = [UIImage imageNamed:@"img_1depth_nodevice"];
  368. }
  369. }
  370. [_collectionView reloadData];
  371. // [self requestPollingDevicesStatusInBackground];
  372. //refresh controller
  373. if (self.refreshController && self.refreshController.refreshState == JYRefreshStateLoading) {
  374. [self.refreshController stopRefreshWithAnimated:YES completion:nil];
  375. }
  376. } failure:^(id errorObject) {
  377. // [self releaseDevicesTimer];
  378. JDErrorModel *error = (JDErrorModel *)errorObject;
  379. [[JDFacade facade] alert:error.errorMessage];
  380. }];
  381. }
  382. - (void)requestDeviceOrderReset {
  383. NSString *path = [[JDFacade facade] getUrlWithCustAndGroupID:API_PUT_NODE_ORDER_RESET aditional:nil];
  384. NSDictionary *parameter = @{@"type": @"node"};
  385. [[RequestHandler handler] sendAsyncPutRequestAPIPath:path parameters:parameter modelClass:[JDJSONModel class] completion:^(id responseObject) {
  386. NSLog(@"Reset Result : %@", responseObject);
  387. [self refreshDeviceList];
  388. } failure:^(id errorObject) {
  389. JDErrorModel *error = (JDErrorModel *)errorObject;
  390. [[JDFacade facade] alert:error.errorMessage];
  391. }];
  392. }
  393. - (void)requestDeviceOrderChange {
  394. NSString *path = [[JDFacade facade] getUrlWithCustAndGroupID:API_PUT_NODE_ORDER_CHANGE aditional:nil];
  395. NSMutableArray *nodeOrder = [NSMutableArray array];
  396. for (DeviceModel *info in _deviceReOrderList) {
  397. NSDictionary *orderInfo = @{
  398. @"device_id": info.deviceId,
  399. @"node_id": info.nodeId};
  400. [nodeOrder addObject:orderInfo];
  401. }
  402. NSDictionary *parameter = @{@"nodes": nodeOrder};
  403. [[RequestHandler handler] sendAsyncPutRequestAPIPath:path parameters:parameter modelClass:[JDJSONModel class] completion:^(id responseObject) {
  404. NSLog(@"ReOrder Result : %@", responseObject);
  405. // [self refreshDeviceList];
  406. } failure:^(id errorObject) {
  407. JDErrorModel *error = (JDErrorModel *)errorObject;
  408. [[JDFacade facade] alert:error.errorMessage];
  409. }];
  410. }
  411. //디바이스 상태를 3초마다 갱신함.
  412. - (void)requestPollingDevicesStatusInBackground {
  413. return;
  414. //schedul timer.
  415. if (!_devicesBackgroundTimer) {
  416. _devicesBackgroundTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(requestDeviceList:) userInfo:@NO repeats:YES];
  417. }
  418. }
  419. - (void)updateTitle {
  420. // _lblTitle.text = [NSString stringWithFormat:@"장치 전체 %zd", _deviceList.count];
  421. _lblCount.text = [NSString stringWithFormat:@"%zd", _deviceList.count];
  422. NSLog(@"HomeHubID : %@", [JDFacade facade].loginUser.homehubDeviceId);
  423. if (![JDFacade facade].loginUser.hasHomeHub) {//홈허브 아이디가 없는 경우,
  424. [_mainView bringSubviewToFront:_addHubContainerView];
  425. _addHubContainerView.hidden = NO;
  426. _collectionView.hidden = YES;
  427. _btnOption.hidden = NO;
  428. _btnClose.hidden = YES;
  429. if (![JDFacade facade].loginUser.homegrpId) {//연결한 적이 없음
  430. _lblConnectHub.text = @"초대를 받아서\n시작해 보세요";
  431. _imgvHubAlert.hidden = YES;
  432. _imgvConnectHub.image = [UIImage imageNamed:@"img_1depth_invitation"];
  433. _lblLeaveAccount.hidden = YES;
  434. _lblSimpleMemberInfo.hidden = YES;
  435. } else {//홈허브가 삭제됨.
  436. _lblTitle.text = @"홈허브 삭제됨";
  437. _imgvHubAlert.hidden = NO;
  438. _lblConnectHub.text = @"홈허브를 다시 연결하려면\n고객센터에 문의해주세요";
  439. _imgvConnectHub.image = [UIImage imageNamed:@"img_things_homehub_img_hubdelete_cscenter"];
  440. if ([JDFacade facade].loginUser.level < 90) {//일반 유저일 경우,
  441. _imgvConnectHub.image = [UIImage imageNamed:@"img_things_homehub_img_hubdelete_wait"];
  442. _lblLeaveAccount.hidden = NO;
  443. _lblSimpleMemberInfo.hidden = NO;
  444. [_lblLeaveAccount setUnderLine:_lblLeaveAccount.text];
  445. if (!_lblLeaveAccount.touchHandler) {
  446. [_lblLeaveAccount addTouchEventHandler:^(id label) {
  447. [self leaveHomegroup];
  448. }];
  449. }
  450. }
  451. }
  452. } else {
  453. NSLog(@"이쪽으로 빠짐2");
  454. if (![JDFacade facade].loginUser.isHomehubOnline) {
  455. _imgvHubAlert.hidden = NO;
  456. _lblTitle.text = @"홈허브 오프라인";
  457. [_lblTitle setColor:kUITextColor01 text:_lblTitle.text];
  458. } else {
  459. _imgvHubAlert.hidden = YES;
  460. }
  461. [_mainView bringSubviewToFront:_collectionView];
  462. _addHubContainerView.hidden = YES;
  463. _collectionView.hidden = NO;
  464. _btnOption.hidden = NO;
  465. }
  466. if ([_lblTitle.text rangeOfString:@"장치 전체"].location != NSNotFound) {
  467. [_lblTitle setColor:kUITextColor03 text:[NSString stringWithFormat:@"%zd", _deviceList.count]];
  468. }
  469. }
  470. - (void)leaveHomegroup {
  471. HomeMemberViewController *vc = [[HomeMemberViewController alloc] init];
  472. [vc leaveHomegroup];
  473. }
  474. - (void)matchDeviceListWithOnCommandsDevices {
  475. for (DeviceModel *rdevice in _commandArray) {
  476. DeviceModel *matchedDevice = [_deviceList objectByUsingPredicateFormat:@"deviceId == %@", rdevice.deviceId]; //일치하는 디바이스가 있을 경우, 추가하지 않음.
  477. // DeviceModel *matchedDevice = [_deviceList objectByUsingPredicateFormat:@"deviceId == %@ && nodeId == %@", rdevice.deviceId, rdevice.nodeId]; //일치하는 디바이스가 있을 경우, 추가하지 않음.
  478. if (matchedDevice) {
  479. matchedDevice.isRequesting = rdevice.isRequesting;
  480. matchedDevice.requestTime = rdevice.requestTime;
  481. }
  482. }
  483. // [_collectionView reloadData];
  484. }
  485. - (void)releaseDevicesTimer {
  486. if (_devicesBackgroundTimer) {
  487. [_devicesBackgroundTimer invalidate];
  488. _devicesBackgroundTimer = nil;
  489. }
  490. }
  491. #pragma mark - UICollectionView Delegate
  492. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  493. NSInteger auth = [JDFacade facade].loginUser.level == 90 && !_isDeleteMode && [_nodeListData isCanAddNode]; //마스터 권한일 경우,
  494. NSInteger count = _deviceList.count % _deviceFlag == 0 ? _deviceList.count + auth : _deviceList.count + auth; //홀수일 경우, 멤버 초대 버튼을 추가해줌.
  495. // NSInteger count = _deviceList.count;
  496. return count;
  497. }
  498. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  499. UICollectionViewCell *rcell = nil;
  500. UIPanGestureRecognizer *drag = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureHandler:)];
  501. if (indexPath.row < _deviceList.count) {
  502. ThingsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ThingsCellIdentifier" forIndexPath:indexPath];
  503. // [cell.btnDelete setHidden:YES];
  504. // [cell.btnChangeOrder setHidden:YES];
  505. DeviceModel *device =_deviceList[indexPath.row];
  506. cell.indexPath = indexPath;
  507. if([device.prdName isEqualToString:device.prdUserName] || [device.prdUserName isEqualToString:@""]) {
  508. cell.lblDeviceName.text = device.prdName;
  509. } else {
  510. cell.lblDeviceName.text = device.prdUserName;
  511. }
  512. // [cell.btnDevice sd_setImageWithURL:[NSURL URLWithString:device.imageFileName] forState:UIControlStateNormal
  513. // placeholderImage:nil options:SDWebImageRefreshCached completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
  514. // [cell layoutIfNeeded];
  515. // }];
  516. [cell.imgDevice setImage:[UIImage imageNamed:device.deviceclassTypeId]];
  517. [cell.btnDevice addTarget:self action:@selector(btnDeviceTouched:) forControlEvents:UIControlEventTouchUpInside];
  518. cell.btnDevice.value = indexPath;
  519. //커맨드 클래스 뷰를 초기화함.
  520. [[cell.controlContainer subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  521. UIView *subview = (UIView *)obj;
  522. [subview removeFromSuperview];
  523. }];
  524. NSLog(@"Is Requesting : %@", BOOLToString(device.isRequesting));
  525. // TODO : 어떤 부분인지 내용 확인 필요
  526. cell.pcontainerView.hidden = !device.isRequesting;
  527. if (!cell.pcontainerView.hidden) {
  528. [cell startProgressAni];
  529. } else {
  530. [cell stopProgressAni];
  531. }
  532. //허브 On-Off line check
  533. // cell.lblDeviceStatus.hidden = !([[JDFacade facade].loginUser.homehubOnlineState isEqualToString:@"OFF"] || [device.onlineState isEqualToString:@"OFF"]);
  534. // cell.controlContainer.hidden = !cell.lblDeviceStatus.hidden;
  535. cell.btnDelete.hidden = !_isDeleteMode;
  536. cell.btnChangeOrder.hidden = !_isReOrderMode;
  537. if(_isDeleteMode || _isReOrderMode)
  538. {
  539. cell.btnDevice.enabled = NO;
  540. cell.btnDeviceControl.hidden = YES;
  541. }
  542. else
  543. {
  544. cell.btnDevice.enabled = YES;
  545. cell.btnDeviceControl.hidden = NO;
  546. }
  547. [cell.btnChangeOrder addGestureRecognizer:drag];
  548. cell.btnChangeOrder.value = indexPath;
  549. // 이부분 확인해 볼것
  550. if (!cell.controlContainer.hidden) {//커맨드 클래스 타입별 컨트롤 호출
  551. [cell.btnDevice setBackgroundImage:[device backgroundImageForMandatary:device.contentValue] forState:UIControlStateNormal];
  552. CommandClassControlView *controlView = [CommandClassControlView viewForCommandClass:device.cmdclsType];
  553. controlView.device = device;
  554. if(_isDeleteMode || _isReOrderMode)
  555. {
  556. controlView.isReOrderMode = YES;
  557. }
  558. else {
  559. controlView.isReOrderMode = NO;
  560. }
  561. cell.controlContainer.hidden = !controlView;
  562. if (!cell.controlContainer.hidden) {
  563. UIView *superview = cell.controlContainer;
  564. [superview addSubview:controlView];
  565. // controlView.width = IS_IPHONE_6P ? 98.0f : 120;
  566. // NSLog(@"Controll View : %f", ViewWidth(superview));
  567. // controlView.width = ViewWidth(superview);
  568. [controlView mas_makeConstraints:^(MASConstraintMaker *make) {
  569. // make.size.mas_equalTo(superview.frame.size);
  570. // make.center.equalTo(superview);
  571. make.top.equalTo(superview.mas_top).with.offset(0); //with is an optional semantic filler
  572. make.left.equalTo(superview.mas_left).with.offset(0);
  573. make.bottom.equalTo(superview.mas_bottom).with.offset(0);
  574. make.right.equalTo(superview.mas_right).with.offset(0);
  575. }];
  576. }
  577. } else {
  578. cell.lblDeviceStatus.text = @"OFFLINE";
  579. cell.lblDeviceStatus.textColor = kUITextColor01;
  580. [cell.btnDevice setBackgroundImage:[UIImage imageNamed:@"img_thing_icon_bg_default"] forState:UIControlStateNormal];
  581. }
  582. rcell = cell;
  583. } else {
  584. ThingsAddCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ThingsAddCellIdentifier" forIndexPath:indexPath];
  585. //
  586. if (![cell.btnAdd actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) {
  587. [cell.btnAdd addTarget:self action:@selector(addNewDevice) forControlEvents:UIControlEventTouchUpInside];
  588. }
  589. rcell = cell;
  590. }
  591. return rcell;
  592. }
  593. //- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section {
  594. // return CGSizeZero;
  595. //
  596. // //FIXME : 권한 추가
  597. //// if (_memberList.count % 2 == 1 || [JDFacade facade].loginUser.level < 90 || _isDeleteMode) {//마스터 권한이 아니거나, 짝수가 아닐 경우
  598. // if (_deviceList.count % 2 == 1 || _isDeleteMode) {//마스터 권한이 아니거나, 짝수가 아닐 경우
  599. // }
  600. //
  601. // return CGSizeMake(IPHONE_WIDTH, 160.0f);
  602. //}
  603. -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
  604. {
  605. return CGSizeMake(ViewWidth(_collectionView), (((ViewWidth(_collectionView)-kiCellInset)+kiCellRatio) / kiCellItem) / kiCellDivision+(kiCellItem*kiCellItem));
  606. }
  607. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
  608. return CGSizeMake((ViewWidth(_collectionView)-kiCellInset) / kiCellItem, ((ViewWidth(_collectionView)-kiCellInset)+kiCellRatio) / kiCellItem);
  609. }
  610. // Cell 사이 최소 간격
  611. - (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
  612. return kiCellInset;
  613. }
  614. // Line 별 최소 간격
  615. -(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
  616. {
  617. return kiCellInset;
  618. }
  619. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  620. [collectionView deselectItemAtIndexPath:indexPath animated:YES];
  621. if (_isReOrderMode) {
  622. [collectionView beginInteractiveMovementForItemAtIndexPath:indexPath];
  623. return;
  624. }
  625. if (indexPath.row < _deviceList.count) {//디바이스인 경우,
  626. DeviceModel *device = _deviceList[indexPath.row];
  627. ThingsDetailViewController *vc = (ThingsDetailViewController *)[CommonUtil instantiateViewControllerWithIdentifier:@"ThingsDetailViewController" storyboardName:@"Things"];
  628. vc.refDevice = device;
  629. [self presentViewController:vc animated:YES completion:nil];
  630. }
  631. }
  632. -(BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
  633. {
  634. return _isReOrderMode;
  635. }
  636. -(BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)toIndexPath
  637. {
  638. return _isReOrderMode;
  639. }
  640. - (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath
  641. {
  642. return _isReOrderMode;
  643. }
  644. - (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition
  645. {
  646. }
  647. - (void)endInteractiveMovement
  648. {
  649. }
  650. - (void)cancelInteractiveMovement
  651. {
  652. }
  653. -(void)panGestureHandler:(UIGestureRecognizer *)sender
  654. {
  655. CGPoint locationPoint = [self getCellCenter:[sender locationInView:_collectionView]];
  656. switch (sender.state) {
  657. case UIGestureRecognizerStateBegan:
  658. {
  659. NSIndexPath *indexPathOfPoint = [self.collectionView indexPathForItemAtPoint:locationPoint];
  660. _moveCell = (ThingsCollectionViewCell *)[self.collectionView cellForItemAtIndexPath:indexPathOfPoint];
  661. UIGraphicsBeginImageContext(_moveCell.bounds.size);
  662. [_moveCell.layer renderInContext:UIGraphicsGetCurrentContext()];
  663. UIImage *cellImage = UIGraphicsGetImageFromCurrentImageContext();
  664. UIGraphicsEndImageContext();
  665. _cellFakeView = [[UIImageView alloc] initWithImage:cellImage];
  666. [_cellFakeView setCenter:locationPoint];
  667. [_collectionView addSubview:_cellFakeView];
  668. _dragIndexPath = indexPathOfPoint;
  669. _moveCell.hidden = YES;
  670. }
  671. case UIGestureRecognizerStateChanged:
  672. {
  673. [_cellFakeView setCenter:locationPoint];
  674. }
  675. break;
  676. case UIGestureRecognizerStateCancelled:
  677. case UIGestureRecognizerStateEnded:
  678. // [self.collectionView performBatchUpdates:^{
  679. // //update cell indexPath
  680. // _reorderingCellIndexPath = toIndexPath;
  681. // [self.collectionView moveItemAtIndexPath:atIndexPath toIndexPath:toIndexPath];
  682. // //did move
  683. // if ([self.datasource respondsToSelector:@selector(collectionView:itemAtIndexPath:didMoveToIndexPath:)]) {
  684. // [self.datasource collectionView:self.collectionView itemAtIndexPath:atIndexPath didMoveToIndexPath:toIndexPath];
  685. // }
  686. // } completion:nil];
  687. //
  688. // _dragIndexPath= nil;
  689. // [_cellFakeView removeFromSuperview];
  690. //
  691. [self moveItemIfNeeded];
  692. break;
  693. default:
  694. break;
  695. }
  696. }
  697. - (void)moveItemIfNeeded
  698. {
  699. // TODO : 버그 수정
  700. NSIndexPath *atIndexPath = _dragIndexPath;
  701. NSIndexPath *toIndexPath = [_collectionView indexPathForItemAtPoint:_cellFakeView.center];
  702. if (toIndexPath != nil && ![atIndexPath isEqual:toIndexPath]) {
  703. [_collectionView performBatchUpdates:^{
  704. [_collectionView moveItemAtIndexPath:atIndexPath toIndexPath:toIndexPath];
  705. [self updateDataSource:atIndexPath toIndexPath:toIndexPath];
  706. } completion:nil];
  707. }
  708. _moveCell.hidden = NO;
  709. [_cellFakeView removeFromSuperview];
  710. _dragIndexPath = nil;
  711. // [_cellInfo]
  712. }
  713. -(CGPoint)getCellCenter:(CGPoint)point
  714. {
  715. CGPoint btnCenter = _moveCell.btnChangeOrder.center;
  716. CGPoint cellCenter = _moveCell.contentView.center;
  717. CGPoint result = CGPointMake(point.x-(btnCenter.x-cellCenter.x), point.y-(btnCenter.y-cellCenter.y));
  718. return result;
  719. }
  720. -(void)updateDataSource:(NSIndexPath *)atIndexPath toIndexPath:(NSIndexPath *)toIndexPath
  721. {
  722. NSLog(@"Update Data");
  723. NSLog(@"From Index : %li", (long)atIndexPath.item);
  724. NSLog(@"To Index : %li", (long)toIndexPath.item);
  725. DeviceModel *device =_deviceReOrderList[atIndexPath.item];
  726. NSLog(@"DeviceModel : %@", device);
  727. [_deviceReOrderList removeObjectAtIndex:atIndexPath.item];
  728. [_deviceReOrderList insertObject:device atIndex:toIndexPath.item];
  729. }
  730. #pragma mark - UI Events
  731. /**
  732. 첫번째 이미지
  733. - img_bg_morepopup_icon_thingschange
  734. - img_bg_morepopup_icon_thingschange_press
  735. 두번째 이미지 :
  736. - img_bg_morepopup_icon_add
  737. - img_bg_morepopup_icon_add_press
  738. 세번째 이미지 :
  739. - img_bg_morepopup_icon_delete
  740. - img_bg_morepopup_icon_delete_press
  741. 네번째 이미지 :
  742. - img_bg_morepopup_icon_refresh
  743. - img_bg_morepopup_icon_refresh_press
  744. **/
  745. - (IBAction)btnOptionTouched:(id)sender {
  746. [self toggleOptionsWithArray:sender btnArray:_moreBtnArray];
  747. }
  748. - (IBAction)btnReFreshTouched:(id)sender {
  749. [[JDFacade facade] confirmTitle:@"알림" message:@"장치 목록의 순서를\n장치가 등록된 순으로 초괴화합니다." btnOKLabel:@"확인" btnCancelLabel:@"취소" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  750. if (buttonIndex == 0) {
  751. [self requestDeviceOrderReset];
  752. [self toggleReOrderMode:NO];
  753. }
  754. }];
  755. }
  756. - (IBAction)btnConfirmTouched:(id)sender {
  757. [[JDFacade facade] confirmTitle:@"알림" message:@"현재 편집된 장치 목록 순서를\n저장하시겠습니까?" btnOKLabel:@"확인" btnCancelLabel:@"취소" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  758. if (buttonIndex == 0) {
  759. // TODO : 데이터 업데이트 하기
  760. _deviceList = [[NSMutableArray alloc] initWithArray:_deviceReOrderList];
  761. [self requestDeviceOrderChange];
  762. [self toggleReOrderMode:NO];
  763. }
  764. }];
  765. // _deviceList = _deviceReOrderList;
  766. // [self toggleReOrderMode:NO];
  767. }
  768. - (IBAction)btnCloseTouched:(id)sender {
  769. if (_isReOrderMode) {
  770. [[JDFacade facade] confirmTitle:@"알림" message:@"장치 목록 순서를 저장하지 않고\n이전화면으로 이동합니다." btnOKLabel:@"확인" btnCancelLabel:@"취소" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  771. if (buttonIndex == 0) {
  772. [self toggleReOrderMode:NO];
  773. }
  774. }];
  775. }
  776. else {
  777. [self toggleEditMode:NO];
  778. }
  779. }
  780. -(void)toggleReOrderMode:(Boolean)isReOrder
  781. {
  782. _isReOrderMode = isReOrder;
  783. _viewEditMode.hidden = !isReOrder;
  784. _btnOption.hidden = isReOrder;
  785. [_collectionView reloadData];
  786. _viewTitle.hidden = isReOrder;
  787. _lblEditMode.hidden = !isReOrder;
  788. _lblEditMode.text = @"장치 목록 순서 편집";
  789. }
  790. -(void)toggleEditMode:(Boolean)isEdit
  791. {
  792. _isDeleteMode = isEdit;
  793. _viewEditMode.hidden = !isEdit;
  794. _btnOption.hidden = isEdit;
  795. [_collectionView reloadData];
  796. _viewTitle.hidden = isEdit;
  797. _lblEditMode.hidden = !isEdit;
  798. _lblEditMode.text = @"장치 삭제";
  799. _btnEditSave.hidden = !isEdit;
  800. _btnEditRefresh.hidden = !isEdit;
  801. }
  802. #pragma mark - SocketService
  803. - (void) socketDidReceiveMessage:(id)message info:(NSDictionary *)info
  804. {
  805. SocketModel *result = (SocketModel *)message;
  806. NSLog(@"Result Info : %@", result);
  807. SWITCH(result.messageType)
  808. {
  809. CASE (@"node.register")
  810. {
  811. }
  812. CASE (@"node.delete")
  813. {
  814. }
  815. CASE(@"nodes.reload")
  816. {
  817. }
  818. DEFAULT
  819. {
  820. break;
  821. }
  822. }
  823. }
  824. - (void) socketDidFailWithError:(NSError *)error {
  825. [[JDFacade facade] loadIndicator:NO allowUserInteraction:YES];
  826. }
  827. -(void) receiveSocketData:(NSNotification *)notification {
  828. SocketModel *result = [[SocketModel alloc] initWithDictionary:notification.object error:nil];
  829. // CommandModel *response = [[CommandModel alloc] initWithDictionary:notification.object error:nil];
  830. NSLog(@"Result : %@", result);
  831. if ([result.messageType isEquestToIgnoreCase:MSG_TYPE_NODE_CONTENT]) {
  832. ContentModel *response = [[ContentModel alloc] initWithDictionary:notification.object error:nil];
  833. for (DeviceModel *info in _deviceList) {
  834. if ([info.deviceId isEqualToString:response.deviceId] && [info.nodeId isEqualToString:response.nodeId]) {
  835. info.collectTime = response.collectTime;
  836. id contentValue = [NSJSONSerialization JSONObjectWithData:[response.contentValue dataUsingEncoding:NSUTF8StringEncoding]
  837. options:NSJSONReadingAllowFragments
  838. error:nil];
  839. info.contentValue = contentValue[info.cmdclsId];
  840. if (info.isRequesting) {
  841. info.isRequesting = NO;
  842. }
  843. [_collectionView reloadData];
  844. break;
  845. // NSLog(@"Info : %@", contentValue[info.cmdclsId]);
  846. }
  847. }
  848. }
  849. else if ([result.messageType isEquestToIgnoreCase:MSG_TYPE_NODE_COMMAND_RES]) {
  850. }
  851. }
  852. #pragma mark - MoreButtonDelegate
  853. -(void)moreBtnAction:(id)sender
  854. {
  855. NSInteger tag = [(UIButton *)sender tag];
  856. NSLog(@"MoreBtn Action : %li", (long)tag);
  857. switch (tag) {
  858. case ReOrder:
  859. {
  860. [self toggleReOrderMode:YES];
  861. }
  862. break;
  863. case Add:
  864. {
  865. [self addNewDevice];
  866. }
  867. break;
  868. case Del:
  869. {
  870. [self toggleEditMode:YES];
  871. }
  872. break;
  873. case Refresh:
  874. {
  875. [self refreshDeviceList];
  876. }
  877. break;
  878. default:
  879. break;
  880. }
  881. }
  882. #pragma mark - MemoryWarning
  883. - (void)viewWillDisappear:(BOOL)animated {
  884. if (_deviceCommandsBackgroundTimer) {
  885. [_deviceCommandsBackgroundTimer invalidate];
  886. _deviceCommandsBackgroundTimer = nil;
  887. }
  888. [self releaseDevicesTimer];
  889. }
  890. - (void)didReceiveMemoryWarning
  891. {
  892. [super didReceiveMemoryWarning];
  893. // Dispose of any resources that can be recreated.
  894. }
  895. -(void)btnDeviceTouched:(id)sender
  896. {
  897. }
  898. @end