NimBLE-Arduino icon indicating copy to clipboard operation
NimBLE-Arduino copied to clipboard

NimBLE HID + custom service

Open rryando opened this issue 9 months ago • 8 comments

Hi there,

so I tried to create a service that act as I/O via customService from my phone to my esp32c3 the BLE also act as HID devices if connected (it could be connect silmutaneously)

this works just fine when using bluedroid, but when ported into NimBLE, we got security issue to the HID not writing

  • here's my NimBLE version of the script

void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println("Starting ESP32 NimBLE Test...");

    NimBLEDevice::init(DEVICE_NAME);
    Serial.println("NimBLE Device initialized.");

    NimBLEDevice::setSecurityAuth(true, true, true);
    NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
    NimBLEDevice::setSecurityPasskey(PASSKEY);
    NimBLEDevice::setMTU(500);

    pServer = NimBLEDevice::createServer();
    pServer->setCallbacks(&serverCallbacks);
    pHid = new NimBLEHIDDevice(pServer);

    pInputKeyboard = pHid->getInputReport(KEYBOARD_ID);   
    pOutputKeyboard = pHid->getOutputReport(KEYBOARD_ID); 
    pInputMediaKeys = pHid->getInputReport(MEDIA_KEYS_ID);

    pHid->setReportMap((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor));
    pHid->setManufacturer("Manufacture"); // Set manufacturer
    pHid->setPnp(0x02, 0x1234, 0x5678, 0x0110); // Optional: PnP ID 
    pHid->setHidInfo(0x00, 0x01); // Set HID info with just version and country code

    pHid->startServices(); // This creates the HID service and characteristics

    // --- Setup Custom Service ---
    pCustomService = pServer->createService(CUSTOM_SERVICE_UUID);
    pCustomCharacteristic = pCustomService->createCharacteristic(
        CUSTOM_DATA_CHAR_UUID,
        NIMBLE_PROPERTY::READ |
        NIMBLE_PROPERTY::WRITE |
        NIMBLE_PROPERTY::WRITE_ENC |
        NIMBLE_PROPERTY::NOTIFY 
    );

    pCustomCharacteristic->setCallbacks(&charCallbacks); // Set callbacks for custom char
    pCustomCharacteristic->setValue("InitialNimValue");

  
    NimBLEDescriptor* pCCCDesc = pCustomCharacteristic->createDescriptor(
                                        "2902", // Standard CCCD UUID
                                        NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE_ENC,
                                        2 // Max length
                                    );
    pCustomCharacteristic->addDescriptor(pCCCDesc);
    pCustomService->start();
    Serial.println("Custom Service started.");

    // --- Advertising ---
    NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(CUSTOM_SERVICE_UUID);       // Add custom service UUID
    pAdvertising->addServiceUUID(pHid->getHidService()->getUUID()); // Add HID service UUID
    pAdvertising->setAppearance(0x03C1); // HID Keyboard appearance
    // pAdvertising->enableScanResponse(true);

    NimBLEDevice::startAdvertising();
    Serial.println("Advertising started (HID + Custom).");
    Serial.println("Setup Complete!");
}

-- and here's my Bluedroid version --


void setup() {
    Serial.begin(115200);
    delay(1000); 
    Serial.println("Starting ESP32 BLE Test (Adjusted Conn Params)...");

    esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
   

    BLEDevice::init(DEVICE_NAME);
    Serial.println("BLE Device initialized.");

    pServer = BLEDevice::createServer();
    pServer->setCallbacks(&serverCallbacks); 

    pHid = new BLEHIDDevice(pServer);

    inputKeyboard = pHid->inputReport(KEYBOARD_ID);
    outputKeyboard = pHid->outputReport(KEYBOARD_ID);
    inputMediaKeys = pHid->inputReport(MEDIA_KEYS_ID);
    pHid->reportMap((uint8_t*)_hidReportDescriptor, sizeof(_hidReportDescriptor));
    pHid->manufacturer()->setValue("Manufacturer");

    // BLE Security configuration using BLESecurity class (as in previous step)
    BLESecurity *pSecurity = new BLESecurity();
    pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND); 
    pSecurity->setCapability(ESP_IO_CAP_IO); 
    pSecurity->setKeySize(16);
    pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
    pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
    BLEDevice::setSecurityCallbacks(&securityCallbacks); 

    pHid->startServices();
    
    Serial.println("BLE Server created.");

    pCustomService = pServer->createService(CUSTOM_SERVICE_UUID);
    pCustomCharacteristic = pCustomService->createCharacteristic(
        CUSTOM_DATA_CHAR_UUID,
        BLECharacteristic::PROPERTY_READ |
        BLECharacteristic::PROPERTY_WRITE |
        BLECharacteristic::PROPERTY_NOTIFY 
    );

    BLE2902* p2902Descriptor = new BLE2902();
    p2902Descriptor->setAccessPermissions(ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE_ENCRYPTED);
    pCustomCharacteristic->addDescriptor(p2902Descriptor);
    pCustomCharacteristic->setCallbacks(&charCallbacks); 
    pCustomCharacteristic->setValue("InitialValue"); 

    pCustomService->start();

    BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
    if (pAdvertising) {
        pAdvertising->addServiceUUID(CUSTOM_SERVICE_UUID); 
        pAdvertising->addServiceUUID(pHid->hidService()->getUUID());
        pAdvertising->setAppearance(0x03C1); 
        Serial.println("Advertising configured (Custom + HID, adjusted conn params).");
        pAdvertising->setScanResponse(true);
        Serial.println("Advertising started.");
    } else {
        Serial.println("Error: Failed to get Advertising object!");
    }

    BLEDevice::startAdvertising();
    Serial.println("Setup Complete!");
}

things to note that, the setAuthenticationMode when advertising multiple service is tricky, I assume the bluedroid one could complete bonding with ESP_IO_CAP_IO because of onConfirmPIN security callback did auto confirm,

