66
71

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BLEのペリフェラルを今更実装してみた(iOS編)

Last updated at Posted at 2014-10-30

BLEのペリフェラルを今更実装してみた(iOS編)

準備

(1) BLE用のUUIDを作成する

ターミナルを起動して以下コマンドを入力

$ uuidgen

すると以下のようなUUIDが自動生成されるのでコピーしておく

71DA3FD1-7E10-41C1-B16F-4430B506CDE7

CCUUIDとして定義

BLEDefine.swift

/** BLEで用いるサービス用のUUID */
let BLEServiceUUID = CBUUID(string:"71DA3FD1-7E10-41C1-B16F-4430B506CDE7")

/** BLEで用いるキャラクタリスティック用のUUID */
let BLECharacteristicUUID = CBUUID(string:"E977DFF0-36D0-4B3B-89D5-575AAE17B6B3")

(2) CoreBluetooth Frameworkを追加

add_corebluetooth_framework.png

(3) CoreBluetoothをインポート

使うファイル内の先頭辺りでインポート文を書く


import CoreBluetooth

CoreBluetoothのEnum値

ログを出すときに楽なので name プロパティを追加しておきます

BLEEnumExtension.swift
extension CBCentralManagerState
{
    var name : NSString {
        get{
            var enumName = "CBCentralManagerState"
            var valueName = ""
            
            switch self {
            case .PoweredOff:
            valueName = enumName + "PoweredOff"
            case .PoweredOn:
            valueName = enumName + "PoweredOn"
            case .Resetting:
            valueName = enumName + "Resetting"
            case .Unauthorized:
            valueName = enumName + "Unauthorized"
            case .Unknown:
            valueName = enumName + "Unknown"
            case .Unsupported:
            valueName = enumName + "Unsupported"
            }
            
            return valueName
        }
    }
}

extension CBPeripheralState
{
    var name : NSString {
        get{
            var enumName = "CBPeripheralState"
            var valueName = ""
            
            switch self {
            case .Connected:
                valueName = enumName + "Connected"
            case .Connecting:
                valueName = enumName + "Connecting"
            case .Disconnected:
                valueName = enumName + "Disconnected"
            }
            
            return valueName
        }
    }
}

extension CBPeripheralManagerState
{
    var name : NSString {
        get{
            var enumName = "CBPeripheralManagerState"
            var valueName = ""
            
            switch self {
            case .PoweredOff:
                valueName = enumName + "PoweredOff"
            case .PoweredOn:
                valueName = enumName + "PoweredOn"
            case .Resetting:
                valueName = enumName + "Resetting"
            case .Unauthorized:
                valueName = enumName + "Unauthorized"
            case .Unknown:
                valueName = enumName + "Unknown"
            case .Unsupported:
                valueName = enumName + "Unsupported"
            }
            
            return valueName
        }
    }
}

実装

BLEPeripheralManager.swift

class BLEPeripheralManager : NSObject {
    
    // MARK: - Property
    
    /** シングルトンインスタンス */
    class var sharedManager : BLEPeripheralManager {
        struct Static {
            static let instance : BLEPeripheralManager = BLEPeripheralManager()
        }
        return Static.instance
    }
    
    /** BLEのペリフェラルマネージャー、BLE発信側としての機能をサポートする */
    private var peripheralManager : CBPeripheralManager?
    
    /** 発信するキャラクタリスティック */
    private var characteristic = CBMutableCharacteristic(
        type:BLECharacteristicUUID,
        properties:CBCharacteristicProperties.Notify,
        value:nil,
        permissions:CBAttributePermissions.Readable)
    
    /** 発信するデータ */
    var dataToSend = NSData()
    
    /** 発信するデータのインデックス */
    private var sendDataIndex = 0
    
    /** フラグ値 */
    private var sendingEOM : Bool = false
    
    // MARK: - Public
    
    /** BLEのペリフェラルを使用開始できる状態にセットアップ */
    func setup()
    {
        self.peripheralManager = CBPeripheralManager(delegate:self, queue:nil)
    }
    
    /** BLEのペリフェラルを使用できない状態にする */
    func teardown()
    {
        self.peripheralManager = nil
    }
    
    /** アドバタイズを開始 */
    func startAdvertising()
    {
        self.peripheralManager?.startAdvertising([CBAdvertisementDataServiceUUIDsKey:[BLEServiceUUID]])
    }
    
    /** アドバタイズを停止 */
    func stopAdvertising()
    {
        self.peripheralManager?.stopAdvertising()
    }
    
    // MARK: Private
    
    /** データを送信する */
    func sendData()
    {
        if self.sendingEOM {
            
            var data = "EOM".dataUsingEncoding(NSUTF8StringEncoding)
            
            var didSend : Bool = self.peripheralManager!.updateValue(
                data,
                forCharacteristic:self.characteristic,
                onSubscribedCentrals: nil)
            
            if didSend {
                self.sendingEOM = false
                return
            }
        }
        
        var didSend = true
        
        while didSend {
            
            var amountToSend = self.dataToSend.length - self.sendDataIndex
            
            if amountToSend > 20 {
                amountToSend = 20
            }
            
            var chunk = NSData(bytes:self.dataToSend.bytes+self.sendDataIndex, length: amountToSend)
            
            didSend = self.peripheralManager!.updateValue(
                chunk,
                forCharacteristic:self.characteristic,
                onSubscribedCentrals: nil)
            
            if !didSend {
                return
            }
            
            var stringFromData = NSString(data:chunk, encoding:NSUTF8StringEncoding)
            
            self.sendDataIndex += amountToSend
            
            if self.sendDataIndex >= self.dataToSend.length {
                
                self.sendingEOM = false
                
                let eomSent : Bool = self.peripheralManager!.updateValue(
                    "EOM".dataUsingEncoding(NSUTF8StringEncoding),
                    forCharacteristic:self.characteristic,
                    onSubscribedCentrals: nil)
                
                if eomSent {
                    sendingEOM = false
                }
                
                return
            }
        }
    }
}

// MARK: - CBPeripheralManagerDelegate

extension BLEPeripheralManager : CBPeripheralManagerDelegate
{
    func peripheralManager(
        peripheral: CBPeripheralManager!,
        central: CBCentral!,
        didSubscribeToCharacteristic characteristic: CBCharacteristic!)
    {
        self.sendDataIndex = 0
        self.sendData()
    }
    
    func peripheralManager(
        peripheral: CBPeripheralManager!,
        central: CBCentral!,
        didUnsubscribeFromCharacteristic characteristic: CBCharacteristic!)
    {
        println("didUnsubscribeFromCharacteristic")
    }
    
    func peripheralManager(
        peripheral: CBPeripheralManager!,
        didAddService service: CBService!,
        error: NSError!)
    {
        if error == nil {
            println("正常にサービスの追加が完了しました")
        } else {
            println("サービスの追加に失敗しました")
        }
    }
    
    func peripheralManager(
        peripheral: CBPeripheralManager!,
        didReceiveReadRequest request: CBATTRequest!)
    {
        println("didReceiveReadRequest")
    }
    
    func peripheralManager(
        peripheral: CBPeripheralManager!,
        didReceiveWriteRequests requests: [AnyObject]!)
    {
        println("didReceiveWriteRequests")
    }
    
    func peripheralManager(
        peripheral: CBPeripheralManager!,
        willRestoreState dict: [NSObject : AnyObject]!)
    {
        println("willRestoreState")
    }
    
    func peripheralManagerDidStartAdvertising(
        peripheral: CBPeripheralManager!,
        error: NSError!)
    {
        if error == nil {
            println("PeripheralがAdvertisingを開始しました")
        } else {
            println("PeripheralがAdvertisingの開始に失敗しました\(error)")
        }
    }
    
    func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager!)
    {
        println("PeripheralのStateが変更されました(現在のState:\(peripheral.state.name))")
        
        if peripheral.state != CBPeripheralManagerState.PoweredOn {
            println("異常なStateのため処理を終了します")
            return;
        }
        
        var service = CBMutableService(type:BLEServiceUUID, primary:true)
        service.characteristics = [self.characteristic]
        self.peripheralManager?.addService(service)
    }
    
    func peripheralManagerIsReadyToUpdateSubscribers(peripheral: CBPeripheralManager!)
    {
        self.sendData()
    }
}

66
71
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
66
71

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?