iOS-BLE藍牙開發

原文出處:煜寒了 php

在寫這個博客以前,空餘時間抽看了近一個月的文檔和Demo,系統給的解釋很詳細,接口也比較實用,惟獨有一點,對於設備的惟一標示,網上衆說紛紜,在這裏我目前也尚未本身的看法,只是在不斷的測試各類狀況,親測同一設備的UUID對於每臺iPhone設備都不同,只能儘可能保證設備的惟一性,特別是自動重連的過程,讓用戶沒有感知。html

我以前也找了好久,發現CBCentralManager和CBPeripheral裏邊都找不到和Mac地址有關的東西,後來發現通常是外設在Device Information服務中的某個特徵返回的。通過與硬件工程師的協商,決定APP端將從這個服務中獲取到藍牙設備以及個人iPhone手機的藍牙Mac地址,爲自動鏈接的惟一性作準備。ios

 

這裏通過和硬件工程師的測試,發現設備端在獲取手機藍牙MAC地址的時候,當用戶手機重啓以後,這個地址也是會隨機變化的,也就是說,做爲開發者,只有設備的MAC地址可以保持惟一性不變化。git

有疑問的朋友能夠先去這裏瞅一瞅
一個關於藍牙4.0的智能硬件Demo詳解github

  • 下面是兩臺iPhone6鏈接同一臺藍牙設備的結果:數組

1ide

2函數

3測試

4ui

**成功鏈接**** peripheral: <CBPeripheral: 0x1700f4500, identifier = 50084F69-BA5A-34AC-8A6E-6F0CEADB21CD, name = 555555555588, state = connected> with UUID: <__NSConcreteUUID 0x17003d980> 50084F69-BA5A-34AC-8A6E-6F0CEADB21CD**

****

****

**成功鏈接**** peripheral: <CBPeripheral: 0x1742e3000, identifier = 55B7D759-0F1E-6271-EA14-BC5A9C9EEEEC, name = 555555555588, state = connected> with UUID: <__NSConcreteUUID 0x174036c00> 55B7D759-0F1E-6271-EA14-BC5A9C9EEEEC**

 

進入正題

iOS的藍牙開發很簡單,只要包含一個庫,建立CBCentralManager實例,實現代理方法,而後就能夠直接和設備進行通訊。

發現附近的特定藍牙設備

1

#import <CoreBluetooth/CoreBluetooth.h>

 

首先能夠定義一些即將使用到的UUID的宏

1

2

3

#define kPeripheralName     @"360qws Electric Bike Service" //外圍設備名稱

#define kServiceUUID        @"7CACEB8B-DFC4-4A40-A942-AAD653D174DC" //服務的UUID

#define kCharacteristicUUID @"282A67B2-8DAB-4577-A42F-C4871A3EEC4F" //特徵的UUID

 

若是不是把手機做爲中心設備的話,這些沒有必要設置。
這裏我也沒有用到,僅僅是提了一下,具體操做後續添加。

對於生成UUID,你們能夠谷歌一下,直接經過mac終端生成32位UUID。

1.聲明屬性

1

2

3

4

5

6

7

8

9

10

11

12

13