but the NimBLE behaviour with this kinda difference, when I tried to connect, it immediately got disconnected before even pressing the pair prompt (since there's no security callback to handle this (?))

here's the log of immediate connection fail if using BLE_HS_IO_DISPLAY_ONLY

--- NimBLE Server: Client Connected ---
Conn ID: 1, Address: 64:a6:f2:26:92:51
--- NimBLE Security: onAuthenticationComplete ---
Authentication Failed!
Encrypted: No, Conn Interval: 24

i tried different setSecurityIOCap some could be connected both custom service + HID, but the HID was not triggering anything event after bonding with (BLE_HS_IO_DISPLAY_YESNO)

anyone have experienced this ?

thank you!

rryando avatar May 07 '25 12:05 rryando

I would start by deleting this:

    NimBLEDescriptor* pCCCDesc = pCustomCharacteristic->createDescriptor(
                                        "2902", // Standard CCCD UUID
                                        NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE_ENC,
                                        2 // Max length
                                    );
    pCustomCharacteristic->addDescriptor(pCCCDesc);

It has no functionality in this library, the BLE stack will create it internally.

As for the issue itself I would need to see the logs at debug level. One thing to try is disabling SC:

NimBLEDevice::setSecurityAuth(true, true, false);

Sometimes that messes with things.

h2zero avatar May 07 '25 13:05 h2zero

Thank you for fast reply!

here's the log debug level

Starting ESP32 NimBLE Test...
Button pins configured.
I NimBLEDevice: BLE Host Task Started
I NimBLEDevice: NimBle host synced.
NimBLE Device initialized.
D NimBLEDevice: Setting bonding: 1, mitm: 1, sc: 0
D NimBLEService: Adding a duplicate characteristic with UUID: 0x2a4d
D NimBLEService: Adding a duplicate characteristic with UUID: 0x2a4d
D NimBLEService: >> start(): Starting service: UUID: 0x180a, handle: 0x0000
D NimBLEService: Adding 2 characteristics for service UUID: 0x180a, handle: 0x0000
D NimBLEService: << start()
D NimBLEService: >> start(): Starting service: UUID: 0x1812, handle: 0x0000
D NimBLEService: Adding 7 characteristics for service UUID: 0x1812, handle: 0x0000
D NimBLEService: << start()
D NimBLEService: >> start(): Starting service: UUID: 0x180f, handle: 0x0000
D NimBLEService: Adding 1 characteristics for service UUID: 0x180f, handle: 0x0000
D NimBLEService: << start()
D NimBLEService: >> start(): Starting service: UUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, handle: 0x0000
D NimBLEService: Adding 1 characteristics for service UUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, handle: 0x0000
D NimBLEService: << start()
Custom Service started.
Advertising configured (Custom + HID, adjusted conn params).
Advertising started.
D NimBLEAdvertising: >> Advertising start: duration=0, dirAddr=NULL
primary service
           uuid 0x1800
         handle 1
     end_handle 5
characteristic
           uuid 0x2a00
     def_handle 2
     val_handle 3
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2a01
     def_handle 4
     val_handle 5
   min_key_size 0
          flags [READ]
primary service
           uuid 0x1801
         handle 6
     end_handle 13
characteristic
           uuid 0x2a05
     def_handle 7
     val_handle 8
   min_key_size 0
          flags [INDICATE]
ccc descriptor
           uuid 0x2902
         handle 9
   min_key_size 0
          flags [READ|WRITE]
characteristic
           uuid 0x2b3a
     def_handle 10
     val_handle 11
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2b29
     def_handle 12
     val_handle 13
   min_key_size 0
          flags [READ|WRITE]
primary service
           uuid 0x180a
         handle 14
     end_handle 18
characteristic
           uuid 0x2a50
     def_handle 15
     val_handle 16
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2a29
     def_handle 17
     val_handle 18
   min_key_size 0
          flags [READ]
primary service
           uuid 0x1812
         handle 19
     end_handle 38
characteristic
           uuid 0x2a4a
     def_handle 20
     val_handle 21
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2a4b
     def_handle 22
     val_handle 23
   min_key_size 0
          flags [READ]
characteristic
           uuid 0x2a4c
     def_handle 24
     val_handle 25
   min_key_size 0
          flags [WRITE_NO_RSP]
characteristic
           uuid 0x2a4e
     def_handle 26
     val_handle 27
   min_key_size 0
          flags [READ|WRITE_NO_RSP]
characteristic
           uuid 0x2a4d
     def_handle 28
     val_handle 29
   min_key_size 0
          flags [READ|NOTIFY|READ_ENC]
ccc descriptor
           uuid 0x2902
         handle 30
   min_key_size 0
          flags [READ|WRITE]
descriptor
           uuid 0x2908
         handle 31
   min_key_size 0
          flags [READ|READ_ENC]
characteristic
           uuid 0x2a4d
     def_handle 32
     val_handle 33
   min_key_size 0
          flags [READ|WRITE_NO_RSP|WRITE|READ_ENC|WRITE_ENC]
descriptor
           uuid 0x2908
         handle 34
   min_key_size 0
          flags [READ|WRITE|READ_ENC|WRITE_ENC]
characteristic
           uuid 0x2a4d
     def_handle 35
     val_handle 36
   min_key_size 0
          flags [READ|NOTIFY|READ_ENC]
ccc descriptor
           uuid 0x2902
         handle 37
   min_key_size 0
          flags [READ|WRITE]
descriptor
           uuid 0x2908
         handle 38
   min_key_size 0
          flags [READ|READ_ENC]
primary service
           uuid 0x180f
         handle 39
     end_handle 43
characteristic
           uuid 0x2a19
     def_handle 40
     val_handle 41
   min_key_size 0
          flags [READ|NOTIFY]
ccc descriptor
           uuid 0x2902
         handle 42
   min_key_size 0
          flags [READ|WRITE]
descriptor
           uuid 0x2904
         handle 43
   min_key_size 0
          flags [READ]
primary service
           uuid 4fafc201-1fb5-459e-8fcc-c5c9c331914b
         handle 44
     end_handle 47
characteristic
           uuid 4fafc202-1fb5-459e-8fcc-c5c9c331914b
     def_handle 45
     val_handle 46
   min_key_size 0
          flags [WRITE|NOTIFY|READ_ENC]
ccc descriptor
           uuid 0x2902
         handle 47
   min_key_size 0
          flags [READ|WRITE]
D NimBLEAdvertising: setAdvertisementData: 02 01 06 03 03 12 18 11 07 4b 91 31 c3 c9 c5 cc 8f 9e 45 b5 1f 01 c2 af 4f 03 19 c1 03
D NimBLEAdvertising: << Advertising start
Advertising started (HID + Custom).
Setup Complete!
D NimBLEServer: >> handleGapEvent: 
--- NimBLE Server: Client Connected ---
Conn ID: 1, Address: 78:22:1a:1c:fa:ad
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=46, subscribed: true
--- NimBLE Char 4fafc202-1fb5-459e-8fcc-c5c9c331914b: Client 78:22:1a:1c:fa:ad subscribed to notifications/indications
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: >> handleGapEvent: 
D NimBLEServerCallbacks: onPassKeyDisplay: default: 123456
D NimBLEServer: BLE_SM_IOACT_DISP; ble_sm_inject_io result: 0
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: >> handleGapEvent: 
--- NimBLE Security: onAuthenticationComplete ---
Authentication Success!
Bonding Successful!
Encrypted: Yes, Conn Interval: 24
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEServer: >> handleGapEvent:
D NimBLEServerCallbacks: onIdentity: default
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=8, subscribed: true
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEServer: >> handleGapEvent: 
...
D NimBLEServer: << handleGapEvent
D NimBLEServer: Gatt Write event
D NimBLEServer: >> handleGapEvent: 
--- NimBLE Custom Char: Write received from 78:22:1a:1c:fa:ad: ANIMATE_SLEEPY (len 14)
D NimBLEServer: << handleGapEvent
...
D NimBLEServer: Gatt Read event
D NimBLECharacteristicCallbacks: onRead: default
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: Gatt Read event
D NimBLECharacteristicCallbacks: onRead: default
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: Gatt Read event
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: Gatt Read event
...
D NimBLEDescriptorCallbacks: onRead: default
D NimBLEServer: Gatt Read event
D NimBLEDescriptorCallbacks: onRead: default
D NimBLEServer: Gatt Read event
D NimBLEDescriptorCallbacks: onRead: default
D NimBLEServer: Gatt Read event
D NimBLECharacteristicCallbacks: onRead: default
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent:
I NimBLEServer: subscribe event; attr_handle=29, subscribed: true
D NimBLECharacteristicCallbacks: onSubscribe: default
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEServer: Gatt Read event
D NimBLECharacteristicCallbacks: onRead: default
D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=36, subscribed: true
D NimBLECharacteristicCallbacks: onSubscribe: default
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=41, subscribed: true
D NimBLECharacteristicCallbacks: onSubscribe: default
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
D NimBLEServer: << handleGapEvent
[ 28102][D][Tone.cpp:124] tone(): _pin=7, frequency=1800 Hz, duration=100 ms
[ 28109][V][Tone.cpp:62] tone_init(): Creating tone queue
[ 28114][V][Tone.cpp:68] tone_init(): Tone queue created
[ 28119][V][Tone.cpp:72] tone_init(): Creating tone task
[ 28124][V][Tone.cpp:85] tone_init(): Tone task created
Sending Volume Up via HID...
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
[ 28132][D][Tone.cpp:31] tone_task(): Task received from queue TONE_START: _pin=7, frequency=1800 Hz, duration=100 ms
[ 28153][D][Tone.cpp:33] tone_task(): Setup LED controll on channel 0
E (29151) ledc: ledc_get_duty(745): LEDC is not initialized
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
D NimBLEServer: >> handleGapEvent: 
...
D NimBLEServer: << handleGapEvent
[ 31050][D][Tone.cpp:124] tone(): _pin=7, frequency=1800 Hz, duration=100 ms
Sending Volume Up via HID...
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
[ 31060][D][Tone.cpp:31] tone_task(): Task received from queue TONE_START: _pin=7, frequency=1800 Hz, duration=100 ms
[ 31081][D][Tone.cpp:33] tone_task(): Setup LED controll on channel 0
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent

Yes, I guess the secure part did cause some problem when bond,

I think for the multi advertise connection is working now, im trying figuring out the HID part, im not quite sure if it's related to this or not, but it seems that the HID part still got issue ?

I gonna try with simple sketch

rryando avatar May 07 '25 14:05 rryando

Okay, so, I modified this library https://github.com/T-vK/ESP32-BLE-Keyboard to use the latest version of the NimBLE (https://github.com/h2zero/NimBLE-Arduino/releases/tag/2.2.3)

and test for simple sketch, it doesn't work to my android phone but it does work on my windows pc 😅

rryando avatar May 07 '25 15:05 rryando

okay, so I have tried other HID lib (https://github.com/Mystfit/ESP32-BLE-CompositeHID) with minimal sketch + latest NimBLE result: Keypress works, but Media Keys doesn't work in android (tested from NimBLE version 2.1.0 to latest)

I also tried the https://github.com/T-vK/ESP32-BLE-Keyboard with older version of Nimble (1.4.3) everything works in android

is there any workaround for the android media keys to works in latest NimBLE ?

rryando avatar May 08 '25 00:05 rryando

alright, it's confirmed if i downgrade to version 1.4.3 it works fine for both android and my windows pc (media keys) also works (multi advertise - bond - etc), it might be because of the part characteristic reading from HID (?)

but, since this might be different context from what i report at the first place,i will close this issues,

Thank you @h2zero for the Amazing Lib!

rryando avatar May 08 '25 01:05 rryando

Hmm, downgrading versions isn't really a fix lol. I'm going to repoen this and ask that you test with the master branch.

h2zero avatar May 08 '25 13:05 h2zero

ah sure, at least the older version was working for me (better than bluedroid in terms of flash and ram 😅), so I planned to use it temporarily;

but yes, is the version in the master branch have potential fix already ? i will try the lattest commit on main and posted the result here later ya

rryando avatar May 08 '25 13:05 rryando

okay, i tested the code on the master, still not fixed

here's the log

the Sending Volume Up via HID... is the event where i sent the HID key to my paired android device, let me know if you need to to do more testing ya

          flags [READ|READ_ENC]
primary service
           uuid 0x180f
         handle 37
     end_handle 41
characteristic
           uuid 0x2a19
     def_handle 38
     val_handle 39
   min_key_size 0
          flags [READ|NOTIFY]
ccc descriptor
           uuid 0x2902
         handle 40
   min_key_size 0
          flags [READ|WRITE]
descriptor
           uuid 0x2904
         handle 41
   min_key_size 0
          flags [READ]
D NimBLEAdvertising: setAdvertisementData: 02 01 06 03 19 c1 03 03 03 4a 2a
D NimBLEAdvertising: << Advertising start
[   507][D][BleKeyboard.cpp:146] begin(): [] Advertising started!
D NimBLEServer: >> handleGapEvent: 
...
D NimBLEServerCallbacks: onPhyUpdate: default, txPhy: 2, rxPhy: 2
D NimBLEServer: >> handleGapEvent: 
...
D NimBLEServerCallbacks: onIdentity: default
...
D NimBLEServerCallbacks: onAuthenticationComplete: default
D NimBLEServer: << handleGapEvent
...
D NimBLEServerCallbacks: onConnParamsUpdate: default
...
I NimBLEServer: subscribe event; attr_handle=8, subscribed: true
...
D NimBLEServerCallbacks: onConnParamsUpdate: default
D NimBLEServer: << handleGapEvent
D NimBLEServer: Gatt Read event
...
I NimBLEServer: subscribe event; attr_handle=27, subscribed: true
D NimBLECharacteristicCallbacks: onSubscribe: default
...
I NimBLEServer: subscribe event; attr_handle=34, subscribed: true
D NimBLECharacteristicCallbacks: onSubscribe: default
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
D NimBLEServer: >> handleGapEvent: 
I NimBLEServer: subscribe event; attr_handle=39, subscribed: true
D NimBLECharacteristicCallbacks: onSubscribe: default
D NimBLEServer: << handleGapEvent
D NimBLEDeviceCallbacks: onStoreStatus: default
1
[ 14650][D][Tone.cpp:124] tone(): _pin=7, frequency=1800 Hz, duration=100 ms
[ 14657][V][Tone.cpp:62] tone_init(): Creating tone queue
[ 14662][V][Tone.cpp:68] tone_init(): Tone queue created
[ 14667][V][Tone.cpp:72] tone_init(): Creating tone task
[ 14673][V][Tone.cpp:85] tone_init(): Tone task created
Sending Volume Up via HID...
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
[ 14680][D][Tone.cpp:31] tone_task(): Task received from queue TONE_START: _pin=7, frequency=1800 HzD NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
, duration=100 ms
[ 14716][D][Tone.cpp:33] tone_task(): Setup LED controll on channel 0
E (15717) ledc: ledc_get_duty(745): LEDC is not initialized
[ 20676][D][Tone.cpp:124] tone(): _pin=7, frequency=1800 Hz, duration=100 ms
Sending Volume Up via HID...
D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
[ 20686][D][Tone.cpp:31] tone_task(): Task received from queue TONE_START: _pin=7, frequency=18D NimBLEServer: Gatt Read event
D NimBLEServer: >> handleGapEvent:
D NimBLECharacteristicCallbacks: onStatus: default
D NimBLEServer: << handleGapEvent
00 Hz, duration=100 ms
...

rryando avatar May 08 '25 15:05 rryando