Skip to content

Instantly share code, notes, and snippets.

@ChrisMarshallNY
Last active July 20, 2020 22:34
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 ChrisMarshallNY/80f3370d407f9b5f848077e5f2061894 to your computer and use it in GitHub Desktop.
Save ChrisMarshallNY/80f3370d407f9b5f848077e5f2061894 to your computer and use it in GitHub Desktop.
Companion Gists to the Introduction to Core Bluetooth Class
extension ITCB_SDK_Device_Peripheral: CBPeripheralDelegate {
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let error = error {
print("Encountered an error \(error) for the Peripheral \(peripheral.name ?? "ERROR")")
owner?._sendErrorMessageToAllObservers(error: ITCB_Errors.coreBluetooth(error))
return
}
print("Successfully Discovered \(peripheral.services?.count ?? 0) Services for \(peripheral.name ?? "ERROR").")
peripheral.services?.forEach {
print("Discovered Service: \($0.uuid.uuidString)")
peripheral.discoverCharacteristics([_static_ITCB_SDK_8BallService_Question_UUID,
_static_ITCB_SDK_8BallService_Answer_UUID], for: $0)
}
}
}
public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let error = error {
print("Encountered an error \(error) for the Peripheral \(peripheral.name ?? "ERROR")")
owner?._sendErrorMessageToAllObservers(error: ITCB_Errors.coreBluetooth(error))
return
}
print("Successfully Discovered \(service.characteristics?.count ?? 0) Characteristics for the Service \(service.uuid.uuidString), on the Peripheral \(peripheral.name ?? "ERROR").")
service.characteristics?.forEach {
print("Discovered Characteristic: \($0.uuid.uuidString)")
}
owner.peripheralServicesUpdated(self)
}
extension ITCB_SDK_Device_Peripheral {
public func sendQuestion(_ inQuestion: String) {
question = nil
if let peripheral = _peerInstance as? CBPeripheral,
let service = peripheral.services?[_static_ITCB_SDK_8BallServiceUUID.uuidString],
let answerCharacteristic = service.characteristics?[_static_ITCB_SDK_8BallService_Answer_UUID.uuidString] {
_timeoutTimer = Timer.scheduledTimer(withTimeInterval: _timeoutLengthInSeconds, repeats: false) { [unowned self] (_) in
self._timeoutTimer = nil
self.owner?._sendErrorMessageToAllObservers(error: .sendFailed(ITCB_RejectionReason.deviceOffline))
}
_interimQuestion = inQuestion
print("We have received the question \"\(inQuestion)\", and are setting it aside, as we ask the Peripheral to set the notify to true for the answer Characteristic.")
peripheral.setNotifyValue(true, for: answerCharacteristic)
} else {
self.owner?._sendErrorMessageToAllObservers(error: .sendFailed(ITCB_RejectionReason.deviceOffline))
}
}
}
public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if let error = error {
_timeoutTimer?.invalidate()
_timeoutTimer = nil
owner?._sendErrorMessageToAllObservers(error: ITCB_Errors.coreBluetooth(error))
return
}
if let question = _interimQuestion,
let data = question.data(using: .utf8),
characteristic.isNotifying,
let service = peripheral.services?[_static_ITCB_SDK_8BallServiceUUID.uuidString],
let questionCharacteristic = service.characteristics?[_static_ITCB_SDK_8BallService_Question_UUID.uuidString] {
print("The Peripheral's answer Characteristic is now notifying.")
print("Asking the Peripheral \(peripheral.name ?? "ERROR") the question \"\(_interimQuestion ?? "ERROR")\".")
peripheral.writeValue(data, for: questionCharacteristic, type: .withResponse)
}
}
public func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
guard let error = error else {
print("Characteristic \(characteristic.uuid.uuidString) reports that its value was accepted by the Peripheral.")
if let questionString = _interimQuestion {
_interimQuestion = nil
question = questionString
} else {
owner?._sendErrorMessageToAllObservers(error: .sendFailed(ITCB_RejectionReason.peripheralError(nil)))
}
return
}
_timeoutTimer?.invalidate()
_timeoutTimer = nil
if let error = error as? CBATTError {
print("Encountered an error \(error) for the Peripheral \(peripheral.name ?? "ERROR")")
switch error {
case CBATTError.unlikelyError:
owner?._sendErrorMessageToAllObservers(error: .sendFailed(ITCB_Errors.coreBluetooth(ITCB_RejectionReason.questionPlease)))
default:
owner?._sendErrorMessageToAllObservers(error: .sendFailed(ITCB_Errors.coreBluetooth(ITCB_RejectionReason.peripheralError(error))))
}
} else {
owner?._sendErrorMessageToAllObservers(error: .sendFailed(ITCB_RejectionReason.unknown(error)))
}
}
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
_timeoutTimer?.invalidate()
_timeoutTimer = nil
if let error = error {
print("Encountered an error \(error) for the Peripheral \(peripheral.name ?? "ERROR")")
owner?._sendErrorMessageToAllObservers(error: ITCB_Errors.coreBluetooth(error))
return
}
print("Characteristic \(characteristic.uuid.uuidString) Updated its value to \(String(describing: characteristic.value)).")
if let answerData = characteristic.value,
let answerString = String(data: answerData, encoding: .utf8),
!answerString.isEmpty {
peripheral.setNotifyValue(false, for: characteristic)
answer = answerString
}
}
extension Array where Element: CBAttribute {
public subscript(_ inUUIDString: String) -> Element! {
for element in self where element.uuid.uuidString == inUUIDString {
return element
}
return nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment