iOS開發 之 可穿戴設備 藍牙4.0 BLE 開發

1 前言

當前有越來越多的可穿戴設備使用了藍牙4.0 BLE(Bluetooth Low Energy)。對于iOS開發而言,Apple之前專門推出CoreBluetooth的Framework來支持BLE的開發。對于硬件開發有了解的朋友應該知道,在之前使用低版本的藍牙的設備,要連接到iOS設備上,需要注冊MFI,擁有MFI協議才能進行相應的開發。如果大家關注我之前對LEGO EV3的研究,就可以發現,EV3是使用了藍牙2.1,因此需要MFI協議來進行開發。

本文將一步一步講解如何使用CoreBluetooth框架來與各種可穿戴設備進行通信,使用 小米手環 來進行基本的測試。?
小米手環

2 開發環境

1 Macbook Pro Mac OS X 10.10?
2 Xcode 6.3.2?
3 iPhone 5s v8.1?
4 小米手環

3 基本流程

要開發藍牙,需要對整個通訊過程有個基本了解。這里我摘錄一些Apple官方的文檔Core Bluetooth Programming Guide的圖片來加以說明。這個文檔其實對于開發的流程寫的是非常的清楚,大家最好可以看一下。

3.1 可穿戴設備與iOS互聯方式

可穿戴設備與iOS互聯

從上面這幅圖可以看到,我們的iOS設備是Central,用來接收數據和發送命令,而外設比如小米手環是Peripheral,向外傳輸數據和接收命令。我們要做的就是通過Central來連接Peripheral,然后實現數據的接收和控制指令的發送。在做到這一步之后,再根據具體的硬件,對接收到的數據進行parse解析。

3.2 可穿戴設備藍牙的數據結構

可穿戴設備藍牙的數據結構

這里用的是心率設備來做說明,每個外設Peripheral都有對應的服務Service,比如這里是心率Service。一個外設可以有不止一個s、Service。每個service里面可以有多個屬性Characteristic,比如這里有兩個Characteristic,一個是用來測量心率,一個是用來定位位置。

那么很關鍵的一點是每個Service,每個Characteristic都是用UUID來確定的。UUID就是每個Service或Characteristic的identifier。

大家可以在iPhone上下載LightBlue這個應用。可以在這里查看一些設備的UUID。?
LightBlue

在實際使用中,我們都是要通過UUID來獲取數據。這點非常重要。?
在CoreBluetooth中,其具體的數據結構圖如下:?
這里寫圖片描述

4 Step-By-Step 上手BLE開發

4.1 Step 1 創建CBCentralManager

從名字上大家可以很清楚的知道,這個類是用來管理BLE的。我們也就是通過這個類來實現連接。

先創建一個:

@property (nonatomic,strong) CBCentralManager *centralManager;dispatch_queue_t centralQueue = dispatch_queue_create("com.manmanlai", DISPATCH_QUEUE_SERIAL); self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue];
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

然后關鍵在于CBCentralManagerDelegate的使用。這個之后再講。

4.2 Step 2 尋找CBPeripheral外設

有了CBCentralManager,接下來就是尋找CBPeripheral外設,方法很簡單:

[self.centralManager scanForPeripheralsWithServices:@[] options:nil];
  • 1
  • 1

這里的Service就是對應的UUID,如果為空,這scan所有service。

4.3 Step 3 連接CBPeripheral

在上一步中,如果找到了設備,則CBCentralManager的delegate會調用下面的方法:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{NSLog(@"name:%@",peripheral); if (!peripheral || !peripheral.name || ([peripheral.name isEqualToString:@""])) { return; } if (!self.peripheral || (self.peripheral.state == CBPeripheralStateDisconnected)) { self.peripheral = peripheral; self.peripheral.delegate = self; NSLog(@"connect peripheral"); [self.centralManager connectPeripheral:peripheral options:nil]; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我們在這里創建了一個CBPeripheral的對象,然后直接連接?
CBPeripheral的對象也需要設置delegate.

4.4 Step 4 尋找Service

如果Peripheral連接成功的話,就會調用delegate的方法:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{if (!peripheral) {return;}[self.centralManager stopScan]; NSLog(@"peripheral did connect"); [self.peripheral discoverServices:nil]; } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

我們這里先停止Scan,然后讓Peripheral外設尋找其Service。

4.5 Step 5 尋找Characteristic

找到Service后會調用下面的方法:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{NSArray *services = nil;if (peripheral != self.peripheral) { NSLog(@"Wrong Peripheral.\n"); return ; } if (error != nil) { NSLog(@"Error %@\n", error); return ; } services = [peripheral services]; if (!services || ![services count]) { NSLog(@"No Services"); return ; } for (CBService *service in services) { NSLog(@"service:%@",service.UUID); [peripheral discoverCharacteristics:nil forService:service]; } } 
  • 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
  • 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

我們根據找到的service尋找其對應的Characteristic。

4.6 Step 6 找到Characteristic后讀取數據

找到Characteristic后會調用下面的delegate方法:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{NSLog(@"characteristics:%@",[service characteristics]);NSArray *characteristics = [service characteristics]; if (peripheral != self.peripheral) { NSLog(@"Wrong Peripheral.\n"); return ; } if (error != nil) { NSLog(@"Error %@\n", error); return ; } self.characteristic = [characteristics firstObject]; //[self.peripheral readValueForCharacteristic:self.characteristic]; [self.peripheral setNotifyValue:YES forCharacteristic:self.characteristic];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

這里我們可以使用readValueForCharacteristic:來讀取數據。如果數據是不斷更新的,則可以使用setNotifyValue:forCharacteristic:來實現只要有新數據,就獲取。

4.7 Step 7 處理數據

讀到數據后會調用delegate方法:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{NSData *data = characteristic.value;// Parse data ...}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.8 Step 8 向設備寫數據

這個很簡單,只要使用:

[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
  • 1
  • 1

data是NSData類型。

5 實驗

使用小米手環實驗,得到如下結果:

2015-06-10 16:52:31.607 KetherDemo[13786:1792995] scaning device 2015-06-10 16:52:33.474 KetherDemo[13786:1793032] name:<CBPeripheral: 0x1700e4380, identifier = 6FF833E3-93C1-28C6-CBC0-74A706AAAE31, name = LS_SCA16, state = disconnected> 2015-06-10 16:52:33.475 KetherDemo[13786:1793032] connect peripheral 2015-06-10 16:52:37.538 KetherDemo[13786:1793031] peripheral did connect 2015-06-10 16:52:37.984 KetherDemo[13786:1793031] service:FEE7 2015-06-10 16:52:37.985 KetherDemo[13786:1793031] service:Device Information 2015-06-10 16:52:38.099 KetherDemo[13786:1793032] characteristics:( "<CBCharacteristic: 0x17409c250, UUID = FEC8, properties = 0x20, value = (null), notifying = NO>", "<CBCharacteristic: 0x17409c200, UUID = FEC7, properties = 0x8, value = (null), notifying = NO>" ) 2015-06-10 16:52:38.100 KetherDemo[13786:1793032] Kether did connect 2015-06-10 16:52:38.101 KetherDemo[13786:1793032] Kether did connect 2015-06-10 16:52:38.280 KetherDemo[13786:1793031] characteristics:( "<CBCharacteristic: 0x17009f270, UUID = Manufacturer Name String, properties = 0x2, value = (null), notifying = NO>", "<CBCharacteristic: 0x17009f2c0, UUID = Model Number String, properties = 0x2, value = (null), notifying = NO>", "<CBCharacteristic: 0x17009f310, UUID = Serial Number String, properties = 0x2, value = (null), notifying = NO>", "<CBCharacteristic: 0x17009eb90, UUID = Hardware Revision String, properties = 0x2, value = (null), notifying = NO>", "<CBCharacteristic: 0x17009f0e0, UUID = Firmware Revision String, properties = 0x2, value = (null), notifyi`` = NO>", 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

6 小結

通過上面的方法,我們就可以輕松的對BLE進行開發。實際上比想象的要簡單。

轉載于:https://www.cnblogs.com/liaolijun/p/6689858.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372437.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372437.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372437.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

將Java服務公開為Web服務

本教程解決了開發人員面臨的最實際的情況。 大多數時候&#xff0c;我們可能需要將某些現有服務公開為Web服務。 在項目生命周期的不同階段可能會遇到這種情況。 如果這是初始階段&#xff0c;那么您幾乎是安全的&#xff0c;您可以為此做好充分的準備。 但是&#xff0c;將要發…

git服務器維護 備份,gitlab服務運維,備份與恢復 - 橙子檸檬's Blog

gitlab服務運維工作Gitlab-ctl 使用gitlab-ctl start #啟動服務gitlab-ctl stop #停止服務gitlab-ctl restart #重啟服務檢查服務的日志信息gitlab-ctl tail redis #檢查redis的日志gitlab-ctl tail postgresql #…

angular js實現開關效果

功能&#xff1a;實現點擊排序&#xff0c;再點擊排倒序。 實現方法如下 方法一&#xff1a;定義變量實現點擊切換true或false&#xff0c;代碼為&#xff1a; $scope.lidata [ {"name":"Terry","age":12}, {&qu…

使用TestNG的彈簧測試支持

TestNG是一個測試框架&#xff0c;旨在涵蓋所有類別的測試&#xff1a;單元&#xff0c;功能&#xff0c;端到端&#xff0c;集成等。 它包括許多功能&#xff0c;例如靈活的測試配置&#xff0c;對數據驅動測試的支持&#xff08;使用DataProvider&#xff09;&#xff0c;強大…

Entity Framework - 理清關系 - 基于外鍵關聯的單向一對一關系

注&#xff1a;本文針對的是 Entity Framework Code First 場景。 之前寫過三篇文章試圖理清Entity Framework中的一對一關系&#xff08;單相思&#xff08;單向一對一&#xff09;, 兩情相悅&#xff08;雙向一對一&#xff09;, 兩情相悅-續&#xff09;&#xff0c;但當時理…

微信社交小程序服務器,Day12-微信小程序實戰-交友小程序-搭建服務器與上傳文件到后端...

要搞一個小型的cms內容發布系統因為小程序上線之后&#xff0c;直接對數據庫進行操作的話&#xff0c;慧出問題的&#xff0c;所以一般都會做一個管理系統&#xff0c;讓工作人員通過這個管理系統來對這個數據庫進行增刪改查微信小程序其實給我們提供了這樣的能力了(也就是可以…

java go

熟練掌握java技術&#xff0c;對多線程、數據結構有清晰的認識&#xff1b; 熟悉MySQL/Oracle數據庫&#xff0c;熟悉關系數據庫應用設計開發&#xff1b; 熟悉Spring/MyBatis/Freemarker等一種或者多種框架&#xff1b; java基礎扎實&#xff0c;熟練掌握目前主流的開源框架&a…

了解如何解決OSGI捆綁包

我想回顧一下OSGI包如何解決并使用Apache Karaf進行演示。 Karaf是基于Apache Felix內核的功能齊全的OSGI容器&#xff0c;并且是Apache ServiceMix集成容器的基石。 對于第一部分&#xff0c;我將討論OSGI框架如何解決捆綁包。 在第二部分中&#xff0c;我將使用Apache Karaf演…

文件共享服務器imac,iMac怎么在網絡上共享設備windows文件夾和服務 | MOS86

本章通過向您展示如何在網絡和Mac和Windows計算機之間共享文件&#xff0c;文件夾和設備&#xff0c;幫助您充分利用您的iMac網絡連接。→使用Macs共享文件和文件夾使用AirDrop和文件共享→與Windows 7計算機共享文件→設置共享權限→使用共享表快速在線共享文件→共享和訪問網…

【轉】 簡單理解Socket

題外話 前幾天和朋友聊天&#xff0c;朋友問我怎么最近不寫博客了&#xff0c;一個是因為最近在忙著公司使用的一些控件的開發&#xff0c;瀏覽器兼容性搞死人&#xff1b;但主要是因為這段時間一直在看html5的東西&#xff0c;看到web socket時覺得很有意思&#xff0c;動手寫…

.NET基礎

.NET C# ASP.NET關系&#xff1a;.NET是一個平臺&#xff0c;提供程序運行的虛擬機環境和類庫。 C#是.Net平臺上的一種語言&#xff0c;其他語言還有VB.NET PowerShell等。 ASP.NET是在.NET下的網站開發技術。 安裝.NET FrameWork就可以運行。VS集成安裝了.NET FrameWork. 控制…

業務活動監視器(BAM)2.0帶來的革命

生產兼具精益和企業價值的中間件是一項艱巨的工作。 它要么不存在&#xff0c;要么需要創新的思維&#xff08;很多&#xff09;&#xff0c;并且需要在實現中反復進行。 業務風險很大&#xff0c;但是如果您做對了&#xff0c;它就會使您領先于其他任何公司。 這就是為什么我們…

oracle銷售服務器嗎,oracle 服務器 版本

oracle 服務器 版本 內容精選換一換Atlas 800 訓練服務器(型號 9010)安裝上架、服務器基礎參數配置、安裝操作系統等操作請參見《Atlas 800 訓練服務器 用戶指南 (型號9010)》。Atlas 800 訓練服務器(型號 9010)適配操作系統如表1所示。請參考表2下載驅動和固件包。Atlas 800 訓…

Vue組件間通信:一個例子學會Vue組件-Vue.js學習總結)(轉載)

詳情請點擊 http://www.jianshu.com/p/9ad1ba89a04b轉載于:https://www.cnblogs.com/zhongjiang/p/6694459.html

必填字段的自定義JSF驗證器

實現EditableValueHolder接口的JSF組件具有兩個屬性“ required”和“ requiredMessage” –一個標志&#xff0c;指示用戶需要輸入/選擇非空值&#xff0c;以及一個用于驗證消息的文本。 我們可以使用它&#xff0c;但是它不夠靈活&#xff0c;我們不能直接在視圖中&#xff0…

java 轉碼%2f%_JS和JAVA中常用的編碼轉碼函數

js中escape,encodeURI,encodeURIComponent函數和unescape,decodeURI和decodeURIComponent函數的功能1.escape方法對String對象編碼,escape方法返回一個包含了"轉義序列"的字符串值。除了ASCII字母和數字&#xff0c;以及這幾個符號 *-/._外(共有1052769個字符不會被編…

mybatis 下劃線轉駝峰配置

一直以來&#xff0c;在sqlmap文件中&#xff0c;對于數據庫中的下劃線字段轉駝峰&#xff0c;我們都是通過resultmap來做的&#xff0c;如下&#xff1a; <resultMap id"ISTableStatistics" type"com.medsoft.perfstat.pojo.ISTableStatistics" > &…

Python練習-迭代器-模擬cat|grep文件

代碼如下: 1 # 編輯者&#xff1a;閆龍2 def grep(FindWhat):3 fopen("a.txt","r",encoding"utf8")#以只讀的方式打開a.txt文件4 while True:5 try:6 fline next(f).strip()#由于File類型本身就是一個迭代器,所以直…

Spring和JSF集成:轉換器

使用任何Web框架時&#xff0c;都不可避免地需要將用戶輸入的數據從String為其他類型。 盡管Spring和JSF在設計和功能上確實有很大的不同&#xff0c;但它們都具有轉換器策略來處理此問題。 讓我們從春天開始。 Spring 3引入了一個全新的轉換框架&#xff0c;該框架允許將任何類…

nacos配置ap_Nacos 1.0.0 功能預覽

本文來自于我的個人主頁&#xff1a;Nacos 1.0.0 功能預覽&#xff0c;轉載請保留鏈接 ;)Nacos 1.0.0 是正式 GA 的版本&#xff0c;在架構、功能和API設計上進行了全方位的重構和升級&#xff0c;1.0.0版本標志著Nacos的架構已經穩定&#xff0c;API列表最終確定。升級到1.0.0…