Get help on characteristic handle issue

This commit is contained in:
Dimitri del Marmol 2016-10-03 13:28:38 +02:00
parent 8da8ff585c
commit 515c5d5a07
3 changed files with 123 additions and 19 deletions

View File

@ -22,7 +22,7 @@ info = {
'default_console' : "EV_SERIAL1",
'default_console_tx' : "D6",
'default_console_rx' : "D8",
'default_console_baudrate' : "9600",
'default_console_baudrate' : "115200",
# Number of variables can be WAY higher on this board
'variables' : 2040, # How many variables are allocated for Espruino to use. RAM will be overflowed if this number is too high and code won't compile.
# 'bootloader' : 1,

View File

@ -85,6 +85,7 @@ bool nfcEnabled = false;
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000, APP_TIMER_PRESCALER) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
#define APP_CFG_CHAR_MAX_LEN 20 /**< Size of the characteristic value being notified (in bytes). */
#ifdef USE_BOOTLOADER
#define SEC_PARAM_BOND 1 /**< Perform bonding. */
@ -261,10 +262,8 @@ void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) {
}
void advertising_start(void) {
uint32_t err_code = 0;
if (bleStatus & BLE_IS_ADVERTISING) return;
// Actually start advertising
ble_gap_adv_params_t adv_params;
memset(&adv_params, 0, sizeof(adv_params));
adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
@ -274,8 +273,7 @@ void advertising_start(void) {
adv_params.timeout = APP_ADV_TIMEOUT_IN_SECONDS;
adv_params.interval = advertising_interval;
err_code = sd_ble_gap_adv_start(&adv_params);
// APP_ERROR_CHECK(err_code); // don't bother checking
sd_ble_gap_adv_start(&adv_params);
bleStatus |= BLE_IS_ADVERTISING;
}
@ -1500,19 +1498,6 @@ void jswrap_nrf_bluetooth_setServices(JsVar *data) {
}
jsvUnLock(charVar);
/* We'd update the characteristic with:
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = characteristic_handle.value_handle;
hvx_params.p_data = p_string;
hvx_params.p_len = &length;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
Maybe we could find the handle out based on characteristic UUID, rather than having
to store it?
*/
jsvObjectIteratorNext(&serviceit);
}
@ -1530,6 +1515,124 @@ void jswrap_nrf_bluetooth_setServices(JsVar *data) {
}
}
/*JSON{
"type" : "staticmethod",
"class" : "NRF",
"name" : "updateServices",
"generate" : "jswrap_nrf_bluetooth_updateServices",
"params" : [
["data","JsVar","The service (and characteristics) to update"]
]
}
Update values for the services and characteristics Espruino advertises.
Only services and characteristics previously declared using `setServices` are affected.
```
NRF.updateServices({
0xBCDE : {
0xABCD : {
value : "World"
}
// more characteristics allowed
}
// more services allowed
});
```
**Note:** UUIDs can be integers between `0` and `0xFFFF`, strings of
the form `"0xABCD"`, or strings of the form `""ABCDABCD-ABCD-ABCD-ABCD-ABCDABCDABCD""`
*/
void jswrap_nrf_bluetooth_updateServices(JsVar *data) {
if (jsvIsObject(data)) {
JsvObjectIterator it;
jsvObjectIteratorNew(&it, data);
while (jsvObjectIteratorHasValue(&it)) {
ble_uuid_t ble_uuid;
const char *errorStr;
if ((errorStr = bleVarToUUIDAndUnLock(&ble_uuid,
jsvObjectIteratorGetKey(&it)))) {
jsExceptionHere(JSET_ERROR, "Invalid Service UUID: %s", errorStr);
break;
}
JsVar *serviceVar = jsvObjectIteratorGetValue(&it);
JsvObjectIterator serviceit;
jsvObjectIteratorNew(&serviceit, serviceVar);
while (jsvObjectIteratorHasValue(&serviceit)) {
ble_uuid_t char_uuid;
if ((errorStr = bleVarToUUIDAndUnLock(&char_uuid,
jsvObjectIteratorGetKey(&serviceit)))) {
jsExceptionHere(JSET_ERROR, "Invalid Characteristic UUID: %s",
errorStr);
break;
}
JsVar *charVar = jsvObjectIteratorGetValue(&serviceit);
JsVar *charValue = jsvObjectGetChild(charVar, "value", 0);
if (charValue) {
JSV_GET_AS_CHAR_ARRAY(vPtr, vLen, charValue);
if (vPtr && vLen) {
ble_gatts_attr_t attr_char_value;
attr_char_value.p_value = (uint8_t*) vPtr;
attr_char_value.init_len = vLen;
if (attr_char_value.init_len > attr_char_value.max_len) {
attr_char_value.max_len = attr_char_value.init_len;
}
// TODO Actually check all 3 to avoid NRF_ERROR_INVALID_STATE
bool service_characteristic_exists = true;
bool notification_enabled = true;
bool indication_enabled = false;
// Send value if connected and notifying/indicating
if ((m_conn_handle != BLE_CONN_HANDLE_INVALID)
&& service_characteristic_exists
&& (notification_enabled || indication_enabled)) {
ble_gatts_hvx_params_t hvx_params;
uint16_t len = MIN(vLen, APP_CFG_CHAR_MAX_LEN);
memset(&hvx_params, 0, sizeof(hvx_params));
// TODO FINISH Get the handle
// Can it be retrieved from the SoftDevice by UUID or should it be stored in setServices and looked up ?
hvx_params.handle = 17; // TODO REMOVE Hardcoded value
hvx_params.type = indication_enabled ? BLE_GATT_HVX_INDICATION : BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = 0;
hvx_params.p_len = &len;
hvx_params.p_data = attr_char_value.p_value;
uint32_t err_code = sd_ble_gatts_hvx(m_conn_handle, &hvx_params);
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)
&& (err_code != BLE_ERROR_NO_TX_PACKETS)
&& (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)) {
APP_ERROR_CHECK(err_code);
}
// TODO Retry on NO_TX_BUFFERS (for notifications) ?
}
}
}
jsvUnLock(charValue);
jsvUnLock(charVar);
jsvObjectIteratorNext(&serviceit);
}
jsvObjectIteratorFree(&serviceit);
jsvUnLock(serviceVar);
jsvObjectIteratorNext(&it);
}
jsvObjectIteratorFree(&it);
} else if (!jsvIsUndefined(data)) {
jsExceptionHere(JSET_TYPEERROR, "Expecting object or undefined, got %t",
data);
}
}
/*JSON{
"type" : "staticmethod",

View File

@ -26,6 +26,7 @@ void jswrap_nrf_bluetooth_wake(void);
JsVarFloat jswrap_nrf_bluetooth_getBattery(void);
void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options);
void jswrap_nrf_bluetooth_setServices(JsVar *data);
void jswrap_nrf_bluetooth_updateServices(JsVar *data);
void jswrap_nrf_bluetooth_setScan(JsVar *callback);
void jswrap_nrf_bluetooth_setTxPower(JsVarInt pwr);