Skip to content

Instantly share code, notes, and snippets.

@bricklife
Created September 14, 2018 16:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bricklife/f529e73b68771179ad5392d0e9449dd2 to your computer and use it in GitHub Desktop.
Save bricklife/f529e73b68771179ad5392d0e9449dd2 to your computer and use it in GitHub Desktop.
micro:bit simulator for Scratch 3.0
//
// BLEPeripheral.swift
// BLEPeripheral
//
// Created by ooba on 26/07/2017.
// Copyright © 2017 bricklife.com. All rights reserved.
//
import Foundation
import CoreBluetooth
class BLEPeripheral: NSObject {
var peripheralManager: CBPeripheralManager?
let serviceUUID = CBUUID(string: "f005")
let rxUUID = CBUUID(string: "5261da01-fa7e-42ab-850b-7c80220097cc")
let txUUID = CBUUID(string: "5261da02-fa7e-42ab-850b-7c80220097cc")
var rxCharacteristic: CBMutableCharacteristic?
var txCharacteristic: CBMutableCharacteristic?
var timer: Timer?
var pressingButtonA: Bool = false
var pressingButtonB: Bool = false
override init() {
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
}
func startAdvertising() {
let advertisementData: [String : Any] = [
CBAdvertisementDataLocalNameKey: "micro:bit sim",
CBAdvertisementDataServiceUUIDsKey: [serviceUUID],
]
peripheralManager?.startAdvertising(advertisementData)
}
func stopAdvertising() {
peripheralManager?.stopAdvertising()
}
func addService() {
peripheralManager?.removeAllServices()
let service = CBMutableService(type: serviceUUID, primary: true)
let rx = CBMutableCharacteristic(type: rxUUID, properties: [.read, .notify], value: nil, permissions: [.readable])
let tx = CBMutableCharacteristic(type: txUUID, properties: [.write, .writeWithoutResponse], value: nil, permissions: [.writeable])
service.characteristics = [rx, tx]
peripheralManager?.add(service)
rx.value = Data(bytes: Array<UInt8>(repeating: 0, count: 10))
self.rxCharacteristic = rx
self.txCharacteristic = tx
}
func notify() {
guard let characteristic = rxCharacteristic else { return }
let data = Data(bytes: [0x00, 0x00,
0x00, 0x00,
pressingButtonA ? 0x01 : 0x00,
pressingButtonB ? 0x01 : 0x00,
0x00, 0x00, 0x00,
0x00,
])
characteristic.value = data
peripheralManager?.updateValue(data, for: characteristic, onSubscribedCentrals: nil)
}
}
extension BLEPeripheral: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
switch peripheral.state {
case .poweredOn:
print("poweredOn")
addService()
startAdvertising()
default:
print(peripheral.state)
stopAdvertising()
}
}
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
print("didStartAdvertising:", error ?? "success")
}
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
print("didAdd:", service, error ?? "success")
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
print("didReceiveRead:", request)
if let characteristic = rxCharacteristic, request.characteristic.uuid == characteristic.uuid {
request.value = characteristic.value
peripheral.respond(to: request, withResult: .success)
} else {
peripheral.respond(to: request, withResult: .requestNotSupported)
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
print("didReceiveWrite:", requests)
guard let firstRequest = requests.first else {
fatalError()
}
for request in requests {
if let characteristic = txCharacteristic, request.characteristic.uuid == characteristic.uuid {
characteristic.value = request.value
} else {
peripheral.respond(to: firstRequest, withResult: .requestNotSupported)
return
}
}
peripheral.respond(to: firstRequest, withResult: .success)
}
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
print("didSubscribeTo:", central, characteristic)
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { [weak self] (_) in
self?.notify()
})
}
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
print("didUnsubscribeFrom:", central, characteristic)
timer?.invalidate()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment