BLEServiceHandler.m 15 KB

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