My (indoor cycling) Smart Trainer & Crank Power Meter (individually) advertises a few services
Indoor Trainer:
Primary - Service - Cycling Power Service (1818)
- Characteristic - Cycling Power
Primary - Service - Fitness Control (FTMS)
- Characteristic - Cycling Power
- Trainer Target Power (from user)
Crank Power Meter:
Primary - Service - Cycling Power Service (1818)
- Characteristic - Cycling Power
with the cycling power service (1818), it advertises transmitted power data but there's no way to control the trainer resistance.
with FTMS, it advertises transmitted power and has a way to send targeted power to it (trainer resistance control)
When CoreBluetooth connects to my indoor trainer device, it (my current code) will automatically list both services and connects to it. (This is not what I want)
I can of course remove the Cycling Power (1818) service when I connect to the indoor trainer but this is not desired as that would remove any ability to connect to other peripherals which offers only the cycling power service
var services = [serviceHeartRateCBUUID,
serviceCyclingSpeedAndCadenceUUID,
serviceCyclingPowerUUID,
serviceFTMSUUID]
centralManager.scanForPeripherals(withServices: services)
After scanning, I then connect to the peripherals & discover the services it offers using (passing the list of services I'm interested in which again includes both the FTMS and Cycling Power Service) With this, I end up w/ 2 connections to the indoor trainer (instead of 1 which I desire)
peripheral.discoverServices(services)
The Ask: The solution I'm searching for is to be able to only connect to the FTMS service on the Indoor trainer while also be able to connect to the crank power meter.
The workaround I'm thinking of is basically to enable a switch for the user to select between FTMS vs Cycling Power Meter, thereby if the user has Both an indoor trainer & a crank power meter connected simultaneously.
Searching stackoverflow and goggle didn't yield me anything useful, all of them just shows how to connect to services (by listing the in the "services" variable like example above)
Update 1:
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print(" >> Discover Services Found : \(service.uuid) service")
peripheral.discoverCharacteristics(nil, for: service)
}
}
In didDiscoverServices func, Looping thru the services found these 2
>> Discover Services Found : 1818 service
>> Discover Services Found : FTMS service
after which it calls peripheral.discoverCharacteristics(nil, for: service)
How can I use the info from didDiscoverServices
(once it detects both FTMS and 1818) to actually ignore 1818?
Thanks to the discussion w/ @SJoshi, I managed to achieve my goal. Only thing is that the code seems overly complicated with 3 different loops needed to achieve the goal.
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
var discoveredServices = [CBUUID]()
var btServicesOffered = [CBService?]()
guard let services = peripheral.services else { return }
print("\nThere are \(services.count) service(S) advertised namely:")
for service in services {
print(" >> \(service.uuid) service")
// Results in discoveredServices:[1818, FTMS]
discoveredServices.append(CBUUID(string: service.uuid.uuidString))
btServicesOffered.append(service)
}
// Can actually remove btServicesOffered as not really used
print(" >>>>> btServicesOffered:\(btServicesOffered)")
if discoveredServices.contains(FTMS) && discoveredServices.contains(1818) {
print("\n >> This is a Smart Trainer advertising 2 services. Connect ONLY to FTMS")
for service in services {
if service.uuid == FTMS {
print(" >> Connecting to FTMS")
peripheral.discoverCharacteristics(nil, for: service)
} else if service.uuid == 1818 {
print(" >> Doing NOTHING for 1818")
}
}
} else {
for service in services {
print(" >> Discover Services Found : \(service.uuid) service")
peripheral.discoverCharacteristics(nil, for: service)
}
}
print()
}