@@ -11,16 +11,22 @@ import CoreBluetooth
11
11
import Combine
12
12
13
13
@available ( iOS 13 . 0 , * )
14
- class BLEClient : NSObject , CBCentralManagerDelegate {
14
+ class BLEClient : NSObject , CBCentralManagerDelegate , CBPeripheralDelegate {
15
15
16
16
private let tag = " BLEClient "
17
17
18
+ public var onMessageReceivedListener : ( ( String ) -> Void ) ?
19
+
18
20
private lazy var centralManager = CBCentralManager ( delegate: self , queue: nil )
19
21
private var connectedPeripheral : CBPeripheral ?
22
+ private var characteristic : CBCharacteristic ?
20
23
21
24
private var scanResults : AsyncStream < Result < Peripheral , BLEError > > ?
22
25
private var scanResultsContinuation : AsyncStream < Result < Peripheral , BLEError > > . Continuation ?
23
26
27
+ private var connectCompletion : ( ( Result < Any ? , BLEError > ) -> Void ) ?
28
+
29
+
24
30
func start( ) {
25
31
// check the state to init bluetooth manager
26
32
centralManager. state
@@ -74,8 +80,17 @@ class BLEClient : NSObject, CBCentralManagerDelegate {
74
80
centralManager. stopScan ( )
75
81
}
76
82
77
- func connectToPeripheral( address: String ) async {
83
+ func connectToPeripheral( identifier: String , completion: @escaping ( Result < Any ? , BLEError > ) -> Void ) -> Void {
84
+ log ( tag: tag, message: " Trying to connect to \( identifier) " )
85
+ guard let uuid = UUID ( uuidString: identifier) , let peripheral = centralManager. retrievePeripherals ( withIdentifiers: [ uuid] ) . first else {
86
+ log ( tag: tag, message: " Cannot connect to \( identifier) , not found. " )
87
+ completion ( . failure( BLEError ( message: " Could not find peripheral with the specified identifier \( identifier) " ) ) )
88
+ return
89
+ }
78
90
91
+ connectCompletion = completion
92
+ connectedPeripheral = peripheral
93
+ centralManager. connect ( peripheral)
79
94
}
80
95
81
96
func sendMessage( message: String ) async {
@@ -115,11 +130,77 @@ class BLEClient : NSObject, CBCentralManagerDelegate {
115
130
}
116
131
117
132
func centralManager( _ central: CBCentralManager , didConnect peripheral: CBPeripheral ) {
118
- // print("Connected to peer \(peripheral.identifier)")
119
- // connected = true
120
- // centralManager?.stopScan()
121
- // peripheral.delegate = self
122
- // peripheral.discoverServices([service])
133
+ log ( tag: tag, message: " Successfully connected to peer \( peripheral. identifier. uuidString) , discovering services... " )
134
+ peripheral. delegate = self
135
+ peripheral. discoverServices ( [ SERVICE_ID] )
136
+ }
137
+
138
+ func centralManager( _ central: CBCentralManager , didFailToConnect peripheral: CBPeripheral , error: Error ? ) {
139
+ let bleError = BLEError ( message: " Failed to connect to peripheral \( peripheral. identifier. uuidString) " , cause: error)
140
+ connectedPeripheral = nil
141
+ log ( tag: tag, error: bleError)
142
+ connectCompletion ? ( . failure( bleError) )
143
+ }
144
+
145
+ func peripheral( _ peripheral: CBPeripheral , didDiscoverServices error: Error ? ) {
146
+ if let error = error {
147
+ let bleError = BLEError ( message: " Error discovering services of peripheral \( peripheral. identifier. uuidString) " , cause: error)
148
+ log ( tag: tag, error: bleError)
149
+ connectCompletion ? ( . failure( bleError) )
150
+ } else {
151
+ log ( tag: tag, message: " Successfully discovered services, looking for our service... " )
152
+
153
+ if let service = peripheral. services? . first ( where: { $0. uuid == SERVICE_ID} ) {
154
+ log ( tag: tag, message: " Found our service, discovering characteristics... " )
155
+ peripheral. discoverCharacteristics ( [ CHARACTERISTIC_ID] , for: service)
156
+ } else {
157
+ let bleError = BLEError ( message: " Our service was not found, something went horribly wrong " )
158
+ log ( tag: tag, error: bleError)
159
+ connectCompletion ? ( . failure( bleError) )
160
+ }
161
+ }
162
+ }
163
+
164
+ func peripheral( _ peripheral: CBPeripheral , didDiscoverCharacteristicsFor service: CBService , error: Error ? ) {
165
+ if let error = error {
166
+ let bleError = BLEError ( message: " Error discovering characteristics of peripheral \( peripheral. identifier. uuidString) " , cause: error)
167
+ log ( tag: tag, error: bleError)
168
+ connectCompletion ? ( . failure( bleError) )
169
+ } else {
170
+ log ( tag: tag, message: " Successfully discovered characteristics, looking for our characteristic... " )
171
+
172
+ if let characteristic = service. characteristics? . first ( where: { $0. uuid == CHARACTERISTIC_ID } ) {
173
+ log ( tag: tag, message: " Found our characteristic, peripheral is ready! " )
174
+ self . characteristic = characteristic
175
+ peripheral. setNotifyValue ( true , for: characteristic)
176
+ connectCompletion ? ( . success( nil ) )
177
+ } else {
178
+ let bleError = BLEError ( message: " Our characteristic was not found, something went horribly wrong " )
179
+ log ( tag: tag, error: bleError)
180
+ connectCompletion ? ( . failure( bleError) )
181
+ }
182
+ }
183
+ }
184
+
185
+ func peripheral( _ peripheral: CBPeripheral , didUpdateValueFor characteristic: CBCharacteristic , error: Error ? ) {
186
+ log ( tag: tag, message: " Characteristic value updated " )
187
+
188
+ guard let data = characteristic. value else {
189
+ log ( tag: tag, message: " Update was empty " )
190
+ return
191
+ }
192
+
193
+ guard let dataStr = String ( data: data, encoding: String . Encoding. utf8) else {
194
+ log ( tag: tag, message: " Could not convert received data into a string " )
195
+ return
196
+ }
197
+
198
+ if !dataStr. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty {
199
+ log ( tag: tag, message: " Received data: \( dataStr) " )
200
+ onMessageReceivedListener ? ( dataStr)
201
+ } else {
202
+ log ( tag: tag, message: " Update was empty " )
203
+ }
123
204
}
124
205
125
206
private func assertBluetoothState( ) -> Result < Any ? , BLEError > {
0 commit comments