@property (weaknonatomicIBOutlet UITableView *bluetoothTable;

@property (weaknonatomicIBOutlet UITextView *resultTextView;

 

@property BOOL cbReady;

@property(nonatomicfloat batteryValue;

@property (nonatomicstrong) CBCentralManager *manager;

@property (nonatomicstrong) CBPeripheral *peripheral;

 

@property (strong ,nonatomic) CBCharacteristic *writeCharacteristic;

 

@property (strong,nonatomicNSMutableArray *nDevices;

@property (strong,nonatomicNSMutableArray *nServices;

@property (strong,nonatomicNSMutableArray *nCharacteristics;

2.遵照協議(這裏我用到了table)

1

@interface ViewController () <CBCentralManagerDelegate, CBPeripheralDelegate, UITableViewDataSourceUITableViewDelegate>

3.初始化數據

1

2

3

4

5

6

7

8

9

10

11

12

13

14

- (void)viewDidLoad {

    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.

    self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

 

    _cbReady = false;

    _nDevices = [[NSMutableArray alloc]init];

    _nServices = [[NSMutableArray alloc]init];

    _nCharacteristics = [[NSMutableArray alloc]init];

 

    _bluetoothTable.delegate = self;

    _bluetoothTable.dataSource = self;

 

    count = 0;

}

4.實現藍牙的協議方法

  • (1)檢測藍牙狀態

1

2

3

4

5

6

7

8

9

10

//開始查看服務,藍牙開啓-(void)centralManagerDidUpdateState:(CBCentralManager *)central

{    switch (central.state) {        case CBCentralManagerStatePoweredOn:

        {

            [self updateLog:@"藍牙已打開,請掃描外設"];

            [_activity startAnimating];

            [_manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"FF15"]]  options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];

        }            break;        case CBCentralManagerStatePoweredOff:

            [self updateLog:@"藍牙沒有打開,請先打開藍牙"];            break;        default:            break;

    }

}

 

注:[_manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"FF15"]]  options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];中間的@[[CBUUID UUIDWithString:@"FF15"]]是爲了過濾掉其餘設備,能夠搜索特定標示的設備。

  • (2)檢測到外設後,中止掃描,鏈接設備

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

//查到外設後,中止掃描,鏈接設備-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

{

    [self updateLog:[NSString stringWithFormat:@"已發現 peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ ", peripheral, RSSI, peripheral.identifier, advertisementData]];

 

    _peripheral = peripheral;

    [_manager connectPeripheral:_peripheral options:nil];

 

    [self.manager stopScan];

    [_activity stopAnimating];    BOOL replace = NO;    // Match if we have this device from before

    for (int i=0; i < _nDevices.count; i++) {

        CBPeripheral *p = [_nDevices objectAtIndex:i];        if ([p isEqual:peripheral]) {

            [_nDevices replaceObjectAtIndex:i withObject:peripheral];

            replace = YES;

        }

    }    if (!replace) {

        [_nDevices addObject:peripheral];

        [_bluetoothTable reloadData];

    }

}

 

  • (3)鏈接外設後的處理

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

//鏈接外設成功,開始發現服務- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {    NSLog(@"%@", [NSString stringWithFormat:@"成功鏈接 peripheral: %@ with UUID: %@",peripheral,peripheral.identifier]);

 

    [self updateLog:[NSString stringWithFormat:@"成功鏈接 peripheral: %@ with UUID: %@",peripheral,peripheral.identifier]];

 

    [self.peripheral setDelegate:self];

    [self.peripheral discoverServices:nil];

    [self updateLog:@"掃描服務"];

}//鏈接外設失敗-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error

{    NSLog(@"%@",error);

}

 

-(void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(NSError *)error

{    NSLog(@"%s,%@",__PRETTY_FUNCTION__,peripheral);    int rssi = abs([peripheral.RSSI intValue]);    CGFloat ci = (rssi - 49) / (10 * 4.);    NSString *length = [NSString stringWithFormat:@"發現BLT4.0熱點:%@,距離:%.1fm",_peripheral,pow(10,ci)];

    [self updateLog:[NSString stringWithFormat:@"距離:%@", length]];

}

 

  • (4)發現服務和搜索到的Characteristice

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

//已發現服務-(void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{

 

    [self updateLog:@"發現服務."];    int i=0;    for (CBService *s in peripheral.services) {

        [self.nServices addObject:s];

    }    for (CBService *s in peripheral.services) {

        [self updateLog:[NSString stringWithFormat:@"%d :服務 UUID: %@(%@)",i,s.UUID.data,s.UUID]];

        i++;

        [peripheral discoverCharacteristics:nil forService:s];        if ([s.UUID isEqual:[CBUUID UUIDWithString:@"FF15"]]) {            BOOL replace = NO;            // Match if we have this device from before

            for (int i=0; i < _nDevices.count; i++) {

                CBPeripheral *p = [_nDevices objectAtIndex:i];                if ([p isEqual:peripheral]) {

                    [_nDevices replaceObjectAtIndex:i withObject:peripheral];

                    replace = YES;

                }

            }            if (!replace) {

                [_nDevices addObject:peripheral];

                [_bluetoothTable reloadData];

            }

        }

    }

}//已搜索到Characteristics-(void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{

    [self updateLog:[NSString stringWithFormat:@"發現特徵的服務:%@ (%@)",service.UUID.data ,service.UUID]];    for (CBCharacteristic *c in service.characteristics) {

        [self updateLog:[NSString stringWithFormat:@"特徵 UUID: %@ (%@)",c.UUID.data,c.UUID]];        if ([c.UUID isEqual:[CBUUID UUIDWithString:@"FF01"]]) {

            _writeCharacteristic = c;

        }        if ([c.UUID isEqual:[CBUUID UUIDWithString:@"FF02"]]) {

            [_peripheral readValueForCharacteristic:c];

            [_peripheral setNotifyValue:YES forCharacteristic:c];

        }        if ([c.UUID isEqual:[CBUUID UUIDWithString:@"FF04"]]) {

            [_peripheral readValueForCharacteristic:c];

        }        if ([c.UUID isEqual:[CBUUID UUIDWithString:@"FF05"]]) {

            [_peripheral readValueForCharacteristic:c];

            [_peripheral setNotifyValue:YES forCharacteristic:c];

        }        if ([c.UUID isEqual:[CBUUID UUIDWithString:@"FFA1"]]) {

            [_peripheral readRSSI];

        }

 

        [_nCharacteristics addObject:c];

    }

}

 

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {

    [self updateLog:[NSString stringWithFormat:@"已斷開與設備:[%@]的鏈接", peripheral.name]];

}

 

  • (5)獲取外設發來的數據

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

