1. 程式人生 > >iOS藍芽開發:藍芽連線和資料讀寫

iOS藍芽開發:藍芽連線和資料讀寫

當下藍芽開發可謂是越來越火,不論是智慧穿戴的興起還是藍芽傢俱,車聯網藍芽等等,很多同學也會接觸到藍芽的專案,我從事藍芽開發也有一段時間了,經手了兩個專案。廢話不多說了,先向大家簡單的介紹有關藍芽開發的知識。藍芽低能耗(BLE),以下介紹的都是圍繞iOS的框架展開的。

藍芽開發分為中心者模式和管理者模式:1.常用的(其實99.99%)就是使用中心者模式作為開發,就是我們手機作為主機,連線藍芽外設;2.管理者模式,這個基本用到的比較少,我們手機自己作為外設,自己建立服務和特徵,然後有其他的裝置連線我們的手機。

在做藍芽開發之前,最好先了解一些概念:
服務(services):藍芽外設對外廣播的必定會有一個服務,可能也有多個,服務下面包含著一些特徵,服務可以理解成一個模組的視窗;
特徵(characteristic):存在於服務下面的,一個服務下面也可以存在多個特徵,特徵可以理解成具體實現功能的視窗,一般特徵都會有value,也就是特徵值,特徵是與外界互動的最小單位;
UUID:可以理解成藍芽上的唯一識別符號(硬體上肯定不是這個意思,但是這樣理解便於我們開發),為了區分不同的服務和特徵,或者給服務和特徵取名字,我們就用UUID來代表服務和特徵。

藍芽連線可以大致分為以下幾個步驟
1.建立一個Central Manager例項進行藍芽管理
2.搜尋外圍裝置
3.連線外圍裝置
4.獲得外圍裝置的服務
5.獲得服務的特徵
6.從外圍裝置讀資料
7.給外圍裝置傳送資料
其他:提醒

首先我們先匯入系統的BLE的框架

import

必須遵守2個協議

/* 中心管理者 /
@property (nonatomic, strong) CBCentralManager *cMgr;

/* 連線到的外設 /
@property (nonatomic, strong) CBPeripheral *peripheral;

1.建立一個Central Manager例項進行藍芽管理

-(CBCentralManager *)cmgr
{
if (!_cmgr) {
_cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
return _cMgr;
}

//只要中心管理者初始化 就會觸發此代理方法 判斷手機藍芽狀態
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) {
case 0:
NSLog(@”CBCentralManagerStateUnknown”);
break;
case 1:
NSLog(@”CBCentralManagerStateResetting”);
break;
case 2:
NSLog(@”CBCentralManagerStateUnsupported”);//不支援藍芽
break;
case 3:
NSLog(@”CBCentralManagerStateUnauthorized”);
break;
case 4:
{
NSLog(@”CBCentralManagerStatePoweredOff”);//藍芽未開啟
}
break;
case 5:
{
NSLog(@”CBCentralManagerStatePoweredOn”);//藍芽已開啟
// 在中心管理者成功開啟後再進行一些操作
// 搜尋外設
[self.cMgr scanForPeripheralsWithServices:nil // 通過某些服務篩選外設
options:nil]; // dict,條件
// 搜尋成功之後,會呼叫我們找到外設的代理方法
// - (void)centralManager:(CBCentralManager )central didDiscoverPeripheral:(CBPeripheral

)peripheral advertisementData:(NSDictionary )advertisementData RSSI:(NSNumber )RSSI; //找到外設
}
break;
default:
break;
}
}

2.搜尋外圍裝置 (我這裡為了舉例,採用了自己身邊的一個手環)

// 發現外設後呼叫的方法
- (void)centralManager:(CBCentralManager *)central // 中心管理者
didDiscoverPeripheral:(CBPeripheral *)peripheral // 外設
advertisementData:(NSDictionary *)advertisementData // 外設攜帶的資料
RSSI:(NSNumber *)RSSI // 外設發出的藍芽訊號強度
{
//NSLog(@”%s, line = %d, cetral = %@,peripheral = %@, advertisementData = %@, RSSI = %@”, FUNCTION, LINE, central, peripheral, advertisementData, RSSI);

/*
 peripheral = , advertisementData = {
 kCBAdvDataChannel = 38;
 kCBAdvDataIsConnectable = 1;
 kCBAdvDataLocalName = OBand;
 kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;
 kCBAdvDataServiceUUIDs =     (
 FEE7
 );
 kCBAdvDataTxPowerLevel = 0;
 }, RSSI = -55
 根據列印結果,我們可以得到運動手環它的名字叫 OBand-75

 */

// 需要對連線到的外設進行過濾
// 1.訊號強度(40以上才連線, 80以上連線)
// 2.通過裝置名(裝置字串字首是 OBand)
// 在此時我們的過濾規則是:有OBand字首並且訊號強度大於35
// 通過列印,我們知道RSSI一般是帶-的

if ([peripheral.name hasPrefix:@"OBand"]) {
    // 在此處對我們的 advertisementData(外設攜帶的廣播資料) 進行一些處理

    // 通常通過過濾,我們會得到一些外設,然後將外設儲存到我們的可變陣列中,
    // 這裡由於附近只有1個運動手環, 所以我們先按1個外設進行處理

    // 標記我們的外設,讓他的生命週期 = vc
    self.peripheral = peripheral;
    // 發現完之後就是進行連線
    [self.cMgr connectPeripheral:self.peripheral options:nil];
    NSLog(@"%s, line = %d", __FUNCTION__, __LINE__);
}

}

3.連線外圍裝置

// 中心管理者連線外設成功
- (void)centralManager:(CBCentralManager *)central // 中心管理者
didConnectPeripheral:(CBPeripheral *)peripheral // 外設
{
NSLog(@”%s, line = %d, %@=連線成功”, FUNCTION, LINE, peripheral.name);
// 連線成功之後,可以進行服務和特徵的發現

//  設定外設的代理
self.peripheral.delegate = self;

// 外設發現服務,傳nil代表不過濾
// 這裡會觸發外設的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
[self.peripheral discoverServices:nil];

}
// 外設連線失敗
- (void)centralManager:(CBCentralManager )central didFailToConnectPeripheral:(CBPeripheral )peripheral error:(NSError *)error
{
NSLog(@”%s, line = %d, %@=連線失敗”, FUNCTION, LINE, peripheral.name);
}

// 丟失連線
- (void)centralManager:(CBCentralManager )central didDisconnectPeripheral:(CBPeripheral )peripheral error:(NSError *)error
{
NSLog(@”%s, line = %d, %@=斷開連線”, FUNCTION, LINE, peripheral.name);
}

4.獲得外圍裝置的服務 & 5.獲得服務的特徵

// 發現外設服務裡的特徵的時候呼叫的代理方法(這個是比較重要的方法,你在這裡可以通過事先知道UUID找到你需要的特徵,訂閱特徵,或者這裡寫入資料給特徵也可以)
- (void)peripheral:(CBPeripheral )peripheral didDiscoverCharacteristicsForService:(CBService )service error:(NSError *)error
{
NSLog(@”%s, line = %d”, FUNCTION, LINE);

for (CBCharacteristic *cha in service.characteristics) {
    //NSLog(@"%s, line = %d, char = %@", __FUNCTION__, __LINE__, cha);

}

}

6.從外圍裝置讀資料

// 更新特徵的value的時候會呼叫 (凡是從藍芽傳過來的資料都要經過這個回撥,簡單的說這個方法就是你拿資料的唯一方法) 你可以判斷是否
- (void)peripheral:(CBPeripheral )peripheral didUpdateValueForCharacteristic:(CBCharacteristic )characteristic error:(NSError *)error
{
NSLog(@”%s, line = %d”, FUNCTION, LINE);
if (characteristic == @”你要的特徵的UUID或者是你已經找到的特徵”) {
//characteristic.value就是你要的資料
}
}

7.給外圍裝置傳送資料(也就是寫入資料到藍芽)
這個方法你可以放在button的響應裡面,也可以在找到特徵的時候就寫入,具體看你業務需求怎麼用啦

[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];//第一個引數是已連線的藍芽裝置 ;第二個引數是要寫入到哪個特徵; 第三個引數是通過此響應記錄是否成功寫入

// 需要注意的是特徵的屬性是否支援寫資料
- (void)yf_peripheral:(CBPeripheral )peripheral didWriteData:(NSData )data forCharacteristic:(nonnull CBCharacteristic *)characteristic
{
/*
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
CBCharacteristicPropertyBroadcast = 0x01,
CBCharacteristicPropertyRead = 0x02,
CBCharacteristicPropertyWriteWithoutResponse = 0x04,
CBCharacteristicPropertyWrite = 0x08,
CBCharacteristicPropertyNotify = 0x10,
CBCharacteristicPropertyIndicate = 0x20,
CBCharacteristicPropertyAuthenticatedSignedWrites = 0x40,
CBCharacteristicPropertyExtendedProperties = 0x80,
CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x100,
CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0) = 0x200
};

 打印出特徵的許可權(characteristic.properties),可以看到有很多種,這是一個NS_OPTIONS的列舉,可以是多個值
 常見的又read,write,noitfy,indicate.知道這幾個基本夠用了,前倆是讀寫許可權,後倆都是通知,倆不同的通知方式
 */

// NSLog(@”%s, line = %d, char.pro = %d”, FUNCTION, LINE, characteristic.properties);
// 此時由於列舉屬性是NS_OPTIONS,所以一個列舉可能對應多個型別,所以判斷不能用 = ,而應該用包含&
}

其他:提醒
有那麼多的特徵,我們怎麼知道哪些特徵是用來讀資料的,哪些是用來寫入的,哪些是需要訂閱之後再讀的呢?
如果你們硬體工程師事先告訴你了,或者有完成的開發文件,那麼就可以直接知道了,否則你就需要自己去檢視特徵的屬性,推介可以使用下第三方的app——LightBlue,讓你更能清楚的看到你藍芽裡面的服務,特徵,特徵的屬性。

其他後續有關文章,我會慢慢整理髮出來,有需要的同學可以留下郵箱,我這裡有視訊教程,我也可以回答相關的問題,有錯誤的地方可以幫忙指出來呦!

相關推薦

iOS開發連線資料

當下藍芽開發可謂是越來越火,不論是智慧穿戴的興起還是藍芽傢俱,車聯網藍芽等等,很多同學也會接觸到藍芽的專案,我從事藍芽開發也有一段時間了,經手了兩個專案。廢話不多說了,先向大家簡單的介紹有關藍芽開發的知識。藍芽低能耗(BLE),以下介紹的都是圍繞iOS的框架展開

iOS開發連線資料

       藍芽開發說簡單也簡單,說不簡單也有點難,開發人員在首次開發藍芽前首先需要搞清楚藍芽開發的概念,還要了解掌握藍芽開發的一整套流程,這樣才能快速上手開發藍芽。       藍芽開發分為兩種模式:管理者模式和中心者模式。管理者模式基本很少用到,相當於iPhone手機

030Cetus中間件MHA分離

sample ignore 分離 dir sse binary 順序 cpu tar zxvf 030:Cetus中間件和MHA讀寫分離 一、主機環境 虛擬機配置 CPU 內存 硬盤 OS版本 MySQL版本 MHA版本 Cetus版本 2-core 4

1 android開發---與模組進行通訊

原文地址 http://www.cnblogs.com/wenjiang/p/3200138.html 近半個月來一直在搞android藍芽這方面,主要是專案需要與藍芽模組進行通訊。開頭的進展很順利,但因為藍芽模組不在我這裡,所以只能用手機測試。一開頭就發現手機的藍芽

android開發-與模組通訊

因為我馬上要離職了,在很多官網上看到招聘android基本都要會藍芽開發,wifi的經驗,所以就來學習下藍芽! 於是,我得到了很好的教訓:請確保專案中的最關鍵因素是否在我們的掌握中。像是藍芽模組這種東西,應該今早催促對方拿過來才是,而不是自己一個人在那邊瞎搞。 嘮叨話就先到

Android 開發連印表機。

