iOS藍(lán)牙Ble4.0開發(fā)運(yùn)動(dòng)手環(huán)耘纱,數(shù)據(jù)的交互處理

背景:

最近公司項(xiàng)目需要接運(yùn)動(dòng)手環(huán)殴玛,獲取運(yùn)動(dòng)步數(shù),設(shè)備時(shí)間翘地,重置設(shè)備時(shí)間等功能申尤,需要進(jìn)行藍(lán)牙傳輸。

前言:

1.當(dāng)前iOS中開發(fā)藍(lán)牙所運(yùn)用的系統(tǒng)庫是<CoreBluetooth/CoreBluetooth.h>衙耕。

2.藍(lán)牙外設(shè)必須為4.0及以上昧穿,否則無法開發(fā),藍(lán)牙4.0設(shè)備因?yàn)榈秃碾姵艚埽砸步凶鯞LE粤咪。

3.CoreBluetooth框架的核心其實(shí)是兩個(gè)東西,peripheral和central, 可以理解成外設(shè)和中心渴杆,就是你的蘋果手機(jī)就是中心,外部藍(lán)牙稱為外設(shè)宪塔。

4.服務(wù)和特征(service and characteristic):簡而言之磁奖,外部藍(lán)牙中它有若干個(gè)服務(wù)service(服務(wù)你可以理解為藍(lán)牙所擁有的能力),而每個(gè)服務(wù)service下?lián)碛腥舾蓚€(gè)特征characteristic(特征你可以理解為解釋這個(gè)服務(wù)的屬性)某筐。

5.Descriptor(描述)用來描述characteristic變量的屬性比搭。例如,一個(gè)descriptor可以規(guī)定一個(gè)可讀的描述南誊,或者一個(gè)characteristic變量可接受的范圍身诺,或者一個(gè)characteristic變量特定的單位蜜托。

圖示

5361561449141_.pic.jpg
5371561449196_.pic.jpg

名詞解釋:

BLE:(Bluetooth low energy)藍(lán)牙4.0設(shè)備因?yàn)榈秃碾姡?/p>

Central:中心設(shè)備,相對(duì)比較強(qiáng)大霉赡,用來連接其他外圍設(shè)備(手機(jī))橄务;

Peripheral:外圍設(shè)備,這一般就是非常小或者簡單的低功耗設(shè)備穴亏,用來提供數(shù)據(jù)蜂挪,并連接到一個(gè)更加相對(duì)強(qiáng)大的中心設(shè)備(小米手環(huán)等等等);

Services:服務(wù)嗓化,藍(lán)牙外設(shè)對(duì)外廣播的必定會(huì)有一個(gè)服務(wù)棠涮,可能也有多個(gè),服務(wù)下面包含著一些特征刺覆,服務(wù)可以理解成一個(gè)模塊的窗口严肪;

Characteristic:特征,存在于服務(wù)下面的谦屑,一個(gè)服務(wù)下面也可以存在多個(gè)特征驳糯,特征可以理解成具體實(shí)現(xiàn)功能的窗口,一般特征都會(huì)有value伦仍,也就是特征值结窘,特征是與外界交互的最小單位;

Description:描述充蓝,每個(gè)Characteristic可以對(duì)應(yīng)一個(gè)或多個(gè)Description用于描述Characteristic的信息或?qū)傩裕〞簳r(shí)不太了解)

UUID:可以理解成藍(lán)牙上的唯一標(biāo)識(shí)符(硬件上是Mac值隧枫,iOS應(yīng)該是被系統(tǒng)攔截了,所以獲取不到Mac值谓苟,相對(duì)于轉(zhuǎn)化而來是的UUID)官脓,為了區(qū)分不同的服務(wù)和特征,或者給服務(wù)和特征取名字涝焙,我們就用UUID來代表服務(wù)和特征卑笨。

流程:

1、建立一個(gè)Central Manager實(shí)例進(jìn)行藍(lán)牙管理CBCentralManagerDelegate

2仑撞、搜索外圍設(shè)備(一直目標(biāo)設(shè)備名稱可指定搜索)

3赤兴、連接外圍設(shè)備(目標(biāo)設(shè)備)CBPeripheralDelegate

4、獲得外圍設(shè)備的服務(wù)

5隧哮、獲得服務(wù)的特征(該步驟進(jìn)行特征的讀桶良、寫、通知等屬性)

6沮翔、從外圍設(shè)備讀數(shù)據(jù)

7陨帆、給外圍設(shè)備發(fā)送數(shù)據(jù)

1.屬性

// 外圍設(shè)備(一般是手機(jī))設(shè)備
@property (nonatomic, strong) CBCentralManager *mCentral;
// 外設(shè)設(shè)備
@property (nonatomic, strong) CBPeripheral *mPeripheral;
// 特征值
@property (nonatomic, strong) CBCharacteristic *mCharacteristic;
// 服務(wù)
@property (nonatomic, strong) CBService *mService;

2.協(xié)議<CBCentralManagerDelegate, CBPeripheralDelegate>

2.1. CBCentralManagerDelegate----設(shè)備鏈接需要的協(xié)議
/**
*  首先設(shè)備管理的類初始化,一旦初始化完成之后,就會(huì)遵循CBCentralManagerDelegate協(xié)議
*/
_mCentral = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
@required
/**
*  藍(lán)牙的所有狀態(tài)疲牵,根據(jù)狀態(tài)進(jìn)行相關(guān)操作
*  開啟--掃描
*  未開啟/不支持藍(lán)牙等--友好提示
typedef NS_ENUM(NSInteger, CBCentralManagerState) {
    CBCentralManagerStateUnknown = CBManagerStateUnknown,
    CBCentralManagerStateResetting = CBManagerStateResetting,
    CBCentralManagerStateUnsupported = CBManagerStateUnsupported,
    CBCentralManagerStateUnauthorized = CBManagerStateUnauthorized,
    CBCentralManagerStatePoweredOff = CBManagerStatePoweredOff,
    CBCentralManagerStatePoweredOn = CBManagerStatePoweredOn,
} NS_DEPRECATED(10_7, 10_13, 5_0, 10_0, "Use CBManagerState instead");
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central;

@optional
/**
*  發(fā)現(xiàn)外設(shè)藍(lán)牙設(shè)備的方法
*  <這里進(jìn)行會(huì)搜索到周邊具有藍(lán)牙功能的設(shè)備承二,可以通過對(duì)具體藍(lán)牙名稱或者已知藍(lán)牙名稱前綴進(jìn)行篩選你要的藍(lán)牙設(shè)備,并且目標(biāo)設(shè)備在這里遵循CBPeripheralDelegate 協(xié)議纲爸,進(jìn)行搜索設(shè)備的services>
*      [self.mCentral stopScan];          // 停止掃描
        self.mPeripheral = peripheral;  
        // CBPeripheralDelegate
        self.mPeripheral.delegate = self;  // 遵循協(xié)議
        [self.mCentral connectPeripheral:peripheral options:nil]; // 連接外設(shè)-->掃描services
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI;

/**
*  中心管理者(連接外設(shè))連接成功
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;

/**
*  中心管理者(連接外設(shè))連接失敗
*/
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral;

/**
*  中心管理者(外設(shè)丟失)連接丟失
*/
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;

2.2 CBPeripheralDelegate
/**
*  掃描目標(biāo)外設(shè)services回調(diào)
*  [peripheral discoverCharacteristics:nil forService:service]; // 掃描service下面的特征值characteristics
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error;

/**
*  獲取特征值characteristics和描述
*  這里可以查詢到具體characteristic屬性properties(枚舉類型)的讀亥鸠,寫,通知缩焦,根據(jù)UUID(需要跟硬件工程師協(xié)商統(tǒng)一的)
*  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(10_9, 6_0)   = 0x100,
    CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(10_9, 6_0) = 0x200
};
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error;

/**
*  讀取特征中的值和描述:更新特征值的時(shí)候調(diào)用读虏,可以理解為獲取藍(lán)牙返回的數(shù)據(jù)(需要的所有數(shù)據(jù)均在這里進(jìn)行處理)
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;

/**
*  狀態(tài)改變和發(fā)現(xiàn)描述
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;

/**
*  發(fā)現(xiàn)外設(shè)的特征的描述數(shù)組
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error;

/**
*  寫入數(shù)據(jù)成功與否的回調(diào)
*/
-(void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;


描述

  • 我們是從手環(huán)中獲取到運(yùn)動(dòng)步數(shù),怎么獲取袁滥,如何接收數(shù)據(jù)盖桥,怎么處理數(shù)據(jù)?這是開發(fā)前就需要了解的题翻。通常硬件工程師會(huì)制定一個(gè)藍(lán)牙數(shù)據(jù)處理協(xié)議揩徊,就稱之為藍(lán)牙協(xié)議吧,因?yàn)樗P(guān)系著你能否獲取到你想要的數(shù)據(jù)嵌赠,導(dǎo)致能否按時(shí)完成項(xiàng)目塑荒。

  • 我們的藍(lán)牙協(xié)議是這樣的


    WechatIMG535.jpeg
  • 讀懂藍(lán)牙協(xié)議,進(jìn)行指令發(fā)送(按照工程師給的藍(lán)牙協(xié)議拼接指令數(shù)組)

// 獲取總步數(shù)指令
    Byte b[] = {0xC6};
    // 獲取每個(gè)小時(shí)步數(shù)指令
    Byte b2[] = {0xC4, 0x03, 0x01, 0x8, 0x03};
    NSData *data = [NSData dataWithBytes:&b length:sizeof(b)];
    NSData *data2 = [NSData dataWithBytes:&b2 length:sizeof(b2)];
//    NSLog(@"%@", data);
//    [self.mPeripheral writeValue:data forCharacteristic:self.mCharacteristic type:CBCharacteristicWriteWithResponse];
    [self.mPeripheral writeValue:data2 forCharacteristic:self.mCharacteristic type:CBCharacteristicWriteWithResponse];
  • 數(shù)據(jù)的處理姜挺,這里根據(jù)不同的硬件工程師規(guī)定的藍(lán)牙協(xié)議進(jìn)行自行處理數(shù)據(jù)哈(根據(jù)工程師給的藍(lán)牙協(xié)議按照對(duì)應(yīng)字節(jié)進(jìn)行解析16進(jìn)制數(shù)據(jù))
    首先看看硬件工程師返回給我們的數(shù)據(jù):
A*小于20字節(jié)的返回一次就夠了

如:<29071306 1c090303 05130000 00000000 00000000>

B*大于20字節(jié)的分段接受齿税,每次20字節(jié)

如:<24281306 18080034 00000000 02fb0000 0000006d>
<00000000 00000000 00000000 00000000 00000000>
<0000a5>
上面數(shù)據(jù)的解析思路(以我們的協(xié)議為參考,具體情況按照你們的來):
24281306 1808 解析:命令頭24炊豪,數(shù)據(jù)長度0x28凌箕,然后是19年6月24日8點(diǎn)。词渤。
數(shù)據(jù)是每6個(gè)byte為一組牵舱,前兩個(gè)是步數(shù),比如 0034 00000000表示 0x0034步缺虐,高兩bit是用來表示步數(shù)或是睡眠芜壁,00表示步數(shù),01表示睡眠高氮,步數(shù)用14bit表示

圖形化解析
WechatIMG553.jpeg

開發(fā)這種東西首先要理解流程慧妄,其次才是代碼,代碼千千萬剪芍,萬變不離其宗腰涧,因?yàn)閷戇@篇文章的時(shí)候還在開發(fā)公司的項(xiàng)目,而且離交付項(xiàng)目沒多少時(shí)間了紊浩,所以代碼寫的只是為了調(diào)試,都有備注的,各位看官還請(qǐng)手下留情7凰7驯恕!

如果發(fā)現(xiàn)問題還請(qǐng)及時(shí)指出口芍,與君共勉9坎!鬓椭!

如果有需求颠猴,可以直接與本人聯(lián)系,QQ:1749281699

最后再次發(fā)下Demo

附加:
可以使用以下測試軟件進(jìn)行測試:
LightBlue
nrf connect

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末小染,一起剝皮案震驚了整個(gè)濱河市翘瓮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裤翩,老刑警劉巖资盅,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異踊赠,居然都是意外死亡呵扛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門筐带,熙熙樓的掌柜王于貴愁眉苦臉地迎上來今穿,“玉大人,你說我怎么就攤上這事伦籍±渡梗” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵鸽斟,是天一觀的道長拔创。 經(jīng)常有香客問我,道長富蓄,這世上最難降的妖魔是什么剩燥? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮立倍,結(jié)果婚禮上灭红,老公的妹妹穿的比我還像新娘。我一直安慰自己口注,他們只是感情好变擒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寝志,像睡著了一般娇斑。 火紅的嫁衣襯著肌膚如雪策添。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天毫缆,我揣著相機(jī)與錄音唯竹,去河邊找鬼。 笑死苦丁,一個(gè)胖子當(dāng)著我的面吹牛浸颓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播旺拉,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼产上,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛾狗?” 一聲冷哼從身側(cè)響起晋涣,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淘太,沒想到半個(gè)月后姻僧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒲牧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年撇贺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冰抢。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡松嘶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挎扰,到底是詐尸還是另有隱情翠订,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布遵倦,位于F島的核電站尽超,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏梧躺。R本人自食惡果不足惜似谁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掠哥。 院中可真熱鬧巩踏,春花似錦、人聲如沸续搀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽禁舷。三九已至彪杉,卻和暖如春毅往,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背在讶。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工煞抬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人构哺。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像战坤,于是被迫代替她去往敵國和親曙强。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354