void BluetoothHandler::receiveHrNotifications() { qDebug() << "YYYY setting up to receive GATT notifications"; if (!bt_initialised) { qDebug() << "Bluetooth libraries are not initialised!"; return; } HrDataContainer* hrdc = HrDataContainer::getInstance(); QString device_addr = hrdc->getCurrentDeviceAddr(); QString device_name = hrdc->getCurrentDeviceName(); hrdc->clearData(); bt_gatt_conn_parm_t conParm; conParm.minConn = 0x30; conParm.maxConn = 0x50; conParm.latency = 0; conParm.superTimeout = 50; errno= 0; if (bt_gatt_connect_service(device_addr.toAscii().constData(), HR_SERVICE_UUID, NULL, &conParm, this) < 0) { qDebug() << "YYYY GATT connect service request failed: " + QString::number(errno) + " (" + QString(strerror(errno)) + ")"; } else { qDebug() << "YYYY requested connection to HR service OK"; } }
void BluetoothHandler::receiveHrNotifications() { qDebug() << "YYYY setting up to receive GATT notifications"; if (!bt_initialised) { qDebug() << "Bluetooth libraries are not initialised!"; return; } HrDataContainer* hrdc = HrDataContainer::getInstance(); QString device_addr = hrdc->getCurrentDeviceAddr(); QString device_name = hrdc->getCurrentDeviceName(); hrdc->clearData(); bt_gatt_conn_parm_t conParm; conParm.minConn = 0x30; conParm.maxConn = 0x50; conParm.latency = 0; conParm.superTimeout = 50; errno= 0; if (bt_gatt_connect_service(device_addr.toAscii().constData(), HR_SERVICE_UUID, NULL, &conParm, this) < 0) { qDebug() << "YYYY GATT connect service request failed: " + QString::number(errno) + " (" + QString(strerror(errno)) + ")"; // there's a known issue where sometimes we get ERRNO=EBUSY (16) when this is not the case and we've connected to the service OK. So for now we ignore this errno value. if (errno != 16) { Utilities::alert("GATT connect service request failed: " + QString::number(errno)); } } else { qDebug() << "YYYY requested connection to HR service OK"; } }
void BluetoothHandler::stopHrNotifications() { errno= 0; HrDataContainer* hrdc = HrDataContainer::getInstance(); QString device_addr = hrdc->getCurrentDeviceAddr(); if (bt_gatt_disconnect_service(device_addr.toAscii().constData(), HR_SERVICE_UUID) < 0) { qDebug() << "YYYY GATT disconnect service request failed: " + QString::number(errno) + " (" + QString(strerror(errno)) + ")"; } else { qDebug() << "YYYY disconnected from HR service OK"; } }
void notifications_cb(int instance, uint16_t handle, const uint8_t *val, uint16_t len, void *userData) { Q_UNUSED(instance) Q_UNUSED(userData) qDebug() << "YYYY notifications call back received"; if (NULL == val) return; HrDataContainer* hrdc = HrDataContainer::getInstance(); if (handle == hrdc->getHrValueHandle()) { hrdc->addNotification(val,len); hrdc->logMostRecentNotification(); } }
void gatt_service_connected(const char *bdaddr, const char *service, int instance, int err, uint16_t connInt, uint16_t latency, uint16_t superTimeout, void *userData) { Q_UNUSED(superTimeout) Q_UNUSED(userData) Q_UNUSED(latency) Q_UNUSED(connInt) Q_UNUSED(err) qDebug() << "YYYY gatt_service_connected"; QString bdaddr_str = QString(bdaddr); QString service_str = QString(service); qDebug() << "YYYY registering for notifications"; errno = 0; int rc = bt_gatt_reg_notifications(instance, notifications_cb); qDebug() << "YYYY rc from bt_gatt_reg_notifications=" << rc; if (rc != 0) { qDebug() << "YYYY bt_gatt_reg_notifications errno=" << errno; qDebug() << "YYYY bt_gatt_reg_notifications errno=" << strerror(errno); } else { qDebug() << "YYYY bt_gatt_reg_notifications was presumably OK"; } bt_gatt_characteristic_t* heart_rate_measurement; heart_rate_measurement = (bt_gatt_characteristic_t*) malloc(sizeof(bt_gatt_characteristic_t)); if (NULL == heart_rate_measurement) { qDebug() << "YYYY GATT characteristics: Not enough memory"; bt_gatt_disconnect_instance(instance); return; } int num_characteristics = bt_gatt_characteristics_count(instance); if (num_characteristics > -1) { qDebug() << QString("YYYY # characteristics: %1").arg(num_characteristics); bt_gatt_characteristic_t *characteristicList; characteristicList = (bt_gatt_characteristic_t*) malloc(num_characteristics * sizeof(bt_gatt_characteristic_t)); if (NULL == characteristicList) { qDebug() << QString("YYYY GATT characteristics: Not enough memory"); bt_gatt_disconnect_instance(instance); return; } /* BEGIN WORKAROUND - Temporary fix to address race condition */ int number = 0; do { number = bt_gatt_characteristics(instance, characteristicList, num_characteristics); } while ((number == -1) && (errno== EBUSY)); int characteristicListSize = number; HrDataContainer *hrdc = HrDataContainer::getInstance(); for (int i = 0; i < characteristicListSize; i++) { qDebug() << "YYYY characteristic: uuid,handle,value_handle:" << characteristicList[i].uuid << "," << characteristicList[i].handle << "," << characteristicList[i].value_handle; if (strcmp(characteristicList[i].uuid, HEART_RATE_MEASUREMENT) == 0) { qDebug() << "YYYY heart rate characteristic available"; hrdc->setHrHandle(characteristicList[i].handle); hrdc->setHrValueHandle(characteristicList[i].value_handle); // enable=1 switches the notification on for the specified characteristic qDebug() << "YYYY registering for heart_rate_measurement notification. uuid,handle,value_handle=" << characteristicList[i].uuid << "," << characteristicList[i].handle << "," << characteristicList[i].value_handle; errno= 0; rc = bt_gatt_enable_notify(instance, &characteristicList[i], 1); if (rc != 0) { qDebug() << "YYYY bt_gatt_enable_notify errno=" << errno; qDebug() << "YYYY bt_gatt_enable_notify errno=" << strerror(errno); } else { qDebug() << "YYYY bt_gatt_enable_notify was presumably OK"; } qDebug() << "YYYY rc from registering for heart_rate_measurement notification=" << rc; } else { qDebug() << "YYYY other characteristic: uuid,handle,value_handle=" << characteristicList[i].uuid << "," << characteristicList[i].handle << "," << characteristicList[i].value_handle; } } if (characteristicList != NULL) { free(characteristicList); characteristicList = NULL; } /* END WORKAROUND */ qDebug() << "YYYY done registering for heart_rate_measurement notifications"; } }