DFBle.swift

//
//  DFBle.swift
//  DFBle
//
//  Created by LeeYaping on 15/9/2.
//  Copyright (c) 2015年 lisper. All rights reserved.
//

import Foundation
import CoreBluetooth

/**
*  easy protocol, to use ble
*/
@objc public protocol BleProtocol {
    optional func didDiscover (name:String, rssi:NSNumber)
    optional func didConnect (name:String)
    optional func didDisconnect ()
    optional func didBleReady()
    optional func didReadRSSI (rssi:NSNumber)
}

public class DFBle:NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    
    public static let sharedInstance = DFBle ()
    
    struct peripheralWithRssi {
        var RSSI: NSNumber
        var peripheral :CBPeripheral
    }
    
    var bright:UInt8 = 255
    var color:UInt8 = 0
    
    public var delegate :BleProtocol?
    let DFUUID :CBUUID = CBUUID(string: "DFB0")
    var rescanTimer :NSTimer?
    var rssiTimer :NSTimer?
    var centralManager :CBCentralManager!
    var myperipheral :CBPeripheral?
    var mychar :CBCharacteristic?
    var myservice :CBService?
    var peripherals :[peripheralWithRssi]!
    
    var isKeepConnect = true
    var isConnect :Bool = false
    var isScanning :Bool = false
    
    private override init () {
        super.init ()
        print ("shared instance")
        self.centralManager = CBCentralManager(delegate: self, queue: nil)
        peripherals = [peripheralWithRssi]()
    }
    
    /*
    override init () {
        super.init ()
        self.centralManager = CBCentralManager(delegate: self, queue: nil)
        peripherals = [peripheralWithRssi]()
    }
    */
    private convenience init (delegate: BleProtocol) {
        self.init ()
        self.delegate = delegate
    }
 
    
    
    public func beginScan () {
        if isScanning == false {
            isKeepConnect = true
            self.centralManager.scanForPeripheralsWithServices([DFUUID], options: nil)
            rescanTimer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "updateScan", userInfo: nil, repeats: true)
            isScanning = true
        }
    }
    
    /**
    stop scan ble device
    */
    public func breakScan () {
        rescanTimer?.invalidate()
        rescanTimer = nil
        centralManager.stopScan()
        isScanning = false
    }
    
    public func disConnect () {
        isKeepConnect = false
        centralManager.cancelPeripheralConnection(myperipheral!)
    }
    
    /**
    rescan ble device every 2 seconds
    */
    func updateScan () {
        if let p = getMaxPeripheral() {
            myperipheral = p
            connect(myperipheral!)
        } else {
            print ("rescan")
            self.centralManager.scanForPeripheralsWithServices([DFUUID], options: nil)
        }
    }
    
    /**
    connect a peripheral
    
    - parameter peripheral: that rssi is best
    */
    func connect (peripheral:CBPeripheral) {
        myperipheral = peripheral
        centralManager.stopScan()
        isScanning = false
        self.rescanTimer?.invalidate()
        self.rescanTimer = nil
        centralManager.connectPeripheral(peripheral, options: nil)
    }
    
    /**
    send one byte to connected peripheral
    
    - parameter value: one byte data will send
    */
    public func sendByte (value :UInt8) {
        var myvalue = value
        let data = NSData(bytes: &myvalue, length: 1)
        myperipheral?.writeValue(data, forCharacteristic: mychar!, type: CBCharacteristicWriteType.WithoutResponse)
    }
    
    /**
    send String to connected peripheral
    
    - parameter value: -> a string will send
    */
    public func sendString (value :String) {
        if value.lengthOfBytesUsingEncoding(NSASCIIStringEncoding) == 0 {
            return
        }
        let data = value.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)
        print ("data: \(data)")
        myperipheral?.writeValue(data!, forCharacteristic: mychar!, type: CBCharacteristicWriteType.WithoutResponse)
    }
    
    /**
    send data to control a car
    
    - parameter left:    left speed
    - parameter right:   right speed
    */
    func sendRunCommand (left left:Int8, right:Int8) {
        let cmd :UInt8 = 0x10
        let cmdString = String(format: "$%02X%02X%02X\r", cmd, UInt8(bitPattern: left) , UInt8(bitPattern: right))
        print("cmd=\(cmdString.lengthOfBytesUsingEncoding(NSASCIIStringEncoding)):\(cmdString)")
        sendString(cmdString)
    }

