Skip to content

Instantly share code, notes, and snippets.

Created May 3, 2018 16:40
What would you like to do?
// BTHelper.swift
// Buzz
// Created by Erica Sadun on 4/17/18.
// Copyright © 2018 Erica Sadun. All rights reserved.
import Foundation
import CoreBluetooth
public class BTHelper: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
// BLE Access
var centralManager: CBCentralManager
override init() {
self.centralManager = CBCentralManager(delegate: nil, queue: nil)
self.centralManager.delegate = self
public func shutOff() {
if let target = targetPeripheral {
public func startUp() {
if let target = targetPeripheral {
centralManager.connect(target, options: [:])
// Required. Invoked when the central manager’s state is updated.
public func centralManagerDidUpdateState(_ manager: CBCentralManager) {
switch manager.state {
case .poweredOff:
print("BLE has powered off")
case .poweredOn:
print("BLE is now powered on")
centralManager.scanForPeripherals(withServices: nil, options: nil)
case .resetting: print("BLE is resetting")
case .unauthorized: print("Unauthorized BLE state")
case .unknown: print("Unknown BLE state")
case .unsupported: print("This platform does not support BLE")
var targetPeripheral: CBPeripheral? = nil
// Invoked when the central manager discovers a peripheral while scanning.
public func centralManager(_ manager: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData advertisement: [String : Any], rssi: NSNumber) {
guard let name =
else { print("Skipping unnamed service"); return }
guard name.hasPrefix("MI")
else { print("Skipping \"\(name)\" service"); return }
// RSSI is Received Signal Strength Indicator
print("Found \"\(name)\" peripheral (RSSI: \(rssi))")
print("Advertisement data:", advertisement, "\n")
// Attempt connection and service scan
print("Scan stopped.\n")
print("Attempting to connect to \(name)\n")
targetPeripheral = peripheral
targetPeripheral?.delegate = self
centralManager.connect(peripheral, options: nil)
// Invoked when a connection is successfully created with a peripheral.
public func centralManager(_ manager: CBCentralManager, didConnect peripheral: CBPeripheral) {
if let name = {
print("\"\(name)\" has connected.")
print("Requesting service discovery.\n")
// Invoked when you discover the peripheral’s available services.
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let services = {
for service in services {
peripheral.discoverCharacteristics(nil, for: service)
var vibrationCharacteristic: CBCharacteristic? = nil
// Invoked when you discover the characteristics of a specified service.
public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
guard let characteristics = service.characteristics
else { print("Unable to retrieve service characteristics"); return }
for characteristic in characteristics {
let name = characteristic.uuid.uuidString
switch name {
case "2A06":
print("Available: Vibration")
vibrationCharacteristic = characteristic
let note = Notification(name: Notification.Name(rawValue: name))
// Invoked when you write data to a characteristic’s value.
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
print("Peripheral did write characteristic value for " + characteristic.uuid.uuidString)
// Invoked when you retrieve a specified characteristic’s value, or when the peripheral device notifies your app that the characteristic’s value has changed.
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("Peripheral did update characteristic value for " + characteristic.uuid.uuidString)
guard let data = characteristic.value
else { print("missing updated value"); return }
print(data.count, "bytes received")
switch characteristic.uuid.uuidString {
case "FF0F":
func evaluatePairing(_ data: Data) {
let result = data.withUnsafeBytes({ (ptr: UnsafePointer<Int16>) in
ptr.withMemoryRebound(to: Int16.self, capacity: 1) { pointer in
return pointer.pointee
print("Pairing result:", result)
// External vibration consumption
/// Available vibration patterns
// - SeeAlso:
public enum Pattern { case low, high }
public func vibrate(degree: Pattern) {
guard let characteristic = vibrationCharacteristic
else { return }
switch degree {
case .low:
targetPeripheral?.writeValue(Data([0x1]), for: characteristic, type: .withoutResponse)
case .high:
targetPeripheral?.writeValue(Data([0x2]), for: characteristic, type: .withoutResponse)
self.perform(#selector(shutOff), with: nil, afterDelay: 2.0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment