Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with Switching Services #163

Open
michaelboeding opened this issue May 25, 2024 · 7 comments
Open

Issue with Switching Services #163

michaelboeding opened this issue May 25, 2024 · 7 comments

Comments

@michaelboeding
Copy link

michaelboeding commented May 25, 2024

I'm running into an issue where I start provisioning my device using esps prov api, which uses its own services. When I go out of that later in the application I create my services, but it seems like IOS is caching these values until I reset my network settings on the device. Which isn't a great solution for customers, is there anyway to make the client not read from the cache on a new connection with the server? Or some other solution to this?

To add a little more context what I'm trying to accomplish is trigger something like the below for IOS

"Once you remove and re-add the service, that will modify the GATT database and trigger a notification to the central. The Bluetooth-standard way to handle this is using the Service Changed characteristic (0x2a05), but it's possible Apple does this in a proprietary way if you're talking between Apple devices. If these are both iOS devices, you should expect the central's CBPeripheralDelegate to receive peripheral(_:didModifyServices:) (possibly twice, once for removing, and once for adding)"

 func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
        print("Sevices have been updated called for this item")
        peripheral.discoverServices(scanningServiceArray)
    }

And then what I currently have is something like the below

//methoud used to setup the bluetooth as a server
void BluetoothLayer::setupBluetoothServer(){
//check to make sure the bluetooth is not already setup
if (this->server != nullptr){
return;
}
//setup the bluetooth server
NimBLEDevice::init(DEVICE_ID);
// Create the BLE Server
this->server = NimBLEDevice::createServer();
this->server->setCallbacks(this);
//setup the services
this->setupGATTService();
this->setupGenericAccessService();
this->setupDeviceInfoService();
this->setupDeviceBatteryService();
this->setupCustomService();
this->startAdvertising();

this->mtuSize = NimBLEDevice::getMTU();
printf("ALL SERVICES SETUP FOR BLE\n");

}

Basically I am creating all the services I want to use and setting up the characteristics but this is where I also get some weird behavior as the Generic Access Service, and the GATT Service never seem to show up in my ble sniffer apps or they show up on my MAC sniffer app but it says "There aren't any characteristics for this service" but im adding the SERVICE_CHANGED_CHARACTERISTIC_UUID as specified by the BLE SIG. Is there something happening under the hood for this? Or something that I don't understand?

I've also tried to enable dynamic services in the nimble config.

Also here is the link to the esp ble prov api I'm using https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/provisioning/wifi_provisioning.html?highlight=wifi%20prov#_CPPv420wifi_prov_cb_event_t

@h2zero
Copy link
Owner

h2zero commented Jun 4, 2024

The basic required services are automatically created by the stack, no need to define them yourself.

@michaelboeding
Copy link
Author

I never see those services when I run a BLE sniffer though? Should they automatically appear as services?

@h2zero
Copy link
Owner

h2zero commented Jun 4, 2024

They show in nrfConnect on android but not iOS. iOS automatically subscribes to the service changed characteristic.

@michaelboeding
Copy link
Author

michaelboeding commented Jun 4, 2024

Got it - the weird thing is I never get the callbacks for services changed...has it ever been tested?

// This method is called when the peripheral's services are modified
func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
    print("Services modified: \(invalidatedServices)")
    
    // Handle the modified services
    for service in invalidatedServices {
        print("Service \(service.uuid) was invalidated")
        
        // Rediscover the services if necessary
        peripheral.discoverServices([service.uuid])
    }
}

@h2zero
Copy link
Owner

h2zero commented Jun 4, 2024

That is all handled by the stack at a lower level, not presented to the app code. With full debug logging turned on you can see iOS subscribe to it. If you make a change to the services the indication will be sent by the stack as well.

@michaelboeding
Copy link
Author

I'll try to run it in full debug - I'm never receiving it currently in CoreBluetooths callbacks. I'm also running the latest 5.2.1 of the IDF but I can't confirm that it worked previously either.

@h2zero
Copy link
Owner

h2zero commented Jun 4, 2024

You won't see anything for the most part, all you'll see is a log message from the NimBLE core that shows iOS subscribed to a handle. As far as changing services goes there needs to be no active connections or advertising/scanning active when they are changed, then when a bonded device connects they receive the service changed notification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants