I'm pretty far along in my initial development and I was tackling the Bluetooth. I tried the BlueDroid API at first and got it working, but the code size was ridiculous so I decided to try the "lighter" NimBLE API instead.
With the latest ESP-IDF V5.2.1, I then recreated a very basic NimBLE GATT Server that I modeled after an example in the ESP-IDE and some I found online (bleprph). Everything is working EXCEPT...
For some reason, the characteristic access properties (i.e. read, write, notify) are not being applied to the actual characteristics that get advertised. Here is my code which sets up the service and characteristic definitions:
Code: Select all
static const struct ble_gatt_svc_def gatt_svr_svcs[] =
{
{
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &gatt_svr_svc_uuid.u,
.characteristics = (struct ble_gatt_chr_def[])
{
{
.uuid = &gatt_svr_char_tx_uuid.u,
.access_cb = gatt_svr_chr_access_cb,
.val_handle = ¬ification_handle,
.flags = BLE_GATT_CHR_F_NOTIFY
},
{
.uuid = &gatt_svr_char_rx_uuid.u,
.access_cb = gatt_svr_chr_access_cb,
.val_handle = &write_handle,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP
},
{0} // End of characteristic definitions
}
},
{0} // End of services definitions
};
Code: Select all
int gatt_svr_init(void)
{
esp_err_t ret;
ble_svc_gap_init();
ble_svc_gatt_init();
ret = ble_gatts_count_cfg(gatt_svr_svcs);
if (ret) {
printf("BT NimBLE failed to count GATTS configuration, error code = %x\n", ret);
return ret;
}
ret = ble_gatts_add_svcs(gatt_svr_svcs);
if (ret) {
printf("BT NimBLE failed to add GATTS services, error code = %x\n", ret);
return ret;
}
return 0;
}
- Instead of the Notify characteristic having just BLE_GATT_CHR_PROP_NOTIFY (0x10), it gets both BLE_GATT_CHR_PROP_NOTIFY and BLE_GATT_CHR_PROP_READ (0x02), which advertise as 0x12. THIS IS TOTALLY FINE so I'm okay with this, but it would seem I have no control over it now matter what I call out in the notify characteristic's flags.
- Instead of the Write characteristic having BOTH BLE_GATT_CHR_PROP_WRITE (0x08) ORed with BLE_GATT_CHR_F_WRITE_NO_RSP (0x04) which should combine to 0x0C, the advertised data for this characteristic shows 0x0A, which is BLE_GATT_CHR_PROP_WRITE (0x08) ORed with BLE_GATT_CHR_PROP_READ (0x02). THIS IS PROBLEMATIC FOR ME since the existing smartphone apps send writes deliberately with "no response", and one of my iOS apps rejects the write_with_noresponse attempt completely and doesn't even do it as a result.
I then dug into the NimBLE architecture that exists in the IDF library, and I found the NimBLE library file ble_gatts.c that does most of the work (since I'm making a GATT Server here). There I found a long chain of routines that call each other, with the pivotal final routines never getting called (based upon some printf statements I used to track each down):
My GATTS initialization routine calls ble_gatts_count_cfg() and ble_gatts_add_svcs(). A lot of stuff gets added to the BLE Stack for later execution by the NimBLE host task. This all kicks off from a later and internally generated (and confirmed) call to ble_gatts_start(), which then calls...
- ble_gatts_register_svcs() which then calls...
- ble_gatts_register_svcs() which then calls...
- ble_gatts_register_svcs() which then calls...
- ble_gatts_register_svcs() which then calls...
[*}ble_att_svr_register() which registers to the BLE Stack the host callback routine... - ble_gatts_chr_def_access() which then calls...
[*}ble_gatts_chr_properties() which translates all of the 16-bit BLE_GATT_CHR_F_* flags into 8-bit BLE_GATT_CHR_PROP_* properties
[*}...and then ble_gatts_chr_def_access() presumably finishes up the characteristic property assignments by writing into the characteristics assigned os_mbuf.
What's even more weird is the fact that the characteristics do receive "reasonably close" property assignments at all! I assume this is coming from some sort of "default" assignment that NimBLE uses to start off any new low-level service/characteristic definitions. Which routine in the NimBLE API is doing that I have not been able to figure out. I'm not averse to hacking the NimBLE API to brute-force assign the properties I desperately need to my measly little write characteristic, but I don't know where to find this low-level assignment.
Bottom line, the high-level assignment process that is blasted all over the internet GitHub examples and guides for NimBLE does not seem to do the job. I must be doing something wrong since I don't see anyone else complaining about this issue. Any help or incite will be greatly appreciated.