LGUtils.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // The MIT License (MIT)
  2. //
  3. // Created by : l0gg3r
  4. // Copyright (c) 2014 l0gg3r. All rights reserved.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  7. // this software and associated documentation files (the "Software"), to deal in
  8. // the Software without restriction, including without limitation the rights to
  9. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10. // the Software, and to permit persons to whom the Software is furnished to do so,
  11. // subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in all
  14. // copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. #import "LGUtils.h"
  23. #if TARGET_OS_IPHONE
  24. #import <CoreBluetooth/CoreBluetooth.h>
  25. #elif TARGET_OS_MAC
  26. #import <IOBluetooth/IOBluetooth.h>
  27. #endif
  28. #import "LGBluetooth.h"
  29. /**
  30. * Error domain for Write errors
  31. */
  32. NSString * const kLGUtilsWriteErrorDomain = @"LGUtilsWriteErrorDomain";
  33. /**
  34. * Error domain for Read errors
  35. */
  36. NSString * const kLGUtilsReadErrorDomain = @"LGUtilsReadErrorDomain";
  37. /**
  38. * Error domain for Discover errors
  39. */
  40. NSString * const kLGUtilsDiscoverErrorDomain = @"LGUtilsDiscoverErrorDomain";
  41. /**
  42. * Global key for providing errors of LGBluetooth
  43. */
  44. NSString * const kLGErrorMessageKey = @"msg";
  45. /**
  46. * Error code for write operation
  47. * Service was not found on peripheral
  48. */
  49. const NSInteger kLGUtilsMissingServiceErrorCode = 410;
  50. /**
  51. * Error code for write operation
  52. * Characteristic was not found on peripheral
  53. */
  54. const NSInteger kLGUtilsMissingCharacteristicErrorCode = 411;
  55. /**
  56. * Error message for write operation
  57. * Service was not found on peripheral
  58. */
  59. NSString * const kLGUtilsMissingServiceErrorMessage = @"Provided service UUID doesn't exist in provided pheripheral";
  60. /**
  61. * Error message for write operation
  62. * Characteristic was not found on peripheral
  63. */
  64. NSString * const kLGUtilsMissingCharacteristicErrorMessage = @"Provided characteristic doesn't exist in provided service";;
  65. /**
  66. * Timeout of connection to peripheral
  67. */
  68. const NSInteger kLGUtilsPeripheralConnectionTimeoutInterval = 30;
  69. @implementation LGUtils
  70. /*----------------------------------------------------*/
  71. #pragma mark - Public Methods -
  72. /*----------------------------------------------------*/
  73. + (void)writeData:(NSData *)aData
  74. charactUUID:(NSString *)aCharacteristic
  75. serviceUUID:(NSString *)aService
  76. peripheral:(LGPeripheral *)aPeripheral
  77. completion:(LGCharacteristicWriteCallback)aCallback
  78. {
  79. if (aPeripheral.cbPeripheral.state == CBPeripheralStateConnected) {
  80. [self writeData:aData
  81. charactUUID:aCharacteristic
  82. serviceUUID:aService
  83. readyPeripheral:aPeripheral
  84. completion:aCallback];
  85. } else {
  86. [aPeripheral connectWithTimeout:kLGUtilsPeripheralConnectionTimeoutInterval completion:^(NSError *error) {
  87. [self writeData:aData
  88. charactUUID:aCharacteristic
  89. serviceUUID:aService
  90. readyPeripheral:aPeripheral
  91. completion:aCallback];
  92. }];
  93. }
  94. }
  95. + (void)readDataFromCharactUUID:(NSString *)aCharacteristic
  96. serviceUUID:(NSString *)aService
  97. peripheral:(LGPeripheral *)aPeripheral
  98. completion:(LGCharacteristicReadCallback)aCallback
  99. {
  100. if (aPeripheral.cbPeripheral.state == CBPeripheralStateConnected) {
  101. [self readDataFromCharactUUID:aCharacteristic
  102. serviceUUID:aService
  103. readyPeripheral:aPeripheral
  104. completion:aCallback];
  105. } else {
  106. [aPeripheral connectWithTimeout:kLGUtilsPeripheralConnectionTimeoutInterval completion:^(NSError *error) {
  107. [self readDataFromCharactUUID:aCharacteristic
  108. serviceUUID:aService
  109. readyPeripheral:aPeripheral
  110. completion:aCallback];
  111. }];
  112. }
  113. }
  114. + (void)discoverCharactUUID:(NSString *)aCharacteristic
  115. serviceUUID:(NSString *)aService
  116. peripheral:(LGPeripheral *)aPeripheral
  117. completion:(LGUtilsDiscoverCharacterisitcCallback)aCallback
  118. {
  119. if (aPeripheral.cbPeripheral.state == CBPeripheralStateConnected) {
  120. [self discoverCharactUUID:aCharacteristic
  121. serviceUUID:aService
  122. readyPeripheral:aPeripheral
  123. completion:aCallback];
  124. } else {
  125. [aPeripheral connectWithTimeout:kLGUtilsPeripheralConnectionTimeoutInterval completion:^(NSError *error) {
  126. [self discoverCharactUUID:aCharacteristic
  127. serviceUUID:aService
  128. readyPeripheral:aPeripheral
  129. completion:aCallback];
  130. }];
  131. }
  132. }
  133. /*----------------------------------------------------*/
  134. #pragma mark - Private Methods -
  135. /*----------------------------------------------------*/
  136. + (void)writeData:(NSData *)aData
  137. charactUUID:(NSString *)aCharacteristic
  138. serviceUUID:(NSString *)aService
  139. readyPeripheral:(LGPeripheral *)aPeripheral
  140. completion:(LGCharacteristicWriteCallback)aCallback;
  141. {
  142. [aPeripheral discoverServices:@[[CBUUID UUIDWithString:aService]] completion:^(NSArray *services, NSError *error) {
  143. LGService *service = nil;
  144. if (services.count && !error && (service = [self findServiceInList:services byUUID:aService])) {
  145. [service discoverCharacteristicsWithUUIDs:@[[CBUUID UUIDWithString:aCharacteristic]]
  146. completion:^(NSArray *characteristics, NSError *error)
  147. {
  148. LGCharacteristic *characteristic = nil;
  149. if (characteristics.count && (characteristic = [self findCharacteristicInList:characteristics byUUID:aCharacteristic])) {
  150. [characteristic writeValue:aData completion:aCallback];
  151. } else {
  152. if (aCallback) {
  153. if (!error) {
  154. aCallback([LGUtils writeErrorWithCode:kLGUtilsMissingCharacteristicErrorCode
  155. message:kLGUtilsMissingCharacteristicErrorMessage]);
  156. } else {
  157. aCallback(error);
  158. }
  159. }
  160. LGLogError(@"Missing provided characteristic : %@ in service : %@", aCharacteristic, aService);
  161. }
  162. }];
  163. } else {
  164. if (aCallback) {
  165. if (!error) {
  166. aCallback([LGUtils writeErrorWithCode:kLGUtilsMissingServiceErrorCode
  167. message:kLGUtilsMissingServiceErrorMessage]);
  168. } else {
  169. aCallback(error);
  170. }
  171. }
  172. LGLogError(@"Missing provided service : %@ in peripheral", aService);
  173. }
  174. }];
  175. }
  176. + (void)readDataFromCharactUUID:(NSString *)aCharacteristic
  177. serviceUUID:(NSString *)aService
  178. readyPeripheral:(LGPeripheral *)aPeripheral
  179. completion:(LGCharacteristicReadCallback)aCallback;
  180. {
  181. [aPeripheral discoverServices:@[[CBUUID UUIDWithString:aService]] completion:^(NSArray *services, NSError *error) {
  182. if (services.count && !error) {
  183. LGService *service = [self findServiceInList:services
  184. byUUID:aService];
  185. [service discoverCharacteristicsWithUUIDs:@[[CBUUID UUIDWithString:aCharacteristic]] completion:^(NSArray *characteristics, NSError *error) {
  186. if (characteristics.count) {
  187. LGCharacteristic *characteristic = [self findCharacteristicInList:characteristics
  188. byUUID:aCharacteristic];
  189. [characteristic readValueWithBlock:aCallback];
  190. } else {
  191. if (aCallback) {
  192. if (!error) {
  193. aCallback(nil, [LGUtils readErrorWithCode:kLGUtilsMissingCharacteristicErrorCode
  194. message:kLGUtilsMissingCharacteristicErrorMessage]);
  195. } else {
  196. aCallback(nil, error);
  197. }
  198. }
  199. }
  200. }];
  201. } else {
  202. if (aCallback) {
  203. if (!error) {
  204. aCallback(nil, [LGUtils readErrorWithCode:kLGUtilsMissingServiceErrorCode
  205. message:kLGUtilsMissingServiceErrorMessage]);
  206. } else {
  207. aCallback(nil, error);
  208. }
  209. }
  210. LGLogError(@"Missing provided service : %@ in peripheral", aService);
  211. }
  212. }];
  213. }
  214. + (void)discoverCharactUUID:(NSString *)aCharacteristic
  215. serviceUUID:(NSString *)aService
  216. readyPeripheral:(LGPeripheral *)aPeripheral
  217. completion:(LGUtilsDiscoverCharacterisitcCallback)aCallback
  218. {
  219. [aPeripheral discoverServices:@[[CBUUID UUIDWithString:aService]] completion:^(NSArray *services, NSError *error) {
  220. if (services.count && !error) {
  221. LGService *service = [self findServiceInList:services
  222. byUUID:aService];
  223. [service discoverCharacteristicsWithUUIDs:@[[CBUUID UUIDWithString:aCharacteristic]] completion:^(NSArray *characteristics, NSError *error) {
  224. if (characteristics.count) {
  225. LGCharacteristic *characteristic = [self findCharacteristicInList:characteristics
  226. byUUID:aCharacteristic];
  227. if (aCallback) {
  228. aCallback(characteristic, nil);
  229. }
  230. } else {
  231. if (aCallback) {
  232. if (!error) {
  233. aCallback(nil, [LGUtils discoverErrorWithCode:kLGUtilsMissingCharacteristicErrorCode
  234. message:kLGUtilsMissingCharacteristicErrorMessage]);
  235. } else {
  236. aCallback(nil, error);
  237. }
  238. }
  239. }
  240. }];
  241. } else {
  242. if (aCallback) {
  243. if (!error) {
  244. aCallback(nil, [LGUtils discoverErrorWithCode:kLGUtilsMissingServiceErrorCode
  245. message:kLGUtilsMissingServiceErrorMessage]);
  246. } else {
  247. aCallback(nil, error);
  248. }
  249. }
  250. LGLogError(@"Missing provided service : %@ in peripheral", aService);
  251. }
  252. }];
  253. }
  254. /**
  255. * Find characteristic in characteristic list by providied UUID string
  256. * @return Found characteristic, nil if no one found
  257. */
  258. + (LGCharacteristic *)findCharacteristicInList:(NSArray *)characteristics
  259. byUUID:(NSString *)anID
  260. {
  261. for (LGCharacteristic *characteristic in characteristics) {
  262. if ([[characteristic.UUIDString lowercaseString] isEqualToString:[anID lowercaseString]]) {
  263. return characteristic;
  264. }
  265. }
  266. return nil;
  267. }
  268. /**
  269. * Find service in services list by providied UUID string
  270. * @return Found service, nil if no one found
  271. */
  272. + (LGService *)findServiceInList:(NSArray *)services
  273. byUUID:(NSString *)anID
  274. {
  275. for (LGService *service in services) {
  276. if ([[service.UUIDString lowercaseString] isEqualToString:[anID lowercaseString]]) {
  277. return service;
  278. }
  279. }
  280. return nil;
  281. }
  282. /*----------------------------------------------------*/
  283. #pragma mark - Error Generators -
  284. /*----------------------------------------------------*/
  285. + (NSError *)writeErrorWithCode:(NSInteger)aCode message:(NSString *)aMsg
  286. {
  287. return [NSError errorWithDomain:kLGUtilsWriteErrorDomain
  288. code:aCode
  289. userInfo:@{kLGErrorMessageKey : aMsg}];
  290. }
  291. + (NSError *)readErrorWithCode:(NSInteger)aCode message:(NSString *)aMsg
  292. {
  293. return [NSError errorWithDomain:kLGUtilsReadErrorDomain
  294. code:aCode
  295. userInfo:@{kLGErrorMessageKey : aMsg}];
  296. }
  297. + (NSError *)discoverErrorWithCode:(NSInteger)aCode message:(NSString *)aMsg
  298. {
  299. return [NSError errorWithDomain:kLGUtilsDiscoverErrorDomain
  300. code:aCode
  301. userInfo:@{kLGErrorMessageKey : aMsg}];
  302. }
  303. @end