//獲取外設發來的數據,不管是read和notify,獲取數據都是從這個方法中讀取。- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

{    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FF02"]]) {        NSData * data = characteristic.value;

        Byte * resultByte = (Byte *)[data bytes];        for(int i=0;i<[data length];i++)

            printf("testByteFF02[%d] = %d\n",i,resultByte[i]);        if (resultByte[1] == 0) {            switch (resultByte[0]) {                case 3: // 加解鎖

                {                    if (resultByte[2] == 0) {

                        [self updateLog:@"撤防成功!!!"];

                    }else if (resultByte[2] == 1) {

                        [self updateLog:@"設防成功!!!"];

                    }

                }                    break;                case 4: // 開坐桶

                {                    if (resultByte[2] == 0) {

                        [self updateLog:@"關坐桶成功!!!"];

                    }else if (resultByte[2] == 1) {

                        [self updateLog:@"開坐桶成功!!!"];

                    }

                }                    break;                case 5: // 鎖定電機

                {                    if (resultByte[2] == 0) {

                        [self updateLog:@"解鎖電機控制器成功!!!"];

                    }else if (resultByte[2] == 1) {

                        [self updateLog:@"鎖定電機控制器成功!!!"];

                    }

                }                    break;                default:                    break;

            }

        }else if (resultByte[1] == 1) {

            [self updateLog:@"未知錯誤"];

        }else if (resultByte[1] == 2) {

            [self updateLog:@"鑑權失敗"];

        }

    }    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FF04"]]) {        NSData * data = characteristic.value;

        Byte * resultByte = (Byte *)[data bytes];        for(int i=0;i<[data length];i++)

            printf("testByteFF04[%d] = %d\n",i,resultByte[i]);        if (resultByte[0] == 0) {            // 未綁定 -》寫鑑權碼

            [self updateLog:@"當前車輛未綁定,請鑑權"];

            [self authentication];  // 鑑權

            [self writePassword:nil newPw:nil];

        }else if (resultByte[0] == 1) {            // 已綁定 -》鑑權

            [self updateLog:@"當前車輛已經綁定,請鑑權"];

            [self writePassword:nil newPw:nil];

        }else if (resultByte[0] == 2) {            // 容許綁定

            [self updateLog:@"當前車輛容許綁定"];

        }

    }    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FF05"]]) {        NSData * data = characteristic.value;

        Byte * resultByte = (Byte *)[data bytes];        for(int i=0;i<[data length];i++)

            printf("testByteFF05[%d] = %d\n",i,resultByte[i]);        if (resultByte[0] == 0) {            // 設備加解鎖狀態 0 撤防     1 設防

            [self updateLog:@"當前車輛撤防狀態"];

        }else if (resultByte[0] == 1) {            // 設備加解鎖狀態 0 撤防     1 設防

            [self updateLog:@"當前車輛設防狀態"];

        }

    }

}//中心讀取外設實時數據- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {    if (error) {        NSLog(@"Error changing notification state: %@", error.localizedDescription);

    }    // Notification has started

    if (characteristic.isNotifying) {

        [peripheral readValueForCharacteristic:characteristic];

 

    else // Notification has stopped

        // so disconnect from the peripheral

        NSLog(@"Notification stopped on %@.  Disconnecting", characteristic);

        [self updateLog:[NSString stringWithFormat:@"Notification stopped on %@.  Disconnecting", characteristic]];

        [self.manager cancelPeripheralConnection:self.peripheral];

    }

}//用於檢測中心向外設寫數據是否成功-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error