@objc public func centralManagerDidUpdateState(central: CBCentralManager) {
        if centralManager.state == .PoweredOn {
            print ("ble opened")
        } else {
            print ("ble open error")
        }
    }
    
    public func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {
        //println ("didDiscoverPeripheral ")
        print ("name=\(peripheral.name)  RSSI=\(Int32(RSSI.intValue))")
        if peripheral.name == "car_007" {
            connect(peripheral)
        }
        if RSSI.integerValue > -50 && RSSI.integerValue < -10 {
            appendPeripheral(peripheral, RSSI: RSSI)
        }
        delegate?.didDiscover?(peripheral.name!, rssi: RSSI)
    }
    
    /**
    append new find peripheral to peripherals and update rssi
    
    - parameter peripheral:
    - parameter RSSI:
    */
    func appendPeripheral (peripheral :CBPeripheral, RSSI :NSNumber) {
        for var p=1; p < self.peripherals.count; p++  {
            if self.peripherals[p].peripheral == peripheral {
                self.peripherals[p].RSSI = RSSI
                return
            }
        }
        self.peripherals.append(peripheralWithRssi(RSSI: RSSI, peripheral: peripheral))
    }
    
    /**
    return the max rssi peripheral tin peripherals
    
    - returns: peripheral with best rssi or nil
    */
    func getMaxPeripheral () -> CBPeripheral? {
        if self.peripherals.count == 0 {
            return nil
        }
        var max :NSNumber = self.peripherals[0].RSSI
        var maxPeripheral :CBPeripheral = self.peripherals[0].peripheral
        
        for p in self.peripherals {
            if p.RSSI.integerValue > max.integerValue {
                max = p.RSSI
                maxPeripheral = p.peripheral
            }
        }
        return maxPeripheral
    }
    
    public func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
        //println ("didConnectPeripheral ")
        peripheral.delegate = self
        peripheral.discoverServices(nil)
        peripheral.readRSSI()
        rescanTimer?.invalidate()
        rescanTimer = nil
        delegate?.didConnect?(peripheral.name!)
    }
    
    public func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {
        //println ("didDisconnectPeripheral ")
        isConnect = false
        rssiTimer?.invalidate()
        rssiTimer = nil
        rescanTimer?.invalidate()
        if isKeepConnect == true {
            centralManager.connectPeripheral(myperipheral!, options: nil)
        }
        delegate?.didDisconnect?()
    }
    
    public func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
        //println ("didDiscoverServices ")
        if (peripheral.services![1] ).UUID.UUIDString == "DFB0" {
            //println ("get DFB0")
            myservice = peripheral.services![1]// as? CBService
            peripheral.discoverCharacteristics(nil, forService: peripheral.services![1])// as! CBService)
        }
        
    }
    
    public func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
        //println ("didDiscoverCharacteristicsForService ")
        let char = (service.characteristics![0]) //as! CBCharacteristic)
        if char.UUID.UUIDString == "DFB1" {
            //println ("get DFB1")
            mychar = char
            myperipheral?.setNotifyValue(true, forCharacteristic: mychar!)
            isConnect = true
            rssiTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "updateRSSI", userInfo: nil, repeats: true)
            delegate?.didBleReady?()
        }
    }
    
    /**
    read rssi every seconds
    */
    func updateRSSI () {
        myperipheral?.readRSSI()
    }
    
    public func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
        //println ("didUpdateNotificationStateForCharacteristic ")
    }
    
    //
    public func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
        print ("didUpdateValueForCharacteristic")
        let str = NSString(data: characteristic.value!, encoding: NSASCIIStringEncoding)
        //var str = NSString(data: characteristic.value(), encoding: NSASCIIStringEncoding)
        if str != nil {
            print ("read:(\(str!.length)) \(str!)")
        }
    }
    
    public func peripheral(peripheral: CBPeripheral, didWriteValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
        //println ("didWriteValueForCharacteristic ")
    }
    
    /*
    func peripheralDidUpdateRSSI(peripheral: CBPeripheral!, error: NSError!) {
    rssiLabel.text = peripheral.RSSI.stringValue
    }
    */
    
    func peripheral(peripheral: CBPeripheral!, didReadRSSI RSSI: NSNumber!, error: NSError!) {
        //      println ("didReadRSSI ")
        delegate?.didReadRSSI?(RSSI)
    }
    
}

时间: 2024-10-01 22:36:23

DFBle.swift的相关文章

Apple Swift编程语言新手教程

Apple Swift编程语言新手教程 作者: 日期: gashero 2014-06-03 FROM:http://gashero.iteye.com/blog/2075324 文件夹 1   简单介绍 2   Swift入门 3   简单值 4   控制流 5   函数与闭包 6   对象与类 7   枚举与结构 1   简单介绍 今天凌晨Apple刚刚公布了Swift编程语言,本文从其公布的书籍<The Swift Programming Language>中摘录和提取而成.希望对各位的

swift 深入理解Swift的闭包

我们可用swift的闭包来定义变量的值. 先来一个简单的例子大家先感受感受. 定义一个字符串的变量的方法: 直接赋值 var str="JobDeer" 还可以用闭包的方式定义: var str:String={ return "JobDeer" }() 闭包还可以这么定义,省略了等号和括号: var str:String{ return "JobDeer" } 闭包中可以定义get方法. var str:String{ get{ return

在Swift结构体中如何实现写时复制?

结构体(Struct)在Swift语言中占有重要地位,在Swift标准库中,大约有90%的公开类型都是结构体,包括我们常用的Array.String.Dictionary.结构体相比类,一个最重要的特性就是它是值类型,而类似引用类型.值类型是通过复制值来赋值的,而不是引用同一个内存地址,这样就不存在数据共享的问题,能防止意外的数据改变,并且它是线程安全的. 举一个很简单的例子,在objc中,数组是类,是引用类型,在Swift中,数组是结构体,是值类型.因此下面的代码中: let array1 =

Swift学习之位移枚举的按位或运算

在OC里面我们经常遇到一些枚举值可以多选的,需要用或运算来把这些枚举值链接起来,这样的我们称为位移枚举,但是在swift语言里面却不能这么做,下面来讲解一下如何在swift里面使用 OC的位移枚举的区分 //位移枚举typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutores

Swift - 用UIScrollView实现视差动画效果

效果 源码 https://github.com/YouXianMing/Swift-Animations // // MoreInfoView.swift // Swift-Animations // // Created by YouXianMing on 16/8/18. // Copyright © 2016年 YouXianMing. All rights reserved. // import UIKit class MoreInfoView: UIView { var imageV

Swift 入门之简单语法(一)

定义 let 定义常量,一经赋值不允许再修改 var 定义变量,赋值之后仍然可以修改 //: # 常量 //: 定义常量并且直接设置数值 let x = 20 //: 常量数值一经设置,不能修改,以下代码会报错 // x = 30 //: 使用 `: 类型`,仅仅只定义类型,而没有设置数值 let x1: Int //: 常量有一次设置数值的机会,以下代码没有问题,因为 x1 还没有被设置数值 x1 = 30 //: 一旦设置了数值之后,则不能再次修改,以下代码会报错,因为 x1 已经被设置了数

Swift和Java关于字符串和字符的比较

1. 字符串字面量 Swift和Java关于字符串操作大同小异. Swift:字符串字面量(String Literals):我们可以在代码中包含一段预定义的字符串值作为字符串字面量. 字符串字面量是由双引号 ("") 包裹着的具有固定顺序的文本字符集.字符串字面量可以用于为常量和变量提供初始值. 代码如下: let someString = "Some string literal value" 字符串字面量可以包含以下特殊字符: 转义字符\0(空字符).\\(反

Swift Tour

设置常数使用let,设置变量使用var var myVariable = 42 myVariable = 50 let myConstant = 42 编译器可以自己推断出变量类型因此不用显式限定. 如果没有赋初值或信息不足以让编译器判断,则可以通过冒号显式声明: let implicitInteger = 70 let implicitDouble = 70.0 let explicitDouble: Double = 70 任何变量类型都不可以隐式转换,所有变量之间的转换都为显式: let

Swift备忘录

Swift 备忘录 2015-4 一.简介 1.Swift 语言由苹果公司在2010年7月开始设计,在 2014 年6月推出,在 2015 年 12 月 3 日开源 2.特点(官方): (1)苹果宣称 Swift 的特点是:快速.现代.安全.互动,而且明显优于 Objective-C 语言 (2)可以使用现有的 Cocoa 和 Cocoa Touch 框架 (3)Swift 取消了 Objective-C 的指针及其他不安全访问的使用 (4)舍弃 Objective-C 早期应用 Smallta