iOS -- 低功耗藍(lán)牙


藍(lán)牙介紹:使用的是網(wǎng)上購買的一個簡單的藍(lán)牙模塊
藍(lán)牙模塊地址:藍(lán)牙模塊地址
USB轉(zhuǎn)TTL:轉(zhuǎn)接模塊地址

AT-09藍(lán)牙4.0BLE 模塊 串口引出 CC2541兼容HM-10模塊

AT-09藍(lán)牙4.0BLE 模塊

該藍(lán)牙模塊相當(dāng)簡單,適合初學(xué)者入門使用
下面是該藍(lán)牙的設(shè)備信息以及傳輸特性:
廣播數(shù)據(jù):

{
是否可連接
kCBAdvDataIsConnectable = 1;
Mac地址
kCBAdvDataManufacturerData = <1a9888a0 3ca30807 b90a>;
兩種服務(wù)
kCBAdvDataServiceUUIDs = (
FFE0,
FEE0
);
}
這里的服務(wù)有FFE0和FEE0兩種董济,F(xiàn)FE0代表攜帶設(shè)備信息的服務(wù)矢赁,F(xiàn)EE0代表傳輸特性

FFE0服務(wù)的特征:

(
攜帶設(shè)備信息
"<CBCharacteristic: 0x13d6ba1d0, UUID = System ID, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba390, UUID = Model Number String, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba3f0, UUID = Serial Number String, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba330, UUID = Firmware Revision String, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba550, UUID = Hardware Revision String, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba480, UUID = Software Revision String, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba750, UUID = Manufacturer Name String, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba800, UUID = IEEE Regulatory Certification, properties = 0x2, value = (null), notifying = NO>",
"<CBCharacteristic: 0x13d6ba860, UUID = PnP ID, properties = 0x2, value = (null), notifying = NO>"
)

FEE0服務(wù)的特征:

"<CBCharacteristic: 0x13d563890, UUID = FFE1, properties = 0x1E, value = (null), notifying = NO>"

此藍(lán)牙模塊只有簡單的傳輸特性,讀寫的特征為同一個基协,并且由于讀寫服務(wù)FEE0的屬性properties0x1E,按照網(wǎng)上的資料,0x1E應(yīng)該是CBCharacteristicPropertyRead=0x02CBCharacteristicPropertyWriteWithoutResponse=0x04CBCharacteristicPropertyWrite=0x08信峻,CBCharacteristicPropertyNotify=0x10的組合,可是實(shí)際上當(dāng)發(fā)送數(shù)據(jù)后去讀數(shù)據(jù)時只能采取手動調(diào)用的方式讀取并且返回固定值;

藍(lán)牙相關(guān)對象需要被控制器對象持有

創(chuàng)建NSObjectBLEManager 導(dǎo)入<CoreBluetooth/CoreBluetooth.h>框架,在.h文件接口遵守CBCentralManagerDelegate,CBPeripheralDelegate協(xié)議,在控制器文件BLEManager下創(chuàng)建以下屬性:

@property (retain, nonatomic) CBCentralManager *centralManager; //中心設(shè)備
@property (retain, nonatomic) CBPeripheral *discoveredPeripheral; //外圍設(shè)備
@property (retain, nonatomic) CBCharacteristic *discoveredCharacteristic; //服務(wù)特征

用于持有相關(guān)對象瓮床。

  • 1.實(shí)例化一個中心設(shè)備對象
if (!self.centralManager){
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}

設(shè)置代理盹舞,默認(rèn)主線程操作。

  • 2.設(shè)備對象實(shí)例化代理
#pragma mark - CentralManager Delegate
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    if (central.state==CBCentralManagerStateUnsupported)
    {
        //手機(jī)不支持低功耗藍(lán)牙
        return;
    }
    if (central.state==CBCentralManagerStatePoweredOff) {
        //手機(jī)藍(lán)牙未開啟
        return;
    }
    if (central.state == CBCentralManagerStateUnauthorized)
    {
        //系統(tǒng)設(shè)置不允許
        return;
    }
    if (central.state == CBCentralManagerStatePoweredOn) {
       在這里開始掃描外圍設(shè)備的服務(wù)
       這里的Services表示UUID隘庄,傳參代表值掃描帶有該UUID的設(shè)備踢步,也可以傳nil
       CBCentralManagerScanOptionAllowDuplicatesKey設(shè)置為NO表示不會重復(fù)掃描已經(jīng)發(fā)現(xiàn)的設(shè)備
       [self.centralManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @NO }];  
    }
}

這個代理返回中心設(shè)備能否進(jìn)行藍(lán)牙操作的信息,這里列出了不支持丑掺,未開啟获印,支持三種狀態(tài)。

  • 3.掃描周圍設(shè)備
    在這里可以得到掃描到廣播的設(shè)備信息街州,包括設(shè)備對象兼丰,信號,廣播信息等唆缴,
    這個方法不斷刷新鳍征,一直尋找周圍的設(shè)備,篩選設(shè)備連接成功之后面徽,可以手動停止掃描艳丛。
/**
 掃描周圍設(shè)備的回調(diào)

 @param central 中心設(shè)備對象
 @param peripheral 周圍設(shè)備對象
 @param advertisementData 廣播數(shù)據(jù)
 @param RSSI 信號
 */
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
     可以在這里設(shè)置連接名字以MLT開頭的設(shè)備
   if ([peripheral.name  hasPrefix:@"MLT"]) {
     self.discoveredPeripheral = peripheral;                
     [self.centralManager connectPeripheral:peripheral options:nil];   
   }
}
  • 4連接結(jié)果回調(diào)
//成功鏈接外圍設(shè)備
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
 //停止掃描  
 [self.centralManager stopScan];
 //設(shè)置外圍設(shè)備代理
 peripheral.delegate = self;
 //查找連接設(shè)備的所有服務(wù)
  [peripheral discoverServices:nil];
}
//連接外圍設(shè)備失敗
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error

//與外圍設(shè)備連接斷開
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    可以在這里向外部發(fā)送連接斷開的通知
    可以這里可以設(shè)置自動重新掃描連接
 }


  • 5外圍設(shè)備的代理方法
#pragma mark - Peripheral Delegate
//找到對應(yīng)的服務(wù)代理方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    if (error) {
        NSLog(@"Error is %@", [error localizedDescription]);
        return;
    }
    //查找連接設(shè)備的服務(wù)的所有特征
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
}
  • 6.查找特征的代理方法
//找到特性代理方法
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    if (error) {
        NSLog(@"Error is %@", [error localizedDescription]);
        return;
    }
    for (CBCharacteristic *characteristic in service.characteristics)
    {
        //設(shè)置特性2的通知為YES,以收取外圍設(shè)備發(fā)過來的數(shù)據(jù) - 讀數(shù)據(jù)
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]])
        {
            開啟讀服務(wù)通知
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            self.discoveredCharacteristic=characteristic;  //保持服務(wù)特征
        }
    }
}

特征值的通知設(shè)置發(fā)生改變時觸發(fā)的方法斗忌,在代碼中設(shè)置允許讀寫通知時都會進(jìn)入此方法

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
   if (error){
       NSLog(@"改變特征通知錯誤: %@", error.localizedDescription);
   }
   當(dāng)不是傳輸特征時质礼,不做處理
   if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]]){
       return;
   }
   當(dāng)傳輸特征通知開啟時,連接成功(到這一步才可以正常進(jìn)行數(shù)據(jù)交互)
   if (characteristic.isNotifying){
        在這里可以向外發(fā)送連接成功通知
   }else{
        否則取消連接
        [self.centralManager cancelPeripheralConnection:peripheral];
   }
}
  • 7.寫數(shù)據(jù)
//自定義寫數(shù)據(jù)的動態(tài)方法
-(void)writeDataToBle:(NSString *)instruction{
    if (self.discoveredPeripheral&&self.discoveredCharacteristic)
    {
        [self.discoveredPeripheral writeValue:[[NSData alloc] initWithBytes:[self hexStringToBytes:instruction] length:[instruction length]/2.0] forCharacteristic:self.discoveredCharacteristic type:CBCharacteristicWriteWithResponse];
    }
}

其中CBCharacteristicWriteType有兩個選擇:
1 . CBCharacteristicWriteWithResponse 接收寫操作回調(diào)
2 . CBCharacteristicWriteWithoutResponse 不接受寫操作回調(diào)
前者表示寫數(shù)據(jù)成功或者失敗都會得到回調(diào)织阳,后者則沒有。
當(dāng)選擇2的模式時候砰粹,藍(lán)牙的讀數(shù)據(jù)必須允許通知唧躲,不然讀數(shù)據(jù)的回調(diào)將沒有反應(yīng)造挽。在藍(lán)牙讀數(shù)據(jù)通知開啟,特征的屬性值包含CBCharacteristicWriteWithoutResponse,并且選擇2的方式發(fā)送數(shù)據(jù)的情況下弄痹,一旦發(fā)送數(shù)據(jù)到藍(lán)牙饭入,藍(lán)牙將通過讀數(shù)據(jù)回調(diào)返回?cái)?shù)據(jù)。
當(dāng)選擇1的模式的時候肛真,發(fā)送數(shù)據(jù)操作將進(jìn)入下面的回調(diào)方法里面谐丢,我們可以判斷發(fā)送數(shù)據(jù)的操作是否成功,如果成功可以手動調(diào)用蚓让,讀取藍(lán)牙返回?cái)?shù)據(jù)的方法來得到藍(lán)牙返回的數(shù)據(jù)
寫數(shù)據(jù)的回調(diào)

-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
   //當(dāng)錯誤為空的時候可以在這里手動調(diào)用讀數(shù)據(jù)的方法乾忱,調(diào)用該方法,程序也會在讀數(shù)據(jù)的代理里面得到藍(lán)牙返回的數(shù)據(jù)历极。
   [self.discoveredPeripheral readValueForCharacteristic: self.discoveredCharacteristic];
}
  • 8.讀數(shù)據(jù)的回調(diào)
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    if (error) {
        NSLog(@"Error: %@", [error localizedDescription]);
        return;
    }
    NSString *stringFromData = [characteristic.value description];
    //刪除字符串中的空格
    stringFromData=[stringFromData stringByReplacingOccurrencesOfString:@" " withString:@""];
    //刪除字符串中的尖括號
    stringFromData=[stringFromData stringByReplacingOccurrencesOfString:@"<" withString:@""];  
    stringFromData=[stringFromData stringByReplacingOccurrencesOfString:@">" withString:@""];
    NSLog(@"Received: %@", stringFromData);
}

附錄:

下面文章作為借鑒

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趟卸,一起剝皮案震驚了整個濱河市蹄葱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌锄列,老刑警劉巖图云,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邻邮,居然都是意外死亡竣况,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門饶囚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帕翻,“玉大人,你說我怎么就攤上這事萝风∴值В” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵规惰,是天一觀的道長睬塌。 經(jīng)常有香客問我,道長歇万,這世上最難降的妖魔是什么揩晴? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮贪磺,結(jié)果婚禮上硫兰,老公的妹妹穿的比我還像新娘。我一直安慰自己寒锚,他們只是感情好劫映,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布违孝。 她就那樣靜靜地躺著,像睡著了一般泳赋。 火紅的嫁衣襯著肌膚如雪雌桑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天祖今,我揣著相機(jī)與錄音校坑,去河邊找鬼。 笑死千诬,一個胖子當(dāng)著我的面吹牛耍目,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播大渤,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼制妄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泵三?” 一聲冷哼從身側(cè)響起耕捞,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烫幕,沒想到半個月后俺抽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡较曼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年磷斧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捷犹。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡弛饭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出萍歉,到底是詐尸還是另有隱情侣颂,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布枪孩,位于F島的核電站憔晒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蔑舞。R本人自食惡果不足惜拒担,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望攻询。 院中可真熱鬧从撼,春花似錦、人聲如沸钧栖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桐经。三九已至毁兆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阴挣,已是汗流浹背气堕。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留畔咧,地道東北人茎芭。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像誓沸,于是被迫代替她去往敵國和親梅桩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容