public synchronized void connect(String macAddress, BluetoothDevice device) { if (mThread != null) { mThread.interrupt(); m

Android開發模組進行通訊(基於eclipse)

public class ComminuteActivity extends Activity { private BluetoothReceiver receiver; private BluetoothAdapter bluetoothAdapter; private Lis

【視頻】零基礎學Android開發牙聊天室APP(一)

android入門 mod http 開發 org 薪資 get target 下載 零基礎學Android開發:藍牙聊天室APP第一講 1. Android介紹與環境搭建:史上最高效Android入門學習 1.1 Google的大小戰略 1.2 物聯網與雲計算 1.3

基於Swift的iOS應用程式開發通過UITextFieldDelegate快速理解Delegate事件代理

// // 關於文字輸入框的事件代理,摘錄蘋果開發者中心的官方解釋如下: //*******************************************************************************************// //* To understand wh

Java Web開發Spring MVC連線 MongoDB啟動使用者名稱密碼

預先準備 配置版本 spring MVC 4.1.1 spring-data-mongodb 1.60 mongodb3.2.1 springMVC開發環境已經配好 mongodb新增使用者 注意事項:mongodb3.0版本後密碼加密有兩種方式,MONGODB-CR兩種方

iOS App開發最好的設計開發工具

眾所周知,iOS是一個作業系統,由蘋果公司設計與開發而且依靠蘋果硬體執行,如iPhone、iPad和iPod。設計該作業系統最初的想法是開發一個介面,可在小屏手機上較為容易地執行應用程式。因此iPhone派上用場。像其他的任意一款移動作業系統,iPhone提供使

安卓開發SmartImageView簡單實現應用

overload override ans geb actor dsta pub pac 獲取 通常從服務器端獲取的圖片是URL地址,如果簡單地通過URL地址獲取圖片? 有一個開源項目:SmartImageView,做到了這個功能,同時還有其他功能,下載不便,過於龐大 這裏

Android OpenSL ES 開發Android OpenSL 介紹開發流程說明

ror logic ogr activity engine eid 優化 als 分享 一、Android OpenSL ES 介紹 OpenSL ES (Open Sound Library for Embedded Systems)是無授權費、跨平臺、針對嵌入式系統精心

基礎知識概念(1)Socket 長連線連線的概念

1.短連線 連線->傳輸資料->關閉連線     HTTP是無狀態的,瀏覽器和伺服器每進行一次HTTP操作,就建立一次連線,但任務結束後就中斷連線。短連線是指SOCKET建立連線後 ,傳送後或接收完資料後,就馬上斷開連線。 2.長連線

SpringBoot專案開發(二十二)SpringBoot MongoDB實現副本集(分離)

1.MongoDB可以單庫、主從(官方現已不推薦)、副本集、分片加副本集,通過分片加副本集可以組成龐大的資料儲存叢集,而大部分專案使用副本集就能滿足需求了 2.MongoDB副本集(Replica Set):有自動故障恢復功能的主從叢集,有一個Primary節點和一個或多個Secon

Android開發(2)資料儲存之一SharedPrefrences檔案

一、資料儲存 本文主要講前兩種儲存方式,其中檔案讀寫只記錄Internal Storage方式 1. SharedPrefrences方式 輕量級NVP方式儲存,以XML的檔案方式儲存,適合少量資料的儲存。 NVP:Name/Value pair, 名稱/值 對。 2.

Windows網路程式設計(四)建立UDP連線收發訊息

UDP訊息的傳送和接收需要UDP連線,所以,上面的TCP連線已經不適用了,具體的區別主要有: 建立Socket時引數不同建立服務端時不需要listen和accept操作建立客戶端時不需要connect操作伺服器需要bind操作,客戶端不需要。 傳送和接收UDP訊息要用到sendt

Windows網路程式設計(三)建立TCP連線收發訊息

先看服務端: // ConsoleApplication3.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #define _WINSOCK_DEPRECATED_NO_WARNINGS //這個宣告要在stdafx.h的後面,但要

kotlin安卓開發fragment向activity傳遞資料通過handler,設定回撥方法

從activity向fragment傳遞就比較方便了,直接用: fg.arguments = arguments 現在看看怎麼從fragment向activity傳遞資料。 比如說,我們在一個ViewPage裡面設定了若干個fragment,fragment裡面有一個按鈕,提交相關

Python web開發Flask的URL檢視

URL與檢視 URL與函式的對映: 從之前的helloworld.py檔案中,我們已經看到,一個URL要與執行函式進行對映,使用的是@app.route裝飾器。@app.route裝飾器中,可以指定URL的規則來進行更加詳細的對映,比如現在要對映一個文章詳情的URL,文章詳情的URL