i can create three service each with one notifiable characteristic. i am using nrf connect to test if it is work and i am able to send data through UART Rx and then enabled all the notifiable characteristics of each services. and I am able to read fro and send data to my device. but when i use my android to send and read data it is not working. On my Android i am able to retrieve all the characteristics and services at onServicesDiscovered(BluetoothGatt gatt, int status). But it is not read the values although all the connection works good.
I used the nRF5_SDK_15.2.0_9412b96\examples\ble_peripheral\ble_app_uart\pca10056\s140\ses Just add two more service with a notifiable characteristics. and I use Android-nRF-UART-master example from the git-hub for my android code. here is my Android code for the UartService .
/* * Copyright (c) 2015, Nordic Semiconductor * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.multicharacter.UART; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** * Service for managing connection and data communication with a GATT server hosted on a * given Bluetooth LE device. */ public class UartService extends Service { private final static String TAG = UartService.class.getSimpleName(); private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; public final static String ACTION_GATT_CONNECTED = "com.nordicsemi.nrfUART.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.nordicsemi.nrfUART.ACTION_GATT_DISCONNECTED"; public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.nordicsemi.nrfUART.ACTION_GATT_SERVICES_DISCOVERED"; public final static String ACTION_DATA_AVAILABLE = "com.nordicsemi.nrfUART.ACTION_DATA_AVAILABLE"; public final static String EXTRA_DATA = "com.nordicsemi.nrfUART.EXTRA_DATA"; public final static String DEVICE_DOES_NOT_SUPPORT_UART = "com.nordicsemi.nrfUART.DEVICE_DOES_NOT_SUPPORT_UART"; public static final UUID CCCD = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); public static final UUID RX_SERVICE_UUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e"); public static final UUID RX_CHAR_UUID = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e"); public static final UUID TX_CHAR_UUID = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e"); /*---------------------------------------------------------------------------------------------------------------*/ public static final UUID RX_SERVICE_2_UUID = UUID.fromString("6e401001-b5a3-f393-e0a9-e50e24dcca9e"); public static final UUID RX_SERVICE_3_UUID = UUID.fromString("6e400000-b5a3-f393-e0a9-e50e24dcca9e"); public static final UUID service_2_CHAR_UUID = UUID.fromString("6e401003-b5a3-f393-e0a9-e50e24dcca9e"); public static final UUID service_3_CHAR_UUID = UUID.fromString("6e402004-b5a3-f393-e0a9-e50e24dcca9e"); /*---------------------------------------------------------------------------------------------------------------------------*/ List<BluetoothGattCharacteristic> chars = new ArrayList<>(); private int ReadQueueIndex; // Implements callback methods for GATT events that the app cares about. For example, // connection change and services discovered. private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { String intentAction; if (newState == BluetoothProfile.STATE_CONNECTED) { intentAction = ACTION_GATT_CONNECTED; broadcastUpdate(intentAction); Log.i(TAG, "Connected to GATT server."); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_GATT_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server."); broadcastUpdate(intentAction); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { int x = 0; if (status == BluetoothGatt.GATT_SUCCESS) { Log.w(TAG, "mBluetoothGatt = " + mBluetoothGatt ); List<BluetoothGattService> services = gatt.getServices(); Log.e("onServicesDiscovered", services.toString()); for (int i = 0; i < services.size(); i++){ if(services.get(i).getUuid().toString().contains("6e400001")){ for(int j = 0; j < services.get(i).getCharacteristics().size(); j++){ if(services.get(i).getCharacteristics().get(j).getUuid().toString().contains("6e400003")){ String Characte = services.get(i).getCharacteristics().get(j).getUuid().toString(); Log.w(TAG, "first character: " + " UUID " + Characte ); chars.add(services.get(i).getCharacteristics().get(j)); } } } else if(services.get(i).getUuid().toString().contains("6e401001")){ for(int j = 0; j < services.get(i).getCharacteristics().size(); j++){ if(services.get(i).getCharacteristics().get(j).getUuid().toString().contains("6e401003")){ String Characte2 = services.get(i).getCharacteristics().get(j).getUuid().toString(); Log.w(TAG, "second character: " + " UUID " + Characte2 ); chars.add(services.get(i).getCharacteristics().get(j)); } } } else if(services.get(i).getUuid().toString().contains("6e400000")){ for(int j = 0; j < services.get(i).getCharacteristics().size(); j++){ if(services.get(i).getCharacteristics().get(j).getUuid().toString().contains("6e402004")){ String Characte3 = services.get(i).getCharacteristics().get(j).getUuid().toString(); Log.w(TAG, "first character: " + " UUID " + Characte3 ); chars.add(services.get(i).getCharacteristics().get(j)); } } } /* x = x + 1; String ser_num = String.valueOf(x); String mCurrentService = srv.getUuid().toString(); Log.w(TAG, "onserviceRead: " + " UUID " + mCurrentService + "number" + ser_num); List<BluetoothGattCharacteristic> mListCars = srv.getCharacteristics(); int num_char = mListCars.size(); Log.i(TAG, String.valueOf(num_char)); for(BluetoothGattCharacteristic bc : mListCars){ String mCurrentchar = bc.getUuid().toString(); Log.e(TAG, "onCharacteristicRead: " + " UUID " + mCurrentchar ); gatt.readCharacteristic(srv.getCharacteristic(bc.getUuid())); }*/ } ReadQueueIndex = chars.size() - 1; requestCharacteristics(0); broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } public void requestCharacteristics(int index) { Log.w(TAG, "I am Reading: " + "" + chars.get(index).getUuid().toString()); mBluetoothGatt.readCharacteristic(chars.get(index)); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { String value = characteristic.getStringValue(0); Log.e(TAG, "I am OnReading: " + "" + characteristic.getUuid().toString()); broadcastUpdate(characteristic); chars.remove(chars.get(ReadQueueIndex)); if (chars.size() < chars.size()) { ReadQueueIndex++; if (ReadQueueIndex == -1) { Log.i("Read Queue: ", "Complete"); } else { requestCharacteristics(ReadQueueIndex); } } } }; private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } private void broadcastUpdate(final BluetoothGattCharacteristic characteristic) { final Intent intent = new Intent(ACTION_DATA_AVAILABLE); // This is handling for the notification on TX Character of NUS service if ((TX_CHAR_UUID.equals(characteristic.getUuid())) && (characteristic.getValue() != null) ) { //Log.d(TAG, String.format("Received TX: %d",characteristic.getValue() )); intent.putExtra(EXTRA_DATA, characteristic.getValue()); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } else if ((service_2_CHAR_UUID.equals(characteristic.getUuid())) && (characteristic.getValue() != null)) { //Log.d(TAG, String.format("Received TX: %d",characteristic.getValue() )); intent.putExtra(EXTRA_DATA, characteristic.getValue()); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } if ((service_3_CHAR_UUID.equals(characteristic.getUuid())) && (characteristic.getValue() != null) ) { //Log.d(TAG, String.format("Received TX: %d",characteristic.getValue() )); intent.putExtra(EXTRA_DATA, characteristic.getValue()); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } } /*-----------------------------------------------------------------------------------------------------------------------------*/ public class LocalBinder extends Binder { UartService getService() { return UartService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public boolean onUnbind(Intent intent) { // After using a given device, you should make sure that BluetoothGatt.close() is called // such that resources are cleaned up properly. In this particular example, close() is // invoked when the UI is disconnected from the Service. close(); return super.onUnbind(intent); } private final IBinder mBinder = new LocalBinder(); /** * Initializes a reference to the local Bluetooth adapter. * * @return Return true if the initialization is successful. */ public boolean initialize() { // For API level 18 and above, get a reference to BluetoothAdapter through // BluetoothManager. if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { Log.e(TAG, "Unable to initialize BluetoothManager."); return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } return true; } /** * Connects to the GATT server hosted on the Bluetooth LE device. * * @param address The device address of the destination device. */ public void connect(final String address) { if (mBluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return; } // Previously connected device. Try to reconnect. if (address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection."); if (mBluetoothGatt.connect()) { return; } else { return; } } final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if (device == null) { Log.w(TAG, "Device not found. Unable to connect."); return; } // We want to directly connect to the device, so we are setting the autoConnect // parameter to false. mBluetoothGatt = device.connectGatt(this, false, mGattCallback); Log.d(TAG, "Trying to create a new connection."); mBluetoothDeviceAddress = address; } /** * Disconnects an existing connection or cancel a pending connection. The disconnection result * is reported asynchronously through the * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} * callback. */ public void disconnect() { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.disconnect(); // mBluetoothGatt.close(); } /** * After using a given BLE device, the app must call this method to ensure resources are * released properly. */ public void close() { if (mBluetoothGatt == null) { return; } Log.w(TAG, "mBluetoothGatt closed"); mBluetoothDeviceAddress = null; mBluetoothGatt.close(); mBluetoothGatt = null; } /** * Enable Notification on TX characteristic */ public void enableTXNotification() { /* if (mBluetoothGatt == null) { showMessage("mBluetoothGatt null" + mBluetoothGatt); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } */ BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE_UUID); if (RxService == null) { showMessage("Rx service not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } BluetoothGattCharacteristic TxChar = RxService.getCharacteristic(TX_CHAR_UUID); if (TxChar == null) { showMessage("Tx charateristic not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } mBluetoothGatt.setCharacteristicNotification(TxChar,true); BluetoothGattDescriptor descriptor = TxChar.getDescriptor(CCCD); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } /*---------------------------------------------------------------------------------------------------------------*/ public void enableTXNotification_2() { /* if (mBluetoothGatt == null) { showMessage("mBluetoothGatt null" + mBluetoothGatt); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } */ BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE_2_UUID); if (RxService == null) { showMessage("Rx service not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } BluetoothGattCharacteristic TxChar = RxService.getCharacteristic(service_2_CHAR_UUID); if (TxChar == null) { showMessage("Tx charateristic not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } mBluetoothGatt.setCharacteristicNotification(TxChar,true); BluetoothGattDescriptor descriptor = TxChar.getDescriptor(CCCD); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } /*---------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------*/ public void enableTXNotification_3() { /* if (mBluetoothGatt == null) { showMessage("mBluetoothGatt null" + mBluetoothGatt); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } */ BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE_3_UUID); if (RxService == null) { showMessage("Rx service not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } BluetoothGattCharacteristic TxChar = RxService.getCharacteristic(service_3_CHAR_UUID); if (TxChar == null) { showMessage("Tx charateristic not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } mBluetoothGatt.setCharacteristicNotification(TxChar,true); BluetoothGattDescriptor descriptor = TxChar.getDescriptor(CCCD); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } /*---------------------------------------------------------------------------------------------------------------*/ public void writeRXCharacteristic(byte[] value) { BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE_UUID); showMessage("mBluetoothGatt null"+ mBluetoothGatt); if (RxService == null) { showMessage("Rx service not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } BluetoothGattCharacteristic RxChar = RxService.getCharacteristic(RX_CHAR_UUID); if (RxChar == null) { showMessage("Rx charateristic not found!"); broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART); return; } RxChar.setValue(value); boolean status = mBluetoothGatt.writeCharacteristic(RxChar); Log.d(TAG, "write TXchar - status=" + status); } private void showMessage(String msg) { Log.e(TAG, msg); } }
My NRF52840 main.c
/** * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** @file * * @defgroup ble_sdk_uart_over_ble_main main.c * @{ * @ingroup ble_sdk_app_nus_eval * @brief UART over BLE application main file. * * This file contains the source code for a sample application that uses the Nordic UART service. * This application uses the @ref srvlib_conn_params module. */ #include <stdio.h> #include <stdint.h> #include <string.h> #include "nordic_common.h" #include "nrf.h" #include "ble_hci.h" #include "ble_advdata.h" #include "ble_advertising.h" #include "ble_conn_params.h" #include "nrf_sdh.h" #include "nrf_sdh_soc.h" #include "nrf_sdh_ble.h" #include "nrf_ble_gatt.h" #include "nrf_ble_qwr.h" #include "app_timer.h" #include "ble_nus.h" #include "app_uart.h" #include "app_util_platform.h" #include "bsp_btn_ble.h" #include "nrf_pwr_mgmt.h" #if defined (UART_PRESENT) #include "nrf_uart.h" #endif #if defined (UARTE_PRESENT) #include "nrf_uarte.h" #endif #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ #define DEVICE_NAME "CYNCH Connect" /**< Name of device. Will be included in the advertising data. */ #define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ #define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */ #define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ #define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ #define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ #define MAX_CONN_INTERVAL MSEC_TO_UNITS(100, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ #define SLAVE_LATENCY 0 /**< Slave latency. */ #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< 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) /**< 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 DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */ #define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ #define UART_RX_BUF_SIZE 2048 /**< UART RX buffer size. */ BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ static bool isConnected = false; static char lastCommand[256]; //static char command_line[256]; static const uint8_t version[] = "EVENTS"; //what does this do??? this looks weird....idk...I'm only a dumb computer static const uint8_t report[] = "VERSION"; static bool second_ser = false; static bool third_ser = false; static bool Report_control = false; static bool Version_control = false; static bool first_ser = false; //string data; static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ { {BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE} }; /**@brief Function for assert macro callback. * * @details This function will be called in case of an assert in the SoftDevice. * * @warning This handler is an example only and does not fit a final product. You need to analyse * how your product is supposed to react in case of Assert. * @warning On assert from the SoftDevice, the system can only recover on reset. * * @param[in] line_num Line number of the failing ASSERT call. * @param[in] p_file_name File name of the failing ASSERT call. */ void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) { app_error_handler(DEAD_BEEF, line_num, p_file_name); } /**@brief Function for initializing the timer module. */ static void timers_init(void) { ret_code_t err_code = app_timer_init(); APP_ERROR_CHECK(err_code); } /**@brief Function for the GAP initialization. * * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of * the device. It also sets the permissions and appearance. */ static void gap_params_init(void) { uint32_t err_code; ble_gap_conn_params_t gap_conn_params; ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) DEVICE_NAME, strlen(DEVICE_NAME)); APP_ERROR_CHECK(err_code); memset(&gap_conn_params, 0, sizeof(gap_conn_params)); gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; gap_conn_params.slave_latency = SLAVE_LATENCY; gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; err_code = sd_ble_gap_ppcp_set(&gap_conn_params); APP_ERROR_CHECK(err_code); } /**@brief Function for handling Queued Write Module errors. * * @details A pointer to this function will be passed to each service which may need to inform the * application about an error. * * @param[in] nrf_error Error code containing information about what went wrong. */ static void nrf_qwr_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } /**@brief Function for handling the data from the Nordic UART Service. * * @details This function will process the data received from the Nordic UART BLE Service and send * it to the UART module. * * @param[in] p_evt Nordic UART Service event. */ /**@snippet [Handling the data received over BLE] */ static void nus_data_handler(ble_nus_evt_t * p_evt) { if ((p_evt->type == BLE_NUS_EVT_RX_DATA) && (isConnected)) { Report_control = false; Version_control = false; if(p_evt->params.rx_data.length > 2) { NRF_LOG_INFO(" first character should st"); first_ser = true; third_ser =false; second_ser = false; uint32_t err_code; memset (lastCommand, 0, 256); strncpy (lastCommand, (char *) p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); // printf("%s\r\n", lastCommand); //NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++) { do { err_code = app_uart_put(p_evt->params.rx_data.p_data[i]); NRF_LOG_INFO("Data len is set to 0x%X(%d)", p_evt->params.rx_data.p_data[i],p_evt->params.rx_data.length); if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_BUSY); } while (app_uart_put('\r') == NRF_ERROR_BUSY); } } /*----------------------------------------------------------------------------------------------------------------*/ if ( ((p_evt->type == BLE_NUS_EVT_COMM_STARTED) && (isConnected)) || (Version_control)) { NRF_LOG_INFO(" second character should st"); second_ser = true; third_ser = false; first_ser = false; Report_control = false; Version_control = false; size_t length = sizeof(version) / sizeof(version[0]); int i; uint32_t err_code; memset (lastCommand, 0, 256); strncpy (lastCommand, (char *) version,length-1); for (i = 0; i < length-1; i++) { do { err_code = app_uart_put(version[i]); NRF_LOG_INFO("Data ver is set to 0x%X(%d)", version[i],length-1); if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_BUSY); } while (app_uart_put('\r') == NRF_ERROR_BUSY); } /*---------------------------------------------------------------------------------------------------------------*/ if ((isConnected) && (Report_control)) { third_ser = true; first_ser = false; second_ser = false; Report_control = false; size_t length = sizeof(report) / sizeof(report[0]); int i; uint32_t err_code; memset (lastCommand, 0, 256); strncpy (lastCommand, (char *) report,length-1); for (i = 0; i < length-1; i++) { do { err_code = app_uart_put(report[i]); NRF_LOG_INFO("Data ver is set to 0x%X(%d)", report[i],length-1); if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_BUSY); } while (app_uart_put('\r') == NRF_ERROR_BUSY); } /*---------------------------------------------------------------------------------------------------------------*/ } /*static void command_send(ble_nus_evt_t * p_evt) { static const uint8_t s[] = "VERSION"; size_t length = sizeof(s) / sizeof(s[0]); int i; if (isConnected) { uint32_t err_code; //memset (command_line, 0, 256); //strncpy (command_line,s.c_str,sizeof(command_line)); // printf("%s\r\n", lastCommand); //NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); for (i = 0; i < length; i++) { do { err_code = app_uart_put(s[i]); NRF_LOG_INFO("Data ver is set to 0x%X(%d)", s[i],length); if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_BUSY); } while (app_uart_put('\r') == NRF_ERROR_BUSY); } } /*----------------------------------------------------------------------------------------*/ /**@snippet [Handling the data received over BLE] */ /**@brief Function for initializing services that will be used by the application. */ static void services_init(void) { uint32_t err_code; uint32_t err_code_2; ble_nus_init_t nus_init; nrf_ble_qwr_init_t qwr_init = {0}; //ble_nus_init_2(&m_nus); // ble_nus_init_3(&m_nus); // Initialize Queued Write Module. qwr_init.error_handler = nrf_qwr_error_handler; err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); APP_ERROR_CHECK(err_code); // Initialize NUS. memset(&nus_init, 0, sizeof(nus_init)); nus_init.data_handler = nus_data_handler; err_code = ble_nus_init(&m_nus, &nus_init); APP_ERROR_CHECK(err_code); err_code = ble_nus_init_2(&m_nus, &nus_init); APP_ERROR_CHECK(err_code); err_code = ble_nus_init_3(&m_nus, &nus_init); APP_ERROR_CHECK(err_code); } /**@brief Function for handling an event from the Connection Parameters Module. * * @details This function will be called for all events in the Connection Parameters Module * which are passed to the application. * * @note All this function does is to disconnect. This could have been done by simply setting * the disconnect_on_fail config parameter, but instead we use the event handler * mechanism to demonstrate its use. * * @param[in] p_evt Event received from the Connection Parameters Module. */ static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) { uint32_t err_code; if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); APP_ERROR_CHECK(err_code); } } /**@brief Function for handling errors from the Connection Parameters module. * * @param[in] nrf_error Error code containing information about what went wrong. */ static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } /**@brief Function for initializing the Connection Parameters module. */ static void conn_params_init(void) { uint32_t err_code; ble_conn_params_init_t cp_init; memset(&cp_init, 0, sizeof(cp_init)); cp_init.p_conn_params = NULL; cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; cp_init.disconnect_on_fail = false; cp_init.evt_handler = on_conn_params_evt; cp_init.error_handler = conn_params_error_handler; err_code = ble_conn_params_init(&cp_init); APP_ERROR_CHECK(err_code); } /**@brief Function for putting the chip into sleep mode. * * @note This function will not return. */ static void sleep_mode_enter(void) { uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); // Prepare wakeup buttons. err_code = bsp_btn_ble_sleep_mode_prepare(); APP_ERROR_CHECK(err_code); // Go to system-off mode (this function will not return; wakeup will cause a reset). err_code = sd_power_system_off(); // APP_ERROR_CHECK(err_code); } /**@brief Function for handling advertising events. * * @details This function will be called for advertising events which are passed to the application. * * @param[in] ble_adv_evt Advertising event. */ static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { uint32_t err_code; switch (ble_adv_evt) { case BLE_ADV_EVT_FAST: err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); APP_ERROR_CHECK(err_code); break; case BLE_ADV_EVT_IDLE: sleep_mode_enter(); break; default: break; } } /**@brief Function for handling BLE events. * * @param[in] p_ble_evt Bluetooth stack event. * @param[in] p_context Unused. */ static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); APP_ERROR_CHECK(err_code); isConnected = true; break; case BLE_GAP_EVT_DISCONNECTED: // LED indication will be changed when advertising starts. printf ("report 0\r"); m_conn_handle = BLE_CONN_HANDLE_INVALID; isConnected = false; break; case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { // printf("PHY update request.\r\n"); ble_gap_phys_t const phys = { .rx_phys = BLE_GAP_PHY_AUTO, .tx_phys = BLE_GAP_PHY_AUTO, }; err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); APP_ERROR_CHECK(err_code); } break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported // printf ("Params request\r\n"); err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: // printf ("Attribute missing\r\n"); // No system attributes have been stored. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); APP_ERROR_CHECK(err_code); break; case BLE_GATTC_EVT_TIMEOUT: // printf ("Character timeout\r\n"); // Disconnect on GATT Client timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_TIMEOUT: // printf ("Service timeout\r\n"); // Disconnect on GATT Server timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; default: // No implementation needed. break; } } /**@brief Function for the SoftDevice initialization. * * @details This function initializes the SoftDevice and the BLE event interrupt. */ static void ble_stack_init(void) { ret_code_t err_code; err_code = nrf_sdh_enable_request(); APP_ERROR_CHECK(err_code); // Configure the BLE stack using the default settings. // Fetch the start address of the application RAM. uint32_t ram_start = 0; err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); APP_ERROR_CHECK(err_code); // Enable BLE stack. err_code = nrf_sdh_ble_enable(&ram_start); APP_ERROR_CHECK(err_code); // Register a handler for BLE events. NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); } /**@brief Function for handling events from the GATT library. */ void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt) { if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len); } // printf("ATT MTU exchange completed. central 0x%x peripheral 0x%x\r\n", // p_gatt->att_mtu_desired_central, // p_gatt->att_mtu_desired_periph); } /**@brief Function for initializing the GATT library. */ void gatt_init(void) { ret_code_t err_code; err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); APP_ERROR_CHECK(err_code); err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); APP_ERROR_CHECK(err_code); } /**@brief Function for handling events from the BSP module. * * @param[in] event Event generated by button press. */ void bsp_event_handler(bsp_event_t event) { uint32_t err_code; switch (event) { case BSP_EVENT_SLEEP: sleep_mode_enter(); break; case BSP_EVENT_DISCONNECT: err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } break; case BSP_EVENT_WHITELIST_OFF: if (m_conn_handle == BLE_CONN_HANDLE_INVALID) { err_code = ble_advertising_restart_without_whitelist(&m_advertising); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } } break; default: break; } } /**@brief Function for handling app_uart events. * * @details This function will receive a single character from the app_uart module and append it to * a string. The string will be be sent over BLE when the last character received was a * 'new line' '\n' (hex 0x0A) or if the string has reached the maximum data length. */ /**@snippet [Handling the data received over UART] */ void uart_event_handle(app_uart_evt_t * p_event) { static uint8_t data_array[BLE_NUS_MAX_DATA_LEN]; static uint8_t index = 0; uint32_t err_code; switch (p_event->evt_type) { case APP_UART_DATA_READY: UNUSED_VARIABLE(app_uart_get(&data_array[index])); index++; if ((isConnected) && ((data_array[index - 1] == '\n') || (data_array[index - 1] == '\r') || (index >= m_ble_nus_max_data_len)) && (strncmp ((char *) data_array, "shell>", 6) != 0) && (strncmp ((char *) data_array, lastCommand, strlen (lastCommand)) != 0)) { //printf("%s", data_array); if ((index > 1) && (first_ser)) { NRF_LOG_HEXDUMP_DEBUG(data_array, index); static char command_line[256]; size_t siz = sizeof(command_line) / sizeof(command_line[0]); memset (command_line, 0, 256); strncpy (command_line, (char *) data_array,siz-1); //NRF_LOG_INFO("Data"); //NRF_LOG_INFO("Data %s",command_line); //std::string dat(command_line); //NRF_LOG_INFO("Data ver is set to %c(%d)",command_line ,siz-1); for(int i=0; i<10; i++) { NRF_LOG_INFO(" %c",command_line[i]); } do { uint16_t length = (uint16_t)index; err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle); if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_RESOURCES) && (err_code != NRF_ERROR_NOT_FOUND)) { APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_RESOURCES); Version_control = true; } /*---------------------------------------------------------------------------------------------------*/ if ((index > 1) && (second_ser)) { NRF_LOG_HEXDUMP_DEBUG(data_array, index); //second_ser = false; static char command[256]; size_t siz = sizeof(command) / sizeof(command[0]); memset (command, 0, 256); strncpy (command, (char *) data_array,siz-1); //std::string dat(command_line); //NRF_LOG_INFO("Data ver is set to %c(%d)",command_line ,siz-1); /*for(int i=0; i<30; i++) { NRF_LOG_INFO(" %c",command[i]); /*if(command[i] == ']') { Report_control = true; } } NRF_LOG_INFO("UART is empty");*/ do { uint16_t length = (uint16_t)index; // string converted = Encoding.UTF8.GetString(data_array, 0, data_array.Length); //NRF_LOG_INFO("Data ver is set to %s(%d)",converted ,sizeof(converted)); err_code = ble_nus_data_send_2(&m_nus, data_array, &length, m_conn_handle); if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_RESOURCES) && (err_code != NRF_ERROR_NOT_FOUND)) { APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_RESOURCES); } /*---------------------------------------------------------------------------------------------------------*/ if (index > 1 && (third_ser)) { NRF_LOG_HEXDUMP_DEBUG(data_array, index); static char Report_line[256]; size_t siz = sizeof(Report_line) / sizeof(Report_line[0]); memset (Report_line, 0, 256); strncpy (Report_line, (char *) data_array,siz-1); for(int i=0; i<10; i++) { NRF_LOG_INFO(" %c",Report_line[i]); } do { uint16_t length = (uint16_t)index; err_code = ble_nus_data_send_3(&m_nus, data_array, &length, m_conn_handle); if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_RESOURCES) && (err_code != NRF_ERROR_NOT_FOUND)) { APP_ERROR_CHECK(err_code); } } while (err_code == NRF_ERROR_RESOURCES); } index = 0; memset (data_array, 0, BLE_NUS_MAX_DATA_LEN); } else if ((isConnected) && ((strncmp ((char *) data_array, "shell>", 6) == 0) || (strncmp ((char *) data_array, lastCommand, strlen (lastCommand)) == 0))) { index = 0; memset (data_array, 0, BLE_NUS_MAX_DATA_LEN); } if(strncmp ((char *) data_array,"Software Reset Count", 20) == 0) { NRF_LOG_INFO("Ready for report"); Report_control = true; } /*else { NRF_LOG_INFO("Not ready for report"); }*/ break; /*case APP_UART_TX_EMPTY: NRF_LOG_INFO("UART is empty"); break;*/ case APP_UART_COMMUNICATION_ERROR: // printf ("UART Comm error\r\n"); APP_ERROR_HANDLER(p_event->data.error_communication); break; case APP_UART_FIFO_ERROR: // printf ("UART FIFO error\r\n"); APP_ERROR_HANDLER(p_event->data.error_code); break; default: break; } } /**@snippet [Handling the data received over UART] */ /**@brief Function for initializing the UART module. */ /**@snippet [UART Initialization] */ static void uart_init(void) { uint32_t err_code; app_uart_comm_params_t const comm_params = { .rx_pin_no = RX_PIN_NUMBER, .tx_pin_no = TX_PIN_NUMBER, .rts_pin_no = RTS_PIN_NUMBER, .cts_pin_no = CTS_PIN_NUMBER, .flow_control = APP_UART_FLOW_CONTROL_DISABLED, .use_parity = false, #if defined (UART_PRESENT) .baud_rate = NRF_UART_BAUDRATE_19200 #else .baud_rate = NRF_UARTE_BAUDRATE_19200 #endif }; APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_event_handle, APP_IRQ_PRIORITY_LOWEST, err_code); APP_ERROR_CHECK(err_code); } /**@snippet [UART Initialization] */ /**@brief Function for initializing the Advertising functionality. */ static void advertising_init(void) { uint32_t err_code; ble_advertising_init_t init; memset(&init, 0, sizeof(init)); init.advdata.name_type = BLE_ADVDATA_FULL_NAME; init.advdata.include_appearance = false; init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); init.srdata.uuids_complete.p_uuids = m_adv_uuids; init.config.ble_adv_fast_enabled = true; init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; init.config.ble_adv_fast_timeout = APP_ADV_DURATION; init.evt_handler = on_adv_evt; err_code = ble_advertising_init(&m_advertising, &init); APP_ERROR_CHECK(err_code); ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); } /**@brief Function for initializing buttons and leds. * * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up. */ static void buttons_leds_init(bool * p_erase_bonds) { bsp_event_t startup_event; uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler); APP_ERROR_CHECK(err_code); err_code = bsp_btn_ble_init(NULL, &startup_event); APP_ERROR_CHECK(err_code); *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); } /**@brief Function for initializing the nrf log module. */ static void log_init(void) { ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); } /**@brief Function for initializing power management. */ static void power_management_init(void) { ret_code_t err_code; err_code = nrf_pwr_mgmt_init(); APP_ERROR_CHECK(err_code); } /**@brief Function for handling the idle state (main loop). * * @details If there is no pending log operation, then sleep until next the next event occurs. */ static void idle_state_handle(void) { UNUSED_RETURN_VALUE(NRF_LOG_PROCESS()); nrf_pwr_mgmt_run(); } /**@brief Function for starting advertising. */ static void advertising_start(void) { uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); } /**@brief Application main function. */ int main(void) { bool erase_bonds; // Initialize. uart_init(); log_init(); timers_init(); buttons_leds_init(&erase_bonds); power_management_init(); ble_stack_init(); gap_params_init(); gatt_init(); //command_send(); services_init(); advertising_init(); conn_params_init(); // Start execution. // printf("\r\nUART started.\r\n"); advertising_start(); app_uart_put('\r'); // Enter main loop. for (;;) { idle_state_handle(); } } /** * @} */
my NRF ble_nus.c
/** * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "sdk_common.h" #if NRF_MODULE_ENABLED(BLE_NUS) #include "ble.h" #include "ble_nus.h" #include "ble_srv_common.h" #define NRF_LOG_MODULE_NAME ble_nus #if BLE_NUS_CONFIG_LOG_ENABLED #define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL #define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR #define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR #else // BLE_NUS_CONFIG_LOG_ENABLED #define NRF_LOG_LEVEL 0 #endif // BLE_NUS_CONFIG_LOG_ENABLED #include "nrf_log.h" NRF_LOG_MODULE_REGISTER(); #define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ #define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ #define BLE_UUID_NUS_RX_2_CHARACTERISTIC 0x1002 #define BLE_UUID_NUS_TX_2_CHARACTERISTIC 0x1003 #define BLE_UUID_NUS_RD_CHARACTERISTIC 0x2004 #define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ #define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ #define BLE_NUS_MAX_RD_CHAR_LEN BLE_NUS_MAX_DATA_LEN #define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */ /**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice. * * @param[in] p_nus Nordic UART Service structure. * @param[in] p_ble_evt Pointer to the event received from BLE stack. */ static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) { ret_code_t err_code; ble_nus_evt_t evt; ble_gatts_value_t gatts_val; uint8_t cccd_value[2]; ble_nus_client_context_t * p_client = NULL; err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, p_ble_evt->evt.gap_evt.conn_handle, (void *) &p_client); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", p_ble_evt->evt.gap_evt.conn_handle); } /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */ memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); gatts_val.p_value = cccd_value; gatts_val.len = sizeof(cccd_value); gatts_val.offset = 0; err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle, p_nus->rx_handles.cccd_handle, &gatts_val); if ((err_code == NRF_SUCCESS) && (p_nus->data_handler != NULL) && ble_srv_is_notification_enabled(gatts_val.p_value)) { if (p_client != NULL) { p_client->is_notification_enabled = true; } memset(&evt, 0, sizeof(ble_nus_evt_t)); evt.type = BLE_NUS_EVT_COMM_STARTED; evt.p_nus = p_nus; evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; evt.p_link_ctx = p_client; p_nus->data_handler(&evt); } } /**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. * * @param[in] p_nus Nordic UART Service structure. * @param[in] p_ble_evt Pointer to the event received from BLE stack. */ static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) { ret_code_t err_code; ble_nus_evt_t evt; ble_nus_client_context_t * p_client; ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, p_ble_evt->evt.gatts_evt.conn_handle, (void *) &p_client); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", p_ble_evt->evt.gatts_evt.conn_handle); } memset(&evt, 0, sizeof(ble_nus_evt_t)); evt.p_nus = p_nus; evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; evt.p_link_ctx = p_client; if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) && (p_evt_write->len == 2)) { if (p_client != NULL) { if (ble_srv_is_notification_enabled(p_evt_write->data)) { p_client->is_notification_enabled = true; evt.type = BLE_NUS_EVT_COMM_STARTED; NRF_LOG_INFO("Communication Started"); } else { p_client->is_notification_enabled = false; evt.type = BLE_NUS_EVT_COMM_STOPPED; NRF_LOG_INFO("Communication Stopped"); } if (p_nus->data_handler != NULL) { p_nus->data_handler(&evt); } } } else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) && (p_nus->data_handler != NULL)) { evt.type = BLE_NUS_EVT_RX_DATA; evt.params.rx_data.p_data = p_evt_write->data; evt.params.rx_data.length = p_evt_write->len; p_nus->data_handler(&evt); } else { // Do Nothing. This event is not relevant for this service. } } /**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice. * * @param[in] p_nus Nordic UART Service structure. * @param[in] p_ble_evt Pointer to the event received from BLE stack. */ static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) { ret_code_t err_code; ble_nus_evt_t evt; ble_nus_client_context_t * p_client; err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, p_ble_evt->evt.gatts_evt.conn_handle, (void *) &p_client); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", p_ble_evt->evt.gatts_evt.conn_handle); return; } if (p_client->is_notification_enabled) { NRF_LOG_INFO(" notfication Enabled"); memset(&evt, 0, sizeof(ble_nus_evt_t)); evt.type = BLE_NUS_EVT_TX_RDY; evt.p_nus = p_nus; evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; evt.p_link_ctx = p_client; p_nus->data_handler(&evt); } } /**@brief Function for adding TX characteristic. * * @param[in] p_nus Nordic UART Service structure. * @param[in] p_nus_init Information needed to initialize the service. * * @return NRF_SUCCESS on success, otherwise an error code. */ static uint32_t tx_char_add(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { /**@snippet [Adding proprietary characteristic to the SoftDevice] */ ble_gatts_char_md_t char_md; ble_gatts_attr_md_t cccd_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.notify = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = &cccd_md; char_md.p_sccd_md = NULL; ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_USER; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = sizeof(uint8_t); attr_char_value.init_offs = 0; attr_char_value.max_len = BLE_NUS_MAX_TX_CHAR_LEN; return sd_ble_gatts_characteristic_add(p_nus->service_handle, &char_md, &attr_char_value, &p_nus->tx_handles); /**@snippet [Adding proprietary characteristic to the SoftDevice] */ } /*-----------------------------------------------------------------------------------------------------------*/ static uint32_t tx_char_add_2(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { /**@snippet [Adding proprietary characteristic to the SoftDevice] */ ble_gatts_char_md_t char_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.notify = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = NULL; char_md.p_sccd_md = NULL; ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_TX_2_CHARACTERISTIC; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_USER; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = sizeof(uint8_t); attr_char_value.init_offs = 0; attr_char_value.max_len = BLE_NUS_MAX_TX_CHAR_LEN; return sd_ble_gatts_characteristic_add(p_nus->service_handle, &char_md, &attr_char_value, &p_nus->tx_2_handles); /**@snippet [Adding proprietary characteristic to the SoftDevice] */ } /*------------------------------------------------------------------------------------------------------------*/ /**@brief Function for adding RX characteristic. * * @param[in] p_nus Nordic UART Service structure. * @param[in] p_nus_init Information needed to initialize the service. * * @return NRF_SUCCESS on success, otherwise an error code. */ static uint32_t rx_char_add(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init) { ble_gatts_char_md_t char_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.write = 1; char_md.char_props.write_wo_resp = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = NULL; char_md.p_sccd_md = NULL; ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_USER; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = 1; attr_char_value.init_offs = 0; attr_char_value.max_len = BLE_NUS_MAX_RX_CHAR_LEN; return sd_ble_gatts_characteristic_add(p_nus->service_handle, &char_md, &attr_char_value, &p_nus->rx_handles); } /*-------------------------------------------------------------------------------------------*/ static uint32_t rx_char_2_add(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init) { ble_gatts_char_md_t char_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = NULL; char_md.p_sccd_md = NULL; ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_RX_2_CHARACTERISTIC; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_USER; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); uint8_t value[7] = {0x56,0x45,0x52,0x53,0x49,0x4F,0x4E}; attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = 7; attr_char_value.init_offs = 0; attr_char_value.max_len = BLE_NUS_MAX_RX_CHAR_LEN; attr_char_value.p_value = value; return sd_ble_gatts_characteristic_add(p_nus->service_handle, &char_md, &attr_char_value, &p_nus->rx_2_handles); } /*--------------------------------------------------------------------------------------------*/ /*--------------------------READ FROM Character-----------------------------------*/ static uint32_t rd_char_add(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { /**@snippet [Adding proprietary characteristic to the SoftDevice] */ ble_gatts_char_md_t char_md; ble_gatts_attr_t attr_char_value; ble_uuid_t ble_uuid; ble_gatts_attr_md_t attr_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.notify = 1; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = NULL; char_md.p_sccd_md = NULL; ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_RD_CHARACTERISTIC; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_USER; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 1; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &ble_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = sizeof(uint8_t); attr_char_value.init_offs = 0; attr_char_value.max_len = BLE_NUS_MAX_RD_CHAR_LEN; return sd_ble_gatts_characteristic_add(p_nus->service_handle, &char_md, &attr_char_value, &p_nus->rd_handles); } /*----------------------------------------------------------------------------------------------*/ void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) { if ((p_context == NULL) || (p_ble_evt == NULL)) { return; } ble_nus_t * p_nus = (ble_nus_t *)p_context; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: on_connect(p_nus, p_ble_evt); break; case BLE_GATTS_EVT_WRITE: on_write(p_nus, p_ble_evt); break; case BLE_GATTS_EVT_HVN_TX_COMPLETE: on_hvx_tx_complete(p_nus, p_ble_evt); break; default: // No implementation needed. break; } } /*-----------------------------------------------------------------------------------------*/ uint32_t ble_nus_init_2(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { ret_code_t err_code; ble_uuid_t ble_uuid; ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; VERIFY_PARAM_NOT_NULL(p_nus); VERIFY_PARAM_NOT_NULL(p_nus_init); // Initialize the service structure. p_nus->data_handler = p_nus_init->data_handler; /**@snippet [Adding proprietary Service to the SoftDevice] */ // Add a custom base UUID. err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); VERIFY_SUCCESS(err_code); ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_SERVICE_2; // Add the service. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); /**@snippet [Adding proprietary Service to the SoftDevice] */ VERIFY_SUCCESS(err_code); // Add the RX Characteristic. // Add the TX Characteristic. err_code = tx_char_add_2(p_nus, p_nus_init); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; } /*-----------------------------------------------------------------------------------------*/ /*------------------------------Service Three -----------------------------------------*/ uint32_t ble_nus_init_3(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { ret_code_t err_code; ble_uuid_t ble_uuid; ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; VERIFY_PARAM_NOT_NULL(p_nus); VERIFY_PARAM_NOT_NULL(p_nus_init); // Initialize the service structure. p_nus->data_handler = p_nus_init->data_handler; /**@snippet [Adding proprietary Service to the SoftDevice] */ // Add a custom base UUID. err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); VERIFY_SUCCESS(err_code); ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = 00; // Add the service. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); /**@snippet [Adding proprietary Service to the SoftDevice] */ VERIFY_SUCCESS(err_code); // Add the RX Characteristic. err_code = rx_char_2_add(p_nus, p_nus_init); VERIFY_SUCCESS(err_code); // Add the TX Characteristic. err_code = rd_char_add(p_nus, p_nus_init); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; } /*------------------------------------------------------------------------------------------------*/ uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) { ret_code_t err_code; ble_uuid_t ble_uuid; ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; VERIFY_PARAM_NOT_NULL(p_nus); VERIFY_PARAM_NOT_NULL(p_nus_init); // Initialize the service structure. p_nus->data_handler = p_nus_init->data_handler; /**@snippet [Adding proprietary Service to the SoftDevice] */ // Add a custom base UUID. err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); VERIFY_SUCCESS(err_code); ble_uuid.type = p_nus->uuid_type; ble_uuid.uuid = BLE_UUID_NUS_SERVICE; // Add the service. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); /**@snippet [Adding proprietary Service to the SoftDevice] */ VERIFY_SUCCESS(err_code); // Add the RX Characteristic. err_code = rx_char_add(p_nus, p_nus_init); VERIFY_SUCCESS(err_code); // Add the TX Characteristic. err_code = tx_char_add(p_nus, p_nus_init); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; } /*---------------------------------------------------------------------------------------------*/ uint32_t ble_nus_data_send(ble_nus_t * p_nus, uint8_t * p_data, uint16_t * p_length, uint16_t conn_handle) { ret_code_t err_code; ble_gatts_hvx_params_t hvx_params; ble_nus_client_context_t * p_client; VERIFY_PARAM_NOT_NULL(p_nus); err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client); VERIFY_SUCCESS(err_code); if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) { return NRF_ERROR_NOT_FOUND; } if (!p_client->is_notification_enabled) { return NRF_ERROR_INVALID_STATE; } if (*p_length > BLE_NUS_MAX_DATA_LEN) { return NRF_ERROR_INVALID_PARAM; } memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = p_nus->tx_handles.value_handle; hvx_params.p_data = p_data; hvx_params.p_len = p_length; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; return sd_ble_gatts_hvx(conn_handle, &hvx_params); } /*------------------------------------------------------------------------------------------------------*/ uint32_t ble_nus_data_send_2(ble_nus_t * p_nus, uint8_t * p_data, uint16_t * p_length, uint16_t conn_handle) { ret_code_t err_code; ble_gatts_hvx_params_t hvx_params; ble_nus_client_context_t * p_client; VERIFY_PARAM_NOT_NULL(p_nus); err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client); VERIFY_SUCCESS(err_code); if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) { return NRF_ERROR_NOT_FOUND; } if (!p_client->is_notification_enabled) { return NRF_ERROR_INVALID_STATE; } if (*p_length > BLE_NUS_MAX_DATA_LEN) { return NRF_ERROR_INVALID_PARAM; } memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = p_nus->tx_2_handles.value_handle; hvx_params.p_data = p_data; hvx_params.p_len = p_length; hvx_params.type = BLE_GATT_HVX_2_NOTIFICATION; return sd_ble_gatts_hvx(conn_handle, &hvx_params); } /*----------------------------------------------send for reading ---------------------------------*/ uint32_t ble_nus_data_send_3(ble_nus_t * p_nus, uint8_t * p_data, uint16_t * p_length, uint16_t conn_handle) { ret_code_t err_code; ble_gatts_hvx_params_t hvx_params; ble_nus_client_context_t * p_client; VERIFY_PARAM_NOT_NULL(p_nus); err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client); VERIFY_SUCCESS(err_code); if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) { return NRF_ERROR_NOT_FOUND; } if (!p_client->is_notification_enabled) { return NRF_ERROR_INVALID_STATE; } if (*p_length > BLE_NUS_MAX_DATA_LEN) { return NRF_ERROR_INVALID_PARAM; } memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = p_nus->rd_handles.value_handle; hvx_params.p_data = p_data; hvx_params.p_len = p_length; hvx_params.type = BLE_GATT_HVX_3_NOTIFICATION; return sd_ble_gatts_hvx(conn_handle, &hvx_params); } /*--------------------------------------------------------------------------------------------------*/ #endif // NRF_MODULE_ENABLED(BLE_NUS)
On Android studio Console i got this.
D/My Device: UART_CONNECT_MSG D/BluetoothGatt: onSearchComplete() = Device=E7:89:27:D2:B1:DA Status=0 W/UartService: mBluetoothGatt = android.bluetooth.BluetoothGatt@c8f41f0 E/onServicesDiscovered: [android.bluetooth.BluetoothGattService@eb66369, android.bluetooth.BluetoothGattService@22881ee, android.bluetooth.BluetoothGattService@eea068f, android.bluetooth.BluetoothGattService@93e8d1c, android.bluetooth.BluetoothGattService@e48cd25] W/UartService: first character: UUID 6e400003-b5a3-f393-e0a9-e50e24dcca9e W/UartService: second character: UUID 6e401003-b5a3-f393-e0a9-e50e24dcca9e W/UartService: first character: UUID 6e402004-b5a3-f393-e0a9-e50e24dcca9e W/UartService: I am Reading: 6e400003-b5a3-f393-e0a9-e50e24dcca9e D/BluetoothGatt: setCharacteristicNotification() - uuid: 6e400003-b5a3-f393-e0a9-e50e24dcca9e enable: true D/BluetoothGatt: setCharacteristicNotification() - uuid: 6e402004-b5a3-f393-e0a9-e50e24dcca9e enable: true D/BluetoothGatt: setCharacteristicNotification() - uuid: 6e401003-b5a3-f393-e0a9-e50e24dcca9e enable: true D/My Device: Sending device command E/UartService: mBluetoothGatt nullandroid.bluetooth.BluetoothGatt@c8f41f0 D/UartService: write TXchar - status=true D/CYNCH: time is going to terminate D/BluetoothAdapter: STATE_ON D/BluetoothLeScanner: could not find callback wrapper D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=5 device=E7:89:27:D2:B1:DA I/UartService: Disconnected from GATT server. D/My Device: UART_DISCONNECT_MSG