Hello,
I am implementing the Physical Activity Monitor Service which looks like this:
/* Physical Activity Monitor Service Declaration */ BT_GATT_SERVICE_DEFINE(pam_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_PAMS), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_PHY_AMF, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_amf, NULL, NULL), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_GEN_AID, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, NULL, NULL), BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_GEN_ASD, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE, NULL, NULL, NULL), //TODO: Indication callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_CR_AID, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, NULL, NULL), BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_CR_ASD, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE, NULL, NULL, NULL), //TODO: Indication callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SLP_AID, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE, NULL, NULL, NULL), BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SC_ASD, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE, NULL, NULL, NULL), //TODO: Indication callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_SLP_ASD, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE, NULL, NULL, NULL), //TODO: Indication callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_PHY_AMCP, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE, PAMS_GATT_PERM_DEFAULT & GATT_PERM_WRITE_MASK, NULL, ctrl_point_write, NULL), //TODO: Test control point write callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_ACS, BT_GATT_CHRC_INDICATE | BT_GATT_CHRC_READ, BT_GATT_PERM_NONE, read_acs, NULL, NULL), //TODO: Indication callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), BT_GATT_CHARACTERISTIC(BT_UUID_GATT_PHY_ASDESC, BT_GATT_CHRC_INDICATE, BT_GATT_PERM_NONE, NULL, NULL, NULL), //TODO: Indication callback BT_GATT_CCC(pamc_ccc_cfg_changed, BT_GATT_PERM_WRITE | BT_GATT_PERM_READ), }
Every notify or indicate characteristic needs a CCC according to The PAMS spec, but when I try to do this, I need to match every characteristic to its associated callback. Right now, using the HRS example, it simply iterates over every registered callback with a the notify boolean:
static void pams_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) { ARG_UNUSED(attr); struct bt_pams_cb *listener; bool notif_enabled = (value == BT_GATT_CCC_NOTIFY); LOG_INF("PAMS notifications %s", notif_enabled ? "enabled" : "disabled"); SYS_SLIST_FOR_EACH_CONTAINER(&pams_cbs, listener, _node) { if (listener->ntf_changed) { listener->ntf_changed(notif_enabled); } } }
I am now trying to match the GATT characteristic with the correct `_node` in order to turn on notifications on a per-characteristic basis as the spec says.
However, the attribute passed into the ccc function is just the UUID of the CCC function. How can I know which function (below) to pass it to?
static void pams_gen_aid_ntf_changed(bool enabled) { pams_gen_aid_ntf_en = enabled; LOG_INF("PAMS GEN AID notification status changed: %s\n", enabled ? "enabled" : "disabled"); } static struct bt_pams_cb pams_gen_aid_cb = { .ntf_changed = pams_gen_aid_ntf_changed, }; static void pams_cr_aid_ntf_changed(bool enabled) { pams_cr_aid_ntf_en = enabled; LOG_INF("PAMS CR AID notification status changed: %s\n", enabled ? "enabled" : "disabled"); } static struct bt_pams_cb pams_cf_aid_cb = { .ntf_changed = pams_cr_aid_ntf_changed, }; static void pams_slp_aid_ntf_changed(bool enabled) { pams_slp_aid_ntf_en = enabled; LOG_INF("PAMS SLEEP AID notification status changed: %s\n", enabled ? "enabled" : "disabled"); } static struct bt_pams_cb pams_slp_aid_cb = { .ntf_changed = pams_slp_aid_ntf_changed, }; static void pams_ctrl_point_ntf_changed(bool enabled) { pams_ctrl_point_ntf_en = enabled; LOG_INF("PAMS CTRL Point notification status changed: %s\n", enabled ? "enabled" : "disabled"); }
Do I have to make a separate CCC_changed function for every single characteristic?
Is there a way I can return a node of the desired callback and the attribute (uuid for example) of the clicked "notify" in the nrfConnect app? I am a bit stuck as a lot of the macros have less than ideal documentation.
Thank you.