{    if (error) {        NSLog(@"=======%@",error.userInfo);

        [self updateLog:[error.userInfo JSONString]];

    }else{        NSLog(@"發送數據成功");

        [self updateLog:@"發送數據成功"];

    }    /* When a write occurs, need to set off a re-read of the local CBCharacteristic to update its value */

    [peripheral readValueForCharacteristic:characteristic];

}

 

  • (6)其餘輔助性的

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

#pragma mark - 藍牙的相關操做- (IBAction)bluetoothAction:(UIButton *)sender {    switch (sender.tag) {        case 201:

        {   // 搜索設備

            [self updateLog:@"正在掃描外設..."];

            [_activity startAnimating];

            [_manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@"FF15"]]  options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];            double delayInSeconds = 30.0;            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));

            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

                [self.manager stopScan];

                [_activity stopAnimating];

                [self updateLog:@"掃描超時,中止掃描"];

            });

        }            break;        case 202:

        {   // 鏈接

            if (_peripheral && _cbReady) {

                [_manager connectPeripheral:_peripheral options:nil];

                _cbReady = NO;

            }

        }            break;        case 203:

        {   // 斷開

            if (_peripheral && !_cbReady) {

                [_manager cancelPeripheralConnection:_peripheral];

                _cbReady = YES;

            }

        }            break;        case 204:

        {   // 暫停搜索

            [self.manager stopScan];

        }            break;        case 211:

        {   // 車輛上鎖

            [self lock];

        }            break;        case 212:

        {   // 車輛解鎖

            [self unLock];

        }            break;        case 213:

        {   // 開啓坐桶

            [self open];

        }            break;        case 214:

        {   // 當即尋車

            [self find];

        }            break;        default:            break;

    }

}

 

-(NSOperationQueue *)queue {    if (!_queue) {  // 請求隊列

        self.queue = [[NSOperationQueue alloc]init];

        [self.queue setMaxConcurrentOperationCount:1];

    }    return _queue;

}#pragma mark - 命令#pragma mark - 鑑權-(void)authentication {

    Byte byte[] = {1, 1, 2, 3, 4, 5, 6, 7, 8};    if (_peripheral.state == CBPeripheralStateConnected) {

        [_peripheral writeValue:[NSData dataWithBytes:byte length:9] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}#pragma mark - 寫密碼 -(void)writePassword:(NSString *)initialPw newPw:(NSString *)newPw {

    Byte byte[] = {2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8};    if (_peripheral.state == CBPeripheralStateConnected) {

        [_peripheral writeValue:[NSData dataWithBytes:byte length:17] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}#pragma mark - 車輛上鎖-(void)lock {

    Byte byte[] = {3, 1};    if (_peripheral.state == CBPeripheralStateConnected) {

        [_peripheral writeValue:[NSData dataWithBytes:byte length:2] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}#pragma mark - 車輛解鎖-(void)unLock {

    Byte byte[] = {3, 0};    if (_peripheral.state == CBPeripheralStateConnected) {

        [_peripheral writeValue:[NSData dataWithBytes:byte length:2] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}#pragma mark - 開啓坐桶-(void)open {

    Byte byte[] = {4, 1};    if (_peripheral.state == CBPeripheralStateConnected) {

        [_peripheral writeValue:[NSData dataWithBytes:byte length:2] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}#pragma mark - 當即尋車-(void)find {

    Byte byte[] = {7};    if (_peripheral.state == CBPeripheralStateConnected) {

        [_peripheral writeValue:[NSData dataWithBytes:byte length:1] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

    }

}

 

-(NSData *)hexString:(NSString *)hexString {    int j=0;

    Byte bytes[20];    ///3ds key的Byte 數組, 128位

    for(int i=0; i<[hexString length]; i++)

    {        int int_ch;  /// 兩位16進制數轉化後的10進制數

 

        unichar hex_char1 = [hexString characterAtIndex:i]; ////兩位16進制數中的第一位(高位*16)

        int int_ch1;        if(hex_char1 >= '0' && hex_char1 <='9')

            int_ch1 = (hex_char1-48)*16;   //// 0 的Ascll - 48

        else if(hex_char1 >= 'A' && hex_char1 <='F')

            int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65

        else

            int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97

        i++;

 

        unichar hex_char2 = [hexString characterAtIndex:i]; ///兩位16進制數中的第二位(低位)

        int int_ch2;        if(hex_char2 >= '0' && hex_char2 <='9')

            int_ch2 = (hex_char2-48); //// 0 的Ascll - 48

        else if(hex_char1 >= 'A' && hex_char1 <='F')

            int_ch2 = hex_char2-55; //// A 的Ascll - 65

        else

            int_ch2 = hex_char2-87; //// a 的Ascll - 97

 

        int_ch = int_ch1+int_ch2;

        NSLog(@"int_ch=%d",int_ch);

        bytes[j] = int_ch;  ///將轉化後的數放入Byte數組裏

        j++;

    }

 

    NSData *newData = [[NSData alloc] initWithBytes:bytes length:20];    return newData;

}

 

在和硬件之間的數據發送和接受,用的都是byte數組。最後,添加一個存儲已鏈接過得設備

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

- (void) addSavedDevice:(CFUUIDRef)uuid {    NSArray *storedDevices = [[NSUserDefaults standardUserDefaults] arrayForKey:@"StoredDevices"];     NSMutableArray *newDevices = nil;    CFStringRef uuidString = NULL;    if (![storedDevices isKindOfClass:[NSArray class]]) {        NSLog(@"Can't find/create an array to store the uuid");        return;

    }

 

    newDevices = [NSMutableArray arrayWithArray:storedDevices];

    uuidString = CFUUIDCreateString(NULLuuid);    if (uuidString) {

        [newDevices addObject:(__bridge NSString*)uuidString];        CFRelease(uuidString);

    }    /* Store */

    [[NSUserDefaults standardUserDefaults] setObject:newDevices forKey:@"StoredDevices"];

    [[NSUserDefaults standardUserDefaults] synchronize];

}

 

- (void) loadSavedDevices {    NSArray *storedDevices = [[NSUserDefaults standardUserDefaults] arrayForKey:@"StoredDevices"];    if (![storedDevices isKindOfClass:[NSArray class]]) {         NSLog(@"No stored array to load");        return;

    }    for (id deviceUUIDString in storedDevices) {        if (![deviceUUIDString isKindOfClass:[NSString class]]) continue;        CFUUIDRef uuid CFUUIDCreateFromString(NULL, (CFStringRef)deviceUUIDString);        if (!uuidcontinue;

        [CBCentralManager retrievePeripherals:[NSArray arrayWithObject:(__bridge id)uuid]];        CFRelease(uuid);

    }

}//And the delegate function for the Retrieve Peripheral- (void) centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals {

    CBPeripheral *peripheral;    /* Add to list. */

    for (peripheral in peripherals) {

         [central connectPeripheral:peripheral options:nil];

    }

}

 

 - (void) centralManager:(CBCentralManager *)central didRetrievePeripheral:(CBPeripheral *)peripheral {

    [central connectPeripheral:peripheral options:nil];

}

 

後記

  • 最主要是用UUID來肯定你要乾的事情,特徵和服務的UUID都是外設定義好的。咱們只須要讀取,肯定你要讀取什麼的時候,就去判斷UUID是否相符。 通常來講咱們使用的iPhone都是作centralManager的,藍牙模塊是peripheral的,因此咱們是want datas,須要接受數據。
    1.判斷狀態爲powerOn,而後執行掃描
    2.中止掃描,鏈接外設
    3.鏈接成功,尋找服務
    4.在服務裏尋找特徵
    5.爲特徵添加通知
    5.通知添加成功,那麼就能夠實時的讀取value[也就是說只要外設發送數據[通常外設的頻率爲10Hz],代理就會調用此方法]。
    6.處理接收到的value,[hex值,得轉換] 以後就自由發揮了,在這期間都是經過代理來實現的,也就是說你只須要處理你想要作的事情,代理會幫你調用方法。[別忘了添加代理]

2015-07-28 更

關於write我這裏還有些注意的地方要強調!!!!

並非每個Characteristic均可以經過回調函數來查看它寫入狀態的。就好比針對 immediateAlertService(1802) 的 alertLevelCharacteristic(2A06),就是一個不能有response的Characteristic。剛開始我就一直用CBCharacteristicWriteType.WithResponse來進行寫入始終不成功,鬱悶壞了,最後看到每一個Characteristic還有個屬性值是指示這個的,我將每一個Characteristic打印出來有以下信息:

1

2

immediateAlertService Discover characteristic <CBCharacteristic: 0x15574d00, UUID = 2A06, properties = 0x4, value = (null), notifying = NO>

linkLossAlertService Discover characteristic <CBCharacteristic: 0x15671d00, UUID = 2A06, properties = 0xA, value = (null), notifying = NO>

 

這個的properties是什麼剛開始不知道,以爲他沒意義,後面才注意到properties是Characteristic的一個參數,具體解釋以下:

1

2

3

4

DeclarationSWIFTstruct CBCharacteristicProperties : RawOptionSetType {    init(_ value: UInt)    var value: UInt

    static var Broadcast: CBCharacteristicProperties { get }    static var Read: CBCharacteristicProperties { get }    static var WriteWithoutResponse: CBCharacteristicProperties { get }    static var Write: CBCharacteristicProperties { get }    static var Notify: CBCharacteristicProperties { get }    static var Indicate: CBCharacteristicProperties { get }    static var AuthenticatedSignedWrites: CBCharacteristicProperties { get }    static var ExtendedProperties: CBCharacteristicProperties { get }    static var NotifyEncryptionRequired: CBCharacteristicProperties { get }    static var IndicateEncryptionRequired: CBCharacteristicProperties { get }

}OBJECTIVE-Ctypedef enum {   CBCharacteristicPropertyBroadcast = 0x01,   CBCharacteristicPropertyRead = 0x02,   CBCharacteristicPropertyWriteWithoutResponse = 0x04,   CBCharacteristicPropertyWrite = 0x08,   CBCharacteristicPropertyNotify = 0x10,   CBCharacteristicPropertyIndicate = 0x20,   CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,   CBCharacteristicPropertyExtendedProperties = 0x80,   CBCharacteristicPropertyNotifyEncryptionRequired = 0x100,   CBCharacteristicPropertyIndicateEncryptionRequired = 0x200,

} CBCharacteristicProperties;

 

能夠看到0x04對應的是CBCharacteristicPropertyWriteWithoutResponse
          0x0A對應的是CBCharacteristicPropertyNotify

因此 immediateAlertService(1802) 的 alertLevelCharacteristic(2A06)是不能用CBCharacteristicWriteType.WithRespons進行寫入,只能用CBCharacteristicWriteType.WithOutRespons。這樣在之後的開發中能夠對每一個Characteristic的這個參數進行檢查再進行設置。

最後講一下關於藍牙綁定的過程,在iOS中,沒有講當綁定的過程,直接就是掃描、鏈接、交互。從而不少人會認爲,鏈接就是綁定了,其實否則。在iOS開發中,鏈接並無完成綁定,在網上找到了個很好的解釋:

you cannot initiate pairing from the iOS central side. Instead, you have to read/write a characteristic value,
and then let your peripheral respond with an "Insufficient Authentication" error.
iOS will then initiate pairing, will store the keys for later use (bonding) and encrypts the link. As far as I know,
it also caches discovery information, so that future connections can be set up faster.

就是當發生讀寫交互時,系統在會和外設進行綁定操做!!!

2016-02-20 更

ios藍牙如何獲取廣播包數據  

如題,手機做爲主設備,在使用CoreBluetooth時候,想獲取藍牙的數據廣播包。在使用

1

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)aPeripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

 

方法時候獲取的advertisementData打印出來只有

1

** ****kCBAdvDataIsConnectable****kCBAdvDataLocalName****kCBAdvDataManufacturerData**

 

三個屬性對應的值,但這並不是廣播包的數據。例如安卓能夠經過scandata來獲取到廣播包的值,那麼iOS這邊我應該怎麼作呢?

好像蘋果這邊禁止讀取這種廣播內容的的,真要的話你可讓硬件那邊把數據作到kCBAdvDataManufacturerData這個字段裏面。

Demo地址:一個藍牙4.0的智能硬件Demo

 

原文:http://bbs.520it.com/forum.php?mod=viewthread&tid=3033&page=&extra=#pid33613

相關文章
相關標籤/搜索