h2zero / NimBLE-Arduino

A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.
https://h2zero.github.io/NimBLE-Arduino/
Apache License 2.0
672 stars 138 forks source link

Adverstisement Data does not contain service information after restarting advertisement #550

Closed sanastasiou closed 1 year ago

sanastasiou commented 1 year ago

Hi,

I have the following code

` fPServer = BLEDevice::createServer(); fPServer->setCallbacks(new ble::ServerCallbacks(fDevicePin, *this));

    fPKillswitchService = fPServer->createService(constants::SERVICE_UUID.c_str());

    // setup characteristics
    fPServiceCharacteristics[CHARACTERISTICS_INDEX::PING] = addCharacteristicToService(*fPKillswitchService, constants::PING_CHARACTERISTIC_UUID.c_str(), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::INDICATE);
    fPServiceCharacteristics[CHARACTERISTICS_INDEX::VOLTAGE] = addCharacteristicToService(*fPKillswitchService, constants::VOLTAGE_CHARACTERISTIC_UUID.c_str(), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::INDICATE);
    fPServiceCharacteristics[CHARACTERISTICS_INDEX::STATE] = addCharacteristicToService(*fPKillswitchService, constants::STATE_CHARACTERISTIC_UUID.c_str(), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::INDICATE);
    fPServiceCharacteristics[CHARACTERISTICS_INDEX::SETTINGS] = addCharacteristicToService(*fPKillswitchService, constants::SETTINGS_CHARACTERISTIC_UUID.c_str(), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_ENC);
    fPServiceCharacteristics[CHARACTERISTICS_INDEX::SETTINGS]->setCallbacks(new ble::SettingsCallbacks());

    //start service
    fPKillswitchService->start();
    fPAdvertisingData = NimBLEDevice::getAdvertising();
    fPAdvertisingData->addServiceUUID(constants::SERVICE_UUID.c_str());
    fPAdvertisingData->setScanResponse(true);
    fPAdvertisingData->start();`

That works fine and in the scan response I can see the service offered. Now, later in the code I want to modify the advertisement data.

NimBLEAdvertisementData adData;
 char buffer[20];
 auto const count = sprintf(buffer, "v:%d|%d", aPseudoVoltage, fState);
 adData.setManufacturerData(std::string((char *)&buffer[0], count));
        fPAdvertisingData->stop();
        fPAdvertisingData->setServiceData(NimBLEUUID(constants::SERVICE_UUID.c_str()), std::string((char*)&fState, sizeof(fState)));
        fPAdvertisingData->setAdvertisementData(adData);
        fPAdvertisingData->start();`

After this is done, the advrtisement data does not contain any information about the service.. So I am confused a bit. Why does the advertisement data does not contain service info after I stop-start it?

h2zero commented 1 year ago
        fPAdvertisingData->setServiceData(NimBLEUUID(constants::SERVICE_UUID.c_str()), std::string((char*)&fState, sizeof(fState)));
        fPAdvertisingData->setAdvertisementData(adData);

Those 2 lines are the issue. You cannot mix the use of the NimBLEAdvertisementData and the advertising class data. What you need to do is set one or the other, such as changing the first line here to:

adData.setServiceData(NimBLEUUID(constants::SERVICE_UUID.c_str()), std::string((char*)&fState, sizeof(fState)));

Or remove the use of NimBLEAdvertisementData and instead just set the manufacturer data in the advertising class:

fPAdvertisingData->setManufacturerData(std::string((char *)&buffer[0], count));
sanastasiou commented 1 year ago

Oh thank you very much for the fast reply. Going to try this out and let u know. I have just migrated from the old kolban libraries to this one and that used to work back there.

I will let u know and close this ticket if it works.

sanastasiou commented 1 year ago

            auto const count = sprintf(buffer, "v:%d|%d", aPseudoVoltage, fState);
            fPAdvertisingData->stop();
            fPAdvertisingData->setManufacturerData(std::string((char *)&buffer[0], count));
            fPAdvertisingData->addServiceUUID(constants::SERVICE_UUID.c_str());
            fPAdvertisingData->setScanResponse(true);
            fPAdvertisingData->start();

So, after stoping / starting the advertisement like this, still the same issue.
sanastasiou commented 1 year ago

More testing. Simply doing this (no start/stop involved):


        char buffer[20];
        auto const count = sprintf(buffer, "v:%d|%d", voltage, 5);
        fPAdvertisingData->setServiceData(NimBLEUUID(constants::SERVICE_UUID.c_str()), std::string((char*)&count, sizeof(count)));
        fPAdvertisingData->setScanResponse(true);
        fPAdvertisingData->start();

Results in advertisement data but which does not contain any service information.
sanastasiou commented 1 year ago

    {
        fPAdvertisingData = NimBLEDevice::getAdvertising();
        char buffer[20];
        auto const count = sprintf(buffer, "v:%d|%d", voltage, 5);
        fAdvertisementData.setCompleteServices(NimBLEUUID(constants::SERVICE_UUID.c_str()));
        fAdvertisementData.setManufacturerData(std::string((char*)&count, sizeof(count)));
        fPAdvertisingData->setAdvertisementData(fAdvertisementData);
        fPAdvertisingData->setScanResponse(true);
    }

This works, including start/stop. Closing the ticket.