iOS开发:使用swfit进行蓝牙开发详解

最近我一直在做蓝牙开发的应用,大家也可能意识到,当下蓝牙开发可谓是越来越火,不论是智能穿戴的兴起还是蓝牙家具,车联网蓝牙等等,很多同学也会接触到蓝牙的项目,我从事蓝牙开发也有一段时间了,经手了两个项目。废话不多说了,先向大家简单的介绍有关蓝牙开发的知识。蓝牙低能耗(BLE),以下介绍的都是围绕iOS的框架展开的。

蓝牙开发分为中心者模式和管理者模式:1.常用的(其实99.99%)就是使用中心者模式作为开发,就是我们手机作为主机,连接蓝牙外设;2.管理者模式,这个基本用到的比较少,我们手机自己作为外设,自己创建服务和特征,然后有其他的设备连接我们的手机。

在做蓝牙开发之前,最好先了解一些概念:
服务(services):蓝牙外设对外广播的必定会有一个服务,可能也有多个,服务下面包含着一些特征,服务可以理解成一个模块的窗口;
特征(characteristic):存在于服务下面的,一个服务下面也可以存在多个特征,特征可以理解成具体实现功能的窗口,一般特征都会有value,也就是特征值,特征是与外界交互的最小单位;
UUID:可以理解成蓝牙上的唯一标识符(硬件上肯定不是这个意思,但是这样理解便于我们开发),为了区分不同的服务和特征,或者给服务和特征取名字,我们就用UUID来代表服务和特征。

蓝牙连接可以大致分为以下几个步骤
1.建立一个Central Manager实例进行蓝牙管理
2.搜索外围设备
3.连接外围设备
4.获得外围设备的服务
5.获得服务的特征
6.从外围设备读数据
7.给外围设备发送数据
其他:提醒

首先是导入框架import CoreBluetooth
必须遵守2个协议
    <CBCentralManagerDelegate, CBPeripheralDelegate>
定义中心管理者
    fileprivate var centralManager :CBCentralManager!
定义外设
     fileprivate var curretPeripheral :CBPeripheral!
1.创建中心设备进行蓝牙管理并设置代理:
func setupBluretooth(){
     centralManager = CBCentralManager(delegate: self, queue: nil)
  }

//只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态

func centralManagerDidUpdateState(_ central: CBCentralManager) {

    switch central.state {

    case.poweredOff:
        print("蓝牙以关闭")
    case .unsupported:
        print("不支持蓝牙")
    case .unknown:
        print("蓝牙状态未知")
    case .resetting:
        print("重置")
    case .poweredOn:
        print("蓝牙以打开")
        //利用中心设备扫描外部设备:
        //第一个参数那里表示扫描带有相关服务的外部设备,例如填写@[[CBUUIDUUIDWithString:@"需要连接的外部设备的服务的UUID"]],即表示带有需要连接的外部设备的服务的UUID的外部设备,nil表示扫描全部设备;
        central.scanForPeripherals(withServices: nil, options: nil)
        // 搜索成功之后,会调用我们找到外设的代理方法 
        // func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
    default:
        print("此设备不支持BLE或未打开蓝牙功能,无法作为外围设备.")
    }
  
}
2.搜索外围设备(发现设备),一旦扫描到外部设备,就会进入下列协议中的
/// - parameter central:           中心管理者
/// - parameter peripheral:        外设
/// - parameter advertisementData: 外设携带的数据
/// - parameter RSSI:              外设发出的蓝牙信号强度

func centralManager(_ central: CBCentralManager,didDiscover peripheral: CBPeripheral, advertisementData: [String : Any],rssi RSSI: NSNumber)  {
     
//在这个方法里,我们可以根据我们获取到的硬件的某些条件进行筛选,然后连接我们需要连接的外部设备
    print("扫描到的蓝牙设备:\(peripheral)")
    //这里我是将扫描到的设备显示在tableView里
    //通过点击tableView的cell选择连接到蓝牙设备
    //peripherals 是存放 蓝牙设备的数组
    
    peripherals.append(peripheral)
    tableView.reloadData()

}
3.连接外围设备
// 中心管理者连接  外设成功
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
     print("连接成功")
    //停止扫描
     centralManager.stopScan()
    // 外围设备设置代理
    peripheral.delegate = self
    
    //我们在连接成功的方法中开始扫描外部设备的服务
   
    peripheral.discoverServices(nil)

}

 //连接失败
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
    print("连接失败")
}
//断开连接
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
    print("断开连接")
}
4.获得外围设备的服务
 //接着就会跳入发现服务的代理方法中去:
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
 print("发现服务:\(peripheral.services)")

    for service in peripheral.services! {
        //我们在这个方法里面开始扫描服务中的特征:

       //serviceUUID 服务UUID(已知)
       //kCharacteristicUUID 特证UUID(已知)


        let serviceuuid:CBUUID? =
            CBUUID.init(string: "\(serviceUUID)")
        let characteristicUUID:CBUUID? =
            CBUUID.init(string: "\(kCharacteristicUUID)")

        if service.uuid == serviceuuid {
peripheral.discoverCharacteristics([characteristicUUID!], for: service)
        }

    }
}
5.获得服务的特征
//当我们扫描到特征的时候,就会跳入发现特征的协议方法里去
//(这个是比较重要的方法,你在这里可以通过事先知道UUID找到你需要的特征,订阅特征,或者这里写入数据给特征也可以)
 func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if (error != nil) {
        print("error Discovered characteristics for\(service.uuid)---\(error?.localizedDescription)")
    }
    
    let serviceuuid:CBUUID? =
        CBUUID.init(string: "\(serviceUUID)")
    let characteristicUUID:CBUUID? =
        CBUUID.init(string: "\(kCharacteristicUUID)")

    if service.uuid == serviceuuid {
        
        for characteristic in service.characteristics! {
            print(service.uuid)
            print(service.uuid.description)
               print("\(service.uuid)-----\(characteristic.uuid)")
            if characteristic.uuid == characteristicUUID {
                
                
                //获取Characteristic的值,读数据:
                peripheral.readValue(for: characteristic)
                
                //1.给外围设备发送数据(也就是写入数据到蓝牙)
                //2.这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦
                //3.第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入
                //4. 需要注意的是特征的属性是否支持写数据
           //peripheral.writeValue(要写入的Data, for: characteristic, type: CBCharacteristicWriteType.withResponse)

            }

        }

    }
    
    //这就读取了特征包含的相关信息,只要读取就会进入下面方法:

}
6.从外围设备读数据
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

    if (error != nil) {
        print("更新特征值时发生错误,错误信息:\(error?.localizedDescription)")
        return
    }
 
    if characteristic == @"你要的特征的UUID或者是你已经找到的特征" {
//characteristic.value就是你要的数据
    }

}
7.给外围设备发送数据(也就是写入数据到蓝牙)
//这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦
 peripheral.writeValue(characteristic.value!, for: characteristic, type:.withResponse)
    // 最后的type类型有两个,分别是CBCharacteristicWriteWithResponse和CBCharacteristicWriteWithoutResponse;
    // 选择第一个,每往硬件写入一次数据都会进入下边的方法

这个方法会告诉我们这次的写入是否成功,但是如果我们不用考虑往硬件写入的数据成功与否的话,选择第二个类型就ok。
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    
}

蓝牙开发的基本方法就这么多,有写的不好不对的地方欢迎指正,分享一是为了提升自己和二是希望能对需要的朋友有所帮助!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容