iOS藍芽開發(二):iOS 藍芽4.0中心模式 程式碼實現
上一篇簡單介紹了藍芽的部分基礎知識,詳細的東西大家可以去github上搜babyBluetooth,裡面有一些學習資料
iOS連線外設的流程
- 建立中心管理者
- 掃描外設 discoverPeripheral
- 連線外設 connectPeripheral
- 掃描外設中的服務和特徵 discoverServices discoverCharacteristics
- 獲取外設的services
- 獲取外設service中的characteristics
- 獲取characteristic的值value、descriptor的value
- 與外設做資料互動 write、read
- 訂閱characteristic的通知notify
- 斷開連線 disconnected
實現步驟
1、匯入CoreBluetooth標頭檔案,建立中心管理類,設定代理
#import <CoreBluetooth/CoreBluetooth.h> @interface ViewController : UIViewController<CBCentralManagerDelegate> @interface ViewController (){ //系統藍芽裝置管理物件,可以把他理解為主裝置,通過他,可以去掃描和連結外設 CBCentralManager *manager; //用於儲存被發現裝置 NSMutableArray *peripherals; } - (void)viewDidLoad { [super viewDidLoad]; /* 設定主裝置的委託,CBCentralManagerDelegate 必須實現的: - (void)centralManagerDidUpdateState:(CBCentralManager *)central;//主裝置狀態改變的委託,在初始化CBCentralManager的適合會開啟裝置,只有當裝置正確開啟後才能使用 其他選擇實現的委託中比較重要的: - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //找到外設的委託 - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//連線外設成功的委託 - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外設連線失敗的委託 - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//斷開外設的委託 */ //初始化並設定委託和執行緒佇列,最好一個執行緒的引數可以為nil,預設會就main執行緒 manager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
2、掃描外設(discover),掃描外設的方法我們放在centralManager成功開啟的委託中,因為只有裝置成功開啟,才能開始掃描,否則會報錯。
所以當重新連線外設時,都不會成功,因為states還沒開啟;一般自己寫藍芽,這個地方要處理一下,連線的時候判斷一下,還未開啟就重連,一直等到PoweredOn
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{ switch (central.state) { case CBCentralManagerStateUnknown: NSLog(@">>>CBCentralManagerStateUnknown"); break; case CBCentralManagerStateResetting: NSLog(@">>>CBCentralManagerStateResetting"); break; case CBCentralManagerStateUnsupported: NSLog(@">>>CBCentralManagerStateUnsupported"); break; case CBCentralManagerStateUnauthorized: NSLog(@">>>CBCentralManagerStateUnauthorized"); break; case CBCentralManagerStatePoweredOff: NSLog(@">>>CBCentralManagerStatePoweredOff"); break; case CBCentralManagerStatePoweredOn: NSLog(@">>>CBCentralManagerStatePoweredOn"); //開始掃描周圍的外設 /* 第一個引數nil就是掃描周圍所有的外設,掃描到外設後會進入 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; */ [manager scanForPeripheralsWithServices:nil options:nil]; break; default: break; } } //掃描到裝置會進入方法 -(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{ NSLog(@"當掃描到裝置:%@",peripheral.name); //接下來可以連線裝置 }
3、連線外設
有一點注意,找到的peripheral必須被持有:(比如新增到陣列、賦值給另一個被持有的變數),否則CBCentralManager中也不會儲存這個peripheral,那麼CBPeripheralDelegate中的方法也不會被呼叫
//掃描到裝置會進入方法
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
//接下連線我們的測試裝置,如果你沒有裝置,可以下載一個app叫lightbule的app去模擬一個裝置
//這裡自己去設定下連線規則,我設定的是P開頭的裝置
if ([peripheral.name hasPrefix:@"P"]){
/*
一個主裝置最多能連7個外設,每個外設最多隻能給一個主裝置連線,連線成功,失敗,斷開會進入各自的委託
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;//連線外設成功的委託
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//外設連線失敗的委託
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;//斷開外設的委託
*/
//找到的裝置必須持有它,否則CBCentralManager中也不會儲存peripheral,那麼CBPeripheralDelegate中的方法也不會被呼叫!!
[peripherals addObject:peripheral];
//連線裝置
[manager connectPeripheral:peripheral options:nil];
}
}
//連線到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@">>>連線到名稱為(%@)的裝置-成功",peripheral.name);
}
//連線到Peripherals-失敗
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(@">>>連線到名稱為(%@)的裝置-失敗,原因:%@",[peripheral name],[error localizedDescription]);
}
//Peripherals斷開連線
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
NSLog(@">>>外設連線斷開連線 %@: %@\n", [peripheral name], [error localizedDescription]);
}
4、掃描外設中的服務和特徵(discover)
裝置連線成功後,就可以掃描裝置的服務了,同樣是通過委託形式,掃描到結果後會進入委託方法。但是這個委託已經不再是主裝置的委託(CBCentralManagerDelegate),而是外設的委託(CBPeripheralDelegate),這個委託包含了主裝置與外設互動的許多 回叫方法,包括獲取services,獲取characteristics,獲取characteristics的值,獲取characteristics的Descriptor,和Descriptor的值,寫資料,讀rssi,用通知的方式訂閱資料等等。5、獲取外設的services
//連線到Peripherals-成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@">>>連線到名稱為(%@)的裝置-成功",peripheral.name);
//設定的peripheral委託CBPeripheralDelegate
//@interface ViewController : UIViewController<CBCentralManagerDelegate,CBPeripheralDelegate>
[peripheral setDelegate:self];
//掃描外設Services,成功後會進入方法:-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
[peripheral discoverServices:nil];
}
//掃描到Services
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
// NSLog(@">>>掃描到服務:%@",peripheral.services);
if (error)
{
NSLog(@">>>Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);
return;
}
for (CBService *service in peripheral.services) {
NSLog(@"%@",service.UUID);
//掃描每個service的Characteristics,掃描到後會進入方法: -(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
[peripheral discoverCharacteristics:nil forService:service];
}
}
6、獲取外設的Characteristics,獲取Characteristics的值,獲取Characteristics的Descriptor和Descriptor的值
//掃描到Characteristics
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
if (error)
{
NSLog(@"error Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
return;
}
for (CBCharacteristic *characteristic in service.characteristics)
{
NSLog(@"service:%@ 的 Characteristic: %@",service.UUID,characteristic.UUID);
}
//獲取Characteristic的值,讀到資料會進入方法:-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
for (CBCharacteristic *characteristic in service.characteristics){
{
[peripheral readValueForCharacteristic:characteristic];
}
}
//搜尋Characteristic的Descriptors,讀到資料會進入方法:-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
for (CBCharacteristic *characteristic in service.characteristics){
[peripheral discoverDescriptorsForCharacteristic:characteristic];
}
}
//獲取的charateristic的值
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//打印出characteristic的UUID和值
//!注意,value的型別是NSData,具體開發時,會根據外設協議制定的方式去解析資料
NSLog(@"characteristic uuid:%@ value:%@",characteristic.UUID,characteristic.value);
}
//搜尋到Characteristic的Descriptors
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
//打印出Characteristic和他的Descriptors
NSLog(@"characteristic uuid:%@",characteristic.UUID);
for (CBDescriptor *d in characteristic.descriptors) {
NSLog(@"Descriptor uuid:%@",d.UUID);
}
}
//獲取到Descriptors的值
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
//打印出DescriptorsUUID 和value
//這個descriptor都是對於characteristic的描述,一般都是字串,所以這裡我們轉換成字串去解析
NSLog(@"characteristic uuid:%@ value:%@",[NSString stringWithFormat:@"%@",descriptor.UUID],descriptor.value);
}
7、把資料寫到Characteristic中
//寫資料
-(void)writeCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic
value:(NSData *)value{
//打印出 characteristic 的許可權,可以看到有很多種,這是一個NS_OPTIONS,就是可以同時用於好幾個值,常見的有read,write,notify,indicate,知知道這幾個基本就夠用了,前連個是讀寫許可權,後兩個都是通知,兩種不同的通知方式。
/*
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
};
*/
NSLog(@"%lu", (unsigned long)characteristic.properties);
//只有 characteristic.properties 有write的許可權才可以寫
if(characteristic.properties & CBCharacteristicPropertyWrite){
/*
最好一個type引數可以為CBCharacteristicWriteWithResponse或type:CBCharacteristicWriteWithResponse,區別是是否會有反饋
*/
[peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}else{
NSLog(@"該欄位不可寫!");
}
}
8、訂閱Characteristic的通知
一般在discoverCharacteristic的代理中,發現了型別是notify的characteristic,直接就可以訂閱了
//設定通知
-(void)notifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
//設定通知,資料通知會進入:didUpdateValueForCharacteristic方法
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
//取消通知
-(void)cancelNotifyCharacteristic:(CBPeripheral *)peripheral
characteristic:(CBCharacteristic *)characteristic{
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
}
9、斷開連線(disconnect)
//停止掃描並斷開連線
-(void)disconnectPeripheral:(CBCentralManager *)centralManager
peripheral:(CBPeripheral *)peripheral{
//停止掃描
[centralManager stopScan];
//斷開連線
[centralManager cancelPeripheralConnection:peripheral];
}
iOS中藍芽模組OTA升級(YModem協議)
相關推薦
iOS藍芽開發(二):iOS 藍芽4.0中心模式 程式碼實現
上一篇簡單介紹了藍芽的部分基礎知識,詳細的東西大家可以去github上搜babyBluetooth,裡面有一些學習資料 iOS連線外設的流程 建立中心管理者 掃描外設 discoverPeripheral 連線外設 connectPeripheral
iOS藍芽開發(二)在裝置端實現Central角色
若想在裝置上實現Central角色的功能,主要有以下步驟: 2.搜尋周圍廣播的裝置 3.與一個外設進行連線,並探索外設提供的服務 4.向外設傳送讀寫characteristic的請求,如果有需要訂閱characteristic值得更新,來跟蹤資料的變化。 myCe
藍芽開發(二)掃描裝置
一、申請位置許可權 在Android6.0以後要掃描藍芽裝置,還需要請求位置許可權: <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <
Android藍芽開發(二) BLE4.0低功耗藍芽
一、BLE4.0低功耗藍芽 Bluetooth Low Energy,藍芽低功耗,是從藍芽4.0開始支援的技術。相較傳統藍芽,傳輸速度更快、覆蓋範圍廣、安全性高、延時短、耗電低等特點。 二、關鍵術語 1.GATT(通用屬性配置):通用屬性配置檔案,用於ble鏈路上傳送和接
星雲鏈智能合約開發(二):Mac下安裝星雲鏈
Mac下安裝星雲鏈 星雲鏈智能合約開發 Golang環境搭建 版本用最新版:1.10.2 安裝 brew install go 配置環境變量 vi ~/.bash_profile 打開.bash_profile文件,按"i"鍵可進行編輯,添加: export GOROOT=/u
即時通訊音視訊開發(二):視訊編解碼之數字視訊介紹
前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 本文是系列文章中的第2篇,本系列文章的大綱如下: 《即時
Python爬蟲開發(二):整站爬蟲與Web挖掘
0×00 介紹 在網際網路這個複雜的環境中,搜尋引擎本身的爬蟲,出於個人目的的爬蟲,商業爬蟲肆意橫行,肆意掠奪網上的或者公共或者私人的資源。顯然資料的收集並不是為所欲為,有一些協議或者原則還是需要每一個人注意。本文主要介紹關於爬蟲的一些理論和約定協議,然後相對完整完成一個爬蟲的基本功能。 本
iOS 元件化開發(三):載入資原始檔
經過前兩篇文章的學習,相信對元件化開發有了大致的瞭解,那我們這篇文章就來講講資原始檔的載入吧 這裡我新建了一個LXFMain元件庫,主要是用來顯示TabBar的玩意,然後再進行元件化抽離出來,其中的過程這裡不再贅述,還沒了解過的同學建議先閱讀下這兩篇文
iOS 元件化開發(一):遠端私有庫的基本使用
隨著專案功能的不斷增加,越來越多的開發人員加入,業務主線也隨之越來越多,造成耦合越來越嚴重,編譯越來越慢,測試不獨立等一系列問題。為了解決此類情況,我們可以考慮到使用元件化開發 概念 元件化就是將一個單一工程的專案, 分解成為各個獨立的元件, 然後
使用NetBeans進行J2ME開發(二):把程式轉移到手機上
原文地址:http://juansusan.iteye.com/admin/blogs/251869/edit【IT168 技術文件】上一篇,我們見識了編寫一個手機程式其實很簡單。但是很多人大概不是很明白怎樣把程式轉移到手機上,不信你就試試,不管你是用資料線,還是用紅外藍芽,
Hyperledger Fabric開發(二):建立網路
執行fabric-samples專案中的一個例子:first-network,建立第一個網路(Building Your First Network)。 該網路共有4個peer節點,劃分為2個組織(organizations),以及1個單獨的orde
Android藍芽開發(一)之開啟藍芽和裝置搜尋
Android藍芽開發系列目錄: 一、判斷是否系統是否支援藍芽 在使用藍芽之前,我們首先要判斷手機裝置是否支援藍芽,雖然現在基本都支援藍芽了,但是為了程式碼的嚴謹性我們還是需要在程式碼中判斷: private BluetoothManager bluetoothma
Unity3D開發(二):NGUI之UIButton"禁用"狀態時置灰
NGUI中的Button幾乎是最常用到的控制元件之一,並且可以組合各種元件(比如UIButtonColor,UIButtonOffset,UITweenxx),方便設定Button的各種狀態下的屬性,幾乎可以滿足我們的所有需求。 但是對於當Button的isEnabled屬
JavaWeb專案開發(二):Servlet+Bean+Dao+MySQL
需要使用的技術: JSP動態網頁 Servlet獲得客戶端請求、轉發請求、跳轉到下一個介面 JavaBean 業務Bean (業務邏輯具體實現類),處理業務邏輯 Dao 訪問資料庫,操作資料庫例表 (增刪查改) MySQL 資料庫 實現系統以下介面和功能: 登入 我的資
android Bluetooth 開發(二):開啟、關閉、搜尋、允許搜尋、檢視
相關專案的下載連結繼本專案之後實現了語音識別:點選開啟連結1.承接上一篇文章,本篇文章主要實現了藍芽的開啟 關閉 允許搜尋 檢視配對裝置2. BluetoothInit,主要實現了部件的初始化,按鈕的點選事件,通過ListVIew顯示本地配對的藍芽裝置,ListView的點選
Android微信開發(二):程式碼分析
package com.example.teststudyshare.wxapi; import java.io.ObjectOutputStream.PutField; import android.R; import android.app.Activity; import android.content
Android 藍芽開發(2)——低功耗藍芽
低功耗藍芽官方文件 本文章是參考官網,然後加入自己實踐中的理解完成!沒有看上一篇的讀者,可以先閱讀一下前一篇,這是一個系列。 官網地址:https://developer.android.com/guide/topics/connectivity/bluetooth-le Android 4.3 (API
建造者模式-Builder Pattern 複雜物件的組裝與建立——建造者模式(二):遊戲角色設計的建造者模式解決方案
8.3 完整解決方案 Sunny公司開發人員決定使用建造者模式來實現遊戲角色的建立,其基本結構如圖8-3所示: 圖8-3 遊戲角色建立結構圖 在圖8-3中,Ac
機器學習與神經網路(四):BP神經網路的介紹和Python程式碼實現
前言:本篇博文主要介紹BP神經網路的相關知識,採用理論+程式碼實踐的方式,進行BP神經網路的學習。本文首先介紹BP神經網路的模型,然後介紹BP學習演算法,推導相關的數學公式,最後通過Python程式碼實現BP演算法,從而給讀者一個更加直觀的認識。 1.BP網路模型 為了將理
資料結構(二)雙向連結串列的的分析與python程式碼實現
概念 每個節點有兩個連結:一個指向前一個節點,當此節點為第一個節點時,指向空值;而另一個指向下一個節點,當此節點為最後一個節點時,指向空值。 特點: 節點包含