diff --git a/Bluejay.podspec b/Bluejay.podspec
index 0ea97a3..6a90a6a 100644
--- a/Bluejay.podspec
+++ b/Bluejay.podspec
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = 'Bluejay'
- spec.version = '0.4.8'
+ spec.version = '0.4.9'
spec.license = { type: 'MIT', file: 'LICENSE' }
spec.homepage = 'https://github.com/steamclock/bluejay'
spec.authors = { 'Jeremy Chiang' => 'jeremy@steamclock.com' }
spec.summary = 'Bluejay is a simple Swift framework for building reliable Bluetooth apps.'
spec.homepage = 'https://github.com/steamclock/bluejay'
- spec.source = { git: 'https://github.com/steamclock/bluejay.git', tag: 'v0.4.8' }
+ spec.source = { git: 'https://github.com/steamclock/bluejay.git', tag: 'v0.4.9' }
spec.source_files = 'Bluejay/Bluejay/*.{h,swift}'
spec.framework = 'SystemConfiguration'
spec.platform = :ios, '9.3'
diff --git a/Bluejay/Bluejay/Error.swift b/Bluejay/Bluejay/Error.swift
index 3cf8621..aa7e414 100644
--- a/Bluejay/Bluejay/Error.swift
+++ b/Bluejay/Bluejay/Error.swift
@@ -54,6 +54,8 @@ public enum BluejayError {
case listenCacheDecoding(Error)
/// Bluejay has cancelled an expected end listen request.
case endListenCancelled
+ /// Indefinite flush will not exit.
+ case indefiniteFlush
}
extension BluejayError: LocalizedError {
@@ -103,6 +105,8 @@ extension BluejayError: LocalizedError {
return "Listen cache decoding failed with error: \(error.localizedDescription)"
case .endListenCancelled:
return "End listen cancelled."
+ case .indefiniteFlush:
+ return "Flush listen timeout cannot be none or zero."
}
}
}
@@ -137,6 +141,7 @@ extension BluejayError: CustomNSError {
case .listenCacheEncoding: return 20
case .listenCacheDecoding: return 21
case .endListenCancelled: return 22
+ case .indefiniteFlush: return 23
}
}
diff --git a/Bluejay/Bluejay/Info.plist b/Bluejay/Bluejay/Info.plist
index 1fafae9..e4ee6b9 100644
--- a/Bluejay/Bluejay/Info.plist
+++ b/Bluejay/Bluejay/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 0.4.8
+ 0.4.9
CFBundleVersion
$(CURRENT_PROJECT_VERSION)
NSPrincipalClass
diff --git a/Bluejay/Bluejay/SynchronizedPeripheral.swift b/Bluejay/Bluejay/SynchronizedPeripheral.swift
index 79f9210..cca8ea7 100644
--- a/Bluejay/Bluejay/SynchronizedPeripheral.swift
+++ b/Bluejay/Bluejay/SynchronizedPeripheral.swift
@@ -202,75 +202,77 @@ public class SynchronizedPeripheral {
/**
Flush a listen to a characteristic by receiving and discarding values for the specified duration.
+ **Warning** Timeout defaults to 3 seconds. Specifying no timeout or a timeout with zero second will result in a fatal error.
+
- Parameters:
- characteristicIdentifier: The characteristic to flush.
- - idleWindow: How long to flush for in seconds.
+ - nonZeroTimeout: How long to wait for incoming data.
- completion: Block to call when the flush is complete.
*/
- public func flushListen(to characteristicIdentifier: CharacteristicIdentifier, idleWindow: Int = 3, completion: @escaping () -> Void) throws {
- let flushSem = DispatchSemaphore(value: 0)
- let cleanUpSem = DispatchSemaphore(value: 0)
- let sem = DispatchSemaphore(value: 0)
+ public func flushListen(to characteristicIdentifier: CharacteristicIdentifier, nonZeroTimeout: Timeout = .seconds(3), completion: @escaping () -> Void) throws {
+ guard case let .seconds(timeoutInterval) = nonZeroTimeout, timeoutInterval > 0 else {
+ fatalError(BluejayError.indefiniteFlush.errorDescription!)
+ }
+
+ let listenSem = DispatchSemaphore(value: 0)
+ let endListenSem = DispatchSemaphore(value: 0)
var error : Error?
var shouldListenAgain = false
- repeat {
- DispatchQueue.main.async {
- log("Flushing listen to \(characteristicIdentifier.uuid.uuidString)")
-
- shouldListenAgain = false
+ DispatchQueue.main.async {
+ log("Flushing listen to \(characteristicIdentifier.uuid.uuidString)")
+
+ shouldListenAgain = false
+
+ self.parent.listen(to: characteristicIdentifier, completion: { (result : ReadResult) in
+ switch result {
+ case .success:
+ log("Flushed some data.")
+
+ shouldListenAgain = true
+ case .cancelled:
+ log("Flush cancelled.")
+
+ shouldListenAgain = false
+ error = BluejayError.cancelled
+ case .failure(let e):
+ log("Flush failed with error: \(e.localizedDescription)")
+
+ shouldListenAgain = false
+ error = e
+ }
- self.parent.listen(to: characteristicIdentifier, completion: { (result : ReadResult) in
+ listenSem.signal()
+ })
+ }
+
+ repeat {
+ shouldListenAgain = false
+ _ = listenSem.wait(timeout: .now() + DispatchTimeInterval.seconds(Int(timeoutInterval)))
+ log("Flush to \(characteristicIdentifier.uuid.uuidString) finished, should flush again: \(shouldListenAgain).")
+ } while shouldListenAgain
+
+ DispatchQueue.main.async {
+ if self.parent.isListening(to: characteristicIdentifier) {
+ self.parent.endListen(to: characteristicIdentifier, error: nil, completion: { (result) in
switch result {
case .success:
- log("Flushed some data.")
- shouldListenAgain = true
-
- flushSem.signal()
+ break
case .cancelled:
break
case .failure(let e):
- log("Flush failed with error: \(e.localizedDescription)")
- shouldListenAgain = false
error = e
-
- flushSem.signal()
}
+
+ endListenSem.signal()
})
+ } else {
+ endListenSem.signal()
}
-
- _ = flushSem.wait(timeout: .now() + .seconds(idleWindow))
-
- DispatchQueue.main.async {
- if self.parent.isListening(to: characteristicIdentifier) {
- self.parent.endListen(to: characteristicIdentifier, error: nil, completion: { (result) in
- switch result {
- case .success:
- break
- case .cancelled:
- break
- case .failure(let e):
- error = e
- }
-
- cleanUpSem.signal()
- })
- }
- }
-
- _ = cleanUpSem.wait(timeout: .distantFuture)
-
- DispatchQueue.main.async {
- log("Flush to \(characteristicIdentifier.uuid.uuidString) finished, should flush again: \(shouldListenAgain).")
-
- if !shouldListenAgain {
- sem.signal()
- }
- }
- } while shouldListenAgain
+ }
- _ = sem.wait(timeout: .distantFuture)
+ _ = endListenSem.wait(timeout: .now() + DispatchTimeInterval.seconds(Int(timeoutInterval)))
if let error = error {
throw error