BLEServiceHandler.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. //
  2. // BLEServiceHandler.m
  3. // OneCable
  4. //
  5. // Created by KaRam Kim on 2017. 5. 18..
  6. // Copyright © 2017년 ntels. All rights reserved.
  7. //
  8. #import "BLEServiceHandler.h"
  9. #import <CoreBluetooth/Corebluetooth.h>
  10. #import "Definitions.h"
  11. #import "JDJSONModel.h"
  12. #import "JDObject.h"
  13. @interface BLEServiceHandler()<CBCentralManagerDelegate, CBPeripheralDelegate>
  14. {
  15. CBCentralManager *_manager;
  16. NSMutableArray *_devices;
  17. BOOL _scanning;
  18. NSTimer *_scanTimer;
  19. BTLEDeivceModel *_connectedDevice;
  20. //service characteristic
  21. CBService *lastService;
  22. }
  23. @end
  24. @implementation BLEServiceHandler
  25. + (id)sharedManager
  26. {
  27. static BLEServiceHandler *sharedBLEServiceHandler = nil;
  28. static dispatch_once_t onceToken;
  29. dispatch_once(&onceToken, ^{
  30. sharedBLEServiceHandler = [[self alloc] init];
  31. });
  32. return sharedBLEServiceHandler;
  33. }
  34. - (id) init
  35. {
  36. self = [super init];
  37. if (self) {
  38. _manager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
  39. // *peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:nil queue:nil options:@{CBPeripheralManagerOptionShowPowerAlertKey:@NO}]
  40. _devices = [NSMutableArray array];
  41. // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startScan) name:kBLEConnect object:nil];
  42. // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startScan) name:kBLEDisConnect object:nil];
  43. }
  44. return self;
  45. }
  46. - (void)connect:(BTLEDeivceModel *)info
  47. {
  48. if (info.peripheralRef.state != CBPeripheralStateDisconnected) {
  49. [_manager cancelPeripheralConnection:info.peripheralRef];
  50. } else {
  51. [_manager connectPeripheral:info.peripheralRef options:nil];
  52. }
  53. }
  54. - (void)disConnect
  55. {
  56. _conDevice = nil;
  57. }
  58. -(void) openBluetoothSettings{
  59. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"App-Prefs:root=Bluetooth"]];
  60. }
  61. - (void) startScan
  62. {
  63. if (_manager.state == CBCentralManagerStatePoweredOff) {
  64. [[JDFacade facade] confirmTitle:@"Notice"
  65. message:@"블루투스가 비활성화 되어 있습니다. 활성화 해주세요."
  66. btnOKLabel:@"OK"
  67. btnCancelLabel:@"Cancel"
  68. completion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
  69. if (buttonIndex == 1) {
  70. [self openBluetoothSettings];
  71. }
  72. }];
  73. return;
  74. }
  75. _devices = [NSMutableArray array];
  76. if (_scanTimer) [_scanTimer invalidate];
  77. _scanning = YES;
  78. [_manager stopScan];
  79. [_manager scanForPeripheralsWithServices:nil options:nil];
  80. _scanTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(stopScan:) userInfo:@"Y" repeats:NO];
  81. }
  82. - (void)stopScan:(NSString*)timeout
  83. {
  84. NSLog(@"STOP SCAN");
  85. [_manager stopScan] ;
  86. _scanning = NO ;
  87. if( _delegate && [_delegate respondsToSelector:@selector(BLEEndScan:)] ) {
  88. [_delegate BLEEndScan:_devices] ;
  89. }
  90. }
  91. -(NSMutableArray *)getDeviceList
  92. {
  93. return _devices;
  94. }
  95. -(CBCharacteristic *)getChrInfo:(NSString *)name
  96. {
  97. CBCharacteristic *result = nil;
  98. for (CBService *serviceInfo in [_conDevice getServiceList]) {
  99. for (CBCharacteristic *chrInfo in serviceInfo.characteristics) {
  100. if ([[self getStrUUID:chrInfo] isEquestToIgnoreCase:[self getServiceUUID:name]]) {
  101. //NSLog(@"\nname : %@, chrInfo : %@", name, chrInfo.UUID);
  102. result = chrInfo;
  103. break;
  104. }
  105. }
  106. }
  107. return result;
  108. }
  109. -(NSString *)getChrName:(CBCharacteristic *)info
  110. {
  111. NSString *result = nil;
  112. for (NSString *key in [[self getGatewayCharDict] allKeysForObject:[[self getStrUUID:info] lowercaseString]]) {
  113. result = key;
  114. }
  115. return result;
  116. }
  117. -(NSString *)getStrUUID:(CBCharacteristic *)info
  118. {
  119. NSString *uuid =[NSString stringWithFormat:@"%@", info.UUID];
  120. return uuid;
  121. }
  122. - (BTLEDeivceModel *)addPeripheral:(CBPeripheral*)peripheral {
  123. BTLEDeivceModel *device = [[BTLEDeivceModel alloc] init];
  124. device.peripheralRef = peripheral;
  125. device.manager = _manager;
  126. peripheral.delegate = self;
  127. if (![_devices containsObject:device]) {
  128. [_devices addObject:device];
  129. }
  130. // if( _delegate && [_delegate respondsToSelector:@selector(BLEUpldateDevice:)] ) {
  131. // [_delegate BLEUpldateDevice:device] ;
  132. // }
  133. return device;
  134. }
  135. - (NSString*)hexStringValue:(CBCharacteristic *)input {
  136. if (!input.value) return @"-";
  137. // NSLog(@"hexString : %@", self.value);
  138. NSString *raw = [NSString stringWithFormat:@"0x%@", input.value];
  139. raw = [raw stringByReplacingOccurrencesOfString:@"<" withString:@""];
  140. raw = [raw stringByReplacingOccurrencesOfString:@">" withString:@""];
  141. return raw;
  142. }
  143. - (NSString*)asciiStringValue:(CBCharacteristic *)input {
  144. if (!input.value) return @"-";
  145. NSString *ascii = [[NSString alloc] initWithData:input.value encoding:NSASCIIStringEncoding];
  146. return ascii;
  147. }
  148. -(void)sendData:(CBCharacteristic *)chr str:(NSString *)str
  149. {
  150. NSData *data = [NSData data];
  151. if ([str isDigit]) {
  152. int dataToWrite = [str intValue];
  153. data = [NSData dataWithBytes:&dataToWrite length:1];
  154. } else {
  155. data = [str dataUsingEncoding:NSASCIIStringEncoding];
  156. }
  157. if (chr.properties & CBCharacteristicPropertyWriteWithoutResponse)
  158. [chr.service.peripheral writeValue:data forCharacteristic:chr type:CBCharacteristicWriteWithoutResponse];
  159. else if (chr.properties & CBCharacteristicPropertyWrite)
  160. [chr.service.peripheral writeValue:data forCharacteristic:chr type:CBCharacteristicWriteWithResponse];
  161. }
  162. #pragma mark - WiFi Settings
  163. //WiFi Setting관련 메뉴
  164. -(void)scanWiFiList
  165. {
  166. NSLog(@"scanWiFiList : %@", [self getChrInfo:kBLEChrStWiFiScan]) ;
  167. [self sendData:[self getChrInfo:kBLEChrStWiFiScan] str:@"1"];
  168. // todo : Timer 돌면서 List 1~3까지 채워지는지 체크할것
  169. }
  170. -(NSString *)getWLanList:(BLEWlanListType)type
  171. {
  172. // TODO : WLanList 가져오기
  173. NSString *result = @"";
  174. switch (type) {
  175. case BLEWlanListType1:
  176. result = [self asciiStringValue:[self getChrInfo:kBLEChrRdWiFiList1]];
  177. break;
  178. case BLEWlanListType2:
  179. result = [self asciiStringValue:[self getChrInfo:kBLEChrRdWiFiList2]];
  180. break;
  181. case BLEWlanListType3:
  182. result = [self asciiStringValue:[self getChrInfo:kBLEChrRdWiFiList3]];
  183. break;
  184. default:
  185. break;
  186. }
  187. return result;
  188. }
  189. -(void)setWiFiSSID:(NSString *)ssid
  190. {
  191. [self sendData:[self getChrInfo:kBLEChrStSSIDArg] str:ssid];
  192. }
  193. -(void)readAndNotifyCharacteristicUUID:(NSString *)uuid
  194. isNotify:(BOOL)isNotify
  195. {
  196. for (CBService *service in _conDevice.peripheralRef.services) {
  197. for (CBCharacteristic *characteristic in service.characteristics) {
  198. if ([characteristic.UUID.UUIDString isEquestToIgnoreCase:[self getGatewayDicUUIDForKey:uuid]]) {
  199. if (isNotify) {
  200. [_conDevice.peripheralRef setNotifyValue:YES forCharacteristic:characteristic];
  201. }
  202. else {
  203. [_conDevice.peripheralRef readValueForCharacteristic:characteristic];
  204. }
  205. break;
  206. }
  207. }
  208. }
  209. }
  210. -(void)setWiFiPwd:(NSString *)pwd
  211. {
  212. [self sendData:[self getChrInfo:kBLEChrStPWDArg] str:pwd];
  213. }
  214. -(void)enableDHCP
  215. {
  216. [self sendData:[self getChrInfo:kBLEChrStDHCPArg] str:@"1"];
  217. }
  218. -(void)applyWiFiSettingInfo
  219. {
  220. [self sendData:[self getChrInfo:kBLEChrStSetApply] str:@"1"];
  221. // todo : Connection정보가 notify로 들어오면, delegate를 통해서 알리기
  222. }
  223. -(NSString *)getServiceName:(NSString *)uuid
  224. {
  225. NSString *result = nil;
  226. for (NSString *key in [[self getGatewayCharDict] allKeysForObject:uuid.lowercaseString]) {
  227. result = key;
  228. }
  229. return result;
  230. }
  231. -(NSString *)getServiceUUID:(NSString *)strKey
  232. {
  233. NSString *result = nil;
  234. for (NSString *key in [[self getGatewayCharDict] allKeys]) {
  235. if ([key isEquestToIgnoreCase:strKey]) {
  236. result = [[self getGatewayCharDict] objectForKey:key];
  237. break;
  238. }
  239. }
  240. return result;
  241. }
  242. - (NSString*)getGatewayDicUUIDForKey:(NSString*)key{
  243. return [[self getGatewayCharDict] objectForKey:key];
  244. }
  245. -(NSDictionary *)getGatewayCharDict
  246. {
  247. NSDictionary *db = @{@"WFNPS_UUID":@"6f819d94-dddf-11e6-bf26-cec0c932ce01",
  248. @"SCAN_CHR_UUID":@"b364676d-dd76-11e6-bf26-cec0c932ce01",
  249. @"WLAN_LIST1_CHR_UUID":@"f333f87c-0787-11e7-93ae-92361f002671",
  250. @"WLAN_LIST2_CHR_UUID":@"f333fad4-0787-11e7-93ae-92361f002671",
  251. @"WLAN_LIST3_CHR_UUID":@"f333fbec-0787-11e7-93ae-92361f002671",
  252. @"SSID_ARG_CHR_UUID":@"508e6c28-0788-11e7-93ae-92361f002671",
  253. @"PASSWORD_ARG_CHR_UUID":@"b3646c08-dd76-11e6-bf26-cec0c932ce01",
  254. @"CONNECTION_CHR_UUID":@"b3646fbe-dd76-11e6-bf26-cec0c932ce01",
  255. @"SSID_CHR_UUID":@"b3647108-dd76-11e6-bf26-cec0c932ce01",
  256. @"BSSID_CHR_UUID":@"b3647234-dd76-11e6-bf26-cec0c932ce01",
  257. @"WF_IP_SET_ARG_CHR_UUID":@"8e0b49e6-088b-11e7-93ae-92361f002671",
  258. @"WF_IP_ADDR_ARG_CHR_UUID":@"8e0b4c2a-088b-11e7-93ae-92361f002671",
  259. @"WF_NET_PRE_LEN_ARG_CHR_UUID":@"8e0b4e32-088b-11e7-93ae-92361f002671",
  260. @"WF_GATEWAY_ARG_CHR_UUID":@"8e0b4ffe-088b-11e7-93ae-92361f002671",
  261. @"WF_DNS_ARG_CHR_UUID":@"8e0b50d0-088b-11e7-93ae-92361f002671",
  262. @"APPLY_CHR_UUID":@"8e0b51a2-088b-11e7-93ae-92361f002671",
  263. @"WF_IP_SET_CHR_UUID":@"8e0b5314-088b-11e7-93ae-92361f002671",
  264. @"WF_IP_ADDR_CHR_UUID":@"8e0b54a4-088b-11e7-93ae-92361f002671",
  265. @"WF_NET_PRE_LEN_CHR_UUID":@"8e0b5576-088b-11e7-93ae-92361f002671",
  266. @"WF_GATEWAY_CHR_UUID":@"8e0b568e-088b-11e7-93ae-92361f002671",
  267. @"WF_DNS_CHR_UUID":@"8e0b5878-088b-11e7-93ae-92361f002671",
  268. @"IPNPS_UUID":@"09d38ae8-dbb9-11e6-bf26-cec0c932ce01",
  269. @"IP_SET_ARG_CHR_UUID":@"09d38d68-dbb9-11e6-bf26-cec0c932ce01",
  270. @"IP_ADDR_ARG_CHR_UUID":@"09d38e62-dbb9-11e6-bf26-cec0c932ce01",
  271. @"NET_PRE_LEN_ARG_CHR_UUID":@"09d38f48-dbb9-11e6-bf26-cec0c932ce01",
  272. @"GATEWAY_ARG_CHR_UUID":@"09d39024-dbb9-11e6-bf26-cec0c932ce01",
  273. @"DNS_ARG_CHR_UUID":@"09d3960a-dbb9-11e6-bf26-cec0c932ce01",
  274. @"APPLY_IP_CHR_UUID":@"73207ac8-dd72-11e6-bf26-cec0c932ce01",
  275. @"IP_SET_CHR_UUID":@"73208018-dd72-11e6-bf26-cec0c932ce01",
  276. @"IP_ADDR_CHR_UUID":@"73208126-dd72-11e6-bf26-cec0c932ce01",
  277. @"NET_PRE_LEN_CHR_UUID":@"73208202-dd72-11e6-bf26-cec0c932ce01",
  278. @"GATEWAY_CHR_UUID":@"732082de-dd72-11e6-bf26-cec0c932ce01",
  279. @"DNS_CHR_UUID":@"732083a6-dd72-11e6-bf26-cec0c932ce01"};
  280. return db;
  281. }
  282. #pragma mark - CBCentralManagerDelegate
  283. - (void)centralManagerDidUpdateState:(CBCentralManager *)central {
  284. NSLog(@"Central manager changed state: %ld", central.state);
  285. if( _delegate && [_delegate respondsToSelector:@selector(BLEStateChange:)] ) {
  286. [_delegate BLEStateChange:central.state == CBCentralManagerStatePoweredOn] ;
  287. }
  288. if (central.state == CBCentralManagerStatePoweredOn) {
  289. [self startScan];
  290. }
  291. }
  292. - (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals {
  293. NSLog(@"%ld periphirals retrieved", [peripherals count]);
  294. }
  295. - (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals {
  296. for (CBPeripheral *peripheral in peripherals)
  297. {
  298. NSLog(@"1Periphiral discovered: %@, %@", peripheral.name, peripheral.identifier);
  299. BOOL isExist = NO;
  300. for (BTLEDeivceModel *device in _devices)
  301. {
  302. if ([[device.peripheralRef.identifier UUIDString] isEqualToString:[peripheral.identifier UUIDString]])
  303. {
  304. isExist = YES;
  305. }
  306. }
  307. if (!isExist)
  308. [self addPeripheral:peripheral];
  309. }
  310. }
  311. - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
  312. NSLog(@"2Periphiral discovered: %@, %@, signal strength: %d", peripheral.name, peripheral.identifier, RSSI.intValue);
  313. for (BTLEDeivceModel *device in _devices) {
  314. if ([[device.peripheralRef.identifier UUIDString] isEqualToString:[peripheral.identifier UUIDString]]) {
  315. return;
  316. }
  317. }
  318. if (peripheral.name != nil && peripheral.name != (id)[NSNull null]) {
  319. if ([peripheral.name rangeOfString:@"DKC"].location != NSNotFound || [peripheral.name rangeOfString:@"BlueZ"].location != NSNotFound) {
  320. BTLEDeivceModel *device = [self addPeripheral:peripheral];
  321. if (![_devices containsObject:device]) {
  322. [_devices addObject:device];
  323. }
  324. }
  325. }
  326. }
  327. - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
  328. NSLog(@"Periphiral connected name : %@", peripheral.name);
  329. [peripheral discoverServices:nil] ;
  330. }
  331. - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
  332. NSLog(@"Periphiral disconnected: %@", peripheral.name);
  333. if( _delegate && [_delegate respondsToSelector:@selector(BLEDisConnected:)] ) {
  334. [_delegate BLEDisConnected:_conDevice] ;
  335. }
  336. _conDevice = nil;
  337. }
  338. - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
  339. NSLog(@"Periphiral failed to connect: %@", peripheral.name);
  340. }
  341. #pragma mark - CBPeripheralDelegate
  342. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
  343. NSLog(@"\nServices dicovered for peripheral %@:", peripheral.name);
  344. //NSLog(@"Services dicovered for peripheral : %@", peripheral.services);
  345. //NSLog(@"error dicovered for peripheral %@:", error);
  346. lastService = [peripheral.services lastObject];
  347. for (CBService *service in peripheral.services) {
  348. //NSLog(@"%@", service.UUID);
  349. [peripheral discoverCharacteristics:nil forService:service];
  350. }
  351. }
  352. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
  353. NSLog(@"\ncharacteristics dicovered for service : %@", service.UUID);
  354. //NSLog(@"characteristics dicovered for service : %@", peripheral.services);
  355. if ([lastService.UUID isEqual:service.UUID]) {
  356. _conDevice = [self addPeripheral:peripheral];
  357. lastService = nil;
  358. if( _delegate && [_delegate respondsToSelector:@selector(BLEConnected:)] ) {
  359. [_delegate BLEConnected:_conDevice] ;
  360. }
  361. }
  362. for (CBCharacteristic *characteristic in service.characteristics) {
  363. //NSLog(@"characteristic : %@", characteristic.UUID);
  364. [self readValueSetNotifyValueForCharacteristic:characteristic peripheral:peripheral];
  365. // [peripheral setNotifyValue:YES forCharacteristic:characteristic];
  366. // [peripheral readValueForCharacteristic:characteristic];
  367. }
  368. }
  369. - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  370. NSLog(@"Incoming: [%@] %@ %@", [self getChrName:characteristic],[self asciiStringValue:characteristic], [self hexStringValue:characteristic]);
  371. if ([[self getStrUUID:characteristic] isEquestToIgnoreCase:
  372. [self getServiceUUID:kBLEChrRdConInfo]]) {
  373. if( _delegate && [_delegate respondsToSelector:@selector(BLEWiFiConnectionInfoUpdate:)] ) {
  374. [_delegate BLEWiFiConnectionInfoUpdate:characteristic];
  375. }
  376. }
  377. //ssid 읽음
  378. else if ([[self getStrUUID:characteristic] isEquestToIgnoreCase:
  379. [self getServiceUUID:kBLEChrStSSIDArg]]) {
  380. if( _delegate && [_delegate respondsToSelector:@selector(BLEWiFiSSIDRead:)] ) {
  381. [_delegate BLEWiFiSSIDRead:[self asciiStringValue:characteristic]];
  382. }
  383. }
  384. //dhcp 읽음
  385. else if ([[self getStrUUID:characteristic] isEquestToIgnoreCase:
  386. [self getServiceUUID:kBLEChrStDHCPArg]]) {
  387. if( _delegate && [_delegate respondsToSelector:@selector(BLEWiFiDHCPRead:)] ) {
  388. [_delegate BLEWiFiDHCPRead:nil];
  389. }
  390. }
  391. }
  392. -(void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices
  393. {
  394. // device = peripheral;
  395. NSLog(@"peripheral : %@", peripheral);
  396. NSLog(@"didModifyServices : %@", invalidatedServices);
  397. }
  398. - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
  399. NSLog(@"didWriteValueForCharacteristic : %@", characteristic.value) ;
  400. }
  401. //characteristic 에 맞춰서 read or notify
  402. - (void)readValueSetNotifyValueForCharacteristic:(CBCharacteristic*)characteristic
  403. peripheral:(CBPeripheral *)peripheral {
  404. NSString *uuid = characteristic.UUID.UUIDString;
  405. BOOL rdWiFi = [uuid isEquestToIgnoreCase:[self getGatewayDicUUIDForKey:kBLEChrRdWiFiList1]] ||
  406. [uuid isEquestToIgnoreCase:[self getGatewayDicUUIDForKey:kBLEChrRdWiFiList2]] ||
  407. [uuid isEquestToIgnoreCase:[self getGatewayDicUUIDForKey:kBLEChrRdWiFiList3]];
  408. if (rdWiFi) {
  409. [peripheral readValueForCharacteristic:characteristic];
  410. }
  411. }
  412. @end