Add NimBLEAttValue class. (#67)

This is a specialized container class to hold BLE attribute values.

- Removes the use of std::string previously used to store the values.
- Allows for setting/getting/notifying values from std::string, std::vector<uint8_t>, Arduino String, const char*, and uint8_t buffers.
- Has operators retrieve the value as std::string, Arduino String, std::vector<uint8_t>, uint8_t* or char pointers.
- Includes iterators and subscript/random access operator.
- Introduces a max length parameter to the creation of server characteristics/descriptors to limit the size of the memory footprint.
- Nearly Seamless integration with existing code.
- Adds a config option to enable/disable timestamp storage when the value is updated.
- Adds a config option to specify the initial size of the value container if not specified in the constructor.
This commit is contained in:
h2zero
2022-01-16 20:11:18 -07:00
committed by GitHub
parent be9cdc1ab6
commit e3ee082dd7
17 changed files with 901 additions and 296 deletions
+29 -25
View File
@@ -58,7 +58,6 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic";
m_charProp = chr->properties;
m_pRemoteService = pRemoteService;
m_notifyCallback = nullptr;
m_timestamp = 0;
NIMBLE_LOGD(LOG_TAG, "<< NimBLERemoteCharacteristic(): %s", m_uuid.toString().c_str());
} // NimBLERemoteCharacteristic
@@ -414,15 +413,12 @@ NimBLEUUID NimBLERemoteCharacteristic::getUUID() {
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @return The value of the remote characteristic.
*/
std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
ble_npl_hw_enter_critical();
std::string value = m_value;
NimBLEAttValue NimBLERemoteCharacteristic::getValue(time_t *timestamp) {
if(timestamp != nullptr) {
*timestamp = m_timestamp;
*timestamp = m_value.getTimeStamp();
}
ble_npl_hw_exit_critical(0);
return value;
return m_value;
}
@@ -470,12 +466,12 @@ float NimBLERemoteCharacteristic::readFloat() {
* @param [in] timestamp A pointer to a time_t struct to store the time the value was read.
* @return The value of the remote characteristic.
*/
std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
NimBLEAttValue NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
NIMBLE_LOGD(LOG_TAG, ">> readValue(): uuid: %s, handle: %d 0x%.2x",
getUUID().toString().c_str(), getHandle(), getHandle());
NimBLEClient* pClient = getRemoteService()->getClient();
std::string value;
NimBLEAttValue value;
if (!pClient->isConnected()) {
NIMBLE_LOGE(LOG_TAG, "Disconnected");
@@ -526,14 +522,11 @@ std::string NimBLERemoteCharacteristic::readValue(time_t *timestamp) {
}
} while(rc != 0 && retryCount--);
time_t t = time(nullptr);
ble_npl_hw_enter_critical();
value.setTimeStamp();
m_value = value;
m_timestamp = t;
if(timestamp != nullptr) {
*timestamp = m_timestamp;
*timestamp = value.getTimeStamp();
}
ble_npl_hw_exit_critical(0);
NIMBLE_LOGD(LOG_TAG, "<< readValue length: %d rc=%d", value.length(), rc);
return value;
@@ -558,17 +551,17 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
NIMBLE_LOGI(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
std::string *strBuf = (std::string*)pTaskData->buf;
NimBLEAttValue *valBuf = (NimBLEAttValue*)pTaskData->buf;
int rc = error->status;
if(rc == 0) {
if(attr) {
uint16_t data_len = OS_MBUF_PKTLEN(attr->om);
if(((*strBuf).length() + data_len) > BLE_ATT_ATTR_MAX_LEN) {
if((valBuf->size() + data_len) > BLE_ATT_ATTR_MAX_LEN) {
rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
} else {
NIMBLE_LOGD(LOG_TAG, "Got %u bytes", data_len);
(*strBuf) += std::string((char*) attr->om->om_data, data_len);
valBuf->append(attr->om->om_data, data_len);
return 0;
}
}
@@ -719,22 +712,33 @@ std::string NimBLERemoteCharacteristic::toString() {
/**
* @brief Write the new value for the characteristic.
* @param [in] newValue The new value to write.
* @param [in] response Do we expect a response?
* @return false if not connected or cant perform write for some reason.
* @brief Write a new value to the remote characteristic from a std::vector<uint8_t>.
* @param [in] vec A std::vector<uint8_t> value to write to the remote characteristic.
* @param [in] response Whether we require a response from the write.
* @return false if not connected or otherwise cannot perform write.
*/
bool NimBLERemoteCharacteristic::writeValue(const std::string &newValue, bool response) {
return writeValue((uint8_t*)newValue.c_str(), newValue.length(), response);
bool NimBLERemoteCharacteristic::writeValue(const std::vector<uint8_t>& vec, bool response) {
return writeValue((uint8_t*)&vec[0], vec.size(), response);
} // writeValue
/**
* @brief Write the new value for the characteristic from a data buffer.
* @brief Write a new value to the remote characteristic from a const char*.
* @param [in] char_s A character string to write to the remote characteristic.
* @param [in] response Whether we require a response from the write.
* @return false if not connected or otherwise cannot perform write.
*/
bool NimBLERemoteCharacteristic::writeValue(const char* char_s, bool response) {
return writeValue((uint8_t*)char_s, strlen(char_s), response);
} // writeValue
/**
* @brief Write a new value to the remote characteristic from a data buffer.
* @param [in] data A pointer to a data buffer.
* @param [in] length The length of the data in the data buffer.
* @param [in] response Whether we require a response from the write.
* @return false if not connected or cant perform write for some reason.
* @return false if not connected or otherwise cannot perform write.
*/
bool NimBLERemoteCharacteristic::writeValue(const uint8_t* data, size_t length, bool response) {