I'm having an issue understanding or using Dispatchgroup. I've read a lot about them however most examples / documentation are very vague or doesn't resemble what I want to do, however every time I mention my problem everyone says "USE DISPATCH GROUPS!".
Here's what I want to do(NOTE: SEQUENTIAL ORDER IS CRUCIAL):
- Send Bluetooth Write characteristic.
- device receives value, and spits something in response
- Read Bluetooth response (via a read characteristic)
- Send a new write characteristic (a different command)
- device receives NEW command, spits NEW data response
Repeat twice (3 commands total, 3 different responses total).
My code:
func tPodInitialSetUp()
{
print ("* * * * * BEGIN SET-UP * * * * *")
let setupDispatchGroup = DispatchGroup()
setupDispatchGroup.enter()
self.writeValue(command: Data(CommandModeCmd)) //231: Put t-Pod in command mode, burst mode is OFF returns OK
setupDispatchGroup.leave()
setupDispatchGroup.wait()
setupDispatchGroup.enter()
deviceConnected?.readValue(for: deviceConnectedCh1n2Char!)
print("Sent command 231: returned: \(receivedString1)")
if receivedString1.lowercased() == "ok"
{
print("t-Pod burst mode is OFF")
}
setupDispatchGroup.leave()
setupDispatchGroup.wait()
setupDispatchGroup.enter()
self.writeValue(command: Data(loadProbeCalCmd)) //202: load calibration constants of probe, returns ok or 0
setupDispatchGroup.leave()
setupDispatchGroup.wait()
setupDispatchGroup.enter()
deviceConnected?.readValue(for: deviceConnectedCh1n2Char!)
print("Sent command 202: returned: \(receivedString1)")
if receivedString1.lowercased() == "ok"
{
print("Probe Constants loaded")
}
if receivedString1 == "0"
{
print("No probe connected")
}
setupDispatchGroup.leave()
setupDispatchGroup.wait()
setupDispatchGroup.enter()
self.writeValue(command: Data(probeSNCmd)) //205: load probe serial number
setupDispatchGroup.leave()
setupDispatchGroup.wait()
setupDispatchGroup.enter()
deviceConnected?.readValue(for: deviceConnectedCh1n2Char!)
print("Sent command 205: returned: \(receivedString1)")
if (receivedString1.count == 6)
{
print("received Probe SN: \(receivedString1)")
probeSN = receivedString1
}
setupDispatchGroup.leave()
setupDispatchGroup.notify(queue: .main)
{
tPodSN = String(describing: connectedDeviceName!.dropFirst(7))
print ("* * * SET-UP COMPLETE * * *")
self.writeValue(command: Data(resetCmd)) //200: resets t-Pod
self.writeValue(command: Data(beaconOffCmd)) //211: turns beacon off (temperature output)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)
{
self.dataDisplaySubView.isHidden = false
print ("Adding observers!")
NotificationCenter.default.addObserver(self, selector: #selector(self.updateIncomingData), name: NSNotification.Name(rawValue: DATA_PARSED), object: nil) //Run every time you receive data from BLE
NotificationCenter.default.addObserver(self, selector: #selector(self.calculateTNU), name: NSNotification.Name(rawValue: TOGGLESWITCH_TOGGLED), object: nil) //Run in case the toggle switches change and data needs to be re-calculated
NotificationCenter.default.addObserver(self, selector: #selector(self.parseReceivedData), name: NSNotification.Name(rawValue: DEVICE_FINISHED_SENT_DATA), object: nil) //Run every time you receive the notification that the whole data has been sent
}
}
This calls the bluetooth write command which has the following code and confirmation:
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
guard error == nil else {
print("Error writing descriptor: " + (error?.localizedDescription)!)
return
}
print("Descriptor Value sent")
}
Now, Here's my output:
* * * * * BEGIN SET-UP * * * * *
***** WRITING *****
Wrote: 1 bytes
***** WRITING *****
Wrote: 1 bytes
Sent command 231: returned: **T-Pod-9Ch**
***** WRITING *****
Wrote: 1 bytes
Sent command 202: returned: **T-Pod-9Ch**
***** WRITING *****
Wrote: 1 bytes
Sent command 205: returned: **T-Pod-9Ch**
* * * SET-UP COMPLETE * * *
***** WRITING *****
Wrote: 1 bytes
***** WRITING *****
Wrote: 1 bytes
Characteristic Value sent
Adding observers!
Characteristic Value sent
Characteristic Value sent
Characteristic Value sent
Characteristic Value sent
Clearing TNU Array
Now, as you can see "Characteristic Value Sent" is the confirmation the bluetooth function gives when it sends the value, however this output is created AFTER it finished running the entire code, so basically it put the commands in some pipeline, forgot about them did everything else and THEN sent the commands and therefore the response I'm reading are all nonsense! As you can see all received strings are T-Pod-9Ch (which is just its normal burst output), the expected responses I should get from the commands are OK, OK and a 6 digit number (in that order).
Please help, I've read so many times about how dispatch groups are supposed to work but I just can't get them to do what I want.
If I got your question right, you need to wait for an answer before sending new command.
But your writes doesn't have a completion block, that's why in your case using dispatchGroup makes no sense.
The code below is a common example to use dispatch groups
In your situation you may have several options:
First, if you know that if you send one command and receive an answer exactly for that command, you can call methods in order below:
Call one method to Send command 1
Call another method after an answer for command 1 will be received
Call yet another method to Send command 2
And one more method after getting an answer for command 2 ...
n. Finish setup
Like if I need to register a user, I need to send defined credentials first, get token from the server, then run something after it.
So you will have to add an additional method for each command and you will call them according the order
If you can't recognize for which command you're going to get an answer and you sure that you've send only one command and waiting only one answer, then you can use dispatch group in the way described below:
Let me know if you need more details