//
//  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)
    }
    
}

DFBle.swift的更多相关文章

  1. iOS代码规范(OC和Swift)

    下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...

  2. Swift与C#的基础语法比较

    背景: 这两天不小心看了一下Swift的基础语法,感觉既然看了,还是写一下笔记,留个痕迹~ 总体而言,感觉Swift是一种前后端多种语言混合的产物~~~ 做为一名.NET阵营人士,少少多多总喜欢通过对 ...

  3. iOS开发系列--Swift语言

    概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...

  4. 算法与数据结构(十七) 基数排序(Swift 3.0版)

    前面几篇博客我们已经陆陆续续的为大家介绍了7种排序方式,今天博客的主题依然与排序算法相关.今天这篇博客就来聊聊基数排序,基数排序算法是不稳定的排序算法,在排序数字较小的情况下,基数排序算法的效率还是比 ...

  5. 算法与数据结构(十五) 归并排序(Swift 3.0版)

    上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...

  6. Swift enum(枚举)使用范例

    //: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...

  7. swift开发新项目总结

    新项目用swift3.0开发,现在基本一个月,来总结一下遇到的问题及解决方案   1,在确定新项目用swift后,第一个考虑的问题是用纯swift呢?还是用swift跟OC混编      考虑到新项目 ...

  8. swift 中关于open ,public ,fileprivate,private ,internal,修饰的说明

    关于 swift 中的open ,public ,fileprivate,private, internal的区别 以下按照修饰关键字的访问约束范围 从约束的限定范围大到小的排序进行说明 open,p ...

  9. 【swift】BlockOperation和GCD实用代码块

    //BlockOperation // // ViewController.swift import UIKit class ViewController: UIViewController { @I ...

随机推荐

  1. 结束指定Activity实例代码

    开通博客两个多月了,一直在看你们的文章 终于发觉伸手党真的很可耻.. 于是就随便写了个Demo来结束伸手党生涯~ Demo很简单:结束指定Activity... 不过也是我的一个小心意嘛.. 不要责怪 ...

  2. 用MS自带的VS构建joint语句

    在其中一个表上,右键,选择"New Query",弹出"Add Table"对话框,将待joint的两个表Add,并选择相应字段,则会自动构建joint语句,其 ...

  3. jQuery ui 利用 datepicker插件实现开始日期(minDate)和结束日期(maxDate)

    这篇文章主要介绍了jQuery ui 利用 datepicker插件实现开始日期(minDate)和结束日期(maxDate),需要的朋友可以参考下 使用jQuery ui首先需要引入jQuery类库 ...

  4. 启动mySQL安装出现1067错误

    可能几种的办法: 删除data目录下的ib_logfile0和ib_logfile1 查看my.ini文件中的dir设置 查看err文件,如果是temp出现错误文件,则添加temp文件的路径

  5. poj2236 基础并查集

    题目链接:http://poj.org/problem?id=2236 题目大意:城市网络由n台电脑组成,因地震全部瘫痪,现在进行修复,规定距离小于等于d的电脑修复之后是可以直接相连 进行若干操作,O ...

  6. Java语言实现简单FTP软件------>FTP软件远程窗口的实现(六)

    1.首先看一下远程窗口的布局效果 2.看一下本地窗口实现的代码框架 3.远程窗口主要实现代码FtpPanel.java package com.oyp.ftp.panel.ftp; import ja ...

  7. php生成短网址的思路与方法

    生成短网址的思路以及使用php生成短网址的实现方法. 生成短网址的思路:如果把短网址还原了,你知道是个什么样子的吗?比如:http://www.jbxue.com/sitejs-17300-1.htm ...

  8. 国内开源html5游戏引擎全收录

    本文引自<国内开源html5游戏引擎全收录> 游戏开发这潭水太深,英文水平太差,不敢看国外的, 而且这几年国内技术水平也挺高了不少,特别是JS方面.(我个人感觉) 最近看了几个国产的js游 ...

  9. 3.4 C与汇编程序的相互调用

    为了提高代码执行效率,内核源代码中有些地方直接使用了汇编语言编制.这就会涉及在两种语言编制的程序之间相互调用的问题. 函数调用包括从一块代码到另一块代码之间的双向数据传递和执行控制转移.数据传递通过函 ...

  10. asp.net 防止页面刷新或后退引起重复提交

     项目中经常遇到刷新后重复的向数据库增加一条相同的记录,造成数据重复,如何规避这些问题呢?下面我们就一起讨论一下在asp.net怎样防止页面刷新或后退引起重复提交数据的问题: 其实asp.net防止刷 ...